diff options
252 files changed, 2148 insertions, 857 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 3592287b95c..ca4b3662a08 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -937,6 +937,7 @@ pub fn find_deprecation( #[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)] pub enum ReprAttr { ReprInt(IntType), + ReprRust, ReprC, ReprPacked(u32), ReprSimd, @@ -985,6 +986,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> { let mut recognised = false; if item.is_word() { let hint = match item.name_or_empty() { + sym::Rust => Some(ReprRust), sym::C => Some(ReprC), sym::packed => Some(ReprPacked(1)), sym::simd => Some(ReprSimd), diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index d4c42a75874..84be50a6416 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -202,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } TerminatorKind::Goto { target: _ } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3f544bf7209..770c180ff2c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -770,7 +770,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } TerminatorKind::Goto { target: _ } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::UnwindResume | TerminatorKind::Return @@ -817,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro } } - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d91a3d94045..3004291c3e7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1334,7 +1334,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match &term.kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable @@ -1613,7 +1613,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, block_data, "resume on non-cleanup block!") } } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { if !is_cleanup { span_mirbug!(self, block_data, "abort on non-cleanup block!") } @@ -1697,7 +1697,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, ctxt, "unwind on cleanup block") } } - UnwindAction::Unreachable | UnwindAction::Terminate => (), + UnwindAction::Unreachable | UnwindAction::Terminate(_) => (), } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index ed371a04c53..9159bc36987 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -474,8 +474,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::UnwindTerminate => { - codegen_panic_cannot_unwind(fx, source_info); + TerminatorKind::UnwindTerminate(reason) => { + codegen_unwind_terminate(fx, source_info, *reason); } TerminatorKind::UnwindResume => { // FIXME implement unwinding @@ -971,13 +971,14 @@ pub(crate) fn codegen_panic_nounwind<'tcx>( codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span); } -pub(crate) fn codegen_panic_cannot_unwind<'tcx>( +pub(crate) fn codegen_unwind_terminate<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, + reason: UnwindTerminateReason, ) { let args = []; - codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span); + codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span); } fn codegen_panic_inner<'tcx>( diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 7db5f79eead..a934b0767f1 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -551,7 +551,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index d1bfd833cd8..a81585d4128 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> { _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: RValue<'gcc>, _mir: &mir::Body<'tcx>, - ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> { + ) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>> { // TODO(antoyo) None } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 7a68c291aa5..d174a3593b9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -20,7 +20,7 @@ pub fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, - debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, + debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, ) { // Find all scopes with variables defined in them. let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { @@ -51,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>( instance: Instance<'tcx>, mir: &Body<'tcx>, variables: &Option<BitSet<SourceScope>>, - debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, + debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, instantiated: &mut BitSet<SourceScope>, scope: SourceScope, ) { @@ -84,6 +84,7 @@ fn make_mir_scope<'ll, 'tcx>( } let loc = cx.lookup_debug_loc(scope_data.span.lo()); + let file_metadata = file_metadata(cx, &loc.file); let dbg_scope = match scope_data.inlined { Some((callee, _)) => { @@ -94,26 +95,18 @@ fn make_mir_scope<'ll, 'tcx>( ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(callee), ); - debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { - let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); - cx.dbg_scope_fn(callee, callee_fn_abi, None) - }) - } - None => { - let file_metadata = file_metadata(cx, &loc.file); - debug_context - .lexical_blocks - .entry((parent_scope.dbg_scope, loc.line, loc.col, file_metadata)) - .or_insert_with(|| unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( - DIB(cx), - parent_scope.dbg_scope, - file_metadata, - loc.line, - loc.col, - ) - }) + let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); + cx.dbg_scope_fn(callee, callee_fn_abi, None) } + None => unsafe { + llvm::LLVMRustDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope.dbg_scope, + file_metadata, + loc.line, + loc.col, + ) + }, }; let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 9cdeae2841b..40714a0afe9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_di_node}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::utils::{create_DIArray, debug_context, is_node_local_to_unit, DIB}; +use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; use crate::builder::Builder; @@ -67,8 +67,6 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> { type_map: metadata::TypeMap<'ll, 'tcx>, namespace_map: RefCell<DefIdMap<&'ll DIScope>>, recursion_marker_type: OnceCell<&'ll DIType>, - /// Maps a variable (name, scope, kind (argument or local), span) to its debug information. - variables: RefCell<FxHashMap<(Symbol, &'ll DIScope, VariableKind, Span), &'ll DIVariable>>, } impl Drop for CodegenUnitDebugContext<'_, '_> { @@ -93,7 +91,6 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { type_map: Default::default(), namespace_map: RefCell::new(Default::default()), recursion_marker_type: OnceCell::new(), - variables: RefCell::new(Default::default()), } } @@ -295,7 +292,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: &'ll Value, mir: &mir::Body<'tcx>, - ) -> Option<FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>> { + ) -> Option<FunctionDebugContext<&'ll DIScope, &'ll DILocation>> { if self.sess().opts.debuginfo == DebugInfo::None { return None; } @@ -307,11 +304,8 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { file_start_pos: BytePos(0), file_end_pos: BytePos(0), }; - let mut fn_debug_context = FunctionDebugContext { - scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes), - inlined_function_scopes: Default::default(), - lexical_blocks: Default::default(), - }; + let mut fn_debug_context = + FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes) }; // Fill in all the scopes, with the information from the MIR body. compute_mir_scopes(self, instance, mir, &mut fn_debug_context); @@ -612,39 +606,33 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { variable_kind: VariableKind, span: Span, ) -> &'ll DIVariable { - debug_context(self) - .variables - .borrow_mut() - .entry((variable_name, scope_metadata, variable_kind, span)) - .or_insert_with(|| { - let loc = self.lookup_debug_loc(span.lo()); - let file_metadata = file_metadata(self, &loc.file); - - let type_metadata = type_di_node(self, variable_type); - - let (argument_index, dwarf_tag) = match variable_kind { - ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), - LocalVariable => (0, DW_TAG_auto_variable), - }; - let align = self.align_of(variable_type); - - let name = variable_name.as_str(); - unsafe { - llvm::LLVMRustDIBuilderCreateVariable( - DIB(self), - dwarf_tag, - scope_metadata, - name.as_ptr().cast(), - name.len(), - file_metadata, - loc.line, - type_metadata, - true, - DIFlags::FlagZero, - argument_index, - align.bytes() as u32, - ) - } - }) + let loc = self.lookup_debug_loc(span.lo()); + let file_metadata = file_metadata(self, &loc.file); + + let type_metadata = type_di_node(self, variable_type); + + let (argument_index, dwarf_tag) = match variable_kind { + ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), + LocalVariable => (0, DW_TAG_auto_variable), + }; + let align = self.align_of(variable_type); + + let name = variable_name.as_str(); + unsafe { + llvm::LLVMRustDIBuilderCreateVariable( + DIB(self), + dwarf_tag, + scope_metadata, + name.as_ptr().cast(), + name.len(), + file_metadata, + loc.line, + type_metadata, + true, + DIFlags::FlagZero, + argument_index, + align.bytes() as u32, + ) + } } } diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 2be7bce115d..831645579b9 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -405,7 +405,11 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { // Vectors, even for non-power-of-two sizes, have the same layout as // arrays but don't count as aggregate types + // While LLVM theoretically supports non-power-of-two sizes, and they + // often work fine, sometimes x86-isel deals with them horribly + // (see #115212) so for now only use power-of-two ones. if let FieldsShape::Array { count, .. } = self.layout.fields() + && count.is_power_of_two() && let element = self.field(cx, 0) && element.ty.is_integral() { diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 3f5b46333d9..7fda2d5fadf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -285,7 +285,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi match data.terminator().kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 19228183462..6aef1664394 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,7 +12,7 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{self, AssertKind, SwitchTargets}; +use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -178,7 +178,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, - mir::UnwindAction::Terminate => { + mir::UnwindAction::Terminate(reason) => { if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) { // MSVC SEH will abort automatically if an exception tries to // propagate out from cleanup. @@ -191,7 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { None } else { - Some(fx.terminate_block()) + Some(fx.terminate_block(reason)) } } }; @@ -264,7 +264,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { let unwind_target = match unwind { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), - mir::UnwindAction::Terminate => Some(fx.terminate_block()), + mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, }; @@ -649,12 +649,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx, terminator: &mir::Terminator<'tcx>, + reason: UnwindTerminateReason, ) { let span = terminator.source_info.span; self.set_debug_loc(bx, terminator.source_info); // Obtain the panic entry point. - let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind); + let (fn_abi, llfn) = common::build_langcall(bx, Some(span), reason.lang_item()); // Codegen the actual panic invoke/call. let merging_succ = helper.do_call( @@ -1229,8 +1230,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::UnwindTerminate => { - self.codegen_terminate_terminator(helper, bx, terminator); + mir::TerminatorKind::UnwindTerminate(reason) => { + self.codegen_terminate_terminator(helper, bx, terminator, reason); MergingSucc::False } @@ -1579,79 +1580,81 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - fn terminate_block(&mut self) -> Bx::BasicBlock { - self.terminate_block.unwrap_or_else(|| { - let funclet; - let llbb; - let mut bx; - if base::wants_msvc_seh(self.cx.sess()) { - // This is a basic block that we're aborting the program for, - // notably in an `extern` function. These basic blocks are inserted - // so that we assert that `extern` functions do indeed not panic, - // and if they do we abort the process. - // - // On MSVC these are tricky though (where we're doing funclets). If - // we were to do a cleanuppad (like below) the normal functions like - // `longjmp` would trigger the abort logic, terminating the - // program. Instead we insert the equivalent of `catch(...)` for C++ - // which magically doesn't trigger when `longjmp` files over this - // frame. - // - // Lots more discussion can be found on #48251 but this codegen is - // modeled after clang's for: - // - // try { - // foo(); - // } catch (...) { - // bar(); - // } - // - // which creates an IR snippet like - // - // cs_terminate: - // %cs = catchswitch within none [%cp_terminate] unwind to caller - // cp_terminate: - // %cp = catchpad within %cs [null, i32 64, null] - // ... - - llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); - let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); - - let mut cs_bx = Bx::build(self.cx, llbb); - let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); - - // The "null" here is actually a RTTI type descriptor for the - // C++ personality function, but `catch (...)` has no type so - // it's null. The 64 here is actually a bitfield which - // represents that this is a catch-all block. - bx = Bx::build(self.cx, cp_llbb); - let null = - bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space)); - let sixty_four = bx.const_i32(64); - funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null])); - } else { - llbb = Bx::append_block(self.cx, self.llfn, "terminate"); - bx = Bx::build(self.cx, llbb); + fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { + if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason { + return cached_bb; + } - let llpersonality = self.cx.eh_personality(); - bx.filter_landing_pad(llpersonality); + let funclet; + let llbb; + let mut bx; + if base::wants_msvc_seh(self.cx.sess()) { + // This is a basic block that we're aborting the program for, + // notably in an `extern` function. These basic blocks are inserted + // so that we assert that `extern` functions do indeed not panic, + // and if they do we abort the process. + // + // On MSVC these are tricky though (where we're doing funclets). If + // we were to do a cleanuppad (like below) the normal functions like + // `longjmp` would trigger the abort logic, terminating the + // program. Instead we insert the equivalent of `catch(...)` for C++ + // which magically doesn't trigger when `longjmp` files over this + // frame. + // + // Lots more discussion can be found on #48251 but this codegen is + // modeled after clang's for: + // + // try { + // foo(); + // } catch (...) { + // bar(); + // } + // + // which creates an IR snippet like + // + // cs_terminate: + // %cs = catchswitch within none [%cp_terminate] unwind to caller + // cp_terminate: + // %cp = catchpad within %cs [null, i32 64, null] + // ... + + llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); + let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); + + let mut cs_bx = Bx::build(self.cx, llbb); + let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); + + // The "null" here is actually a RTTI type descriptor for the + // C++ personality function, but `catch (...)` has no type so + // it's null. The 64 here is actually a bitfield which + // represents that this is a catch-all block. + bx = Bx::build(self.cx, cp_llbb); + let null = + bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space)); + let sixty_four = bx.const_i32(64); + funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null])); + } else { + llbb = Bx::append_block(self.cx, self.llfn, "terminate"); + bx = Bx::build(self.cx, llbb); - funclet = None; - } + let llpersonality = self.cx.eh_personality(); + bx.filter_landing_pad(llpersonality); + + funclet = None; + } - self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); + self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); - let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind); - let fn_ty = bx.fn_decl_backend_type(&fn_abi); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, reason.lang_item()); + let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); - bx.do_not_inline(llret); + let llret = bx.call(fn_ty, None, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); + bx.do_not_inline(llret); - bx.unreachable(); + bx.unreachable(); - self.terminate_block = Some(llbb); - llbb - }) + self.terminate_block = Some((llbb, reason)); + llbb } /// Get the backend `BasicBlock` for a MIR `BasicBlock`, either already diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 7df830692d3..564b5da32cc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,12 +1,10 @@ use crate::traits::*; -use rustc_data_structures::fx::FxHashMap; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; -use rustc_middle::ty::Instance; use rustc_middle::ty::Ty; use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; @@ -19,19 +17,11 @@ use super::{FunctionCx, LocalRef}; use std::ops::Range; -pub struct FunctionDebugContext<'tcx, S, L> { - /// Maps from source code to the corresponding debug info scope. +pub struct FunctionDebugContext<S, L> { pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>, - - /// Maps from a given inlined function to its debug info declaration. - pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>, - - /// Maps from a lexical block (parent scope, line, column, file) to its debug info declaration. - /// This is particularily useful if the parent scope is an inlined function. - pub lexical_blocks: FxHashMap<(S, u32, u32, S), S>, } -#[derive(Copy, Clone, Eq, PartialEq, Hash)] +#[derive(Copy, Clone)] pub enum VariableKind { ArgumentVariable(usize /*index*/), LocalVariable, diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index ccf93f208d5..3d0c17e9cfb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -5,6 +5,7 @@ use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::traversal; +use rustc_middle::mir::UnwindTerminateReason; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -45,7 +46,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { mir: &'tcx mir::Body<'tcx>, - debug_context: Option<FunctionDebugContext<'tcx, Bx::DIScope, Bx::DILocation>>, + debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>, llfn: Bx::Function, @@ -83,8 +84,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option<Bx::BasicBlock>, - /// Cached terminate upon unwinding block - terminate_block: Option<Bx::BasicBlock>, + /// Cached terminate upon unwinding block and its reason + terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -174,7 +175,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let mut start_bx = Bx::build(cx, start_llbb); if mir.basic_blocks.iter().any(|bb| { - bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate)) + bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate(_))) }) { start_bx.set_personality_fn(cx.eh_personality()); } diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 4acc0ea076c..63fecaf34fd 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -26,7 +26,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Function, mir: &mir::Body<'tcx>, - ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>>; + ) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>>; // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 61d3de5c405..90848dbfbc7 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -756,6 +756,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow /// unwinding, and doing so is UB. + #[cold] // usually we have normal returns, not unwinding pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> { self.frame_mut().loc = match target { mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), @@ -763,9 +764,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { mir::UnwindAction::Unreachable => { throw_ub_custom!(fluent::const_eval_unreachable_unwind); } - mir::UnwindAction::Terminate => { + mir::UnwindAction::Terminate(reason) => { self.frame_mut().loc = Right(self.frame_mut().body.span); - M::unwind_terminate(self)?; + M::unwind_terminate(self, reason)?; // This might have pushed a new stack frame, or it terminated execution. // Either way, `loc` will not be updated. return Ok(()); diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index d3c73b896c0..91c07d73fce 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment; use super::{ AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx, - InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, + InterpResult, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, }; /// Data returned by Machine::stack_pop, @@ -222,7 +222,10 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>; /// Called when unwinding reached a state where execution should be terminated. - fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>; + fn unwind_terminate( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + reason: mir::UnwindTerminateReason, + ) -> InterpResult<'tcx>; /// Called for all binary operations where the LHS has pointer type. /// @@ -462,6 +465,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Called immediately after a stack frame got popped, but before jumping back to the caller. /// The `locals` have already been destroyed! + #[inline(always)] fn after_stack_pop( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _frame: Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>, @@ -471,6 +475,18 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { assert!(!unwinding); Ok(StackPopJump::Normal) } + + /// Called immediately after actual memory was allocated for a local + /// but before the local's stack frame is updated to point to that memory. + #[inline(always)] + fn after_local_allocated( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _frame: usize, + _local: mir::Local, + _mplace: &MPlaceTy<'tcx, Self::Provenance>, + ) -> InterpResult<'tcx> { + Ok(()) + } } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines @@ -501,7 +517,10 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { } #[inline(always)] - fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> { + fn unwind_terminate( + _ecx: &mut InterpCx<$mir, $tcx, Self>, + _reason: mir::UnwindTerminateReason, + ) -> InterpResult<$tcx> { unreachable!("unwinding cannot happen during compile-time evaluation") } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index daadb758964..40a7a0f4e56 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -899,7 +899,7 @@ where if local_layout.is_unsized() { throw_unsup_format!("unsized locals are not supported"); } - let mplace = *self.allocate(local_layout, MemoryKind::Stack)?; + let mplace = self.allocate(local_layout, MemoryKind::Stack)?; // Preserve old value. (As an optimization, we can skip this if it was uninit.) if !matches!(local_val, Immediate::Uninit) { // We don't have to validate as we can assume the local was already @@ -909,15 +909,16 @@ where local_val, local_layout, local_layout.align.abi, - mplace, + *mplace, )?; } + M::after_local_allocated(self, frame, local, &mplace)?; // Now we can call `access_mut` again, asserting it goes well, and actually // overwrite things. This points to the entire allocation, not just the part // the place refers to, i.e. we do this before we apply `offset`. *M::access_local_mut(self, frame, local).unwrap() = - Operand::Indirect(mplace); - mplace + Operand::Indirect(*mplace); + *mplace } &mut Operand::Indirect(mplace) => mplace, // this already was an indirect local }; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index b2ebcceceb3..ca7c484ea31 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -196,8 +196,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - UnwindTerminate => { - M::unwind_terminate(self)?; + UnwindTerminate(reason) => { + M::unwind_terminate(self, reason)?; } // When we encounter Resume, we've finished unwinding 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 e67098a3ac3..f288ddc25d3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_op(ops::Generator(hir::GeneratorKind::Gen)) } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`). span_bug!(self.span, "`Terminate` terminator outside of cleanup block") } 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 a8c61d2c8fd..fd6bc2ee9af 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 @@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { } } - mir::TerminatorKind::UnwindTerminate + mir::TerminatorKind::UnwindTerminate(_) | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 0dfbbf73dce..b829f24ab7a 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -10,8 +10,8 @@ use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, - Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, - START_BLOCK, + Terminator, TerminatorKind, UnOp, UnwindAction, UnwindTerminateReason, VarDebugInfo, + VarDebugInfoContents, START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -274,7 +274,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { self.fail(location, "`UnwindAction::Continue` in no-unwind function"); } } - UnwindAction::Unreachable | UnwindAction::Terminate => (), + UnwindAction::Terminate(UnwindTerminateReason::InCleanup) => { + if !is_cleanup { + self.fail( + location, + "`UnwindAction::Terminate(InCleanup)` in a non-cleanup block", + ); + } + } + // These are allowed everywhere. + UnwindAction::Unreachable | UnwindAction::Terminate(UnwindTerminateReason::Abi) => (), } } } @@ -501,7 +510,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind") } } - TerminatorKind::UnwindTerminate => { + TerminatorKind::UnwindTerminate(_) => { let bb = location.block; if !self.body.basic_blocks[bb].is_cleanup { self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block") @@ -1233,7 +1242,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | TerminatorKind::InlineAsm { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable => {} } diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 4f39dad205a..c1f0ff260d2 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -40,7 +40,7 @@ where } } -fn is_within_packed<'tcx, L>( +pub fn is_within_packed<'tcx, L>( tcx: TyCtxt<'tcx>, local_decls: &L, place: Place<'tcx>, diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 289e3422595..0aef7fa469e 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -5,7 +5,7 @@ mod check_validity_requirement; mod compare_types; mod type_name; -pub use self::alignment::is_disaligned; +pub use self::alignment::{is_disaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; pub use self::type_name::type_name; diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index ca908671ae5..30403a61442 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -11,9 +11,14 @@ pub struct Mmap(Vec<u8>); #[cfg(not(target_arch = "wasm32"))] impl Mmap { + /// # Safety + /// + /// The given file must not be mutated (i.e., not written, not truncated, ...) until the mapping is closed. + /// + /// However in practice most callers do not ensure this, so uses of this function are likely unsound. #[inline] pub unsafe fn map(file: File) -> io::Result<Self> { - // Safety: this is in fact not safe. + // Safety: the caller must ensure that this is safe. unsafe { memmap2::Mmap::map(&file).map(Mmap) } } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7bbed0877f0..841c626d0a3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -140,12 +140,6 @@ pub const EXIT_FAILURE: i32 = 1; pub const DEFAULT_BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md"; -const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"]; - -const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"]; - -const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"]; - pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T { match result { Err(..) => { @@ -1250,47 +1244,6 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { } } -/// Gets a list of extra command-line flags provided by the user, as strings. -/// -/// This function is used during ICEs to show more information useful for -/// debugging, since some ICEs only happens with non-default compiler flags -/// (and the users don't always report them). -fn extra_compiler_flags() -> Option<(Vec<String>, bool)> { - let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable(); - - let mut result = Vec::new(); - let mut excluded_cargo_defaults = false; - while let Some(arg) = args.next() { - if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) { - let content = if arg.len() == a.len() { - // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` - match args.next() { - Some(arg) => arg.to_string(), - None => continue, - } - } else if arg.get(a.len()..a.len() + 1) == Some("=") { - // An equals option, like `--crate-type=rlib` - arg[a.len() + 1..].to_string() - } else { - // A non-space option, like `-Cincremental=foo` - arg[a.len()..].to_string() - }; - let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); - if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { - excluded_cargo_defaults = true; - } else { - result.push(a.to_string()); - match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { - Some(s) => result.push(format!("{s}=[REDACTED]")), - None => result.push(content), - } - } - } - } - - if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } -} - /// Runs a closure and catches unwinds triggered by fatal errors. /// /// The compiler currently unwinds with a special sentinel value to abort @@ -1449,7 +1402,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str, extra_info: None }; - if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() { + if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") }); if excluded_cargo_defaults { handler.emit_note(session_diagnostics::IceExcludeCargoDefaults); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index db5df554d23..b7e1b0c8ad1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -197,8 +197,14 @@ impl CodeSuggestion { use rustc_span::{CharPos, Pos}; - /// Append to a buffer the remainder of the line of existing source code, and return the - /// count of lines that have been added for accurate highlighting. + /// Extracts a substring from the provided `line_opt` based on the specified low and high indices, + /// appends it to the given buffer `buf`, and returns the count of newline characters in the substring + /// for accurate highlighting. + /// If `line_opt` is `None`, a newline character is appended to the buffer, and 0 is returned. + /// + /// ## Returns + /// + /// The count of newline characters in the extracted substring. fn push_trailing( buf: &mut String, line_opt: Option<&Cow<'_, str>>, @@ -206,22 +212,30 @@ impl CodeSuggestion { hi_opt: Option<&Loc>, ) -> usize { let mut line_count = 0; + // Convert CharPos to Usize, as CharPose is character offset + // Extract low index and high index let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { + // Get high index while account for rare unicode and emoji with char_indices let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); match hi_opt { + // If high index exist, take string from low to high index Some(hi) if hi > lo => { + // count how many '\n' exist line_count = line[lo..hi].matches('\n').count(); buf.push_str(&line[lo..hi]) } Some(_) => (), + // If high index absence, take string from low index till end string.len None => { + // count how many '\n' exist line_count = line[lo..].matches('\n').count(); buf.push_str(&line[lo..]) } } } + // If high index is None if hi_opt.is_none() { buf.push('\n'); } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 302a9498413..23b20543d53 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -238,6 +238,7 @@ language_item_table! { PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0); + PanicInCleanup, sym::panic_in_cleanup, panic_in_cleanup, Target::Fn, GenericRequirement::Exact(0); /// libstd panic entry point. Necessary for const eval to be able to catch it BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index c44d12e61e3..f6a5b8f97a1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -1,6 +1,6 @@ use crate::FnCtxt; use rustc_hir as hir; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -133,15 +133,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - // Notably, we only point to params that are local to the - // item we're checking, since those are the ones we are able - // to look in the final `hir::PathSegment` for. Everything else - // would require a deeper search into the `qpath` than I think - // is worthwhile. - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() { - return true; + if self.point_at_path_if_possible(error, def_id, param, qpath) { + return true; + } } } hir::ExprKind::MethodCall(segment, receiver, args, ..) => { @@ -166,12 +165,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { return true; } + // Handle `Self` param specifically, since it's separated in + // the method call representation + if self_param_to_point_at.is_some() { + error.obligation.cause.span = receiver + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(receiver.span); + return true; + } } hir::ExprKind::Struct(qpath, fields, ..) => { - if let Res::Def( - hir::def::DefKind::Struct | hir::def::DefKind::Variant, - variant_def_id, - ) = self.typeck_results.borrow().qpath_res(qpath, hir_id) + if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) = + self.typeck_results.borrow().qpath_res(qpath, hir_id) { for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] @@ -193,10 +199,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if let Some(param_to_point_at) = param_to_point_at - && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) + + for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] + .into_iter() + .flatten() { - return true; + if self.point_at_path_if_possible(error, def_id, param, qpath) { + return true; + } } } _ => {} @@ -213,17 +223,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &hir::QPath<'tcx>, ) -> bool { match qpath { - hir::QPath::Resolved(_, path) => { - if let Some(segment) = path.segments.last() - && self.point_at_generic_if_possible(error, def_id, param, segment) + hir::QPath::Resolved(self_ty, path) => { + for segment in path.segments.iter().rev() { + if let Res::Def(kind, def_id) = segment.res + && !matches!(kind, DefKind::Mod | DefKind::ForeignMod) + && self.point_at_generic_if_possible(error, def_id, param, segment) + { + return true; + } + } + // Handle `Self` param specifically, since it's separated in + // the path representation + if let Some(self_ty) = self_ty + && let ty::GenericArgKind::Type(ty) = param.unpack() + && ty == self.tcx.types.self_param { + error.obligation.cause.span = self_ty + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(self_ty.span); return true; } } - hir::QPath::TypeRelative(_, segment) => { + hir::QPath::TypeRelative(self_ty, segment) => { if self.point_at_generic_if_possible(error, def_id, param, segment) { return true; } + // Handle `Self` param specifically, since it's separated in + // the path representation + if let ty::GenericArgKind::Type(ty) = param.unpack() + && ty == self.tcx.types.self_param + { + error.obligation.cause.span = self_ty + .span + .find_ancestor_in_same_ctxt(error.obligation.cause.span) + .unwrap_or(self_ty.span); + return true; + } } _ => {} } @@ -618,14 +654,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let variant_def_id = match expr_struct_def_kind { - hir::def::DefKind::Struct => { + DefKind::Struct => { if in_ty_adt.did() != expr_struct_def_id { // FIXME: Deal with type aliases? return Err(expr); } expr_struct_def_id } - hir::def::DefKind::Variant => { + DefKind::Variant => { // If this is a variant, its parent is the type definition. if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) { // FIXME: Deal with type aliases? @@ -727,14 +763,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let variant_def_id = match expr_struct_def_kind { - hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { + DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { // FIXME: Deal with type aliases? return Err(expr); } self.tcx.parent(expr_ctor_def_id) } - hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { + DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { // For a typical enum like // `enum Blah<T> { Variant(T) }` // we get the following resolutions: diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c4d3cbc9faa..f17f1d14bf3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -436,6 +436,12 @@ fn fatally_break_rust(tcx: TyCtxt<'_>) { tcx.sess.cfg_version, config::host_triple(), )); + if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { + handler.note_without_error(format!("compiler flags: {}", flags.join(" "))); + if excluded_cargo_defaults { + handler.note_without_error("some of the compiler flags provided by cargo are hidden"); + } + } } fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d7cb159149d..7f7f36ca170 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -158,13 +158,15 @@ lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name} +lint_check_name_removed = lint `{$lint_name}` has been removed: {$reason} + +lint_check_name_renamed = lint `{$lint_name}` has been renamed to `{$replace}` + lint_check_name_unknown = unknown lint: `{$lint_name}` .help = did you mean: `{$suggestion}` lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}` -lint_check_name_warning = {$msg} - lint_command_line_source = `forbid` lint level was set on command line lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike @@ -484,8 +486,11 @@ lint_redundant_semicolons = *[false] this semicolon } -lint_renamed_or_removed_lint = {$msg} +lint_removed_lint = lint `{$name}` has been removed: {$reason} + +lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` .suggestion = use the new name + .help = use the new name `{$replace}` lint_requested_level = requested on the command line with `{$level} {$lint_name}` diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index aabefb729f3..9dfde84b552 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -17,8 +17,8 @@ use self::TargetLint::*; use crate::errors::{ - CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel, - UnsupportedGroup, + CheckNameDeprecated, CheckNameRemoved, CheckNameRenamed, CheckNameUnknown, + CheckNameUnknownTool, RequestedLevel, UnsupportedGroup, }; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; @@ -124,9 +124,10 @@ pub enum CheckLintNameResult<'a> { NoLint(Option<Symbol>), /// The lint refers to a tool that has not been registered. NoTool, - /// The lint is either renamed or removed. This is the warning - /// message, and an optional new name (`None` if removed). - Warning(String, Option<String>), + /// The lint has been renamed to a new name. + Renamed(String), + /// The lint has been removed due to the given reason. + Removed(String), /// The lint is from a tool. If the Option is None, then either /// the lint does not exist in the tool or the code was not /// compiled with the tool and therefore the lint was never @@ -342,25 +343,32 @@ impl LintStore { sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() }); return; } - let lint_name = lint_name.to_string(); match self.check_lint_name(lint_name_only, tool_name, registered_tools) { - CheckLintNameResult::Warning(msg, _) => { - sess.emit_warning(CheckNameWarning { - msg, + CheckLintNameResult::Renamed(replace) => { + sess.emit_warning(CheckNameRenamed { + lint_name, + replace: &replace, + sub: RequestedLevel { level, lint_name }, + }); + } + CheckLintNameResult::Removed(reason) => { + sess.emit_warning(CheckNameRemoved { + lint_name, + reason: &reason, sub: RequestedLevel { level, lint_name }, }); } CheckLintNameResult::NoLint(suggestion) => { sess.emit_err(CheckNameUnknown { - lint_name: lint_name.clone(), + lint_name, suggestion, sub: RequestedLevel { level, lint_name }, }); } CheckLintNameResult::Tool(Err((Some(_), new_name))) => { sess.emit_warning(CheckNameDeprecated { - lint_name: lint_name.clone(), - new_name, + lint_name, + new_name: &new_name, sub: RequestedLevel { level, lint_name }, }); } @@ -445,14 +453,8 @@ impl LintStore { } } match self.by_name.get(&complete_name) { - Some(Renamed(new_name, _)) => CheckLintNameResult::Warning( - format!("lint `{complete_name}` has been renamed to `{new_name}`"), - Some(new_name.to_owned()), - ), - Some(Removed(reason)) => CheckLintNameResult::Warning( - format!("lint `{complete_name}` has been removed: {reason}"), - None, - ), + Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()), + Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()), None => match self.lint_groups.get(&*complete_name) { // If neither the lint, nor the lint group exists check if there is a `clippy::` // variant of this lint diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 68167487a1b..607875b3faa 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -91,9 +91,9 @@ pub struct BuiltinEllipsisInclusiveRangePatterns { #[derive(Subdiagnostic)] #[note(lint_requested_level)] -pub struct RequestedLevel { +pub struct RequestedLevel<'a> { pub level: Level, - pub lint_name: String, + pub lint_name: &'a str, } #[derive(Diagnostic)] @@ -102,13 +102,13 @@ pub struct UnsupportedGroup { pub lint_group: String, } -pub struct CheckNameUnknown { - pub lint_name: String, +pub struct CheckNameUnknown<'a> { + pub lint_name: &'a str, pub suggestion: Option<Symbol>, - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } -impl IntoDiagnostic<'_> for CheckNameUnknown { +impl IntoDiagnostic<'_> for CheckNameUnknown<'_> { fn into_diagnostic( self, handler: &Handler, @@ -127,25 +127,35 @@ impl IntoDiagnostic<'_> for CheckNameUnknown { #[derive(Diagnostic)] #[diag(lint_check_name_unknown_tool, code = "E0602")] -pub struct CheckNameUnknownTool { +pub struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } #[derive(Diagnostic)] -#[diag(lint_check_name_warning)] -pub struct CheckNameWarning { - pub msg: String, +#[diag(lint_check_name_renamed)] +pub struct CheckNameRenamed<'a> { + pub lint_name: &'a str, + pub replace: &'a str, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, +} + +#[derive(Diagnostic)] +#[diag(lint_check_name_removed)] +pub struct CheckNameRemoved<'a> { + pub lint_name: &'a str, + pub reason: &'a str, + #[subdiagnostic] + pub sub: RequestedLevel<'a>, } #[derive(Diagnostic)] #[diag(lint_check_name_deprecated)] -pub struct CheckNameDeprecated { - pub lint_name: String, - pub new_name: String, +pub struct CheckNameDeprecated<'a> { + pub lint_name: &'a str, + pub new_name: &'a str, #[subdiagnostic] - pub sub: RequestedLevel, + pub sub: RequestedLevel<'a>, } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 0a40d17f98e..f58782c0f22 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -4,8 +4,8 @@ use crate::{ fluent_generated as fluent, late::unerased_lint_store, lints::{ - DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, - RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion, + DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RemovedLint, + RenamedLint, RenamedLintSuggestion, UnknownLint, UnknownLintSuggestion, }, }; use rustc_ast as ast; @@ -915,18 +915,26 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { _ if !self.warn_about_weird_lints => {} - CheckLintNameResult::Warning(msg, renamed) => { + CheckLintNameResult::Renamed(new_name) => { let suggestion = - renamed.as_ref().map(|replace| RenamedOrRemovedLintSuggestion { - suggestion: sp, - replace: replace.as_str(), - }); + RenamedLintSuggestion { suggestion: sp, replace: new_name.as_str() }; + let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + self.emit_spanned_lint( + RENAMED_AND_REMOVED_LINTS, + sp.into(), + RenamedLint { name: name.as_str(), suggestion }, + ); + } + + CheckLintNameResult::Removed(reason) => { + let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); self.emit_spanned_lint( RENAMED_AND_REMOVED_LINTS, sp.into(), - RenamedOrRemovedLint { msg, suggestion }, + RemovedLint { name: name.as_str(), reason: reason.as_str() }, ); } + CheckLintNameResult::NoLint(suggestion) => { let name = if let Some(tool_ident) = tool_ident { format!("{}::{}", tool_ident.name, name) @@ -945,7 +953,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // If this lint was renamed, apply the new lint instead of ignoring the attribute. // This happens outside of the match because the new lint should be applied even if // we don't warn about the name change. - if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result { + if let CheckLintNameResult::Renamed(new_name) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate // NOTE: `new_name` already includes the tool name, so we don't have to add it again. if let CheckLintNameResult::Ok(ids) = diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 993c576d697..0e942d774a7 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1012,24 +1012,30 @@ pub struct DeprecatedLintName<'a> { pub replace: &'a str, } -// FIXME: Non-translatable msg #[derive(LintDiagnostic)] -#[diag(lint_renamed_or_removed_lint)] -pub struct RenamedOrRemovedLint<'a> { - pub msg: &'a str, +#[diag(lint_renamed_lint)] +pub struct RenamedLint<'a> { + pub name: &'a str, #[subdiagnostic] - pub suggestion: Option<RenamedOrRemovedLintSuggestion<'a>>, + pub suggestion: RenamedLintSuggestion<'a>, } #[derive(Subdiagnostic)] #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] -pub struct RenamedOrRemovedLintSuggestion<'a> { +pub struct RenamedLintSuggestion<'a> { #[primary_span] pub suggestion: Span, pub replace: &'a str, } #[derive(LintDiagnostic)] +#[diag(lint_removed_lint)] +pub struct RemovedLint<'a> { + pub name: &'a str, + pub reason: &'a str, +} + +#[derive(LintDiagnostic)] #[diag(lint_unknown_lint)] pub struct UnknownLint { pub name: String, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9ef3a1b30e4..6484c30167c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1275,9 +1275,11 @@ impl<O> AssertKind<O> { matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..)) } - /// Getting a description does not require `O` to be printable, and does not - /// require allocation. - /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately. + /// Get the message that is printed at runtime when this assertion fails. + /// + /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` by + /// invoking the appropriate lang item (panic_bounds_check/panic_misaligned_pointer_dereference) + /// instead of printing a static message. pub fn description(&self) -> &'static str { use AssertKind::*; match self { @@ -1303,6 +1305,11 @@ impl<O> AssertKind<O> { } /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing. + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn fmt_assert_args<W: Write>(&self, f: &mut W) -> fmt::Result where O: Debug, @@ -1358,6 +1365,12 @@ impl<O> AssertKind<O> { } } + /// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval). + /// + /// Needs to be kept in sync with the run-time behavior (which is defined by + /// `AssertKind::description` and the lang items mentioned in its docs). + /// Note that we deliberately show more details here than we do at runtime, such as the actual + /// numbers that overflowed -- it is much easier to do so here than at runtime. pub fn diagnostic_message(&self) -> DiagnosticMessage { use crate::fluent_generated::*; use AssertKind::*; diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index cd74a403ff6..da486c3465a 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -14,7 +14,8 @@ pub struct MirPatch<'tcx> { resume_block: Option<BasicBlock>, // Only for unreachable in cleanup path. unreachable_cleanup_block: Option<BasicBlock>, - terminate_block: Option<BasicBlock>, + // Cached block for UnwindTerminate (with reason) + terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, next_local: usize, } @@ -35,13 +36,15 @@ impl<'tcx> MirPatch<'tcx> { for (bb, block) in body.basic_blocks.iter_enumerated() { // Check if we already have a resume block - if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() { + if matches!(block.terminator().kind, TerminatorKind::UnwindResume) + && block.statements.is_empty() + { result.resume_block = Some(bb); continue; } // Check if we already have an unreachable block - if let TerminatorKind::Unreachable = block.terminator().kind + if matches!(block.terminator().kind, TerminatorKind::Unreachable) && block.statements.is_empty() && block.is_cleanup { @@ -50,8 +53,10 @@ impl<'tcx> MirPatch<'tcx> { } // Check if we already have a terminate block - if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() { - result.terminate_block = Some(bb); + if let TerminatorKind::UnwindTerminate(reason) = block.terminator().kind + && block.statements.is_empty() + { + result.terminate_block = Some((bb, reason)); continue; } } @@ -93,20 +98,20 @@ impl<'tcx> MirPatch<'tcx> { bb } - pub fn terminate_block(&mut self) -> BasicBlock { - if let Some(bb) = self.terminate_block { - return bb; + pub fn terminate_block(&mut self, reason: UnwindTerminateReason) -> BasicBlock { + if let Some((cached_bb, cached_reason)) = self.terminate_block && reason == cached_reason { + return cached_bb; } let bb = self.new_block(BasicBlockData { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo::outermost(self.body_span), - kind: TerminatorKind::UnwindTerminate, + kind: TerminatorKind::UnwindTerminate(reason), }), is_cleanup: true, }); - self.terminate_block = Some(bb); + self.terminate_block = Some((bb, reason)); bb } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index e91e822f915..79b64a491f4 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -621,7 +621,7 @@ pub enum TerminatorKind<'tcx> { /// /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in /// cleanup blocks. - UnwindTerminate, + UnwindTerminate(UnwindTerminateReason), /// Returns from the function. /// @@ -813,7 +813,7 @@ impl TerminatorKind<'_> { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::UnwindResume => "UnwindResume", - TerminatorKind::UnwindTerminate => "UnwindTerminate", + TerminatorKind::UnwindTerminate(_) => "UnwindTerminate", TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", @@ -842,11 +842,22 @@ pub enum UnwindAction { /// Terminates the execution if unwind happens. /// /// Depending on the platform and situation this may cause a non-unwindable panic or abort. - Terminate, + Terminate(UnwindTerminateReason), /// Cleanups to be done. Cleanup(BasicBlock), } +/// The reason we are terminating the process during unwinding. +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum UnwindTerminateReason { + /// Unwinding is just not possible given the ABI of this function. + Abi, + /// We were already cleaning up for an ongoing unwind, and a *second*, *nested* unwind was + /// triggered by the drop glue. + InCleanup, +} + /// Information about an assertion failure. #[derive(Clone, Hash, HashStable, PartialEq, Debug)] #[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index bd87563e2bb..7eddf13b3fb 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,3 +1,4 @@ +use rustc_hir::LangItem; use smallvec::SmallVec; use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction}; @@ -100,6 +101,40 @@ impl<'a> Iterator for SwitchTargetsIter<'a> { impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {} +impl UnwindAction { + fn cleanup_block(self) -> Option<BasicBlock> { + match self { + UnwindAction::Cleanup(bb) => Some(bb), + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => None, + } + } +} + +impl UnwindTerminateReason { + pub fn as_str(self) -> &'static str { + // Keep this in sync with the messages in `core/src/panicking.rs`. + match self { + UnwindTerminateReason::Abi => "panic in a function that cannot unwind", + UnwindTerminateReason::InCleanup => "panic in a destructor during cleanup", + } + } + + /// A short representation of this used for MIR printing. + pub fn as_short_str(self) -> &'static str { + match self { + UnwindTerminateReason::Abi => "abi", + UnwindTerminateReason::InCleanup => "cleanup", + } + } + + pub fn lang_item(self) -> LangItem { + match self { + UnwindTerminateReason::Abi => LangItem::PanicCannotUnwind, + UnwindTerminateReason::InCleanup => LangItem::PanicInCleanup, + } + } +} + #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct Terminator<'tcx> { pub source_info: SourceInfo, @@ -156,7 +191,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain((&[]).into_iter().copied()) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -198,7 +233,7 @@ impl<'tcx> TerminatorKind<'tcx> { Some(t).into_iter().chain(&mut []) } UnwindResume - | UnwindTerminate + | UnwindTerminate(_) | GeneratorDrop | Return | Unreachable @@ -215,7 +250,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -234,7 +269,7 @@ impl<'tcx> TerminatorKind<'tcx> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -271,18 +306,28 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let labels = self.fmt_successor_labels(); assert_eq!(successor_count, labels.len()); - let unwind = match self.unwind() { - // Not needed or included in successors - None | Some(UnwindAction::Cleanup(_)) => None, - Some(UnwindAction::Continue) => Some("unwind continue"), - Some(UnwindAction::Unreachable) => Some("unwind unreachable"), - Some(UnwindAction::Terminate) => Some("unwind terminate"), + // `Cleanup` is already included in successors + let show_unwind = !matches!(self.unwind(), None | Some(UnwindAction::Cleanup(_))); + let fmt_unwind = |fmt: &mut Formatter<'_>| -> fmt::Result { + write!(fmt, "unwind ")?; + match self.unwind() { + // Not needed or included in successors + None | Some(UnwindAction::Cleanup(_)) => unreachable!(), + Some(UnwindAction::Continue) => write!(fmt, "continue"), + Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"), + Some(UnwindAction::Terminate(reason)) => { + write!(fmt, "terminate({})", reason.as_short_str()) + } + } }; - match (successor_count, unwind) { - (0, None) => Ok(()), - (0, Some(unwind)) => write!(fmt, " -> {unwind}"), - (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), + match (successor_count, show_unwind) { + (0, false) => Ok(()), + (0, true) => { + write!(fmt, " -> ")?; + fmt_unwind(fmt) + } + (1, false) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; for (i, target) in self.successors().enumerate() { @@ -291,8 +336,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } write!(fmt, "{}: {:?}", labels[i], target)?; } - if let Some(unwind) = unwind { - write!(fmt, ", {unwind}")?; + if show_unwind { + write!(fmt, ", ")?; + fmt_unwind(fmt)?; } write!(fmt, "]") } @@ -312,7 +358,9 @@ impl<'tcx> TerminatorKind<'tcx> { Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), UnwindResume => write!(fmt, "resume"), - UnwindTerminate => write!(fmt, "abort"), + UnwindTerminate(reason) => { + write!(fmt, "abort({})", reason.as_short_str()) + } Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({place:?})"), @@ -391,7 +439,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { use self::TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![], + Return | UnwindResume | UnwindTerminate(_) | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], SwitchInt { ref targets, .. } => targets .values @@ -443,7 +491,8 @@ pub enum TerminatorEdges<'mir, 'tcx> { /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { return_: Option<BasicBlock>, - unwind: UnwindAction, + /// The cleanup block, if it exists. + cleanup: Option<BasicBlock>, place: CallReturnPlaces<'mir, 'tcx>, }, /// Special edge for `SwitchInt`. @@ -486,7 +535,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> { use TerminatorKind::*; match *self { - Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => { + Return | UnwindResume | UnwindTerminate(_) | GeneratorDrop | Unreachable => { TerminatorEdges::None } @@ -496,7 +545,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Drop { target, unwind, place: _, replace: _ } | FalseUnwind { real_target: target, unwind } => match unwind { UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind), - UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => { + UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => { TerminatorEdges::Single(target) } }, @@ -508,7 +557,7 @@ impl<'tcx> TerminatorKind<'tcx> { Yield { resume: target, drop, resume_arg, value: _ } => { TerminatorEdges::AssignOnReturn { return_: Some(target), - unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup), + cleanup: drop, place: CallReturnPlaces::Yield(resume_arg), } } @@ -516,7 +565,7 @@ impl<'tcx> TerminatorKind<'tcx> { Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => { TerminatorEdges::AssignOnReturn { return_: target, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::Call(destination), } } @@ -530,7 +579,7 @@ impl<'tcx> TerminatorKind<'tcx> { unwind, } => TerminatorEdges::AssignOnReturn { return_: destination, - unwind, + cleanup: unwind.cleanup_block(), place: CallReturnPlaces::InlineAsm(operands), }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index b3d3366ae10..87b04aabe6a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -470,7 +470,7 @@ macro_rules! make_mir_visitor { match kind { TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume | - TerminatorKind::UnwindTerminate | + TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1274f427e4f..8fedf4dca95 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2150,6 +2150,7 @@ impl<'tcx> TyCtxt<'tcx> { for attr in self.get_attrs(did, sym::repr) { for r in attr::parse_repr_attr(&self.sess, attr) { flags.insert(match r { + attr::ReprRust => ReprFlags::empty(), attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { let pack = Align::from_bytes(pack as u64).unwrap(); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 567e7bfb5bf..4cf6a349af7 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -370,7 +370,7 @@ impl DropTree { let terminator = TerminatorKind::Drop { target: blocks[drop_data.1].unwrap(), // The caller will handle this if needed. - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), place: drop_data.0.local.into(), replace: false, }; @@ -1507,7 +1507,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Yield { .. } diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 84c80bf41a4..94be38beee4 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -186,7 +186,7 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx match self.body[bb].terminator().kind { // These terminators return control flow to the caller. - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::UnwindResume | TerminatorKind::Return 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 383e80851f0..f46cf0dc0ff 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,6 +7,7 @@ use crate::errors::*; use rustc_arena::TypedArena; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, @@ -660,6 +661,17 @@ fn report_arm_reachability<'p, 'tcx>( } } +fn collect_non_exhaustive_tys<'p, 'tcx>( + pat: &DeconstructedPat<'p, 'tcx>, + non_exhaustive_tys: &mut FxHashSet<Ty<'tcx>>, +) { + if matches!(pat.ctor(), Constructor::NonExhaustive) { + non_exhaustive_tys.insert(pat.ty()); + } + pat.iter_fields() + .for_each(|field_pat| collect_non_exhaustive_tys(field_pat, non_exhaustive_tys)) +} + /// Report that a match is not exhaustive. fn non_exhaustive_match<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, @@ -717,22 +729,27 @@ fn non_exhaustive_match<'p, 'tcx>( scrut_ty, if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" } )); - if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize) - && !is_empty_match - && witnesses.len() == 1 - && matches!(witnesses[0].ctor(), Constructor::NonExhaustive) - { - err.note(format!( - "`{scrut_ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ - exhaustively", - )); - if cx.tcx.sess.is_nightly_build() { - err.help(format!( - "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ - enable precise `{scrut_ty}` matching", - )); + + if !is_empty_match && witnesses.len() == 1 { + let mut non_exhaustive_tys = FxHashSet::default(); + collect_non_exhaustive_tys(&witnesses[0], &mut non_exhaustive_tys); + + for ty in non_exhaustive_tys { + if ty == cx.tcx.types.usize || ty == cx.tcx.types.isize { + err.note(format!( + "`{ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ + exhaustively", + )); + if cx.tcx.sess.is_nightly_build() { + err.help(format!( + "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ + enable precise `{ty}` matching", + )); + } + } } } + if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() { if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.param_env) { err.note("references are always considered inhabited"); diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 9e02b027182..ad5f83d9e25 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -80,7 +80,7 @@ impl Unwind { fn into_action(self) -> UnwindAction { match self { Unwind::To(bb) => UnwindAction::Cleanup(bb), - Unwind::InCleanup => UnwindAction::Terminate, + Unwind::InCleanup => UnwindAction::Terminate(UnwindTerminateReason::InCleanup), } } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 8a9e37c5a4f..70451edd500 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::{ - self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction, + self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, }; use std::ops::RangeInclusive; @@ -486,10 +486,10 @@ impl Direction for Forward { propagate(target, exit_state); propagate(unwind, exit_state); } - TerminatorEdges::AssignOnReturn { return_, unwind, place } => { + TerminatorEdges::AssignOnReturn { return_, cleanup, place } => { // This must be done *first*, otherwise the unwind path will see the assignments. - if let UnwindAction::Cleanup(unwind) = unwind { - propagate(unwind, exit_state); + if let Some(cleanup) = cleanup { + propagate(cleanup, exit_state); } if let Some(return_) = return_ { analysis.apply_call_return_effect(exit_state, bb, place); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 5ed8f20b73f..3ad9d3d4264 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -131,7 +131,7 @@ where } } - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 531390c2f07..94d6eb67d49 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -291,7 +291,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. - TerminatorKind::UnwindTerminate + TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } @@ -328,7 +328,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> { // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Yield { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4adf3dec61b..2e3b9577b50 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -371,7 +371,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // need recording. | TerminatorKind::Return | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } => {} diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 1eea8eef0ad..6872ef5e985 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -270,7 +270,7 @@ pub trait ValueAnalysis<'tcx> { } TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 5aed89139e2..4500bb7ff0f 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -104,7 +104,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { for id in calls_to_terminate { let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Terminate; + *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } for id in cleanups_to_remove { diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index fb4705e0754..b814fbf32b1 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -53,8 +53,10 @@ impl AddCallGuards { kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. }, source_info, }) if pred_count[*destination] > 1 - && (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate) - || self == &AllCallEdges) => + && (matches!( + unwind, + UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) + ) || self == &AllCallEdges) => { // It's a critical edge, break it let call_guard = BasicBlockData { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index e72db1a59a0..0fce9cb19a8 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -58,7 +58,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 4f8ca916d5b..da8913d604b 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -679,7 +679,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index d3d4fcd3a52..60461691e7f 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -116,7 +116,7 @@ impl CoverageGraph { match term.kind { TerminatorKind::Return { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 6fabaca524a..717763a94a0 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -868,7 +868,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp // Retain spans from all other terminators TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 3f988930b5e..ef14105041b 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -12,6 +12,7 @@ //! will still not cause any further changes. //! +use crate::util::is_within_packed; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -49,6 +50,11 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS && !place.is_indirect() && !borrowed.contains(place.local) && !state.contains(place.local) + // If `place` is a projection of a disaligned field in a packed ADT, + // the move may be codegened as a pointer to that field. + // Using that disaligned pointer may trigger UB in the callee, + // so do nothing. + && is_within_packed(tcx, body, place).is_none() { call_operands_to_move.push((bb, index)); } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 041f7c7221e..d9a132e5cf1 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -648,7 +648,7 @@ impl WriteInfo { } TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable { .. } => (), TerminatorKind::Drop { .. } => { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index a80ae480089..78d7ffb3698 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -362,8 +362,13 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { UnwindAction::Unreachable => { Unwind::To(self.patch.unreachable_cleanup_block()) } - UnwindAction::Terminate => { - Unwind::To(self.patch.terminate_block()) + UnwindAction::Terminate(reason) => { + debug_assert_ne!( + reason, + UnwindTerminateReason::InCleanup, + "we are not in a cleanup block, InCleanup reason should be impossible" + ); + Unwind::To(self.patch.terminate_block(reason)) } } }; @@ -496,7 +501,8 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { if let TerminatorKind::Call { destination, target: Some(_), - unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate, + unwind: + UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_), .. } = data.terminator().kind { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 96077322575..1e7161189c3 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1091,7 +1091,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { UnwindAction::Cleanup(tgt) => tgt, UnwindAction::Continue => elaborator.patch.resume_block(), UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(), - UnwindAction::Terminate => elaborator.patch.terminate_block(), + UnwindAction::Terminate(reason) => elaborator.patch.terminate_block(reason), }) }; elaborate_drop( @@ -1239,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These never unwind. TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -1759,7 +1759,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 734e93783d1..9551c7a2a8d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -906,12 +906,12 @@ impl Integrator<'_, '_> { UnwindAction::Cleanup(_) | UnwindAction::Continue => { bug!("cleanup on cleanup block"); } - UnwindAction::Unreachable | UnwindAction::Terminate => return unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => return unwind, } } match unwind { - UnwindAction::Unreachable | UnwindAction::Terminate => unwind, + UnwindAction::Unreachable | UnwindAction::Terminate(_) => unwind, UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)), // Add an unwind edge to the original call's cleanup block UnwindAction::Continue => self.cleanup_block, @@ -1022,10 +1022,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt }, UnwindAction::Continue => TerminatorKind::UnwindResume, UnwindAction::Unreachable => TerminatorKind::Unreachable, - UnwindAction::Terminate => TerminatorKind::UnwindTerminate, + UnwindAction::Terminate(reason) => TerminatorKind::UnwindTerminate(reason), }; } - TerminatorKind::UnwindTerminate => {} + TerminatorKind::UnwindTerminate(_) => {} TerminatorKind::Unreachable => {} TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => { *real_target = self.map_block(*real_target); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 5782adbb3ff..8c48a667786 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -72,7 +72,7 @@ impl RemoveNoopLandingPads { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::Return - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index de1b80585d1..e1e4acccccd 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -114,7 +114,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield { .. } - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::InlineAsm { .. } @@ -166,7 +166,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { } TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 079cf9eb4e9..e1000d96932 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -570,10 +570,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { TerminatorKind::Drop { place: dest_field, target: unwind, - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); unwind = next_unwind; } @@ -851,10 +851,10 @@ fn build_call_shim<'tcx>( TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), - unwind: UnwindAction::Terminate, + unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, }, - true, + /* is_cleanup */ true, ); // BB #4 - resume diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cd7908e75e2..f917e52109a 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -737,6 +737,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let source = self.body.source_info(location).span; let tcx = self.tcx; + let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| { + let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); + if should_codegen_locally(tcx, &instance) { + this.output.push(create_fn_mono_item(tcx, instance, source)); + } + }; + match terminator.kind { mir::TerminatorKind::Call { ref func, .. } => { let callee_ty = func.ty(self.body, tcx); @@ -771,19 +778,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck, _ => LangItem::Panic, }; - let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source))); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + push_mono_lang_item(self, lang_item); } - mir::TerminatorKind::UnwindTerminate { .. } => { - let instance = Instance::mono( - tcx, - tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), - ); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + mir::TerminatorKind::UnwindTerminate(reason) => { + push_mono_lang_item(self, reason.lang_item()); } mir::TerminatorKind::Goto { .. } | mir::TerminatorKind::SwitchInt { .. } @@ -796,14 +794,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { | mir::TerminatorKind::FalseUnwind { .. } => bug!(), } - if let Some(mir::UnwindAction::Terminate) = terminator.unwind() { - let instance = Instance::mono( - tcx, - tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), - ); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(tcx, instance, source)); - } + if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() { + push_mono_lang_item(self, reason.lang_item()); } self.super_terminator(terminator, location); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6eacbebe75f..b2a4da885aa 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -721,7 +721,7 @@ passes_unrecognized_field = passes_unrecognized_repr_hint = unrecognized representation hint - .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` passes_unused = unused attribute diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 197b335bdec..50a087c7847 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1732,6 +1732,7 @@ impl CheckAttrVisitor<'_> { } match hint.name_or_empty() { + sym::Rust => {} sym::C => { is_c = true; match target { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 71f2591fe66..f76c69af526 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -111,3 +111,50 @@ impl CanonicalizedPath { &self.original } } + +/// Gets a list of extra command-line flags provided by the user, as strings. +/// +/// This function is used during ICEs to show more information useful for +/// debugging, since some ICEs only happens with non-default compiler flags +/// (and the users don't always report them). +pub fn extra_compiler_flags() -> Option<(Vec<String>, bool)> { + const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"]; + + const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"]; + + const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"]; + + let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable(); + + let mut result = Vec::new(); + let mut excluded_cargo_defaults = false; + while let Some(arg) = args.next() { + if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) { + let content = if arg.len() == a.len() { + // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` + match args.next() { + Some(arg) => arg.to_string(), + None => continue, + } + } else if arg.get(a.len()..a.len() + 1) == Some("=") { + // An equals option, like `--crate-type=rlib` + arg[a.len() + 1..].to_string() + } else { + // A non-space option, like `-Cincremental=foo` + arg[a.len()..].to_string() + }; + let option = content.split_once('=').map(|s| s.0).unwrap_or(&content); + if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) { + excluded_cargo_defaults = true; + } else { + result.push(a.to_string()); + match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { + Some(s) => result.push(format!("{s}=[REDACTED]")), + None => result.push(content), + } + } + } + } + + if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None } +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aea59c31379..925d4a3bdd8 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -15,7 +15,6 @@ use crate::stable_mir::ty::{ }; use crate::stable_mir::{self, Context}; use rustc_hir as hir; -use rustc_middle::mir::coverage::CodeRegion; use rustc_middle::mir::interpret::alloc_range; use rustc_middle::mir::{self, ConstantKind}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; @@ -108,6 +107,23 @@ impl<'tcx> Context for Tables<'tcx> { let generic_def = self.tcx.generics_of(def_id); generic_def.stable(self) } + + fn predicates_of( + &mut self, + trait_def: &stable_mir::ty::TraitDef, + ) -> stable_mir::GenericPredicates { + let trait_def_id = self.trait_def_id(trait_def); + let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(trait_def_id); + stable_mir::GenericPredicates { + parent: parent.map(|did| self.trait_def(did)), + predicates: predicates + .iter() + .map(|(clause, span)| { + (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + }) + .collect(), + } + } } pub struct Tables<'tcx> { @@ -175,10 +191,7 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> { variance: variance.stable(tables), } } - Coverage(coverage) => stable_mir::mir::Statement::Coverage(stable_mir::mir::Coverage { - kind: coverage.kind.stable(tables), - code_region: coverage.code_region.as_ref().map(|reg| reg.stable(tables)), - }), + Coverage(coverage) => stable_mir::mir::Statement::Coverage(opaque(coverage)), Intrinsic(intrinstic) => { stable_mir::mir::Statement::Intrinsic(intrinstic.stable(tables)) } @@ -200,7 +213,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { stable_mir::mir::Rvalue::Repeat(op.stable(tables), len) } Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( - opaque(region), + region.stable(tables), kind.stable(tables), place.stable(tables), ), @@ -464,7 +477,19 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> { match self { Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)), Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)), - Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()), + Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables)), + } + } +} + +impl<'tcx> Stable<'tcx> for mir::Constant<'tcx> { + type T = stable_mir::mir::Constant; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + stable_mir::mir::Constant { + span: self.span.stable(tables), + user_ty: self.user_ty.map(|u| u.as_usize()).or(None), + literal: self.literal.stable(tables), } } } @@ -479,30 +504,6 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> { } } -impl<'tcx> Stable<'tcx> for mir::coverage::CoverageKind { - type T = stable_mir::mir::CoverageKind; - fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::CoverageKind; - match self { - CoverageKind::Counter { function_source_hash, id } => { - stable_mir::mir::CoverageKind::Counter { - function_source_hash: *function_source_hash as usize, - id: opaque(id), - } - } - CoverageKind::Expression { id, lhs, op, rhs } => { - stable_mir::mir::CoverageKind::Expression { - id: opaque(id), - lhs: opaque(lhs), - op: op.stable(tables), - rhs: opaque(rhs), - } - } - CoverageKind::Unreachable => stable_mir::mir::CoverageKind::Unreachable, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { type T = stable_mir::mir::UserTypeProjection; @@ -511,18 +512,6 @@ impl<'tcx> Stable<'tcx> for mir::UserTypeProjection { } } -impl<'tcx> Stable<'tcx> for mir::coverage::Op { - type T = stable_mir::mir::Op; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - use rustc_middle::mir::coverage::Op::*; - match self { - Subtract => stable_mir::mir::Op::Subtract, - Add => stable_mir::mir::Op::Add, - } - } -} - impl<'tcx> Stable<'tcx> for mir::Local { type T = stable_mir::mir::Local; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -569,20 +558,6 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { } } -impl<'tcx> Stable<'tcx> for CodeRegion { - type T = stable_mir::mir::CodeRegion; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - stable_mir::mir::CodeRegion { - file_name: self.file_name.as_str().to_string(), - start_line: self.start_line as usize, - start_col: self.start_col as usize, - end_line: self.end_line as usize, - end_col: self.end_col as usize, - } - } -} - impl<'tcx> Stable<'tcx> for mir::UnwindAction { type T = stable_mir::mir::UnwindAction; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -590,7 +565,7 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction { match self { UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue, UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable, - UnwindAction::Terminate => stable_mir::mir::UnwindAction::Terminate, + UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate, UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()), } } @@ -788,7 +763,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { otherwise: targets.otherwise().as_usize(), }, UnwindResume => Terminator::Resume, - UnwindTerminate => Terminator::Abort, + UnwindTerminate(_) => Terminator::Abort, Return => Terminator::Return, Unreachable => Terminator::Unreachable, Drop { place, target, unwind, replace: _ } => Terminator::Drop { @@ -842,12 +817,9 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::GenericArgKind; match self { - ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)), + ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)), ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)), - ty::GenericArgKind::Const(cnst) => { - let cnst = ConstantKind::from_const(*cnst, tables.tcx); - GenericArgKind::Const(stable_mir::ty::Const { literal: cnst.stable(tables) }) - } + ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)), } } } @@ -950,12 +922,12 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { type T = stable_mir::ty::BoundRegionKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::BoundRegionKind; match self { ty::BoundRegionKind::BrAnon(option_span) => { - BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span))) + BoundRegionKind::BrAnon(option_span.map(|span| span.stable(tables))) } ty::BoundRegionKind::BrNamed(def_id, symbol) => { BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string()) @@ -1053,16 +1025,14 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { - let cnst = ConstantKind::from_const(*constant, tables.tcx); - let cnst = stable_mir::ty::Const { literal: cnst.stable(tables) }; - TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), cnst)) + TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), constant.stable(tables))) } ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { TyKind::RigidTy(RigidTy::RawPtr(tables.intern_ty(*ty), mutbl.stable(tables))) } ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( - opaque(region), + region.stable(tables), tables.intern_ty(*ty), mutbl.stable(tables), )), @@ -1077,7 +1047,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { .iter() .map(|existential_predicate| existential_predicate.stable(tables)) .collect(), - opaque(region), + region.stable(tables), dyn_kind.stable(tables), )) } @@ -1112,6 +1082,15 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { + type T = stable_mir::ty::Const; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let cnst = ConstantKind::from_const(*self, tables.tcx); + stable_mir::ty::Const { literal: cnst.stable(tables) } + } +} + impl<'tcx> Stable<'tcx> for ty::ParamTy { type T = stable_mir::ty::ParamTy; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { @@ -1238,14 +1217,6 @@ impl<'tcx> Stable<'tcx> for ty::Generics { } } -impl<'tcx> Stable<'tcx> for rustc_span::Span { - type T = stable_mir::ty::Span; - - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - opaque(self) - } -} - impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { type T = stable_mir::ty::GenericParamDefKind; @@ -1276,3 +1247,188 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { } } } + +impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { + type T = stable_mir::ty::PredicateKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use ty::PredicateKind; + match self { + PredicateKind::Clause(clause_kind) => { + stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables)) + } + PredicateKind::ObjectSafe(did) => { + stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did)) + } + PredicateKind::ClosureKind(did, generic_args, closure_kind) => { + stable_mir::ty::PredicateKind::ClosureKind( + tables.closure_def(*did), + generic_args.stable(tables), + closure_kind.stable(tables), + ) + } + PredicateKind::Subtype(subtype_predicate) => { + stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables)) + } + PredicateKind::Coerce(coerce_predicate) => { + stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables)) + } + PredicateKind::ConstEquate(a, b) => { + stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables)) + } + PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous, + PredicateKind::AliasRelate(a, b, alias_relation_direction) => { + stable_mir::ty::PredicateKind::AliasRelate( + a.unpack().stable(tables), + b.unpack().stable(tables), + alias_relation_direction.stable(tables), + ) + } + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { + type T = stable_mir::ty::ClauseKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use ty::ClauseKind::*; + match *self { + Trait(trait_object) => stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables)), + RegionOutlives(region_outlives) => { + stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables)) + } + TypeOutlives(type_outlives) => { + let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives; + stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate( + tables.intern_ty(a), + b.stable(tables), + )) + } + Projection(projection_predicate) => { + stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables)) + } + ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType( + const_.stable(tables), + tables.intern_ty(ty), + ), + WellFormed(generic_arg) => { + stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables)) + } + ConstEvaluatable(const_) => { + stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables)) + } + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ClosureKind { + type T = stable_mir::ty::ClosureKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::ClosureKind::*; + match self { + Fn => stable_mir::ty::ClosureKind::Fn, + FnMut => stable_mir::ty::ClosureKind::FnMut, + FnOnce => stable_mir::ty::ClosureKind::FnOnce, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { + type T = stable_mir::ty::SubtypePredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::SubtypePredicate { a, b, a_is_expected: _ } = self; + stable_mir::ty::SubtypePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) } + } +} + +impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { + type T = stable_mir::ty::CoercePredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::CoercePredicate { a, b } = self; + stable_mir::ty::CoercePredicate { a: tables.intern_ty(*a), b: tables.intern_ty(*b) } + } +} + +impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { + type T = stable_mir::ty::AliasRelationDirection; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::AliasRelationDirection::*; + match self { + Equate => stable_mir::ty::AliasRelationDirection::Equate, + Subtype => stable_mir::ty::AliasRelationDirection::Subtype, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { + type T = stable_mir::ty::TraitPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::TraitPredicate { trait_ref, polarity } = self; + stable_mir::ty::TraitPredicate { + trait_ref: trait_ref.stable(tables), + polarity: polarity.stable(tables), + } + } +} + +impl<'tcx, A, B, U, V> Stable<'tcx> for ty::OutlivesPredicate<A, B> +where + A: Stable<'tcx, T = U>, + B: Stable<'tcx, T = V>, +{ + type T = stable_mir::ty::OutlivesPredicate<U, V>; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::OutlivesPredicate(a, b) = self; + stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables)) + } +} + +impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { + type T = stable_mir::ty::ProjectionPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::ProjectionPredicate { projection_ty, term } = self; + stable_mir::ty::ProjectionPredicate { + projection_ty: projection_ty.stable(tables), + term: term.unpack().stable(tables), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ImplPolarity { + type T = stable_mir::ty::ImplPolarity; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::ImplPolarity::*; + match self { + Positive => stable_mir::ty::ImplPolarity::Positive, + Negative => stable_mir::ty::ImplPolarity::Negative, + Reservation => stable_mir::ty::ImplPolarity::Reservation, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { + type T = stable_mir::ty::Region; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable regions + opaque(self) + } +} + +impl<'tcx> Stable<'tcx> for rustc_span::Span { + type T = stable_mir::ty::Span; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable spans + opaque(self) + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index c16bd6cbd70..72f719c2a5e 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,8 +1,8 @@ use crate::rustc_internal::Opaque; use crate::stable_mir::ty::{ - AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, + AdtDef, ClosureDef, Const, ConstantKind, GeneratorDef, GenericArgs, Movability, Region, }; -use crate::stable_mir::{self, ty::Ty}; +use crate::stable_mir::{self, ty::Ty, Span}; #[derive(Clone, Debug)] pub struct Body { @@ -135,9 +135,10 @@ pub enum AsyncGeneratorKind { } pub(crate) type LocalDefId = Opaque; -pub(crate) type CounterValueReference = Opaque; -pub(crate) type InjectedExpressionId = Opaque; -pub(crate) type ExpressionOperandId = Opaque; +/// [`rustc_middle::mir::Coverage`] is heavily tied to internal details of the +/// coverage implementation that are likely to change, and are unlikely to be +/// useful to third-party tools for the foreseeable future. +pub(crate) type Coverage = Opaque; /// The FakeReadCause describes the type of pattern why a FakeRead statement exists. #[derive(Clone, Debug)] @@ -167,42 +168,6 @@ pub enum Variance { } #[derive(Clone, Debug)] -pub enum Op { - Subtract, - Add, -} - -#[derive(Clone, Debug)] -pub enum CoverageKind { - Counter { - function_source_hash: usize, - id: CounterValueReference, - }, - Expression { - id: InjectedExpressionId, - lhs: ExpressionOperandId, - op: Op, - rhs: ExpressionOperandId, - }, - Unreachable, -} - -#[derive(Clone, Debug)] -pub struct CodeRegion { - pub file_name: String, - pub start_line: usize, - pub start_col: usize, - pub end_line: usize, - pub end_col: usize, -} - -#[derive(Clone, Debug)] -pub struct Coverage { - pub kind: CoverageKind, - pub code_region: Option<CodeRegion>, -} - -#[derive(Clone, Debug)] pub struct CopyNonOverlapping { pub src: Operand, pub dst: Operand, @@ -359,7 +324,7 @@ pub enum AggregateKind { pub enum Operand { Copy(Place), Move(Place), - Constant(String), + Constant(Constant), } #[derive(Clone, Debug)] @@ -384,6 +349,13 @@ pub type VariantIdx = usize; type UserTypeAnnotationIndex = usize; #[derive(Clone, Debug)] +pub struct Constant { + pub span: Span, + pub user_ty: Option<UserTypeAnnotationIndex>, + pub literal: ConstantKind, +} + +#[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, pub target: usize, diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index 8e38e394b98..44938eaa035 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -15,7 +15,9 @@ use std::cell::Cell; use crate::rustc_smir::Tables; -use self::ty::{GenericDef, Generics, ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind}; +use self::ty::{ + GenericDef, Generics, ImplDef, ImplTrait, PredicateKind, Span, TraitDecl, TraitDef, Ty, TyKind, +}; pub mod mir; pub mod ty; @@ -38,6 +40,12 @@ pub type TraitDecls = Vec<TraitDef>; /// A list of impl trait decls. pub type ImplTraitDecls = Vec<ImplDef>; +/// A list of predicates. +pub struct GenericPredicates { + pub parent: Option<TraitDef>, + pub predicates: Vec<(PredicateKind, Span)>, +} + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { @@ -101,6 +109,14 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { with(|cx| cx.trait_impl(trait_impl)) } +pub fn generics_of(generic_def: &GenericDef) -> Generics { + with(|cx| cx.generics_of(generic_def)) +} + +pub fn predicates_of(trait_def: &TraitDef) -> GenericPredicates { + with(|cx| cx.predicates_of(trait_def)) +} + pub trait Context { fn entry_fn(&mut self) -> Option<CrateItem>; /// Retrieve all items of the local crate that have a MIR associated with them. @@ -111,6 +127,7 @@ pub trait Context { fn all_trait_impls(&mut self) -> ImplTraitDecls; fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; fn generics_of(&mut self, generic_def: &GenericDef) -> Generics; + fn predicates_of(&mut self, trait_def: &TraitDef) -> GenericPredicates; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index fe7fef5d0c1..5929823b1bb 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -22,7 +22,7 @@ pub struct Const { type Ident = Opaque; pub(crate) type Region = Opaque; -pub type Span = Opaque; +pub(crate) type Span = Opaque; #[derive(Clone, Debug)] pub enum TyKind { @@ -497,3 +497,81 @@ pub struct GenericParamDef { pub pure_wrt_drop: bool, pub kind: GenericParamDefKind, } + +pub struct GenericPredicates { + pub parent: Option<DefId>, + pub predicates: Vec<PredicateKind>, +} + +#[derive(Clone, Debug)] +pub enum PredicateKind { + Clause(ClauseKind), + ObjectSafe(TraitDef), + ClosureKind(ClosureDef, GenericArgs, ClosureKind), + SubType(SubtypePredicate), + Coerce(CoercePredicate), + ConstEquate(Const, Const), + Ambiguous, + AliasRelate(TermKind, TermKind, AliasRelationDirection), +} + +#[derive(Clone, Debug)] +pub enum ClauseKind { + Trait(TraitPredicate), + RegionOutlives(RegionOutlivesPredicate), + TypeOutlives(TypeOutlivesPredicate), + Projection(ProjectionPredicate), + ConstArgHasType(Const, Ty), + WellFormed(GenericArgKind), + ConstEvaluatable(Const), +} + +#[derive(Clone, Debug)] +pub enum ClosureKind { + Fn, + FnMut, + FnOnce, +} + +#[derive(Clone, Debug)] +pub struct SubtypePredicate { + pub a: Ty, + pub b: Ty, +} + +#[derive(Clone, Debug)] +pub struct CoercePredicate { + pub a: Ty, + pub b: Ty, +} + +#[derive(Clone, Debug)] +pub enum AliasRelationDirection { + Equate, + Subtype, +} + +#[derive(Clone, Debug)] +pub struct TraitPredicate { + pub trait_ref: TraitRef, + pub polarity: ImplPolarity, +} + +#[derive(Clone, Debug)] +pub struct OutlivesPredicate<A, B>(pub A, pub B); + +pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>; +pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>; + +#[derive(Clone, Debug)] +pub struct ProjectionPredicate { + pub projection_ty: AliasTy, + pub term: TermKind, +} + +#[derive(Clone, Debug)] +pub enum ImplPolarity { + Positive, + Negative, + Reservation, +} diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index ab57d5c6803..88081700c3b 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1291,11 +1291,11 @@ pub fn register_expn_id( let expn_id = ExpnId { krate, local_id }; HygieneData::with(|hygiene_data| { let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); - debug_assert!(_old_data.is_none()); + debug_assert!(_old_data.is_none() || cfg!(parallel_compiler)); let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash); - debug_assert!(_old_hash.is_none()); + debug_assert!(_old_hash.is_none() || _old_hash == Some(hash)); let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id); - debug_assert!(_old_id.is_none()); + debug_assert!(_old_id.is_none() || _old_id == Some(expn_id)); }); expn_id } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c0eff6dfd8f..07bae08d558 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -232,11 +232,13 @@ symbols! { NonZeroI32, NonZeroI64, NonZeroI8, + NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, + NonZeroUsize, None, Ok, Option, @@ -278,6 +280,7 @@ symbols! { RwLock, RwLockReadGuard, RwLockWriteGuard, + Saturating, Send, SeqCst, SliceIndex, @@ -305,6 +308,7 @@ symbols! { Vec, VecDeque, Wrapper, + Wrapping, Yield, _DECLS, _Self, @@ -1100,6 +1104,7 @@ symbols! { panic_handler, panic_impl, panic_implementation, + panic_in_cleanup, panic_info, panic_location, panic_misaligned_pointer_dereference, @@ -1373,6 +1378,7 @@ symbols! { sanitizer_cfi_normalize_integers, sanitizer_runtime, saturating_add, + saturating_div, saturating_sub, self_in_typedefs, self_struct_ctor, @@ -1691,7 +1697,10 @@ symbols! { windows_subsystem, with_negative_coherence, wrapping_add, + wrapping_div, wrapping_mul, + wrapping_rem, + wrapping_rem_euclid, wrapping_sub, wreg, write_bytes, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index d345368d552..77457c8daaa 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -447,7 +447,7 @@ fn encode_ty<'tcx>( typeid.push('b'); } - ty::Int(..) | ty::Uint(..) | ty::Float(..) => { + ty::Int(..) | ty::Uint(..) => { // u<length><type-name> as vendor extended type let mut s = String::from(match ty.kind() { ty::Int(IntTy::I8) => "u2i8", @@ -462,14 +462,23 @@ fn encode_ty<'tcx>( ty::Uint(UintTy::U64) => "u3u64", ty::Uint(UintTy::U128) => "u4u128", ty::Uint(UintTy::Usize) => "u5usize", - ty::Float(FloatTy::F32) => "u3f32", - ty::Float(FloatTy::F64) => "u3f64", - _ => "", + _ => bug!("encode_ty: unexpected `{:?}`", ty.kind()), }); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } + // Rust's f32 and f64 single (32-bit) and double (64-bit) precision floating-point types + // have IEEE-754 binary32 and binary64 floating-point layouts, respectively. + // + // (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#fixed-width-floating-point-types.) + ty::Float(float_ty) => { + typeid.push(match float_ty { + FloatTy::F32 => 'f', + FloatTy::F64 => 'd', + }); + } + ty::Char => { // u4char as vendor extended type let mut s = String::from("u4char"); diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 56ab63be27d..b048b513592 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -142,9 +142,9 @@ impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.2 // RISC-V defines the possibility of a 128-bit address space (RV128). -// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize. +// CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize. // https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf -// https://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf +// https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf // Note: integers can only be represented with full precision in a float if // they fit in the significand, which is 24 bits in f32 and 53 bits in f64. diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index aec287226a0..ec1810234eb 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -77,6 +77,7 @@ macro marker_impls { #[cfg_attr(not(test), rustc_diagnostic_item = "Send")] #[rustc_on_unimplemented( on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"), + on(_Self = "alloc::rc::Rc<T, A>", note = "use `alloc::sync::Arc` instead of `alloc::rc::Rc`"), message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely", note = "consider using `std::sync::Arc<{Self}>`; for more information visit \ @@ -632,6 +633,7 @@ impl<T: ?Sized> Copy for &T {} note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead", ), on(_Self = "std::rc::Rc<T, A>", note = "use `std::sync::Arc` instead of `std::rc::Rc`"), + on(_Self = "alloc::rc::Rc<T, A>", note = "use `alloc::sync::Arc` instead of `alloc::rc::Rc`"), message = "`{Self}` cannot be shared between threads safely", label = "`{Self}` cannot be shared between threads safely", note = "consider using `std::sync::Arc<{Self}>`; for more information visit \ diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 56460c75eba..6a36dfec098 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1856,13 +1856,7 @@ impl fmt::Display for Ipv6Addr { if f.precision().is_none() && f.width().is_none() { let segments = self.segments(); - // Special case for :: and ::1; otherwise they get written with the - // IPv4 formatter - if self.is_unspecified() { - f.write_str("::") - } else if self.is_loopback() { - f.write_str("::1") - } else if let Some(ipv4) = self.to_ipv4_mapped() { + if let Some(ipv4) = self.to_ipv4_mapped() { write!(f, "::ffff:{}", ipv4) } else { #[derive(Copy, Clone, Default)] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 7b6249207fe..ab6aa0df428 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -179,6 +179,8 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { /// Panic because we cannot unwind out of a function. /// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. /// This function is called directly by the codegen backend, and must not have /// any extra arguments (including those synthesized by track_caller). #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] @@ -186,9 +188,26 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { #[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function #[rustc_nounwind] fn panic_cannot_unwind() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. panic_nounwind("panic in a function that cannot unwind") } +/// Panic because we are unwinding out of a destructor during cleanup. +/// +/// This is a separate function to avoid the codesize impact of each crate containing the string to +/// pass to `panic_nounwind`. +/// This function is called directly by the codegen backend, and must not have +/// any extra arguments (including those synthesized by track_caller). +#[cfg(not(bootstrap))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function +#[rustc_nounwind] +fn panic_in_cleanup() -> ! { + // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`. + panic_nounwind("panic in a destructor during cleanup") +} + /// This function is used instead of panic_fmt in const eval. #[lang = "const_panic_fmt"] #[rustc_const_unstable(feature = "core_panic", issue = "none")] diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 776899dbcfd..c3506175715 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -989,7 +989,9 @@ impl f32 { unsafe { cmath::tgammaf(self) } } - /// Returns the natural logarithm of the gamma function. + /// Natural logarithm of the absolute value of the gamma function + /// + /// The integer part of the tuple indicates the sign of the gamma function. /// /// # Examples /// diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 4f4f5f02471..e4b7bfeeb84 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -989,7 +989,9 @@ impl f64 { unsafe { cmath::tgamma(self) } } - /// Returns the natural logarithm of the gamma function. + /// Natural logarithm of the absolute value of the gamma function + /// + /// The integer part of the tuple indicates the sign of the gamma function. /// /// # Examples /// diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 4094e378034..3c67bea7a22 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -745,14 +745,17 @@ fn buffer_capacity_required(mut file: &File) -> Option<usize> { #[stable(feature = "rust1", since = "1.0.0")] impl Read for &File { + #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.inner.read(buf) } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { self.inner.read_vectored(bufs) } + #[inline] fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { self.inner.read_buf(cursor) } diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 34c0ce9dcf8..d6fce4ee78f 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -916,6 +916,16 @@ impl Error { ErrorData::SimpleMessage(m) => m.kind, } } + + #[inline] + pub(crate) fn is_interrupted(&self) -> bool { + match self.repr.data() { + ErrorData::Os(code) => sys::is_interrupted(code), + ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted, + ErrorData::Simple(kind) => kind == ErrorKind::Interrupted, + ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted, + } + } } impl fmt::Debug for Repr { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 71d91f21362..e89843b5703 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -390,7 +390,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>( let mut cursor = read_buf.unfilled(); match r.read_buf(cursor.reborrow()) { Ok(()) => {} - Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) if e.is_interrupted() => continue, Err(e) => return Err(e), } @@ -421,7 +421,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>( buf.extend_from_slice(&probe[..n]); break; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => return Err(e), } } @@ -470,7 +470,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [ let tmp = buf; buf = &mut tmp[n..]; } - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(ref e) if e.is_interrupted() => {} Err(e) => return Err(e), } } @@ -860,7 +860,7 @@ pub trait Read { let prev_written = cursor.written(); match self.read_buf(cursor.reborrow()) { Ok(()) => {} - Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) if e.is_interrupted() => continue, Err(e) => return Err(e), } @@ -1579,7 +1579,7 @@ pub trait Write { )); } Ok(n) => buf = &buf[n..], - Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(ref e) if e.is_interrupted() => {} Err(e) => return Err(e), } } @@ -1943,7 +1943,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R let (done, used) = { let available = match r.fill_buf() { Ok(n) => n, - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => return Err(e), }; match memchr::memchr(delim, available) { @@ -2734,7 +2734,7 @@ impl<R: Read> Iterator for Bytes<R> { return match self.inner.read(slice::from_mut(&mut byte)) { Ok(0) => None, Ok(..) => Some(Ok(byte)), - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(ref e) if e.is_interrupted() => continue, Err(e) => Some(Err(e)), }; } diff --git a/library/std/src/sys/itron/error.rs b/library/std/src/sys/itron/error.rs index 830c60d329e..fbc822d4eb6 100644 --- a/library/std/src/sys/itron/error.rs +++ b/library/std/src/sys/itron/error.rs @@ -79,6 +79,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> { } } +#[inline] +pub fn is_interrupted(er: abi::ER) -> bool { + er == abi::E_RLWAI +} + pub fn decode_error_kind(er: abi::ER) -> ErrorKind { match er { // Success diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 9865a945bad..09d3f7638ca 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -86,6 +86,12 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> { } } +#[inline] +pub fn is_interrupted(code: i32) -> bool { + use fortanix_sgx_abi::Error; + code == Error::Interrupted as _ +} + pub fn decode_error_kind(code: i32) -> ErrorKind { use fortanix_sgx_abi::Error; diff --git a/library/std/src/sys/solid/error.rs b/library/std/src/sys/solid/error.rs index 547b4f3a984..d1877a8bcd2 100644 --- a/library/std/src/sys/solid/error.rs +++ b/library/std/src/sys/solid/error.rs @@ -31,6 +31,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> { } } +#[inline] +fn is_interrupted(er: abi::ER) -> bool { + false +} + pub fn decode_error_kind(er: abi::ER) -> ErrorKind { match er { // Success diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs index 923d27fd936..e7029174511 100644 --- a/library/std/src/sys/solid/mod.rs +++ b/library/std/src/sys/solid/mod.rs @@ -72,6 +72,11 @@ pub fn unsupported_err() -> crate::io::Error { ) } +#[inline] +pub fn is_interrupted(code: i32) -> bool { + error::is_interrupted(code) +} + pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { error::decode_error_kind(code) } diff --git a/library/std/src/sys/solid/net.rs b/library/std/src/sys/solid/net.rs index 0bd2bc3b961..bdd64ab02b7 100644 --- a/library/std/src/sys/solid/net.rs +++ b/library/std/src/sys/solid/net.rs @@ -181,6 +181,12 @@ pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok() } +#[inline] +pub fn is_interrupted(er: abi::ER) -> bool { + let errno = netc::SOLID_NET_ERR_BASE - er; + errno as libc::c_int == libc::EINTR +} + pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { let errno = netc::SOLID_NET_ERR_BASE - er; match errno as libc::c_int { diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 9f4e66d628b..ff81544ba91 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -8,7 +8,7 @@ use crate::os::{ solid::ffi::{OsStrExt, OsStringExt}, }; use crate::path::{self, PathBuf}; -use crate::sync::RwLock; +use crate::sync::{PoisonError, RwLock}; use crate::sys::common::small_c_string::run_with_cstr; use crate::vec; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 77ef086f29b..6d743903314 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -240,6 +240,11 @@ pub use crate::sys::android::signal; #[cfg(not(target_os = "android"))] pub use libc::signal; +#[inline] +pub(crate) fn is_interrupted(errno: i32) -> bool { + errno == libc::EINTR +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { use ErrorKind::*; match errno as libc::c_int { diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 5cd9e57de19..5c379992b20 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -23,6 +23,10 @@ pub fn unsupported_err() -> std_io::Error { ) } +pub fn is_interrupted(_code: i32) -> bool { + false +} + pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { crate::io::ErrorKind::Uncategorized } diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 98517da1d0f..5cbb5cb65ba 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -76,6 +76,11 @@ cfg_if::cfg_if! { mod common; pub use common::*; +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == wasi::ERRNO_INTR.raw().into() +} + pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { use std_io::ErrorKind::*; if errno > u16::MAX as i32 || errno < 0 { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index bcc172b0fae..b609ad2472c 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -60,6 +60,11 @@ pub unsafe fn cleanup() { net::cleanup(); } +#[inline] +pub fn is_interrupted(_errno: i32) -> bool { + false +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { use ErrorKind::*; diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c5c70f2e18a..9dbc87c337c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -623,7 +623,7 @@ class RustBuild(object): def should_fix_bins_and_dylibs(self): """Whether or not `fix_bin_or_dylib` needs to be run; can only be True - on NixOS. + on NixOS or if config.toml has `build.patch-binaries-for-nix` set. """ if self._should_fix_bins_and_dylibs is not None: return self._should_fix_bins_and_dylibs @@ -643,18 +643,31 @@ class RustBuild(object): if ostype != "Linux": return False - # If the user has asked binaries to be patched for Nix, then - # don't check for NixOS. + # If the user has explicitly indicated whether binaries should be + # patched for Nix, then don't check for NixOS. if self.get_toml("patch-binaries-for-nix", "build") == "true": return True + if self.get_toml("patch-binaries-for-nix", "build") == "false": + return False # Use `/etc/os-release` instead of `/etc/NIXOS`. # The latter one does not exist on NixOS when using tmpfs as root. try: with open("/etc/os-release", "r") as f: - return any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f) + is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') + for ln in f) except FileNotFoundError: - return False + is_nixos = False + + # If not on NixOS, then warn if user seems to be atop Nix shell + if not is_nixos: + in_nix_shell = os.getenv('IN_NIX_SHELL') + if in_nix_shell: + print("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell), + "you may need to set `patch-binaries-for-nix=true` in config.toml", + file=sys.stderr) + + return is_nixos answer = self._should_fix_bins_and_dylibs = get_answer() if answer: diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 762e66ac7cc..e5fdac3ceda 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -137,7 +137,7 @@ pub struct Config { pub json_output: bool, pub test_compare_mode: bool, pub color: Color, - pub patch_binaries_for_nix: bool, + pub patch_binaries_for_nix: Option<bool>, pub stage0_metadata: Stage0Metadata, pub stdout_is_tty: bool, @@ -1339,7 +1339,7 @@ impl Config { set(&mut config.local_rebuild, build.local_rebuild); set(&mut config.print_step_timings, build.print_step_timings); set(&mut config.print_step_rusage, build.print_step_rusage); - set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix); + config.patch_binaries_for_nix = build.patch_binaries_for_nix; config.verbose = cmp::max(config.verbose, flags.verbose as usize); diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 52162bf42ea..17c308e915b 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -91,8 +91,8 @@ impl Config { // NOTE: this intentionally comes after the Linux check: // - patchelf only works with ELF files, so no need to run it on Mac or Windows // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc. - if self.patch_binaries_for_nix { - return true; + if let Some(explicit_value) = self.patch_binaries_for_nix { + return explicit_value; } // Use `/etc/os-release` instead of `/etc/NIXOS`. @@ -105,6 +105,15 @@ impl Config { matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"") }), }; + if !is_nixos { + let in_nix_shell = env::var("IN_NIX_SHELL"); + if let Ok(in_nix_shell) = in_nix_shell { + eprintln!( + "The IN_NIX_SHELL environment variable is `{in_nix_shell}`; \ + you may need to set `patch-binaries-for-nix=true` in config.toml" + ); + } + } is_nixos }); if val { diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 7cc17e11bdb..c1614d02f34 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -313,7 +313,7 @@ target | std | host | notes [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux -[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 `thumbv4t-none-eabi` | * | | Thumb-mode Bare ARMv4T diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 2cc50bc0b63ad20da193e002ba11d391af0104b +Subproject 925280f028db3a322935e040719a0754703947c diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 43523faa236..17233058c9c 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -292,7 +292,7 @@ fn check_terminator<'tcx>( | TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => { if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a2c828701e5..dd4c59fdff5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3622,26 +3622,30 @@ impl<'test> TestCx<'test> { let expected_stderr = self.load_expected_output(stderr_kind); let expected_stdout = self.load_expected_output(stdout_kind); - let normalized_stdout = match output_kind { + let mut normalized_stdout = + self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); + match output_kind { TestOutput::Run if self.config.remote_test_client.is_some() => { // When tests are run using the remote-test-client, the string // 'uploaded "$TEST_BUILD_DIR/<test_executable>, waiting for result"' // is printed to stdout by the client and then captured in the ProcRes, - // so it needs to be removed when comparing the run-pass test execution output + // so it needs to be removed when comparing the run-pass test execution output. static REMOTE_TEST_RE: Lazy<Regex> = Lazy::new(|| { Regex::new( "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n" ) .unwrap() }); - REMOTE_TEST_RE - .replace( - &self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), - "", - ) - .to_string() + normalized_stdout = REMOTE_TEST_RE.replace(&normalized_stdout, "").to_string(); + // When there is a panic, the remote-test-client also prints "died due to signal"; + // that needs to be removed as well. + static SIGNAL_DIED_RE: Lazy<Regex> = + Lazy::new(|| Regex::new("^died due to signal [0-9]+\n").unwrap()); + normalized_stdout = SIGNAL_DIED_RE.replace(&normalized_stdout, "").to_string(); + // FIXME: it would be much nicer if we could just tell the remote-test-client to not + // print these things. } - _ => self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout), + _ => {} }; let stderr = if explicit_format { diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 550c9650fb3..98f82ec9a0f 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -975,9 +975,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.start_panic_nounwind(msg) } - fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>, reason: mir::UnwindTerminateReason) -> InterpResult<'tcx> { // Call the lang item. - let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap(); + let panic = ecx.tcx.lang_items().get(reason.lang_item()).unwrap(); let panic = ty::Instance::mono(ecx.tcx.tcx, panic); ecx.call_function( panic, @@ -1405,4 +1405,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } res } + + fn after_local_allocated( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + frame: usize, + local: mir::Local, + mplace: &MPlaceTy<'tcx, Provenance> + ) -> InterpResult<'tcx> { + let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else { + panic!("after_local_allocated should only be called on fresh allocations"); + }; + let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local]; + let span = local_decl.source_info.span; + ecx.machine + .allocation_spans + .borrow_mut() + .insert(alloc_id, (span, None)); + Ok(()) + } } diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs new file mode 100644 index 00000000000..393127341ca --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs @@ -0,0 +1,13 @@ +// The interpreter tries to delay allocating locals until their address is taken. +// This test checks that we correctly use the span associated with the local itself, not the span +// where we take the address of the local and force it to be allocated. + +fn main() { + let ptr = { + let x = 0usize; // This line should appear in the helps + &x as *const usize // This line should NOT appear in the helps + }; + unsafe { + dbg!(*ptr); //~ ERROR: has been freed + } +} diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr new file mode 100644 index 00000000000..bdc9c31db40 --- /dev/null +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr @@ -0,0 +1,26 @@ +error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | dbg!(*ptr); + | ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling + | + = 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 +help: ALLOC was allocated here: + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | let x = 0usize; // This line should appear in the helps + | ^ +help: ALLOC was deallocated here: + --> $DIR/dangling_primitive.rs:LL:CC + | +LL | }; + | ^ + = note: BACKTRACE (of the first span): + = note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr index fe039ef3ada..92b1fcb1145 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr @@ -6,7 +6,12 @@ LL | let val = unsafe { (*xptr).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 - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/deref-partially-dangling.rs:LL:CC + | +LL | let x = (1, 13); + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/deref-partially-dangling.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr index 33aa6c84410..95a50bc8750 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr @@ -6,7 +6,12 @@ LL | let _ptr = unsafe { &*ptr }; | = 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 - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/dyn_size.rs:LL:CC + | +LL | let buf = [0u32; 1]; + | ^^^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/dyn_size.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr index 500f28a3cbc..4d2dfe28aed 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr @@ -6,7 +6,17 @@ LL | let val = *x; | = 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 - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/stack_temporary.rs:LL:CC + | +LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"! + | ^ +help: ALLOC was deallocated here: + --> $DIR/stack_temporary.rs:LL:CC + | +LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"! + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/stack_temporary.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr index 4422310870a..e1102a6d216 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr @@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(5) }; | = 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 - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/out_of_bounds_ptr_1.rs:LL:CC + | +LL | let v = [0i8; 4]; + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr index 1364e0f9009..99f28b3e4f8 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr @@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(-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 - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/out_of_bounds_ptr_3.rs:LL:CC + | +LL | let v = [0i8; 4]; + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index 25c9a7c44bc..9efba031250 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -5,7 +5,7 @@ thread 'main' panicked at $DIR/double_panic.rs:LL:CC: second stack backtrace: thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC: -panic in a function that cannot unwind +panic in a destructor during cleanup stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution @@ -20,7 +20,7 @@ LL | ABORT(); = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC - = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC + = note: inside `core::panicking::panic_in_cleanup` at RUSTLIB/core/src/panicking.rs:LL:CC note: inside `main` --> $DIR/double_panic.rs:LL:CC | diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3414924007b..6a197527a64 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,8 +10,8 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1891; -const ROOT_ENTRY_LIMIT: usize = 866; +const ISSUES_ENTRY_LIMIT: usize = 1874; +const ROOT_ENTRY_LIMIT: usize = 865; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs deleted file mode 100644 index e2ea9dda4a0..00000000000 --- a/tests/codegen/debuginfo-inline-callsite-location.rs +++ /dev/null @@ -1,26 +0,0 @@ -// compile-flags: -g -O - -// Check that each inline call site for the same function uses the same "sub-program" so that LLVM -// can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail -// calls to panic. - -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E -// CHECK-SAME: !dbg ![[#first_dbg:]] -// CHECK: tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E -// CHECK-SAME: !dbg ![[#second_dbg:]] - -// CHECK: ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap<i32>" -// CHECK: ![[#first_dbg]] = !DILocation(line: [[#]] -// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]]) -// CHECK: ![[#second_dbg]] = !DILocation(line: [[#]] -// CHECK-SAME: scope: ![[#func_dbg]], inlinedAt: ![[#]]) - -#![crate_type = "lib"] - -#[no_mangle] -extern "C" fn add_numbers(x: &Option<i32>, y: &Option<i32>) -> i32 { - let x1 = x.unwrap(); - let y1 = y.unwrap(); - - x1 + y1 -} diff --git a/tests/codegen/mem-replace-simple-type.rs b/tests/codegen/mem-replace-simple-type.rs index 174ac608e01..be3af989ef0 100644 --- a/tests/codegen/mem-replace-simple-type.rs +++ b/tests/codegen/mem-replace-simple-type.rs @@ -33,12 +33,21 @@ pub fn replace_ref_str<'a>(r: &mut &'a str, v: &'a str) -> &'a str { } #[no_mangle] -// CHECK-LABEL: @replace_short_array( -pub fn replace_short_array(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] { +// CHECK-LABEL: @replace_short_array_3( +pub fn replace_short_array_3(r: &mut [u32; 3], v: [u32; 3]) -> [u32; 3] { // CHECK-NOT: alloca - // CHECK: %[[R:.+]] = load <3 x i32>, ptr %r, align 4 - // CHECK: store <3 x i32> %[[R]], ptr %result - // CHECK: %[[V:.+]] = load <3 x i32>, ptr %v, align 4 - // CHECK: store <3 x i32> %[[V]], ptr %r + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %result, ptr align 4 %r, i64 12, i1 false) + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %r, ptr align 4 %v, i64 12, i1 false) + std::mem::replace(r, v) +} + +#[no_mangle] +// CHECK-LABEL: @replace_short_array_4( +pub fn replace_short_array_4(r: &mut [u32; 4], v: [u32; 4]) -> [u32; 4] { + // CHECK-NOT: alloca + // CHECK: %[[R:.+]] = load <4 x i32>, ptr %r, align 4 + // CHECK: store <4 x i32> %[[R]], ptr %result + // CHECK: %[[V:.+]] = load <4 x i32>, ptr %v, align 4 + // CHECK: store <4 x i32> %[[V]], ptr %r std::mem::replace(r, v) } diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index da608e180c5..2d8b13e2080 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -500,12 +500,12 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { } // CHECK: ![[TYPE45]] = !{i64 0, !"_ZTSFvu5usizeE"} // CHECK: ![[TYPE46]] = !{i64 0, !"_ZTSFvu5usizeS_E"} // CHECK: ![[TYPE47]] = !{i64 0, !"_ZTSFvu5usizeS_S_E"} -// CHECK: ![[TYPE48]] = !{i64 0, !"_ZTSFvu3f32E"} -// CHECK: ![[TYPE49]] = !{i64 0, !"_ZTSFvu3f32S_E"} -// CHECK: ![[TYPE50]] = !{i64 0, !"_ZTSFvu3f32S_S_E"} -// CHECK: ![[TYPE51]] = !{i64 0, !"_ZTSFvu3f64E"} -// CHECK: ![[TYPE52]] = !{i64 0, !"_ZTSFvu3f64S_E"} -// CHECK: ![[TYPE53]] = !{i64 0, !"_ZTSFvu3f64S_S_E"} +// CHECK: ![[TYPE48]] = !{i64 0, !"_ZTSFvfE"} +// CHECK: ![[TYPE49]] = !{i64 0, !"_ZTSFvffE"} +// CHECK: ![[TYPE50]] = !{i64 0, !"_ZTSFvfffE"} +// CHECK: ![[TYPE51]] = !{i64 0, !"_ZTSFvdE"} +// CHECK: ![[TYPE52]] = !{i64 0, !"_ZTSFvddE"} +// CHECK: ![[TYPE53]] = !{i64 0, !"_ZTSFvdddE"} // CHECK: ![[TYPE54]] = !{i64 0, !"_ZTSFvu4charE"} // CHECK: ![[TYPE55]] = !{i64 0, !"_ZTSFvu4charS_E"} // CHECK: ![[TYPE56]] = !{i64 0, !"_ZTSFvu4charS_S_E"} diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 419645a3fc6..27bc00bc3ab 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -11,11 +11,12 @@ type RGB48 = [u16; 3]; // CHECK-LABEL: @swap_rgb48_manually( #[no_mangle] pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { - // CHECK-NOT: alloca - // CHECK: %[[TEMP0:.+]] = load <3 x i16>, ptr %x, align 2 - // CHECK: %[[TEMP1:.+]] = load <3 x i16>, ptr %y, align 2 - // CHECK: store <3 x i16> %[[TEMP1]], ptr %x, align 2 - // CHECK: store <3 x i16> %[[TEMP0]], ptr %y, align 2 + // FIXME: See #115212 for why this has an alloca again + + // CHECK: alloca [3 x i16], align 2 + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) let temp = *x; *x = *y; @@ -25,11 +26,25 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { // CHECK-LABEL: @swap_rgb48 #[no_mangle] pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { + // FIXME: See #115212 for why this has an alloca again + + // CHECK: alloca [3 x i16], align 2 + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) + swap(x, y) +} + +type RGBA64 = [u16; 4]; + +// CHECK-LABEL: @swap_rgba64 +#[no_mangle] +pub fn swap_rgba64(x: &mut RGBA64, y: &mut RGBA64) { // CHECK-NOT: alloca - // CHECK: load <3 x i16> - // CHECK: load <3 x i16> - // CHECK: store <3 x i16> - // CHECK: store <3 x i16> + // CHECK-DAG: %[[XVAL:.+]] = load <4 x i16>, ptr %x, align 2 + // CHECK-DAG: %[[YVAL:.+]] = load <4 x i16>, ptr %y, align 2 + // CHECK-DAG: store <4 x i16> %[[YVAL]], ptr %x, align 2 + // CHECK-DAG: store <4 x i16> %[[XVAL]], ptr %y, align 2 swap(x, y) } diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir index a59ffe97bf0..6c3128f8c36 100644 --- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir +++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir @@ -9,7 +9,7 @@ fn main() -> () { bb0: { StorageLive(_1); _1 = const (); - asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate]; + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate(abi)]; } bb1: { diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index 15269fb8f6c..f187f959727 100644 --- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff +++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff @@ -47,7 +47,7 @@ bb2 (cleanup): { _5 = move _6; -- drop(_6) -> [return: bb6, unwind terminate]; +- drop(_6) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb6; } @@ -71,12 +71,12 @@ } bb6 (cleanup): { -- drop(_5) -> [return: bb7, unwind terminate]; +- drop(_5) -> [return: bb7, unwind terminate(cleanup)]; + goto -> bb7; } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir index a9bc2e89034..75070ffda11 100644 --- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir @@ -51,7 +51,7 @@ fn main() -> () { bb2 (cleanup): { _5 = move _6; - drop(_6) -> [return: bb6, unwind terminate]; + drop(_6) -> [return: bb6, unwind terminate(cleanup)]; } bb3: { @@ -73,11 +73,11 @@ fn main() -> () { } bb6 (cleanup): { - drop(_5) -> [return: bb7, unwind terminate]; + drop(_5) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_4) -> [return: bb8, unwind terminate]; + drop(_4) -> [return: bb8, unwind terminate(cleanup)]; } bb8 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir index d196b045a1b..1c7ef7f8345 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-abort.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate]; + drop(_7) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate]; + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir index a72d22a9c9f..4ad1c2de129 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.panic-unwind.mir @@ -54,15 +54,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> [return: bb7, unwind terminate]; + drop(_7) -> [return: bb7, unwind terminate(cleanup)]; } bb7 (cleanup): { - drop(_1) -> [return: bb9, unwind terminate]; + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir index 1caf9e4a523..ea0edb610f5 100644 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir @@ -62,7 +62,7 @@ fn droppy() -> () { } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir index fea1138ba8d..82424de0392 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir @@ -89,15 +89,15 @@ fn move_out_by_subslice() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate]; + drop(_1) -> [return: bb12, unwind terminate(cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate]; + drop(_7) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir index 3def40a8578..0872d1b6ac0 100644 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir @@ -89,15 +89,15 @@ fn move_out_from_end() -> () { } bb9 (cleanup): { - drop(_1) -> [return: bb12, unwind terminate]; + drop(_1) -> [return: bb12, unwind terminate(cleanup)]; } bb10 (cleanup): { - drop(_7) -> [return: bb11, unwind terminate]; + drop(_7) -> [return: bb11, unwind terminate(cleanup)]; } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff index 1a4372afe69..f2b87221f2b 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff @@ -63,7 +63,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff new file mode 100644 index 00000000000..dc0f9073416 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-abort.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination ++ // MIR for `move_packed` after DeadStoreElimination + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff new file mode 100644 index 00000000000..86ef026ec5c --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_packed.DeadStoreElimination.panic-unwind.diff @@ -0,0 +1,15 @@ +- // MIR for `move_packed` before DeadStoreElimination ++ // MIR for `move_packed` after DeadStoreElimination + + fn move_packed(_1: Packed) -> () { + let mut _0: (); + + bb0: { + _0 = use_both(const 0_i32, (_1.1: i32)) -> [return: bb1, unwind continue]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 41f91fc1306..f09cdee1482 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -2,6 +2,12 @@ // unit-test: DeadStoreElimination // compile-flags: -Zmir-enable-passes=+CopyProp +#![feature(core_intrinsics)] +#![feature(custom_mir)] +#![allow(internal_features)] + +use std::intrinsics::mir::*; + #[inline(never)] fn use_both(_: i32, _: i32) {} @@ -10,6 +16,26 @@ fn move_simple(x: i32) { use_both(x, x); } +#[repr(packed)] +struct Packed { + x: u8, + y: i32, +} + +// EMIT_MIR call_arg_copy.move_packed.DeadStoreElimination.diff +#[custom_mir(dialect = "analysis")] +fn move_packed(packed: Packed) { + mir!( + { + Call(RET = use_both(0, packed.y), ret) + } + ret = { + Return() + } + ) +} + fn main() { move_simple(1); + move_packed(Packed { x: 0, y: 1 }); } diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff index 024d9bc7f51..8ac6acd0e4a 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-abort.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff index 2ada087b4bd..aa9fcb505e6 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.panic-unwind.diff @@ -28,7 +28,7 @@ } bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate]; + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 6a4c5436fce..6fcceb6c66b 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -104,7 +104,7 @@ yields () bb13 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate]; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { @@ -113,6 +113,6 @@ yields () bb15 (cleanup): { StorageDead(_3); - drop(_1) -> [return: bb14, unwind terminate]; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } } diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff index 503dc5beb19..aa9429c46d8 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-abort.diff @@ -17,7 +17,7 @@ StorageLive(_1); - _1 = foo() -> [return: bb1, unwind unreachable]; + StorageLive(_2); -+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate]; ++ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind terminate(abi)]; } bb1: { diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index 684211b53b3..ea9c360aa7b 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -32,7 +32,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff index f3a6ee22c20..b7fea4f2e14 100644 --- a/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.f.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index ad801fd280a..1fd1014ba1d 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff index 99dc64115a9..e8299db47db 100644 --- a/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.main.Inline.panic-unwind.diff @@ -36,7 +36,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate]; ++ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index ef85e075eeb..b82961c2815 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -27,7 +27,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index 5df730a9930..47fd0ed0799 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -30,7 +30,7 @@ } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index 073ddeff7ca..9f8c5806c90 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -54,11 +54,11 @@ + } + + bb4 (cleanup): { -+ drop(_4) -> [return: bb5, unwind terminate]; ++ drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index 54c33aac9e8..675292f06d6 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -155,7 +155,7 @@ - StorageDead(_1); - return; + bb3 (cleanup): { -+ drop(_2) -> [return: bb2, unwind terminate]; ++ drop(_2) -> [return: bb2, unwind terminate(cleanup)]; } - bb4 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index b750330df92..5a946712ea4 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -37,7 +37,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate]; + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff index 7765e491d89..cbfb39115b3 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.panic-unwind.diff @@ -40,7 +40,7 @@ } bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate]; + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 6ee6a0ffe4c..ab81f707148 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -40,7 +40,7 @@ bb4 (cleanup): { _8 = &mut _3; - _9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate]; + _9 = <Box<[i32]> as Drop>::drop(move _8) -> [return: bb1, unwind terminate(cleanup)]; } } diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff index 11501907b88..4469270a9b2 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-abort.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate]; +- drop(_3) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate]; +- drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate]; +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff index 11501907b88..4469270a9b2 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.panic-unwind.diff @@ -40,17 +40,17 @@ } bb3 (cleanup): { -- drop(_3) -> [return: bb5, unwind terminate]; +- drop(_3) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb4 (cleanup): { -- drop(_4) -> [return: bb5, unwind terminate]; +- drop(_4) -> [return: bb5, unwind terminate(cleanup)]; + goto -> bb5; } bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate]; +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + goto -> bb8; } @@ -59,7 +59,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate]; ++ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff index 65f4806aaf7..78184f6aeeb 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate]; +- drop(_5) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate]; +- drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate]; +- drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate]; ++ drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff index 4845fc732aa..688887c3c1f 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff @@ -47,7 +47,7 @@ bb3 (cleanup): { _2 = move _5; -- drop(_5) -> [return: bb8, unwind terminate]; +- drop(_5) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } @@ -70,17 +70,17 @@ } bb7 (cleanup): { -- drop(_4) -> [return: bb8, unwind terminate]; +- drop(_4) -> [return: bb8, unwind terminate(cleanup)]; + goto -> bb8; } bb8 (cleanup): { -- drop(_2) -> [return: bb9, unwind terminate]; +- drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + goto -> bb9; } bb9 (cleanup): { -- drop(_1) -> [return: bb10, unwind terminate]; +- drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + goto -> bb12; } @@ -89,7 +89,7 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> [return: bb10, unwind terminate]; ++ drop(_1) -> [return: bb10, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff index aca7fe95c18..b57fe348c2d 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate]; +- drop(_3) -> [return: bb11, unwind terminate(cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate]; +- drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate]; ++ drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff index 60ce9cd8ad9..2156850e38c 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff @@ -58,7 +58,7 @@ + _8 = const true; + _9 = const true; _1 = move _3; -- drop(_3) -> [return: bb11, unwind terminate]; +- drop(_3) -> [return: bb11, unwind terminate(cleanup)]; + goto -> bb11; } @@ -102,7 +102,7 @@ } bb11 (cleanup): { -- drop(_1) -> [return: bb12, unwind terminate]; +- drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + goto -> bb12; } @@ -124,7 +124,7 @@ + } + + bb16 (cleanup): { -+ drop(_1) -> [return: bb12, unwind terminate]; ++ drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb17: { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index ae0beffae18..73462967850 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate]; + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate]; + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index 7ecdc428e59..8264e2cabbc 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -100,11 +100,11 @@ fn test() -> Option<Box<u32>> { } bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate]; + drop(_1) -> [return: bb13, unwind terminate(cleanup)]; } bb12 (cleanup): { - drop(_5) -> [return: bb13, unwind terminate]; + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir index 92f52e138a5..cce1a1fd2ef 100644 --- a/tests/mir-opt/issue_91633.bar.built.after.mir +++ b/tests/mir-opt/issue_91633.bar.built.after.mir @@ -28,7 +28,7 @@ fn bar(_1: Box<[T]>) -> () { } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate]; + drop(_1) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir index 4529c58a137..a66769f0d11 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -45,7 +45,7 @@ fn foo(_1: Box<[T]>) -> T { } bb5 (cleanup): { - drop(_1) -> [return: bb6, unwind terminate]; + drop(_1) -> [return: bb6, unwind terminate(cleanup)]; } bb6 (cleanup): { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index be09ed641b8..3e817ff433b 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate]; +- drop(_2) -> [return: bb26, unwind terminate(cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index be09ed641b8..3e817ff433b 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> [return: bb26, unwind terminate]; +- drop(_2) -> [return: bb26, unwind terminate(cleanup)]; + bb22 (cleanup): { + goto -> bb27; } diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir index e22fc7d54bc..99a7a6b6154 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-abort.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate]; + drop(_2) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir index 6fb107929e6..7364b329e12 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.panic-unwind.mir @@ -31,7 +31,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> [return: bb4, unwind terminate]; + drop(_2) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index bc04790028d..0ef19180459 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -33,7 +33,7 @@ fn main() -> () { bb1 (cleanup): { (_1.0: Aligned) = move _4; - drop(_1) -> [return: bb3, unwind terminate]; + drop(_1) -> [return: bb3, unwind terminate(cleanup)]; } bb2: { diff --git a/tests/mir-opt/pre-codegen/chained_comparison.rs b/tests/mir-opt/pre-codegen/chained_comparison.rs index f7879140f81..43030041983 100644 --- a/tests/mir-opt/pre-codegen/chained_comparison.rs +++ b/tests/mir-opt/pre-codegen/chained_comparison.rs @@ -1,5 +1,4 @@ // compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 -// ignore-debug #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs index dee43b0c6f8..23d78e98777 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.rs +++ b/tests/mir-opt/pre-codegen/checked_ops.rs @@ -1,6 +1,5 @@ // compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 // needs-unwind -// ignore-debug // only-x86_64 #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/intrinsics.rs b/tests/mir-opt/pre-codegen/intrinsics.rs index ecdb656cb85..e32e04384c4 100644 --- a/tests/mir-opt/pre-codegen/intrinsics.rs +++ b/tests/mir-opt/pre-codegen/intrinsics.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // Checks that we do not have any branches in the MIR for the two tested functions. diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 940b9ae1156..4db829a5ec3 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -83,7 +83,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> () } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate]; + drop(_5) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 2614160363e..c30df7425d2 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -75,7 +75,7 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () { } bb9 (cleanup): { - drop(_5) -> [return: bb10, unwind terminate]; + drop(_5) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/loops.rs b/tests/mir-opt/pre-codegen/loops.rs index 67f549a511c..f3ba409229d 100644 --- a/tests/mir-opt/pre-codegen/loops.rs +++ b/tests/mir-opt/pre-codegen/loops.rs @@ -1,6 +1,5 @@ // compile-flags: -O -Zmir-opt-level=2 -g // needs-unwind -// ignore-debug #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index 8eff46fb931..cb29473d762 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -67,7 +67,7 @@ fn vec_move(_1: Vec<impl Sized>) -> () { } bb9 (cleanup): { - drop(_3) -> [return: bb10, unwind terminate]; + drop(_3) -> [return: bb10, unwind terminate(cleanup)]; } bb10 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index e5066c38b96..a139848bab2 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 4d7c017dad4..35f7356d47a 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -127,7 +127,7 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb11 (cleanup): { - drop(_3) -> [return: bb12, unwind terminate]; + drop(_3) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index bbab4e47a3a..a677e8b439f 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -82,7 +82,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb8 (cleanup): { - drop(_3) -> [return: bb9, unwind terminate]; + drop(_3) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/range_iter.rs b/tests/mir-opt/pre-codegen/range_iter.rs index cabd9419e92..9552144787d 100644 --- a/tests/mir-opt/pre-codegen/range_iter.rs +++ b/tests/mir-opt/pre-codegen/range_iter.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir index 68d78f74328..312565e45c3 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir @@ -3,9 +3,9 @@ fn ezmap(_1: Option<i32>) -> Option<i32> { debug x => _1; let mut _0: std::option::Option<i32>; - scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map.rs:18:12: 18:15]>) { + scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map.rs:17:12: 17:15]>) { debug slf => _1; - debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:18:12: 18:15]; + debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:17:12: 17:15]; let mut _2: isize; let _3: i32; let mut _4: i32; diff --git a/tests/mir-opt/pre-codegen/simple_option_map.rs b/tests/mir-opt/pre-codegen/simple_option_map.rs index fb3da68e4af..d4f28dda6c6 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.rs +++ b/tests/mir-opt/pre-codegen/simple_option_map.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug #[inline(always)] fn map<T, U, F>(slf: Option<T>, f: F) -> Option<U> diff --git a/tests/mir-opt/pre-codegen/slice_index.rs b/tests/mir-opt/pre-codegen/slice_index.rs index d80bff50c31..57ffb07e294 100644 --- a/tests/mir-opt/pre-codegen/slice_index.rs +++ b/tests/mir-opt/pre-codegen/slice_index.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 836fa2677b1..3d76bab7ce7 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -195,7 +195,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 65baaf64a9e..e8586cec981 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -182,7 +182,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index f7b19e80e44..8bd072fd625 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -143,7 +143,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate]; + drop(_2) -> [return: bb13, unwind terminate(cleanup)]; } bb13 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 43f8806e165..3cdc49f6056 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -196,7 +196,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate]; + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } bb12 (cleanup): { diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs index 4e954aa3433..1790056369c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.rs +++ b/tests/mir-opt/pre-codegen/slice_iter.rs @@ -1,6 +1,6 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug +// ignore-debug the standard library debug assertions leak into this test // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/try_identity.rs b/tests/mir-opt/pre-codegen/try_identity.rs index 079ecccab28..a227c82d6a3 100644 --- a/tests/mir-opt/pre-codegen/try_identity.rs +++ b/tests/mir-opt/pre-codegen/try_identity.rs @@ -1,6 +1,5 @@ // compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 // only-64bit -// ignore-debug // Track the status of MIR optimizations simplifying `Ok(res?)` for both the old and new desugarings // of that syntax. diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir index 508f964099a..7d3346faba6 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir @@ -167,11 +167,11 @@ fn main() -> () { } bb7 (cleanup): { - drop(_21) -> [return: bb9, unwind terminate]; + drop(_21) -> [return: bb9, unwind terminate(cleanup)]; } bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate]; + drop(_5) -> [return: bb9, unwind terminate(cleanup)]; } bb9 (cleanup): { diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 9bf69acd356..3a8b457a7a1 100644 --- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () { bb3 (cleanup): { _4 = &raw mut (*_1)[_3]; _3 = Add(move _3, const 1_usize); - drop((*_4)) -> [return: bb4, unwind terminate]; + drop((*_4)) -> [return: bb4, unwind terminate(cleanup)]; } bb4 (cleanup): { diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index ee90a540720..b5879418355 100644 --- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () { } bb4 (cleanup): { - drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate]; + drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate(cleanup)]; } bb5: { diff --git a/tests/rustdoc-gui/warning-block.goml b/tests/rustdoc-gui/warning-block.goml index 2a935bd1a9b..8832b65c4d8 100644 --- a/tests/rustdoc-gui/warning-block.goml +++ b/tests/rustdoc-gui/warning-block.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-warning", - (theme, color, border_color, background_color), + (theme, color, border_color), block { set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} reload: @@ -14,32 +14,29 @@ define-function: ( "margin-bottom": "12px", "color": |color|, "border-left": "2px solid " + |border_color|, - "background-color": |background_color|, + "background-color": "transparent", }) assert-css: ("#doc-warning-2", { "margin-bottom": "0px", "color": |color|, "border-left": "2px solid " + |border_color|, - "background-color": |background_color|, + "background-color": "transparent", }) }, ) call-function: ("check-warning", { "theme": "ayu", - "color": "rgb(197, 197, 197)", - "border_color": "rgb(255, 142, 0)", - "background_color": "rgba(0, 0, 0, 0)", + "color": "#c5c5c5", + "border_color": "#ff8e00", }) call-function: ("check-warning", { "theme": "dark", - "color": "rgb(221, 221, 221)", - "border_color": "rgb(255, 142, 0)", - "background_color": "rgba(0, 0, 0, 0)", + "color": "#ddd", + "border_color": "#ff8e00", }) call-function: ("check-warning", { "theme": "light", - "color": "rgb(0, 0, 0)", - "border_color": "rgb(255, 142, 0)", - "background_color": "rgba(0, 0, 0, 0)", + "color": "black", + "border_color": "#ff8e00", }) diff --git a/tests/ui/abi/explicit_repr_rust.rs b/tests/ui/abi/explicit_repr_rust.rs new file mode 100644 index 00000000000..4f8cab3bf0e --- /dev/null +++ b/tests/ui/abi/explicit_repr_rust.rs @@ -0,0 +1,12 @@ +// check-pass + +#[repr(Rust)] +struct A; + +#[repr(Rust, align(16))] +struct B; + +#[repr(Rust, packed)] +struct C; + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr index 86c62e7b7f1..0e0dec35b53 100644 --- a/tests/ui/associated-consts/associated-const-array-len.stderr +++ b/tests/ui/associated-consts/associated-const-array-len.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/associated-const-array-len.rs:5:16 + --> $DIR/associated-const-array-len.rs:5:17 | LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; - | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^ the trait `Foo` is not implemented for `i32` error: aborting due to previous error diff --git a/tests/ui/associated-types/issue-44153.stderr b/tests/ui/associated-types/issue-44153.stderr index 8bddcd95568..73365d64d56 100644 --- a/tests/ui/associated-types/issue-44153.stderr +++ b/tests/ui/associated-types/issue-44153.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `<() as Array>::Element == &()` - --> $DIR/issue-44153.rs:18:5 + --> $DIR/issue-44153.rs:18:6 | LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array>::Element == &()` + | ^^ type mismatch resolving `<() as Array>::Element == &()` | note: expected this to be `&()` --> $DIR/issue-44153.rs:10:20 diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index acdc3be8c67..015b22f790f 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>(); | ++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/substs-ppaux.rs:49:5 + --> $DIR/substs-ppaux.rs:49:6 | LL | <str as Foo<u8>>::bar; - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required for `str` to implement `Foo<'_, '_, u8>` diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index ad67899e6da..484581b1028 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -71,10 +71,10 @@ LL | let x: () = foo::<'static>(); | ++ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/substs-ppaux.rs:49:5 + --> $DIR/substs-ppaux.rs:49:6 | LL | <str as Foo<u8>>::bar; - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` note: required for `str` to implement `Foo<'?0, '?1, u8>` diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs index 66b378f62d6..95783945529 100644 --- a/tests/ui/backtrace.rs +++ b/tests/ui/backtrace.rs @@ -100,14 +100,17 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.stderr).unwrap(); // loosened the following from double::h to double:: due to // spurious failures on mac, 32bit, optimized - assert!(s.contains("stack backtrace") && contains_verbose_expected(s, "double"), - "bad output3: {}", s); + assert!( + s.contains("stack backtrace") && + s.contains("panic in a destructor during cleanup") && + contains_verbose_expected(s, "double"), + "bad output3: {}", s + ); // Make sure a stack trace isn't printed too many times // - // Currently it is printed 3 times ("once", "twice" and "panic in a - // function that cannot unwind") but in the future the last one may be - // removed. + // Currently it is printed 3 times ("once", "twice" and "panic in a destructor during + // cleanup") but in the future the last one may be removed. let p = template(me).arg("double-fail") .env("RUST_BACKTRACE", "1").spawn().unwrap(); let out = p.wait_with_output().unwrap(); diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr index d8eebeb0d21..cb51d9b1ea5 100644 --- a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[Adt; std::mem::size_of::<Self::Assoc>()]: Foo` is not satisfied - --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:9 + --> $DIR/dont-evaluate-array-len-on-err-1.rs:15:10 | LL | <[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[Adt; std::mem::size_of::<Self::Assoc>()]` error: aborting due to previous error diff --git a/tests/ui/const-generics/exhaustive-value.stderr b/tests/ui/const-generics/exhaustive-value.stderr index 4a26e09772d..0828f7896dc 100644 --- a/tests/ui/const-generics/exhaustive-value.stderr +++ b/tests/ui/const-generics/exhaustive-value.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): Foo<N>` is not satisfied - --> $DIR/exhaustive-value.rs:262:5 + --> $DIR/exhaustive-value.rs:262:16 | LL | <() as Foo<N>>::test() - | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` + | ^ the trait `Foo<N>` is not implemented for `()` | = help: the following other types implement trait `Foo<N>`: <() as Foo<0>> diff --git a/tests/ui/consts/const-eval/ub-int-array.64bit.stderr b/tests/ui/consts/const-eval/ub-int-array.64bit.stderr deleted file mode 100644 index b3df41304ac..00000000000 --- a/tests/ui/consts/const-eval/ub-int-array.64bit.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:19:1 - | -LL | const UNINIT_INT_0: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:24:1 - | -LL | const UNINIT_INT_1: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - 00 00 00 00 01 __ 01 01 02 02 __ 02 │ .....░....░. - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:42:1 - | -LL | const UNINIT_INT_2: [u32; 3] = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 12, align: 4) { - 00 00 00 00 01 01 01 01 02 02 02 __ │ ...........░ - } - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ub-int-array.rs b/tests/ui/consts/const-eval/ub-int-array.rs index adcf376b9c7..cde0749dc5f 100644 --- a/tests/ui/consts/const-eval/ub-int-array.rs +++ b/tests/ui/consts/const-eval/ub-int-array.rs @@ -1,4 +1,3 @@ -// stderr-per-bitwidth //! Test the "array of int" fast path in validity checking, and in particular whether it //! points at the right array element. @@ -19,7 +18,12 @@ impl<T: Copy> MaybeUninit<T> { const UNINIT_INT_0: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value //~| invalid value at [0] - mem::transmute([MaybeUninit { uninit: () }, MaybeUninit::new(1), MaybeUninit::new(2)]) + mem::transmute([ + MaybeUninit { uninit: () }, + // Constants chosen to achieve endianness-independent hex dump. + MaybeUninit::new(0x11111111), + MaybeUninit::new(0x22222222), + ]) }; const UNINIT_INT_1: [u32; 3] = unsafe { //~^ ERROR it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr b/tests/ui/consts/const-eval/ub-int-array.stderr index b3df41304ac..c8efd7e1bd3 100644 --- a/tests/ui/consts/const-eval/ub-int-array.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-int-array.stderr @@ -1,16 +1,16 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:19:1 + --> $DIR/ub-int-array.rs:18:1 | LL | const UNINIT_INT_0: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered uninitialized memory, but expected an integer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 12, align: 4) { - __ __ __ __ 01 00 00 00 02 00 00 00 │ ░░░░........ + __ __ __ __ 11 11 11 11 22 22 22 22 │ ░░░░...."""" } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:24:1 + --> $DIR/ub-int-array.rs:28:1 | LL | const UNINIT_INT_1: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer @@ -21,7 +21,7 @@ LL | const UNINIT_INT_1: [u32; 3] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-int-array.rs:42:1 + --> $DIR/ub-int-array.rs:46:1 | LL | const UNINIT_INT_2: [u32; 3] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [2]: encountered uninitialized memory, but expected an integer diff --git a/tests/ui/consts/missing-larger-array-impl.stderr b/tests/ui/consts/missing-larger-array-impl.stderr index b8f6cb5ef97..fe9d0f6e6ed 100644 --- a/tests/ui/consts/missing-larger-array-impl.stderr +++ b/tests/ui/consts/missing-larger-array-impl.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[X; 35]: Default` is not satisfied - --> $DIR/missing-larger-array-impl.rs:7:5 + --> $DIR/missing-larger-array-impl.rs:7:6 | LL | <[X; 35] as Default>::default(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]` + | ^^^^^^^ the trait `Default` is not implemented for `[X; 35]` | = help: the following other types implement trait `Default`: [T; 0] diff --git a/tests/ui/consts/std/alloc.32bit.stderr b/tests/ui/consts/std/alloc.32bit.stderr index 8c83df53dad..da805de451c 100644 --- a/tests/ui/consts/std/alloc.32bit.stderr +++ b/tests/ui/consts/std/alloc.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:12:1 + --> $DIR/alloc.rs:11:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000000, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchec } error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:16:1 + --> $DIR/alloc.rs:15:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000003, but expected a valid enum tag diff --git a/tests/ui/consts/std/alloc.64bit.stderr b/tests/ui/consts/std/alloc.64bit.stderr index addedad1704..094503e1039 100644 --- a/tests/ui/consts/std/alloc.64bit.stderr +++ b/tests/ui/consts/std/alloc.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:12:1 + --> $DIR/alloc.rs:11:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag @@ -10,7 +10,7 @@ LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchec } error[E0080]: it is undefined behavior to use this value - --> $DIR/alloc.rs:16:1 + --> $DIR/alloc.rs:15:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000003, but expected a valid enum tag diff --git a/tests/ui/consts/std/alloc.rs b/tests/ui/consts/std/alloc.rs index 9abf35d63d3..0a2c2f4dec8 100644 --- a/tests/ui/consts/std/alloc.rs +++ b/tests/ui/consts/std/alloc.rs @@ -1,5 +1,4 @@ // stderr-per-bitwidth -// ignore-debug (the debug assertions change the error) // Strip out raw byte dumps to make comparison platform-independent: // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" // normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP" diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr index 1fda460372a..2cee53431a4 100644 --- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr @@ -27,10 +27,10 @@ LL | Infallible: From<T>; | ^^^^^^^ required by this bound in `K` error[E0277]: the trait bound `Vec<u8>: Copy` is not satisfied - --> $DIR/unsatisfied-bounds.rs:32:13 + --> $DIR/unsatisfied-bounds.rs:32:26 | LL | let _ = <() as Trait<Vec<u8>>>::A; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>` + | ^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>` | note: required by a bound in `Trait::A` --> $DIR/unsatisfied-bounds.rs:17:12 diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/issues/issue-39970.stderr index 8344b88c3be..713bc404f67 100644 --- a/tests/ui/issues/issue-39970.stderr +++ b/tests/ui/issues/issue-39970.stderr @@ -1,8 +1,8 @@ error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()` - --> $DIR/issue-39970.rs:19:5 + --> $DIR/issue-39970.rs:19:6 | LL | <() as Visit>::visit(); - | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array<'a>>::Element == ()` + | ^^ type mismatch resolving `<() as Array<'a>>::Element == ()` | note: expected this to be `()` --> $DIR/issue-39970.rs:10:20 diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index 02c5dd5bfb7..7bbb8ed2ca9 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -32,7 +32,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(nothing)] | ^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 @@ -40,7 +40,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:30:5 diff --git a/tests/ui/issue-2804.rs b/tests/ui/macros/issue-2804.rs index 571028c5e40..571028c5e40 100644 --- a/tests/ui/issue-2804.rs +++ b/tests/ui/macros/issue-2804.rs diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs new file mode 100644 index 00000000000..a1c797268d1 --- /dev/null +++ b/tests/ui/panics/panic-in-cleanup.rs @@ -0,0 +1,22 @@ +// run-fail +// exec-env:RUST_BACKTRACE=0 +// check-run-results +// error-pattern: panic in a destructor during cleanup +// normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +// normalize-stderr-test: "\n +at [^\n]+" -> "" +// needs-unwind +// ignore-emscripten "RuntimeError" junk in output +// ignore-msvc SEH doesn't do panic-during-cleanup the same way as everyone else + +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("BOOM"); + } +} + +fn main() { + let _b = Bomb; + panic!(); +} diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr new file mode 100644 index 00000000000..923bac69c50 --- /dev/null +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -0,0 +1,10 @@ +thread 'main' panicked at $DIR/panic-in-cleanup.rs:21:5: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at $DIR/panic-in-cleanup.rs:15:9: +BOOM +stack backtrace: +thread 'main' panicked at library/core/src/panicking.rs:126:5: +panic in a destructor during cleanup +stack backtrace: +thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs new file mode 100644 index 00000000000..da2b24945be --- /dev/null +++ b/tests/ui/panics/panic-in-ffi.rs @@ -0,0 +1,17 @@ +// run-fail +// exec-env:RUST_BACKTRACE=0 +// check-run-results +// error-pattern: panic in a function that cannot unwind +// normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" +// normalize-stderr-test: "\n +at [^\n]+" -> "" +// needs-unwind +// ignore-emscripten "RuntimeError" junk in output +#![feature(c_unwind)] + +extern "C" fn panic_in_ffi() { + panic!("Test"); +} + +fn main() { + panic_in_ffi(); +} diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr new file mode 100644 index 00000000000..3422f5ccc4d --- /dev/null +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -0,0 +1,7 @@ +thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5: +Test +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +thread 'main' panicked at library/core/src/panicking.rs:126:5: +panic in a function that cannot unwind +stack backtrace: +thread caused non-unwinding panic. aborting. diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr index 0e0f0c3e11e..df330c60b1e 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr @@ -77,6 +77,8 @@ LL | m!((0usize, true), (0..5, true) | (5..=usize::MAX, true) | (0..=usize:: | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(usize, bool)` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, (_, _) => todo!() } @@ -131,6 +133,8 @@ LL | m!((0isize, true), (isize::MIN..5, true) | ^^^^^^^^^^^^^^ pattern `(_, _)` not covered | = note: the matched value is of type `(isize, bool)` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL | match $s { $($t)+ => {}, (_, _) => todo!() } diff --git a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs new file mode 100644 index 00000000000..8f58227ee2c --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.rs @@ -0,0 +1,67 @@ +struct A<T> { + a: T, +} + +struct B<T, U>(T, U); + +fn main() { + match 0 { + //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] + 0 => (), + 1..=usize::MAX => (), + } + + match (0usize, 0usize) { + //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] + (0, 0) => (), + (1..=usize::MAX, 1..=usize::MAX) => (), + } + + match (0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `(_, _)` not covered [E0004] + (isize::MIN..=isize::MAX, 0) => (), + (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), + } + + // Should not report note about usize not having fixed max value + match Some(1usize) { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered + None => {} + } + + match Some(4) { + //~^ ERROR non-exhaustive patterns: `Some(_)` not covered + Some(0) => (), + Some(1..=usize::MAX) => (), + None => (), + } + + match Some(Some(Some(0))) { + //~^ ERROR non-exhaustive patterns: `Some(Some(Some(_)))` not covered + Some(Some(Some(0))) => (), + Some(Some(Some(1..=usize::MAX))) => (), + Some(Some(None)) => (), + Some(None) => (), + None => (), + } + + match (A { a: 0usize }) { + //~^ ERROR non-exhaustive patterns: `A { .. }` not covered [E0004] + A { a: 0 } => (), + A { a: 1..=usize::MAX } => (), + } + + match B(0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] + B(isize::MIN..=isize::MAX, 0) => (), + B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), + } + + // Should report only the note about usize not having fixed max value and not report + // report the note about isize + match B(0isize, 0usize) { + //~^ ERROR non-exhaustive patterns: `B(_, _)` not covered [E0004] + B(_, 0) => (), + B(_, 1..=usize::MAX) => (), + } +} diff --git a/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr new file mode 100644 index 00000000000..ea1d99e20ae --- /dev/null +++ b/tests/ui/pattern/usefulness/issue-85222-types-containing-non-exhaustive-types.stderr @@ -0,0 +1,170 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:8:11 + | +LL | match 0 { + | ^ pattern `_` not covered + | + = note: the matched value is of type `usize` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 1..=usize::MAX => (), +LL ~ _ => todo!(), + | + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:14:11 + | +LL | match (0usize, 0usize) { + | ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(usize, usize)` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (1..=usize::MAX, 1..=usize::MAX) => (), +LL ~ (_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:20:11 + | +LL | match (0isize, 0usize) { + | ^^^^^^^^^^^^^^^^ pattern `(_, _)` not covered + | + = note: the matched value is of type `(isize, usize)` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ (isize::MIN..=isize::MAX, 1..=usize::MAX) => (), +LL ~ (_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:27:11 + | +LL | match Some(1usize) { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<usize>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<usize>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:32:11 + | +LL | match Some(4) { + | ^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<usize>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<usize>` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => (), +LL ~ Some(_) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `Some(Some(Some(_)))` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:39:11 + | +LL | match Some(Some(Some(0))) { + | ^^^^^^^^^^^^^^^^^^^ pattern `Some(Some(Some(_)))` not covered + | +note: `Option<Option<Option<usize>>>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + | + = note: not covered + | + = note: not covered + = note: the matched value is of type `Option<Option<Option<usize>>>` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => (), +LL ~ Some(Some(Some(_))) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `A { .. }` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:48:11 + | +LL | match (A { a: 0usize }) { + | ^^^^^^^^^^^^^^^^^ pattern `A { .. }` not covered + | +note: `A<usize>` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:1:8 + | +LL | struct A<T> { + | ^ + = note: the matched value is of type `A<usize>` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ A { a: 1..=usize::MAX } => (), +LL ~ A { .. } => todo!(), + | + +error[E0004]: non-exhaustive patterns: `B(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:54:11 + | +LL | match B(0isize, 0usize) { + | ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered + | +note: `B<isize, usize>` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 + | +LL | struct B<T, U>(T, U); + | ^ + = note: the matched value is of type `B<isize, usize>` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ B(isize::MIN..=isize::MAX, 1..=usize::MAX) => (), +LL ~ B(_, _) => todo!(), + | + +error[E0004]: non-exhaustive patterns: `B(_, _)` not covered + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:62:11 + | +LL | match B(0isize, 0usize) { + | ^^^^^^^^^^^^^^^^^ pattern `B(_, _)` not covered + | +note: `B<isize, usize>` defined here + --> $DIR/issue-85222-types-containing-non-exhaustive-types.rs:5:8 + | +LL | struct B<T, U>(T, U); + | ^ + = note: the matched value is of type `B<isize, usize>` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ B(_, 1..=usize::MAX) => (), +LL ~ B(_, _) => todo!(), + | + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index b8af566de7c..d798ec722dd 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -10,6 +10,8 @@ note: `Foo` defined here LL | struct Foo { | ^^^ = note: the matched value is of type `Foo` + = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo { first: false, second: Some([1, 2, 3, 4]) } => (), diff --git a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr index e2a65ff8524..50c7fc889f4 100644 --- a/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr +++ b/tests/ui/pattern/usefulness/tuple-struct-nonexhaustive.stderr @@ -10,6 +10,8 @@ note: `Foo` defined here LL | struct Foo(isize, isize); | ^^^ = note: the matched value is of type `Foo` + = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively + = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Foo(2, b) => println!("{}", b), diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 48a6af3dd4c..7ffe1287eb3 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -4,7 +4,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:6:8 @@ -12,7 +12,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu = "a")] | ^^^^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:9:8 @@ -20,7 +20,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu(4))] | ^^^^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:14:8 @@ -28,7 +28,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu, u8)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` warning: unknown `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:20:7 @@ -46,7 +46,7 @@ error[E0552]: unrecognized representation hint LL | #[repr(uwu)] | ^^^ | - = help: valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs new file mode 100644 index 00000000000..b4eb541398c --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.rs @@ -0,0 +1,18 @@ +#![feature(if_let_guard)] +#![allow(irrefutable_let_patterns)] + +fn match_option(x: Option<u32>) { + match x { + //~^ ERROR non-exhaustive patterns: `None` not covered + Some(_) => {} + None if let y = x => {} + } +} + +fn main() { + let x = (); + match x { + //~^ ERROR non-exhaustive patterns: `()` not covered + y if let z = y => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr new file mode 100644 index 00000000000..ddd08854ff7 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/exhaustive.stderr @@ -0,0 +1,35 @@ +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/exhaustive.rs:5:11 + | +LL | match x { + | ^ pattern `None` not covered + | +note: `Option<u32>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<u32>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None if let y = x => {}, +LL + None => todo!() + | + +error[E0004]: non-exhaustive patterns: `()` not covered + --> $DIR/exhaustive.rs:14:11 + | +LL | match x { + | ^ pattern `()` not covered + | + = note: the matched value is of type `()` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ y if let z = y => {}, +LL + () => todo!() + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs new file mode 100644 index 00000000000..792225e656f --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.rs @@ -0,0 +1,15 @@ +// References to by-move bindings in an if-let guard *cannot* be used after the guard. + +#![feature(if_let_guard)] + +fn main() { + let x: Option<Option<String>> = Some(Some(String::new())); + match x { + Some(mut y) if let Some(ref z) = y => { + //~^ ERROR: cannot move out of `x.0` because it is borrowed + let _z: &String = z; + let _y: Option<String> = y; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr new file mode 100644 index 00000000000..b8e1bb324b1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-1.stderr @@ -0,0 +1,15 @@ +error[E0505]: cannot move out of `x.0` because it is borrowed + --> $DIR/guard-lifetime-1.rs:8:14 + | +LL | Some(mut y) if let Some(ref z) = y => { + | ^^^^^ + | | + | move out of `x.0` occurs here + | borrow of `x.0` occurs here +LL | +LL | let _z: &String = z; + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs new file mode 100644 index 00000000000..aa2154e3e9e --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-lifetime-2.rs @@ -0,0 +1,16 @@ +// References to by-mutable-ref bindings in an if-let guard *can* be used after the guard. + +// check-pass + +#![feature(if_let_guard)] + +fn main() { + let mut x: Option<Option<String>> = Some(Some(String::new())); + match x { + Some(ref mut y) if let Some(ref z) = *y => { + let _z: &String = z; + let _y: &mut Option<String> = y; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs new file mode 100644 index 00000000000..9353c9d92f8 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.rs @@ -0,0 +1,14 @@ +// Check mutable bindings cannot be mutated by an if-let guard. + +#![feature(if_let_guard)] + +fn main() { + let x: Option<Option<i32>> = Some(Some(6)); + match x { + Some(mut y) if let Some(ref mut z) = y => { + //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + let _: &mut i32 = z; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr new file mode 100644 index 00000000000..009d153387e --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-1.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + --> $DIR/guard-mutability-1.rs:8:33 + | +LL | Some(mut y) if let Some(ref mut z) = y => { + | ^^^^^^^^^ cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs new file mode 100644 index 00000000000..4efa02f57a6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.rs @@ -0,0 +1,14 @@ +// Check mutable reference bindings cannot be mutated by an if-let guard. + +#![feature(if_let_guard)] + +fn main() { + let mut x: Option<Option<i32>> = Some(Some(6)); + match x { + Some(ref mut y) if let Some(ref mut z) = *y => { + //~^ ERROR cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + let _: &mut i32 = z; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr new file mode 100644 index 00000000000..07e7c6a2c07 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/guard-mutability-2.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `y.0` as mutable, as it is immutable for the pattern guard + --> $DIR/guard-mutability-2.rs:8:37 + | +LL | Some(ref mut y) if let Some(ref mut z) = *y => { + | ^^^^^^^^^ cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs new file mode 100644 index 00000000000..423a2cd53fc --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.rs @@ -0,0 +1,16 @@ +// Expression macros can't expand to a let match guard. + +#![feature(if_let_guard)] +#![feature(let_chains)] + +macro_rules! m { + ($e:expr) => { let Some(x) = $e } + //~^ ERROR expected expression, found `let` statement +} + +fn main() { + match () { + () if m!(Some(5)) => {} + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr new file mode 100644 index 00000000000..41a20bf8ae1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `let` statement + --> $DIR/macro-expanded.rs:7:20 + | +LL | ($e:expr) => { let Some(x) = $e } + | ^^^ +... +LL | () if m!(Some(5)) => {} + | ----------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs new file mode 100644 index 00000000000..9cb27c73b14 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs @@ -0,0 +1,27 @@ +// Parenthesised let "expressions" are not allowed in guards + +#![feature(if_let_guard)] +#![feature(let_chains)] + +#[cfg(FALSE)] +fn un_cfged() { + match () { + () if let 0 = 1 => {} + () if (let 0 = 1) => {} + //~^ ERROR expected expression, found `let` statement + () if (((let 0 = 1))) => {} + //~^ ERROR expected expression, found `let` statement + } +} + +fn main() { + match () { + () if let 0 = 1 => {} + () if (let 0 = 1) => {} + //~^ ERROR expected expression, found `let` statement + //~| ERROR `let` expressions are not supported here + () if (((let 0 = 1))) => {} + //~^ ERROR expected expression, found `let` statement + //~| ERROR `let` expressions are not supported here + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr new file mode 100644 index 00000000000..85df360daab --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.stderr @@ -0,0 +1,52 @@ +error: expected expression, found `let` statement + --> $DIR/parens.rs:10:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:12:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^ + +error: expected expression, found `let` statement + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^ + +error: `let` expressions are not supported here + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/parens.rs:20:16 + | +LL | () if (let 0 = 1) => {} + | ^^^^^^^^^ + +error: `let` expressions are not supported here + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/parens.rs:23:18 + | +LL | () if (((let 0 = 1))) => {} + | ^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs new file mode 100644 index 00000000000..d91b3a358da --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/partially-macro-expanded.rs @@ -0,0 +1,18 @@ +// Macros can be used for (parts of) the pattern and expression in an if let guard +// check-pass + +#![feature(if_let_guard)] +#![feature(let_chains)] + +macro_rules! m { + (pattern $i:ident) => { Some($i) }; + (expression $e:expr) => { $e }; +} + +fn main() { + match () { + () if let m!(pattern x) = m!(expression Some(4)) => {} + () if let [m!(pattern y)] = [Some(8 + m!(expression 4))] => {} + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs new file mode 100644 index 00000000000..dba292ef9e2 --- /dev/null +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/shadowing.rs @@ -0,0 +1,23 @@ +// Check shadowing in if let guards works as expected. +// check-pass + +#![feature(if_let_guard)] +#![feature(let_chains)] + +fn main() { + let x: Option<Option<i32>> = Some(Some(6)); + match x { + Some(x) if let Some(x) = x => { + let _: i32 = x; + } + _ => {} + } + + let y: Option<Option<Option<i32>>> = Some(Some(Some(-24))); + match y { + Some(y) if let Some(y) = y && let Some(y) = y => { + let _: i32 = y; + } + _ => {} + } +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 2d9c49af85a..452bf757df7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:25:7 + --> $DIR/call-const-trait-method-fail.rs:25:5 | LL | a.plus(b) - | ^^^^ the trait `Plus` is not implemented for `u32` + | ^ the trait `Plus` is not implemented for `u32` | = help: the trait `Plus` is implemented for `u32` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index e8d0eec020f..c94563d3591 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^ the trait `Bar` is not implemented for `T` + | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::b` --> $DIR/trait-where-clause-const.rs:15:24 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr index 11f0c40160d..255878e1775 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Bar` is not satisfied --> $DIR/trait-where-clause.rs:14:5 | LL | T::b(); - | ^^^^ the trait `Bar` is not implemented for `T` + | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::b` --> $DIR/trait-where-clause.rs:8:24 diff --git a/tests/ui/issues/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index b7e49873da8..b7e49873da8 100644 --- a/tests/ui/issues/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs diff --git a/tests/ui/issues/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index e0a8225507e..e0a8225507e 100644 --- a/tests/ui/issues/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr diff --git a/tests/ui/issues/issue-17431-7.rs b/tests/ui/structs-enums/enum-rec/issue-17431-7.rs index 4fd7862781b..4fd7862781b 100644 --- a/tests/ui/issues/issue-17431-7.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-7.rs diff --git a/tests/ui/issues/issue-17431-7.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr index ecf072b8e8a..ecf072b8e8a 100644 --- a/tests/ui/issues/issue-17431-7.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-7.stderr diff --git a/tests/ui/issues/issue-17431-1.rs b/tests/ui/structs-enums/struct-rec/issue-17431-1.rs index 3b692cc0eeb..3b692cc0eeb 100644 --- a/tests/ui/issues/issue-17431-1.rs +++ b/tests/ui/structs-enums/struct-rec/issue-17431-1.rs diff --git a/tests/ui/issues/issue-17431-1.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr index e3af8976cee..e3af8976cee 100644 --- a/tests/ui/issues/issue-17431-1.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-1.stderr diff --git a/tests/ui/issues/issue-17431-2.rs b/tests/ui/structs-enums/struct-rec/issue-17431-2.rs index f7b9c6a55dd..f7b9c6a55dd 100644 --- a/tests/ui/issues/issue-17431-2.rs +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.rs diff --git a/tests/ui/issues/issue-17431-2.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr index 39a99ec1ef7..39a99ec1ef7 100644 --- a/tests/ui/issues/issue-17431-2.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-2.stderr diff --git a/tests/ui/issues/issue-17431-3.rs b/tests/ui/structs-enums/struct-rec/issue-17431-3.rs index 83a63a88b72..83a63a88b72 100644 --- a/tests/ui/issues/issue-17431-3.rs +++ b/tests/ui/structs-enums/struct-rec/issue-17431-3.rs diff --git a/tests/ui/issues/issue-17431-3.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr index 394134c7855..394134c7855 100644 --- a/tests/ui/issues/issue-17431-3.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-3.stderr diff --git a/tests/ui/issues/issue-17431-4.rs b/tests/ui/structs-enums/struct-rec/issue-17431-4.rs index 48f0dba2aec..48f0dba2aec 100644 --- a/tests/ui/issues/issue-17431-4.rs +++ b/tests/ui/structs-enums/struct-rec/issue-17431-4.rs diff --git a/tests/ui/issues/issue-17431-4.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr index 3d141e44bab..3d141e44bab 100644 --- a/tests/ui/issues/issue-17431-4.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-4.stderr diff --git a/tests/ui/issues/issue-17431-5.rs b/tests/ui/structs-enums/struct-rec/issue-17431-5.rs index 0fd6ee61156..0fd6ee61156 100644 --- a/tests/ui/issues/issue-17431-5.rs +++ b/tests/ui/structs-enums/struct-rec/issue-17431-5.rs diff --git a/tests/ui/issues/issue-17431-5.stderr b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr index 44a90a6fe38..44a90a6fe38 100644 --- a/tests/ui/issues/issue-17431-5.stderr +++ b/tests/ui/structs-enums/struct-rec/issue-17431-5.stderr diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 61b9137eadd..97bd7789a63 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -6,6 +6,11 @@ // normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC" // normalize-stderr-test "note: rustc .+ running on .+" -> "note: rustc $$VERSION running on $$TARGET" +// The test becomes too flaky if we care about exact args. If `-Z ui-testing` +// from compiletest and `-Z track-diagnostics` from `// compile-flags` at the +// top of this file are present, then assume all args are present. +// normalize-stderr-test "note: compiler flags: .*-Z ui-testing.*-Z track-diagnostics" -> "note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics" + fn main() { break rust } diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 8256c1f5f0f..60254dc475b 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -20,6 +20,8 @@ note: we would appreciate a joke overview: https://github.com/rust-lang/rust/iss note: rustc $VERSION running on $TARGET +note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics + error: aborting due to 3 previous errors Some errors have detailed explanations: E0268, E0425. diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs new file mode 100644 index 00000000000..91525bc90c4 --- /dev/null +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.rs @@ -0,0 +1,6 @@ +// Regression test for one part of issue #105306. + +fn main() { + let _ = Option::<[u8]>::None; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} diff --git a/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr new file mode 100644 index 00000000000..32f6b00b20c --- /dev/null +++ b/tests/ui/trait-bounds/enum-unit-variant-trait-bound.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/enum-unit-variant-trait-bound.rs:4:22 + | +LL | let _ = Option::<[u8]>::None; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `None` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-66768.rs b/tests/ui/traits/issue-66768.rs index ce42c8b01cc..ce42c8b01cc 100644 --- a/tests/ui/issues/issue-66768.rs +++ b/tests/ui/traits/issue-66768.rs diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index f3a4c689033..5a539884873 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -38,10 +38,10 @@ LL + fn check<T: Iterator, U>() { | error[E0277]: the trait bound `u64: From<T>` is not satisfied - --> $DIR/suggest-where-clause.rs:15:5 + --> $DIR/suggest-where-clause.rs:15:18 | LL | <u64 as From<T>>::from; - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64` + | ^ the trait `From<T>` is not implemented for `u64` | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | @@ -49,10 +49,10 @@ LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> { | ++++++++++++++++++ error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied - --> $DIR/suggest-where-clause.rs:18:5 + --> $DIR/suggest-where-clause.rs:18:18 | LL | <u64 as From<<T as Iterator>::Item>>::from; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64` | help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement | @@ -60,10 +60,10 @@ LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> { | ++++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied - --> $DIR/suggest-where-clause.rs:23:5 + --> $DIR/suggest-where-clause.rs:23:22 | LL | <Misc<_> as From<T>>::from; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>` + | ^ the trait `From<T>` is not implemented for `Misc<_>` error[E0277]: the size for values of type `[T]` cannot be known at compilation time --> $DIR/suggest-where-clause.rs:28:20 diff --git a/tests/ui/issues/auxiliary/issue-29181.rs b/tests/ui/typeck/auxiliary/issue-29181.rs index bd1a9be4ef1..bd1a9be4ef1 100644 --- a/tests/ui/issues/auxiliary/issue-29181.rs +++ b/tests/ui/typeck/auxiliary/issue-29181.rs diff --git a/tests/ui/issues/issue-29181.rs b/tests/ui/typeck/issue-29181.rs index 70e5bc01920..70e5bc01920 100644 --- a/tests/ui/issues/issue-29181.rs +++ b/tests/ui/typeck/issue-29181.rs diff --git a/tests/ui/issues/issue-29181.stderr b/tests/ui/typeck/issue-29181.stderr index 53addf2fe4d..53addf2fe4d 100644 --- a/tests/ui/issues/issue-29181.stderr +++ b/tests/ui/typeck/issue-29181.stderr diff --git a/tests/ui/unevaluated_fixed_size_array_len.stderr b/tests/ui/unevaluated_fixed_size_array_len.stderr index 5e67b2c44f2..b04a7b7f2f1 100644 --- a/tests/ui/unevaluated_fixed_size_array_len.stderr +++ b/tests/ui/unevaluated_fixed_size_array_len.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied - --> $DIR/unevaluated_fixed_size_array_len.rs:12:5 + --> $DIR/unevaluated_fixed_size_array_len.rs:12:6 | LL | <[(); 0] as Foo>::foo() - | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` + | ^^^^^^^ the trait `Foo` is not implemented for `[(); 0]` | = help: the trait `Foo` is implemented for `[(); 1]`  | 
