diff options
445 files changed, 4275 insertions, 4982 deletions
diff --git a/Cargo.lock b/Cargo.lock index 07dcca0fd47..d4fca32d750 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -632,7 +632,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -4994,8 +4994,8 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 1.0.102", - "synstructure", + "syn 2.0.8", + "synstructure 0.13.0", "unic-langid", ] @@ -6132,6 +6132,18 @@ dependencies = [ ] [[package]] +name = "synstructure" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.8", + "unicode-xid", +] + +[[package]] name = "tar" version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -7154,7 +7166,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -7175,7 +7187,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -7204,5 +7216,5 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 68205fa4558..84f75caa692 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -181,8 +181,8 @@ trait TypeOpInfo<'tcx> { }; let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder { - name: placeholder.name, universe: adjusted_universe.into(), + bound: placeholder.bound, }); let error_region = @@ -191,8 +191,8 @@ trait TypeOpInfo<'tcx> { error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32()); adjusted_universe.map(|adjusted| { tcx.mk_re_placeholder(ty::Placeholder { - name: error_placeholder.name, universe: adjusted.into(), + bound: error_placeholder.bound, }) }) } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index fd1fda2ee4b..e2d04324f3b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -11,7 +11,7 @@ use crate::{ }; use rustc_data_structures::fx::FxIndexSet; use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor}; -use rustc_middle::mir::{Body, Local, Location}; +use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; pub(crate) fn find<'tcx>( @@ -70,7 +70,10 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> { block_data .terminator() .successors() - .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind()) + .filter(|&bb| { + Some(&mir::UnwindAction::Cleanup(bb)) + != block_data.terminator().unwind() + }) .map(|bb| Location { statement_index: 0, block: bb }), ); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 7bd4331c5ed..110354a20d8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -467,9 +467,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Ref(region, ..) = ty.kind() { match **region { ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { - printer.region_highlight_mode.highlighting_bound_region(br, counter) - } + | ty::RePlaceholder(ty::PlaceholderRegion { + bound: ty::BoundRegion { kind: br, .. }, + .. + }) => printer.region_highlight_mode.highlighting_bound_region(br, counter), _ => {} } } @@ -485,9 +486,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let region = if let ty::Ref(region, ..) = ty.kind() { match **region { ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { - printer.region_highlight_mode.highlighting_bound_region(br, counter) - } + | ty::RePlaceholder(ty::PlaceholderRegion { + bound: ty::BoundRegion { kind: br, .. }, + .. + }) => printer.region_highlight_mode.highlighting_bound_region(br, counter), _ => {} } region diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index ffe82b46cfd..9fcebeb0acd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -207,7 +207,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .regioncx .placeholders_contained_in(lower_bound) .map(|placeholder| { - if let Some(id) = placeholder.name.get_id() + if let Some(id) = placeholder.bound.kind.get_id() && let Some(placeholder_id) = id.as_local() && let gat_hir_id = hir.local_def_id_to_hir_id(placeholder_id) && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics() diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index a71c4163286..498d254da65 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -125,7 +125,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { args, destination, target: _, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } => { @@ -135,7 +135,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } self.mutate_place(location, *destination, Deep); } - TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => { + TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { self.consume_operand(location, cond); use rustc_middle::mir::AssertKind; if let AssertKind::BoundsCheck { len, index } = msg { @@ -173,7 +173,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { options: _, line_spans: _, destination: _, - cleanup: _, + unwind: _, } => { for op in operands { match op { @@ -198,7 +198,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } TerminatorKind::Goto { target: _ } - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 1d4d1406239..3d876155fc9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -740,7 +740,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx args, destination, target: _, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } => { @@ -750,7 +750,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } self.mutate_place(loc, (*destination, span), Deep, flow_state); } - TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => { + TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { self.consume_operand(loc, (cond, span), flow_state); use rustc_middle::mir::AssertKind; if let AssertKind::BoundsCheck { len, index } = msg { @@ -770,7 +770,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx options: _, line_spans: _, destination: _, - cleanup: _, + unwind: _, } => { for op in operands { match op { @@ -801,7 +801,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } TerminatorKind::Goto { target: _ } - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Unreachable | TerminatorKind::Resume | TerminatorKind::Return @@ -845,7 +845,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } } - TerminatorKind::Abort + TerminatorKind::Terminate | 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 2fc4e32ecb2..624a4a00c31 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match &term.kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable @@ -1342,9 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let region_ctxt_fn = || { let reg_info = match br.kind { - ty::BoundRegionKind::BrAnon(_, Some(span)) => { - BoundRegionInfo::Span(span) - } + ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span), ty::BoundRegionKind::BrAnon(..) => { BoundRegionInfo::Name(Symbol::intern("anon")) } @@ -1584,7 +1582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, block_data, "resume on non-cleanup block!") } } - TerminatorKind::Abort => { + TerminatorKind::Terminate => { if !is_cleanup { span_mirbug!(self, block_data, "abort on non-cleanup block!") } @@ -1610,25 +1608,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } TerminatorKind::Unreachable => {} TerminatorKind::Drop { target, unwind, .. } - | TerminatorKind::Assert { target, cleanup: unwind, .. } => { + | TerminatorKind::Assert { target, unwind, .. } => { self.assert_iscleanup(body, block_data, target, is_cleanup); - if let Some(unwind) = unwind { - if is_cleanup { - span_mirbug!(self, block_data, "unwind on cleanup block") - } - self.assert_iscleanup(body, block_data, unwind, true); - } + self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } - TerminatorKind::Call { ref target, cleanup, .. } => { + TerminatorKind::Call { ref target, unwind, .. } => { if let &Some(target) = target { self.assert_iscleanup(body, block_data, target, is_cleanup); } - if let Some(cleanup) = cleanup { - if is_cleanup { - span_mirbug!(self, block_data, "cleanup on cleanup block") - } - self.assert_iscleanup(body, block_data, cleanup, true); - } + self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } TerminatorKind::FalseEdge { real_target, imaginary_target } => { self.assert_iscleanup(body, block_data, real_target, is_cleanup); @@ -1636,23 +1624,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } TerminatorKind::FalseUnwind { real_target, unwind } => { self.assert_iscleanup(body, block_data, real_target, is_cleanup); - if let Some(unwind) = unwind { - if is_cleanup { - span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind"); - } - self.assert_iscleanup(body, block_data, unwind, true); - } + self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } - TerminatorKind::InlineAsm { destination, cleanup, .. } => { + TerminatorKind::InlineAsm { destination, unwind, .. } => { if let Some(target) = destination { self.assert_iscleanup(body, block_data, target, is_cleanup); } - if let Some(cleanup) = cleanup { - if is_cleanup { - span_mirbug!(self, block_data, "cleanup on cleanup block") - } - self.assert_iscleanup(body, block_data, cleanup, true); - } + self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); } } } @@ -1669,6 +1647,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + fn assert_iscleanup_unwind( + &mut self, + body: &Body<'tcx>, + ctxt: &dyn fmt::Debug, + unwind: UnwindAction, + is_cleanup: bool, + ) { + match unwind { + UnwindAction::Cleanup(unwind) => { + if is_cleanup { + span_mirbug!(self, ctxt, "unwind on cleanup block") + } + self.assert_iscleanup(body, ctxt, unwind, true); + } + UnwindAction::Continue => { + if is_cleanup { + span_mirbug!(self, ctxt, "unwind on cleanup block") + } + } + UnwindAction::Unreachable | UnwindAction::Terminate => (), + } + } + fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) { match body.local_kind(local) { LocalKind::ReturnPointer | LocalKind::Arg => { diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 305e2c8fe8e..83429f2ddef 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -123,8 +123,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> .constraints .placeholder_region(self.type_checker.infcx, placeholder); - let reg_info = match placeholder.name { - ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span), + let reg_info = match placeholder.bound.kind { + ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span), ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")), ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name), ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")), diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 71177b8789b..7697b592e33 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -7,7 +7,6 @@ #![feature(box_patterns)] #![feature(decl_macro)] #![feature(if_let_guard)] -#![feature(is_some_and)] #![feature(is_sorted)] #![feature(let_chains)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 2630f02e6eb..f5301f9f7f1 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -345,7 +345,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { TerminatorKind::Return => { crate::abi::codegen_return(fx); } - TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => { + TerminatorKind::Assert { cond, expected, msg, target, unwind: _ } => { if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() { let target = fx.get_block(*target); fx.bcx.ins().jump(target, &[]); @@ -450,7 +450,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { destination, target, fn_span, - cleanup: _, + unwind: _, from_hir_call: _, } => { fx.tcx.prof.generic_activity("codegen call").run(|| { @@ -470,7 +470,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { options, destination, line_spans: _, - cleanup: _, + unwind: _, } => { if options.contains(InlineAsmOptions::MAY_UNWIND) { fx.tcx.sess.span_fatal( @@ -488,7 +488,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::Abort => { + TerminatorKind::Terminate => { codegen_panic_cannot_unwind(fx, source_info); } TerminatorKind::Resume => { diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ebb4de33f99..e87f4e25891 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -549,7 +549,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index d9f8170a3cf..e7668341eb6 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -381,7 +381,7 @@ impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> { } unsafe { - llvm::LLVMRustAppendModuleInlineAsm( + llvm::LLVMAppendModuleInlineAsm( self.llmod, template_str.as_ptr().cast(), template_str.len(), diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index fb563f70ed0..7136f750f39 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -904,9 +904,9 @@ unsafe fn embed_bitcode( // We need custom section flags, so emit module-level inline assembly. let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 63e8a67db53..6819a2af09d 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2,7 +2,7 @@ use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::common::Funclet; use crate::context::CodegenCx; -use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock}; +use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -841,7 +841,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { - unsafe { llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } + unsafe { + llvm::LLVMBuildIntCast2( + self.llbuilder, + val, + dest_ty, + if is_signed { True } else { False }, + UNNAMED, + ) + } } fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { @@ -1001,11 +1009,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { let name = cstr!("cleanuppad"); let ret = unsafe { - llvm::LLVMRustBuildCleanupPad( + llvm::LLVMBuildCleanupPad( self.llbuilder, parent, - args.len() as c_uint, args.as_ptr(), + args.len() as c_uint, name.as_ptr(), ) }; @@ -1014,7 +1022,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) { unsafe { - llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) + llvm::LLVMBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) .expect("LLVM does not have support for cleanupret"); } } @@ -1022,11 +1030,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { let name = cstr!("catchpad"); let ret = unsafe { - llvm::LLVMRustBuildCatchPad( + llvm::LLVMBuildCatchPad( self.llbuilder, parent, - args.len() as c_uint, args.as_ptr(), + args.len() as c_uint, name.as_ptr(), ) }; @@ -1041,7 +1049,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) -> &'ll Value { let name = cstr!("catchswitch"); let ret = unsafe { - llvm::LLVMRustBuildCatchSwitch( + llvm::LLVMBuildCatchSwitch( self.llbuilder, parent, unwind, @@ -1052,7 +1060,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let ret = ret.expect("LLVM does not have support for catchswitch"); for handler in handlers { unsafe { - llvm::LLVMRustAddHandler(ret, handler); + llvm::LLVMAddHandler(ret, handler); } } ret @@ -1376,8 +1384,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { } pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { - let ret = - unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; + let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 9116e71beac..940358acde9 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -7,7 +7,6 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use cstr::cstr; -use libc::c_uint; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -486,10 +485,10 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // go into custom sections of the wasm executable. if self.tcx.sess.target.is_like_wasm { if let Some(section) = attrs.link_section { - let section = llvm::LLVMMDStringInContext( + let section = llvm::LLVMMDStringInContext2( self.llcx, section.as_str().as_ptr().cast(), - section.as_str().len() as c_uint, + section.as_str().len(), ); assert!(alloc.provenance().ptrs().is_empty()); @@ -498,17 +497,15 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // as part of the interpreter execution). let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()); - let alloc = llvm::LLVMMDStringInContext( - self.llcx, - bytes.as_ptr().cast(), - bytes.len() as c_uint, - ); + let alloc = + llvm::LLVMMDStringInContext2(self.llcx, bytes.as_ptr().cast(), bytes.len()); let data = [section, alloc]; - let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); + let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len()); + let val = llvm::LLVMMetadataAsValue(self.llcx, meta); llvm::LLVMAddNamedMetadataOperand( self.llmod, "wasm.custom_sections\0".as_ptr().cast(), - meta, + val, ); } } else { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 4bf6762d1f6..21a0a60b012 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -864,8 +864,6 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); if tcx.sess.opts.unstable_opts.profile { - let cu_desc_metadata = - llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata); let default_gcda_path = &output_filenames.with_extension("gcda"); let gcda_path = tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); @@ -873,20 +871,17 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( let gcov_cu_info = [ path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")), path_to_mdstring(debug_context.llcontext, gcda_path), - cu_desc_metadata, + unit_metadata, ]; - let gcov_metadata = llvm::LLVMMDNodeInContext( + let gcov_metadata = llvm::LLVMMDNodeInContext2( debug_context.llcontext, gcov_cu_info.as_ptr(), - gcov_cu_info.len() as c_uint, + gcov_cu_info.len(), ); + let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata); let llvm_gcov_ident = cstr!("llvm.gcov"); - llvm::LLVMAddNamedMetadataOperand( - debug_context.llmod, - llvm_gcov_ident.as_ptr(), - gcov_metadata, - ); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val); } // Insert `llvm.ident` metadata on the wasm targets since that will @@ -907,15 +902,9 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( return unit_metadata; }; - fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { + fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata { let path_str = path_to_c_string(path); - unsafe { - llvm::LLVMMDStringInContext( - llcx, - path_str.as_ptr(), - path_str.as_bytes().len() as c_uint, - ) - } + unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 41a75c9d775..d56c414cf65 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -209,8 +209,7 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) { unsafe { - let dbg_loc_as_llval = llvm::LLVMRustMetadataAsValue(self.cx().llcx, dbg_loc); - llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc_as_llval); + llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 556c6602ff4..09f3fe02165 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1018,7 +1018,7 @@ extern "C" { pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); /// See Module::setModuleInlineAsm. - pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t); + pub fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t); /// See llvm::LLVMTypeKind::getTypeID. pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; @@ -1065,7 +1065,7 @@ extern "C" { // Operations on other types pub fn LLVMVoidTypeInContext(C: &Context) -> &Type; - pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type; + pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type; // Operations on all values pub fn LLVMTypeOf(Val: &Value) -> &Type; @@ -1084,7 +1084,12 @@ extern "C" { pub fn LLVMGetPoison(Ty: &Type) -> &Value; // Operations on metadata + // FIXME: deprecated, replace with LLVMMDStringInContext2 pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; + + pub fn LLVMMDStringInContext2(C: &Context, Str: *const c_char, SLen: size_t) -> &Metadata; + + // FIXME: deprecated, replace with LLVMMDNodeInContext2 pub fn LLVMMDNodeInContext<'a>( C: &'a Context, Vals: *const &'a Value, @@ -1123,6 +1128,8 @@ extern "C" { Packed: Bool, ) -> &'a Value; + // FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17 + // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc pub fn LLVMConstArray<'a>( ElementTy: &'a Type, ConstantVals: *const &'a Value, @@ -1262,7 +1269,7 @@ extern "C" { pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); // Metadata - pub fn LLVMSetCurrentDebugLocation<'a>(Builder: &Builder<'a>, L: &'a Value); + pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: &'a Metadata); // Terminators pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value; @@ -1302,38 +1309,38 @@ extern "C" { pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value; - pub fn LLVMRustBuildCleanupPad<'a>( + pub fn LLVMBuildCleanupPad<'a>( B: &Builder<'a>, ParentPad: Option<&'a Value>, - ArgCnt: c_uint, Args: *const &'a Value, + NumArgs: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCleanupRet<'a>( + pub fn LLVMBuildCleanupRet<'a>( B: &Builder<'a>, CleanupPad: &'a Value, - UnwindBB: Option<&'a BasicBlock>, + BB: Option<&'a BasicBlock>, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchPad<'a>( + pub fn LLVMBuildCatchPad<'a>( B: &Builder<'a>, ParentPad: &'a Value, - ArgCnt: c_uint, Args: *const &'a Value, + NumArgs: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchRet<'a>( + pub fn LLVMBuildCatchRet<'a>( B: &Builder<'a>, - Pad: &'a Value, + CatchPad: &'a Value, BB: &'a BasicBlock, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchSwitch<'a>( + pub fn LLVMBuildCatchSwitch<'a>( Builder: &Builder<'a>, ParentPad: Option<&'a Value>, - BB: Option<&'a BasicBlock>, + UnwindBB: Option<&'a BasicBlock>, NumHandlers: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustAddHandler<'a>(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock); pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value); // Add a case to the switch instruction @@ -1627,11 +1634,12 @@ extern "C" { DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildIntCast<'a>( + pub fn LLVMBuildIntCast2<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, - IsSigned: bool, + IsSigned: Bool, + Name: *const c_char, ) -> &'a Value; // Comparisons @@ -1920,7 +1928,7 @@ extern "C" { ); pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool; - pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; + pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>; diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index ff111d96f84..bef4647f207 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -53,7 +53,7 @@ impl<'ll> CodegenCx<'ll, '_> { } pub(crate) fn type_metadata(&self) -> &'ll Type { - unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) } + unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) } } ///x Creates an integer type with the given number of bits, e.g., i24 diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 4ab56699922..3e3fcc08bd6 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -13,8 +13,7 @@ use object::{ use snap::write::FrameEncoder; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owning_ref::OwningRef; -use rustc_data_structures::rustc_erase_owner; +use rustc_data_structures::owned_slice::try_slice_owned; use rustc_data_structures::sync::MetadataRef; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; @@ -42,10 +41,10 @@ fn load_metadata_with( ) -> Result<MetadataRef, String> { let file = File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?; - let data = unsafe { Mmap::map(file) } - .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e))?; - let metadata = OwningRef::new(data).try_map(f)?; - return Ok(rustc_erase_owner!(metadata.map_owner_box())); + + unsafe { Mmap::map(file) } + .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e)) + .and_then(|mmap| try_slice_owned(mmap, |mmap| f(mmap))) } impl MetadataLoader for DefaultMetadataLoader { diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index dcf533dc39c..115a41050d2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -284,7 +284,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi match data.terminator().kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable @@ -292,11 +292,11 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi | TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ } - TerminatorKind::Call { cleanup: unwind, .. } - | TerminatorKind::InlineAsm { cleanup: unwind, .. } - | TerminatorKind::Assert { cleanup: unwind, .. } + TerminatorKind::Call { unwind, .. } + | TerminatorKind::InlineAsm { unwind, .. } + | TerminatorKind::Assert { unwind, .. } | TerminatorKind::Drop { unwind, .. } => { - if let Some(unwind) = unwind { + if let mir::UnwindAction::Cleanup(unwind) = unwind { debug!( "cleanup_kinds: {:?}/{:?} registering {:?} as funclet", bb, data, unwind diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c086d1b7f5a..dd86977817f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional - /// return destination `destination` and the cleanup function `cleanup`. + /// return destination `destination` and the unwind action `unwind`. fn do_call<Bx: BuilderMethods<'a, 'tcx>>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, @@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { fn_ptr: Bx::Value, llargs: &[Bx::Value], destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>, - cleanup: Option<mir::BasicBlock>, + mut unwind: mir::UnwindAction, copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>], mergeable_succ: bool, ) -> MergingSucc { @@ -164,23 +164,23 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // do an invoke, otherwise do a call. let fn_ty = bx.fn_decl_backend_type(&fn_abi); - let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { - Some(self.llbb_with_cleanup(fx, cleanup)) - } else if fx.mir[self.bb].is_cleanup - && fn_abi.can_unwind - && !base::wants_msvc_seh(fx.cx.tcx().sess) - { - // Exception must not propagate out of the execution of a cleanup (doing so - // can cause undefined behaviour). We insert a double unwind guard for - // functions that can potentially unwind to protect against this. - // - // This is not necessary for SEH which does not use successive unwinding - // like Itanium EH. EH frames in SEH are different from normal function - // frames and SEH will abort automatically if an exception tries to - // propagate out from cleanup. - Some(fx.double_unwind_guard()) - } else { - None + if !fn_abi.can_unwind { + unwind = mir::UnwindAction::Unreachable; + } + + let unwind_block = match unwind { + mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), + mir::UnwindAction::Continue => None, + mir::UnwindAction::Unreachable => None, + mir::UnwindAction::Terminate => { + if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) { + // SEH will abort automatically if an exception tries to + // propagate out from cleanup. + None + } else { + Some(fx.terminate_block()) + } + } }; if let Some(unwind_block) = unwind_block { @@ -234,7 +234,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } } - /// Generates inline assembly with optional `destination` and `cleanup`. + /// Generates inline assembly with optional `destination` and `unwind`. fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>( &self, fx: &mut FunctionCx<'a, 'tcx, Bx>, @@ -244,11 +244,18 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options: InlineAsmOptions, line_spans: &[Span], destination: Option<mir::BasicBlock>, - cleanup: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, instance: Instance<'_>, mergeable_succ: bool, ) -> MergingSucc { - if let Some(cleanup) = cleanup { + 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::Continue => None, + mir::UnwindAction::Unreachable => None, + }; + + if let Some(cleanup) = unwind_target { let ret_llbb = if let Some(target) = destination { fx.llbb(target) } else { @@ -261,7 +268,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { options, line_spans, instance, - Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))), + Some((ret_llbb, cleanup, self.funclet(fx))), ); MergingSucc::False } else { @@ -431,7 +438,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, location: mir::Place<'tcx>, target: mir::BasicBlock, - unwind: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, mergeable_succ: bool, ) -> MergingSucc { let ty = location.ty(self.mir, bx.tcx()).ty; @@ -552,7 +559,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { expected: bool, msg: &mir::AssertMessage<'tcx>, target: mir::BasicBlock, - cleanup: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, mergeable_succ: bool, ) -> MergingSucc { let span = terminator.source_info.span; @@ -618,12 +625,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item); // Codegen the actual panic invoke/call. - let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, cleanup, &[], false); + let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false); assert_eq!(merging_succ, MergingSucc::False); MergingSucc::False } - fn codegen_abort_terminator( + fn codegen_terminate_terminator( &mut self, helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx, @@ -636,7 +643,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind); // Codegen the actual panic invoke/call. - let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, None, &[], false); + let merging_succ = helper.do_call( + self, + bx, + fn_abi, + llfn, + &[], + None, + mir::UnwindAction::Unreachable, + &[], + false, + ); assert_eq!(merging_succ, MergingSucc::False); } @@ -649,7 +666,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { instance: Option<Instance<'tcx>>, source_info: mir::SourceInfo, target: Option<mir::BasicBlock>, - cleanup: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, mergeable_succ: bool, ) -> Option<MergingSucc> { // Emit a panic or a no-op for `assert_*` intrinsics. @@ -696,7 +713,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llfn, &[msg.0, msg.1], target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), - cleanup, + unwind, &[], mergeable_succ, ) @@ -719,7 +736,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args: &[mir::Operand<'tcx>], destination: mir::Place<'tcx>, target: Option<mir::BasicBlock>, - cleanup: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, fn_span: Span, mergeable_succ: bool, ) -> MergingSucc { @@ -783,7 +800,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { instance, source_info, target, - cleanup, + unwind, mergeable_succ, ) { return merging_succ; @@ -1064,7 +1081,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_ptr, &llargs, target.as_ref().map(|&target| (ret_dest, target)), - cleanup, + unwind, &copied_constant_arguments, false, ); @@ -1084,7 +1101,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_ptr, &llargs, target.as_ref().map(|&target| (ret_dest, target)), - cleanup, + unwind, &copied_constant_arguments, mergeable_succ, ) @@ -1100,7 +1117,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options: ast::InlineAsmOptions, line_spans: &[Span], destination: Option<mir::BasicBlock>, - cleanup: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, instance: Instance<'_>, mergeable_succ: bool, ) -> MergingSucc { @@ -1164,7 +1181,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, - cleanup, + unwind, instance, mergeable_succ, ) @@ -1246,8 +1263,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::Abort => { - self.codegen_abort_terminator(helper, bx, terminator); + mir::TerminatorKind::Terminate => { + self.codegen_terminate_terminator(helper, bx, terminator); MergingSucc::False } @@ -1274,7 +1291,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ()) } - mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => self + mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self .codegen_assert_terminator( helper, bx, @@ -1283,7 +1300,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { expected, msg, target, - cleanup, + unwind, mergeable_succ(), ), @@ -1292,7 +1309,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ref args, destination, target, - cleanup, + unwind, from_hir_call: _, fn_span, } => self.codegen_call_terminator( @@ -1303,7 +1320,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args, destination, target, - cleanup, + unwind, fn_span, mergeable_succ(), ), @@ -1320,7 +1337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, - cleanup, + unwind, } => self.codegen_asm_terminator( helper, bx, @@ -1330,7 +1347,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, - cleanup, + unwind, self.instance, mergeable_succ(), ), @@ -1536,62 +1553,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { let llbb = self.llbb(bb); if base::wants_msvc_seh(self.cx.sess()) { - let funclet; - let ret_llbb; - match self.mir[bb].terminator.as_ref().map(|t| &t.kind) { - // 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(); - // } - Some(&mir::TerminatorKind::Abort) => { - let cs_llbb = - Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb)); - let cp_llbb = - Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb)); - ret_llbb = cs_llbb; - - let mut cs_bx = Bx::build(self.cx, cs_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. - let mut cp_bx = Bx::build(self.cx, cp_llbb); - let null = cp_bx.const_null( - cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space), - ); - let sixty_four = cp_bx.const_i32(64); - funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]); - cp_bx.br(llbb); - } - _ => { - let cleanup_llbb = - Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); - ret_llbb = cleanup_llbb; - let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); - funclet = cleanup_bx.cleanup_pad(None, &[]); - cleanup_bx.br(llbb); - } - } + let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); + let mut cleanup_bx = Bx::build(self.cx, cleanup_bb); + let funclet = cleanup_bx.cleanup_pad(None, &[]); + cleanup_bx.br(llbb); self.funclets[bb] = Some(funclet); - ret_llbb + cleanup_bb } else { let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup"); let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb); @@ -1618,26 +1585,68 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - fn double_unwind_guard(&mut self) -> Bx::BasicBlock { - self.double_unwind_guard.unwrap_or_else(|| { - assert!(!base::wants_msvc_seh(self.cx.sess())); + 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(); + // } + 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_i8p_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); + + let llpersonality = self.cx.eh_personality(); + bx.cleanup_landing_pad(llpersonality); - let llbb = Bx::append_block(self.cx, self.llfn, "abort"); - let mut bx = Bx::build(self.cx, llbb); - self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); + funclet = None; + } - let llpersonality = self.cx.eh_personality(); - bx.cleanup_landing_pad(llpersonality); + 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 llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None); + let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], funclet.as_ref()); bx.do_not_inline(llret); bx.unreachable(); - self.double_unwind_guard = Some(llbb); + self.terminate_block = Some(llbb); llbb }) } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 189549953d9..3dadb33c969 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -73,8 +73,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option<Bx::BasicBlock>, - /// Cached double unwind guarding block - double_unwind_guard: Option<Bx::BasicBlock>, + /// Cached terminate upon unwinding block + terminate_block: Option<Bx::BasicBlock>, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -166,7 +166,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let start_llbb = Bx::append_block(cx, llfn, "start"); let mut start_bx = Bx::build(cx, start_llbb); - if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) { + if mir.basic_blocks.iter().any(|bb| { + bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate)) + }) { start_bx.set_personality_fn(cx.eh_personality()); } @@ -189,7 +191,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, - double_unwind_guard: None, + terminate_block: None, cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c87ea18af4f..a5dfd1072f0 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -23,7 +23,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::interpret::{ self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx, - InterpResult, OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind, + InterpResult, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -271,7 +271,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { /* with_caller_location = */ false, dest, ret, - StackPopUnwind::NotAllowed, + mir::UnwindAction::Unreachable, )?; Ok(ControlFlow::Break(())) } else { @@ -401,7 +401,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, args: &[OpTy<'tcx>], dest: &PlaceTy<'tcx>, ret: Option<mir::BasicBlock>, - _unwind: StackPopUnwind, // unwinding is not supported in consts + _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { debug!("find_mir_or_eval_fn: {:?}", instance); @@ -450,7 +450,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, args: &[OpTy<'tcx>], dest: &PlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, - _unwind: StackPopUnwind, + _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { // Shared intrinsics. if ecx.emulate_intrinsic(instance, args, dest, target)? { @@ -526,7 +526,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &AssertMessage<'tcx>, - _unwind: Option<mir::BasicBlock>, + _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { use rustc_middle::mir::AssertKind::*; // Convert `AssertKind<Operand>` to `AssertKind<Scalar>`. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 0918ffcd982..3e58a58aef7 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -139,17 +139,6 @@ pub struct FrameInfo<'tcx> { pub lint_root: Option<hir::HirId>, } -/// Unwind information. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum StackPopUnwind { - /// The cleanup block. - Cleanup(mir::BasicBlock), - /// No cleanup needs to be done. - Skip, - /// Unwinding is not allowed (UB). - NotAllowed, -} - #[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function @@ -157,7 +146,7 @@ pub enum StackPopCleanup { /// we can validate it at that layout. /// `ret` stores the block we jump to on a normal return, while `unwind` /// stores the block used for cleanup during unwinding. - Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind }, + Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction }, /// The root frame of the stack: nowhere else to jump to. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away @@ -735,18 +724,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// *Unwind* to the given `target` basic block. /// Do *not* use for returning! Use `return_to_block` instead. /// - /// If `target` is `StackPopUnwind::Skip`, that indicates the function does not need cleanup + /// If `target` is `UnwindAction::Continue`, that indicates the function does not need cleanup /// during unwinding, and we will just keep propagating that upwards. /// - /// If `target` is `StackPopUnwind::NotAllowed`, that indicates the function does not allow + /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow /// unwinding, and doing so is UB. - pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> { + pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> { self.frame_mut().loc = match target { - StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), - StackPopUnwind::Skip => Right(self.frame_mut().body.span), - StackPopUnwind::NotAllowed => { + mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), + mir::UnwindAction::Continue => Right(self.frame_mut().body.span), + mir::UnwindAction::Unreachable => { throw_ub_format!("unwinding past a stack frame that does not allow unwinding") } + mir::UnwindAction::Terminate => { + self.frame_mut().loc = Right(self.frame_mut().body.span); + M::abort(self, "panic in a function that cannot unwind".to_owned())?; + } }; Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index aca68dc454b..0291cca7378 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, Frame, ImmTy, InterpCx, - InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, + InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, }; /// Data returned by Machine::stack_pop, @@ -185,7 +185,7 @@ pub trait Machine<'mir, 'tcx>: Sized { args: &[OpTy<'tcx, Self::Provenance>], destination: &PlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; /// Execute `fn_val`. It is the hook's responsibility to advance the instruction @@ -197,7 +197,7 @@ pub trait Machine<'mir, 'tcx>: Sized { args: &[OpTy<'tcx, Self::Provenance>], destination: &PlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; /// Directly process an intrinsic without pushing a stack frame. It is the hook's @@ -208,17 +208,17 @@ pub trait Machine<'mir, 'tcx>: Sized { args: &[OpTy<'tcx, Self::Provenance>], destination: &PlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &mir::AssertMessage<'tcx>, - unwind: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; - /// Called to evaluate `Abort` MIR terminator. + /// Called to abort evaluation. fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> { throw_unsup_format!("aborting execution is not supported") } @@ -487,7 +487,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { _args: &[OpTy<$tcx>], _destination: &PlaceTy<$tcx, Self::Provenance>, _target: Option<mir::BasicBlock>, - _unwind: StackPopUnwind, + _unwind: mir::UnwindAction, ) -> InterpResult<$tcx> { match fn_val {} } diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 86de4e4e32c..898d62361ab 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -20,9 +20,7 @@ mod visitor; pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here -pub use self::eval_context::{ - Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup, StackPopUnwind, -}; +pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup}; pub use self::intern::{intern_const_alloc_recursive, InternKind}; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2d9fee9852c..a07702f7d9b 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -13,7 +13,7 @@ use rustc_target::spec::abi::Abi; use super::{ FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand, - PlaceTy, Scalar, StackPopCleanup, StackPopUnwind, + PlaceTy, Scalar, StackPopCleanup, }; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -60,7 +60,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ref args, destination, target, - ref cleanup, + unwind, from_hir_call: _, fn_span: _, } => { @@ -106,11 +106,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { with_caller_location, &destination, target, - match (cleanup, fn_abi.can_unwind) { - (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup), - (None, true) => StackPopUnwind::Skip, - (_, false) => StackPopUnwind::NotAllowed, - }, + if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable }, )?; // Sanity-check that `eval_fn_call` either pushed a new frame or // did a jump to another block. @@ -137,19 +133,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.drop_in_place(&place, instance, target, unwind)?; } - Assert { ref cond, expected, ref msg, target, cleanup } => { + Assert { ref cond, expected, ref msg, target, unwind } => { let ignored = M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check(); let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?; if ignored || expected == cond_val { self.go_to_block(target); } else { - M::assert_panic(self, msg, cleanup)?; + M::assert_panic(self, msg, unwind)?; } } - Abort => { - M::abort(self, "the program aborted execution".to_owned())?; + Terminate => { + // FIXME: maybe should call `panic_no_unwind` lang item instead. + M::abort(self, "panic in a function that cannot unwind".to_owned())?; } // When we encounter Resume, we've finished unwinding @@ -351,7 +348,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { with_caller_location: bool, destination: &PlaceTy<'tcx, M::Provenance>, target: Option<mir::BasicBlock>, - mut unwind: StackPopUnwind, + mut unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { trace!("eval_fn_call: {:#?}", fn_val); @@ -410,9 +407,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind { - // The callee cannot unwind. - unwind = StackPopUnwind::NotAllowed; + if !callee_fn_abi.can_unwind { + // The callee cannot unwind, so force the `Unreachable` unwind handling. + unwind = mir::UnwindAction::Unreachable; } self.push_stack_frame( @@ -676,7 +673,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { place: &PlaceTy<'tcx, M::Provenance>, instance: ty::Instance<'tcx>, target: mir::BasicBlock, - unwind: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { trace!("drop_in_place: {:?},\n {:?}, {:?}", *place, place.layout.ty, instance); // We take the address of the object. This may well be unaligned, which is fine @@ -717,10 +714,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { false, &ret.into(), Some(target), - match unwind { - Some(cleanup) => StackPopUnwind::Cleanup(cleanup), - None => StackPopUnwind::Skip, - }, + unwind, ) } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 16b83af91ac..5ab389d04c7 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -20,7 +20,6 @@ Rust MIR: a lowered representation of Rust. #![feature(try_blocks)] #![feature(yeet_expr)] #![feature(if_let_guard)] -#![feature(is_some_and)] #![recursion_limit = "256"] #[macro_use] 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 20c0852fe33..9dad9479053 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1031,9 +1031,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.check_op(ops::Generator(hir::GeneratorKind::Gen)) } - TerminatorKind::Abort => { + TerminatorKind::Terminate => { // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`). - span_bug!(self.span, "`Abort` terminator outside of cleanup block") + span_bug!(self.span, "`Terminate` terminator outside of cleanup block") } TerminatorKind::Assert { .. } 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 f01ab4c5d61..1f1640fd80a 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 @@ -104,7 +104,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { } } - mir::TerminatorKind::Abort + mir::TerminatorKind::Terminate | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } | mir::TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 6774e5a5837..7919aed097a 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -807,7 +807,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { kind: TerminatorKind::Call { func, args, - cleanup: None, + unwind: UnwindAction::Continue, destination: Place::from(new_temp), target: Some(new_target), from_hir_call, diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index e798c9d236e..0f56fda18f5 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, UnOp, VarDebugInfo, VarDebugInfoContents, START_BLOCK, + TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -232,6 +232,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + fn check_unwind_edge(&mut self, location: Location, unwind: UnwindAction) { + let is_cleanup = self.body.basic_blocks[location.block].is_cleanup; + match unwind { + UnwindAction::Cleanup(unwind) => { + if is_cleanup { + self.fail(location, "unwind on cleanup block"); + } + self.check_edge(location, unwind, EdgeKind::Unwind); + } + UnwindAction::Continue => { + if is_cleanup { + self.fail(location, "unwind on cleanup block"); + } + } + UnwindAction::Unreachable | UnwindAction::Terminate => (), + } + } + /// Check if src can be assigned into dest. /// This is not precise, it will accept some incorrect assignments. fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool { @@ -902,11 +920,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } TerminatorKind::Drop { target, unwind, .. } => { self.check_edge(location, *target, EdgeKind::Normal); - if let Some(unwind) = unwind { - self.check_edge(location, *unwind, EdgeKind::Unwind); - } + self.check_unwind_edge(location, *unwind); } - TerminatorKind::Call { func, args, destination, target, cleanup, .. } => { + TerminatorKind::Call { func, args, destination, target, unwind, .. } => { let func_ty = func.ty(&self.body.local_decls, self.tcx); match func_ty.kind() { ty::FnPtr(..) | ty::FnDef(..) => {} @@ -918,9 +934,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Some(target) = target { self.check_edge(location, *target, EdgeKind::Normal); } - if let Some(cleanup) = cleanup { - self.check_edge(location, *cleanup, EdgeKind::Unwind); - } + self.check_unwind_edge(location, *unwind); // The call destination place and Operand::Move place used as an argument might be // passed by a reference to the callee. Consequently they must be non-overlapping. @@ -946,7 +960,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - TerminatorKind::Assert { cond, target, cleanup, .. } => { + TerminatorKind::Assert { cond, target, unwind, .. } => { let cond_ty = cond.ty(&self.body.local_decls, self.tcx); if cond_ty != self.tcx.types.bool { self.fail( @@ -958,9 +972,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } self.check_edge(location, *target, EdgeKind::Normal); - if let Some(cleanup) = cleanup { - self.check_edge(location, *cleanup, EdgeKind::Unwind); - } + self.check_unwind_edge(location, *unwind); } TerminatorKind::Yield { resume, drop, .. } => { if self.body.generator.is_none() { @@ -992,17 +1004,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } self.check_edge(location, *real_target, EdgeKind::Normal); - if let Some(unwind) = unwind { - self.check_edge(location, *unwind, EdgeKind::Unwind); - } + self.check_unwind_edge(location, *unwind); } - TerminatorKind::InlineAsm { destination, cleanup, .. } => { + TerminatorKind::InlineAsm { destination, unwind, .. } => { if let Some(destination) = destination { self.check_edge(location, *destination, EdgeKind::Normal); } - if let Some(cleanup) = cleanup { - self.check_edge(location, *cleanup, EdgeKind::Unwind); - } + self.check_unwind_edge(location, *unwind); } TerminatorKind::GeneratorDrop => { if self.body.generator.is_none() { @@ -1015,10 +1023,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - TerminatorKind::Resume | TerminatorKind::Abort => { + TerminatorKind::Resume | TerminatorKind::Terminate => { let bb = location.block; if !self.body.basic_blocks[bb].is_cleanup { - self.fail(location, "Cannot `Resume` or `Abort` from non-cleanup basic block") + self.fail( + location, + "Cannot `Resume` or `Terminate` from non-cleanup basic block", + ) } } TerminatorKind::Return => { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 9b52638e612..e373bd18402 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -1,5 +1,5 @@ //! Various data structures used by the Rust compiler. The intention -//! is that code in here should be not be *specific* to rustc, so that +//! is that code in here should not be *specific* to rustc, so that //! it can be easily unit tested and so forth. //! //! # Note @@ -27,6 +27,8 @@ #![feature(thread_id_value)] #![feature(vec_into_raw_parts)] #![feature(get_mut_unchecked)] +#![feature(lint_reasons)] +#![feature(unwrap_infallible)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] @@ -59,7 +61,6 @@ pub mod intern; pub mod jobserver; pub mod macros; pub mod obligation_forest; -pub mod owning_ref; pub mod sip128; pub mod small_c_str; pub mod small_str; @@ -82,6 +83,7 @@ pub mod vec_linked_list; pub mod work_queue; pub use atomic_ref::AtomicRef; pub mod frozen; +pub mod owned_slice; pub mod sso; pub mod steal; pub mod tagged_ptr; diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index 3d44e17f31d..1556873f597 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -2,9 +2,7 @@ use std::fs::File; use std::io; use std::ops::{Deref, DerefMut}; -use crate::owning_ref::StableAddress; - -/// A trivial wrapper for [`memmap2::Mmap`] that implements [`StableAddress`]. +/// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM). #[cfg(not(target_arch = "wasm32"))] pub struct Mmap(memmap2::Mmap); @@ -46,12 +44,6 @@ impl AsRef<[u8]> for Mmap { } } -// SAFETY: On architectures other than WASM, mmap is used as backing storage. The address of this -// memory map is stable. On WASM, `Vec<u8>` is used as backing storage. The `Mmap` type doesn't -// export any function that can cause the `Vec` to be re-allocated. As such the address of the -// bytes inside this `Vec` is stable. -unsafe impl StableAddress for Mmap {} - #[cfg(not(target_arch = "wasm32"))] pub struct MmapMut(memmap2::MmapMut); diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs new file mode 100644 index 00000000000..048401f66c2 --- /dev/null +++ b/compiler/rustc_data_structures/src/owned_slice.rs @@ -0,0 +1,118 @@ +use std::{borrow::Borrow, ops::Deref}; + +// Use our fake Send/Sync traits when on not parallel compiler, +// so that `OwnedSlice` only implements/requires Send/Sync +// for parallel compiler builds. +use crate::sync::{Send, Sync}; + +/// An owned slice. +/// +/// This is similar to `Box<[u8]>` but allows slicing and using anything as the +/// backing buffer. +/// +/// See [`slice_owned`] for `OwnedSlice` construction and examples. +/// +/// --------------------------------------------------------------------------- +/// +/// This is essentially a replacement for `owning_ref` which is a lot simpler +/// and even sound! 🌸 +pub struct OwnedSlice { + /// This is conceptually a `&'self.owner [u8]`. + bytes: *const [u8], + + // +---------------------------------------+ + // | We expect `dead_code` lint here, | + // | because we don't want to accidentally | + // | touch the owner — otherwise the owner | + // | could invalidate out `bytes` pointer | + // | | + // | so be quiet | + // +----+ +-------------------------------+ + // \/ + // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770) + #[expect(dead_code)] + owner: Box<dyn Send + Sync>, +} + +/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function. +/// +/// ## Examples +/// +/// ```rust +/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; +/// let vec = vec![1, 2, 3, 4]; +/// +/// // Identical to slicing via `&v[1..3]` but produces an owned slice +/// let slice: OwnedSlice = slice_owned(vec, |v| &v[1..3]); +/// assert_eq!(&*slice, [2, 3]); +/// ``` +/// +/// ```rust +/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned}; +/// # use std::ops::Deref; +/// let vec = vec![1, 2, 3, 4]; +/// +/// // Identical to slicing via `&v[..]` but produces an owned slice +/// let slice: OwnedSlice = slice_owned(vec, Deref::deref); +/// assert_eq!(&*slice, [1, 2, 3, 4]); +/// ``` +pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice +where + O: Send + Sync + 'static, + F: FnOnce(&O) -> &[u8], +{ + try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok() +} + +/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function that can fail. +/// +/// See [`slice_owned`] for the infallible version. +pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E> +where + O: Send + Sync + 'static, + F: FnOnce(&O) -> Result<&[u8], E>, +{ + // We box the owner of the bytes, so it doesn't move. + // + // Since the owner does not move and we don't access it in any way + // before drop, there is nothing that can invalidate the bytes pointer. + // + // Thus, "extending" the lifetime of the reference returned from `F` is fine. + // We pretend that we pass it a reference that lives as long as the returned slice. + // + // N.B. the HRTB on the `slicer` is important — without it the caller could provide + // a short lived slice, unrelated to the owner. + + let owner = Box::new(owner); + let bytes = slicer(&*owner)?; + + Ok(OwnedSlice { bytes, owner }) +} + +impl Deref for OwnedSlice { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + // Safety: + // `self.bytes` is valid per the construction in `slice_owned` + // (which is the only constructor) + unsafe { &*self.bytes } + } +} + +impl Borrow<[u8]> for OwnedSlice { + #[inline] + fn borrow(&self) -> &[u8] { + self + } +} + +// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send` +unsafe impl Send for OwnedSlice {} + +// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync` +unsafe impl Sync for OwnedSlice {} + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs new file mode 100644 index 00000000000..e715fb55362 --- /dev/null +++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs @@ -0,0 +1,74 @@ +use std::{ + ops::Deref, + sync::{ + atomic::{self, AtomicBool}, + Arc, + }, +}; + +use crate::{ + owned_slice::{slice_owned, try_slice_owned, OwnedSlice}, + OnDrop, +}; + +#[test] +fn smoke() { + let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice); + + assert_eq!(&*slice, [1, 2, 3, 4, 5, 6]); +} + +#[test] +fn static_storage() { + let slice = slice_owned(Box::new(String::from("what")), |_| b"bytes boo"); + + assert_eq!(&*slice, b"bytes boo"); +} + +#[test] +fn slice_the_slice() { + let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice); + let slice = slice_owned(slice, |s| &s[1..][..4]); + let slice = slice_owned(slice, |s| s); + let slice = slice_owned(slice, |s| &s[1..]); + + assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]); +} + +#[test] +fn try_and_fail() { + let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(())); + + assert!(res.is_err()); +} + +#[test] +fn boxed() { + // It's important that we don't cause UB because of `Box`'es uniqueness + + let boxed: Box<[u8]> = vec![1, 1, 2, 3, 5, 8, 13, 21].into_boxed_slice(); + let slice = slice_owned(boxed, Deref::deref); + + assert_eq!(&*slice, [1, 1, 2, 3, 5, 8, 13, 21]); +} + +#[test] +fn drop_drops() { + let flag = Arc::new(AtomicBool::new(false)); + let flag_prime = Arc::clone(&flag); + let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed)); + + let slice = slice_owned(d, |_| &[]); + + assert_eq!(flag.load(atomic::Ordering::Relaxed), false); + + drop(slice); + + assert_eq!(flag.load(atomic::Ordering::Relaxed), true); +} + +#[test] +fn send_sync() { + crate::sync::assert_send::<OwnedSlice>(); + crate::sync::assert_sync::<OwnedSlice>(); +} diff --git a/compiler/rustc_data_structures/src/owning_ref/LICENSE b/compiler/rustc_data_structures/src/owning_ref/LICENSE deleted file mode 100644 index dff72d1e432..00000000000 --- a/compiler/rustc_data_structures/src/owning_ref/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Marvin Löbel - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs deleted file mode 100644 index d1d92b905b8..00000000000 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ /dev/null @@ -1,1211 +0,0 @@ -#![warn(missing_docs)] - -/*! -# An owning reference. - -This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut` -that enables it to bundle a reference together with the owner of the data it points to. -This allows moving and dropping of an `OwningRef` without needing to recreate the reference. - -This can sometimes be useful because Rust borrowing rules normally prevent -moving a type that has been moved from. For example, this kind of code gets rejected: - -```compile_fail,E0515 -fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) { - let v = vec![1, 2, 3, 4]; - let s = &v[1..3]; - (v, s) -} -``` - -Even though, from a memory-layout point of view, this can be entirely safe -if the new location of the vector still lives longer than the lifetime `'a` -of the reference because the backing allocation of the vector does not change. - -This library enables this safe usage by keeping the owner and the reference -bundled together in a wrapper type that ensure that lifetime constraint: - -``` -# use rustc_data_structures::owning_ref::OwningRef; -# fn main() { -fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> { - let v = vec![1, 2, 3, 4]; - let or = OwningRef::new(v); - let or = or.map(|v| &v[1..3]); - or -} -# } -``` - -It works by requiring owner types to dereference to stable memory locations -and preventing mutable access to root containers, which in practice requires heap allocation -as provided by `Box<T>`, `Rc<T>`, etc. - -Also provided are typedefs for common owner type combinations, -which allow for less verbose type signatures. -For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`. - -The crate also provides the more advanced `OwningHandle` type, -which allows more freedom in bundling a dependent handle object -along with the data it depends on, at the cost of some unsafe needed in the API. -See the documentation around `OwningHandle` for more details. - -# Examples - -## Basics - -``` -use rustc_data_structures::owning_ref::BoxRef; - -fn main() { - // Create an array owned by a Box. - let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>; - - // Transfer into a BoxRef. - let arr: BoxRef<[i32]> = BoxRef::new(arr); - assert_eq!(&*arr, &[1, 2, 3, 4]); - - // We can slice the array without losing ownership or changing type. - let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]); - assert_eq!(&*arr, &[2, 3]); - - // Also works for Arc, Rc, String and Vec! -} -``` - -## Caching a reference to a struct field - -``` -use rustc_data_structures::owning_ref::BoxRef; - -fn main() { - struct Foo { - tag: u32, - x: u16, - y: u16, - z: u16, - } - let foo = Foo { tag: 1, x: 100, y: 200, z: 300 }; - - let or = BoxRef::new(Box::new(foo)).map(|foo| { - match foo.tag { - 0 => &foo.x, - 1 => &foo.y, - 2 => &foo.z, - _ => panic!(), - } - }); - - assert_eq!(*or, 200); -} -``` - -## Caching a reference to an entry in a vector - -``` -use rustc_data_structures::owning_ref::VecRef; - -fn main() { - let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]); - assert_eq!(*v, 4); -} -``` - -## Caching a subslice of a String - -``` -use rustc_data_structures::owning_ref::StringRef; - -fn main() { - let s = StringRef::new("hello world".to_owned()) - .map(|s| s.split(' ').nth(1).unwrap()); - - assert_eq!(&*s, "world"); -} -``` - -## Reference counted slices that share ownership of the backing storage - -``` -use rustc_data_structures::owning_ref::RcRef; -use std::rc::Rc; - -fn main() { - let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>); - assert_eq!(&*rc, &[1, 2, 3, 4]); - - let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]); - let rc_b = rc.clone().map(|s| &s[1..3]); - let rc_c = rc.clone().map(|s| &s[2..4]); - assert_eq!(&*rc_a, &[1, 2]); - assert_eq!(&*rc_b, &[2, 3]); - assert_eq!(&*rc_c, &[3, 4]); - - let rc_c_a = rc_c.clone().map(|s| &s[1]); - assert_eq!(&*rc_c_a, &4); -} -``` - -## Atomic reference counted slices that share ownership of the backing storage - -``` -use rustc_data_structures::owning_ref::ArcRef; -use std::sync::Arc; - -fn main() { - use std::thread; - - fn par_sum(rc: ArcRef<[i32]>) -> i32 { - if rc.len() == 0 { - return 0; - } else if rc.len() == 1 { - return rc[0]; - } - let mid = rc.len() / 2; - let left = rc.clone().map(|s| &s[..mid]); - let right = rc.map(|s| &s[mid..]); - - let left = thread::spawn(move || par_sum(left)); - let right = thread::spawn(move || par_sum(right)); - - left.join().unwrap() + right.join().unwrap() - } - - let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]); - let rc: ArcRef<[i32]> = rc.into(); - - assert_eq!(par_sum(rc), 10); -} -``` - -## References into RAII locks - -``` -use rustc_data_structures::owning_ref::RefRef; -use std::cell::{RefCell, Ref}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - // Also works with Mutex and RwLock - - let refref = { - let refref = RefRef::new(refcell.borrow()).map(|x| &x.3); - assert_eq!(*refref, 4); - - // We move the RAII lock and the reference to one of - // the subfields in the data it guards here: - refref - }; - - assert_eq!(*refref, 4); - - drop(refref); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 4)); -} -``` - -## Mutable reference - -When the owned container implements `DerefMut`, it is also possible to make -a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`) - -``` -use rustc_data_structures::owning_ref::RefMutRefMut; -use std::cell::{RefCell, RefMut}; - -fn main() { - let refcell = RefCell::new((1, 2, 3, 4)); - - let mut refmut_refmut = { - let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3); - assert_eq!(*refmut_refmut, 4); - *refmut_refmut *= 2; - - refmut_refmut - }; - - assert_eq!(*refmut_refmut, 8); - *refmut_refmut *= 2; - - drop(refmut_refmut); - - assert_eq!(*refcell.borrow(), (1, 2, 3, 16)); -} -``` -*/ - -pub use stable_deref_trait::{ - CloneStableDeref as CloneStableAddress, StableDeref as StableAddress, -}; -use std::mem; - -/// An owning reference. -/// -/// This wraps an owner `O` and a reference `&T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRef<O, T: ?Sized> { - owner: O, - reference: *const T, -} - -/// An mutable owning reference. -/// -/// This wraps an owner `O` and a reference `&mut T` pointing -/// at something reachable from `O::Target` while keeping -/// the ability to move `self` around. -/// -/// The owner is usually a pointer that points at some base type. -/// -/// For more details and examples, see the module and method docs. -pub struct OwningRefMut<O, T: ?Sized> { - owner: O, - reference: *mut T, -} - -/// Helper trait for an erased concrete type an owner dereferences to. -/// This is used in form of a trait object for keeping -/// something around to (virtually) call the destructor. -pub trait Erased {} -impl<T> Erased for T {} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box<T> -> Box<Erased>`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErased<'a> { - /// Owner with the dereference type substituted to `Erased`. - type Erased; - /// Performs the type erasure. - fn into_erased(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box<T> -> Box<Erased + Send>`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSend<'a> { - /// Owner with the dereference type substituted to `Erased + Send`. - type Erased: Send; - /// Performs the type erasure. - fn into_erased_send(self) -> Self::Erased; -} - -/// Helper trait for erasing the concrete type of what an owner dereferences to, -/// for example `Box<T> -> Box<Erased + Send + Sync>`. This would be unneeded with -/// higher kinded types support in the language. -#[allow(unused_lifetimes)] -pub unsafe trait IntoErasedSendSync<'a> { - /// Owner with the dereference type substituted to `Erased + Send + Sync`. - type Erased: Send + Sync; - /// Performs the type erasure. - fn into_erased_send_sync(self) -> Self::Erased; -} - -///////////////////////////////////////////////////////////////////////////// -// OwningRef -///////////////////////////////////////////////////////////////////////////// - -impl<O, T: ?Sized> OwningRef<O, T> { - /// Creates a new owning reference from an owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new(42)); - /// assert_eq!(*owning_ref, 42); - /// } - /// ``` - pub fn new(o: O) -> Self - where - O: StableAddress, - O: Deref<Target = T>, - { - OwningRef { reference: &*o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(o: O) -> Self - where - O: Deref<Target = T>, - { - OwningRef { reference: &*o, owner: o } - } - - /// Converts `self` into a new owning reference that points at something reachable - /// from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U> - where - O: StableAddress, - F: FnOnce(&T) -> &U, - { - OwningRef { reference: f(&self), owner: self.owner } - } - - /// Tries to convert `self` into a new owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRef; - /// - /// fn main() { - /// let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map<F, U: ?Sized, E>(self, f: F) -> Result<OwningRef<O, U>, E> - where - O: StableAddress, - F: FnOnce(&T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRef<P, T> - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRef { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box<O>`. - /// - /// This can be used to safely erase the owner of any `OwningRef<O, T>` - /// to an `OwningRef<Box<Erased>, T>`. - pub fn map_owner_box(self) -> OwningRef<Box<O>, T> { - OwningRef { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::{OwningRef, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_a: OwningRef<Box<[i32; 4]>, [i32; 4]> - /// = OwningRef::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>> - /// = OwningRef::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_a: OwningRef<Box<[i32; 4]>, i32> - /// = owning_ref_a.map(|a| &a[0]); - /// - /// let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, i32> - /// = owning_ref_b.map(|a| &a[1].0); - /// - /// let owning_refs: [OwningRef<Box<dyn Erased>, i32>; 2] - /// = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs[0], 1); - /// assert_eq!(*owning_refs[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRef<O::Erased, T> - where - O: IntoErased<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased() } - } - - /// Erases the concrete base type of the owner with a trait object which implements `Send`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T> - where - O: IntoErasedSend<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send() } - } - - /// Erases the concrete base type of the owner with a trait object - /// which implements `Send` and `Sync`. - /// - /// This allows mixing of owned references with different owner base types. - pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T> - where - O: IntoErasedSendSync<'a>, - { - OwningRef { reference: self.reference, owner: self.owner.into_erased_send_sync() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -impl<O, T: ?Sized> OwningRefMut<O, T> { - /// Creates a new owning reference from an owner - /// initialized to the direct dereference of it. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new(42)); - /// assert_eq!(*owning_ref_mut, 42); - /// } - /// ``` - pub fn new(mut o: O) -> Self - where - O: StableAddress, - O: DerefMut<Target = T>, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait. - /// Instead, the caller is responsible to make the same promises as implementing the trait. - /// - /// This is useful for cases where coherence rules prevents implementing the trait - /// without adding a dependency to this crate in a third-party library. - pub unsafe fn new_assert_stable_address(mut o: O) -> Self - where - O: DerefMut<Target = T>, - { - OwningRefMut { reference: &mut *o, owner: o } - } - - /// Converts `self` into a new _shared_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.map(|array| &array[2]); - /// assert_eq!(*owning_ref, 3); - /// } - /// ``` - pub fn map<F, U: ?Sized>(mut self, f: F) -> OwningRef<O, U> - where - O: StableAddress, - F: FnOnce(&mut T) -> &U, - { - OwningRef { reference: f(&mut self), owner: self.owner } - } - - /// Converts `self` into a new _mutable_ owning reference that points at - /// something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]); - /// assert_eq!(*owning_ref_mut, 3); - /// } - /// ``` - pub fn map_mut<F, U: ?Sized>(mut self, f: F) -> OwningRefMut<O, U> - where - O: StableAddress, - F: FnOnce(&mut T) -> &mut U, - { - OwningRefMut { reference: f(&mut self), owner: self.owner } - } - - /// Tries to convert `self` into a new _shared_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref = owning_ref_mut.try_map(|array| { - /// if array[2] == 3 { Ok(&array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref.unwrap(), 3); - /// } - /// ``` - pub fn try_map<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRef<O, U>, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&U, E>, - { - Ok(OwningRef { reference: f(&mut self)?, owner: self.owner }) - } - - /// Tries to convert `self` into a new _mutable_ owning reference that points - /// at something reachable from the previous one. - /// - /// This can be a reference to a field of `U`, something reachable from a field of - /// `U`, or even something unrelated with a `'static` lifetime. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::OwningRefMut; - /// - /// fn main() { - /// let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// // create an owning reference that points at the - /// // third element of the array. - /// let owning_ref_mut = owning_ref_mut.try_map_mut(|array| { - /// if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) } - /// }); - /// assert_eq!(*owning_ref_mut.unwrap(), 3); - /// } - /// ``` - pub fn try_map_mut<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRefMut<O, U>, E> - where - O: StableAddress, - F: FnOnce(&mut T) -> Result<&mut U, E>, - { - Ok(OwningRefMut { reference: f(&mut self)?, owner: self.owner }) - } - - /// Converts `self` into a new owning reference with a different owner type. - /// - /// The new owner type needs to still contain the original owner in some way - /// so that the reference into it remains valid. This function is marked unsafe - /// because the user needs to manually uphold this guarantee. - pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRefMut<P, T> - where - O: StableAddress, - P: StableAddress, - F: FnOnce(O) -> P, - { - OwningRefMut { reference: self.reference, owner: f(self.owner) } - } - - /// Converts `self` into a new owning reference where the owner is wrapped - /// in an additional `Box<O>`. - /// - /// This can be used to safely erase the owner of any `OwningRefMut<O, T>` - /// to an `OwningRefMut<Box<Erased>, T>`. - pub fn map_owner_box(self) -> OwningRefMut<Box<O>, T> { - OwningRefMut { reference: self.reference, owner: Box::new(self.owner) } - } - - /// Erases the concrete base type of the owner with a trait object. - /// - /// This allows mixing of owned references with different owner base types. - /// - /// # Example - /// ``` - /// use rustc_data_structures::owning_ref::{OwningRefMut, Erased}; - /// - /// fn main() { - /// // N.B., using the concrete types here for explicitness. - /// // For less verbose code type aliases like `BoxRef` are provided. - /// - /// let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, [i32; 4]> - /// = OwningRefMut::new(Box::new([1, 2, 3, 4])); - /// - /// let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>> - /// = OwningRefMut::new(Box::new(vec![(0, false), (1, true)])); - /// - /// let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, i32> - /// = owning_ref_mut_a.map_mut(|a| &mut a[0]); - /// - /// let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, i32> - /// = owning_ref_mut_b.map_mut(|a| &mut a[1].0); - /// - /// let owning_refs_mut: [OwningRefMut<Box<dyn Erased>, i32>; 2] - /// = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()]; - /// - /// assert_eq!(*owning_refs_mut[0], 1); - /// assert_eq!(*owning_refs_mut[1], 1); - /// } - /// ``` - pub fn erase_owner<'a>(self) -> OwningRefMut<O::Erased, T> - where - O: IntoErased<'a>, - { - OwningRefMut { reference: self.reference, owner: self.owner.into_erased() } - } - - // UNIMPLEMENTED: wrap_owner - - // FIXME: Naming convention? - /// A getter for the underlying owner. - pub fn owner(&self) -> &O { - &self.owner - } - - // FIXME: Naming convention? - /// Discards the reference and retrieves the owner. - pub fn into_inner(self) -> O { - self.owner - } -} - -///////////////////////////////////////////////////////////////////////////// -// OwningHandle -///////////////////////////////////////////////////////////////////////////// - -use std::ops::{Deref, DerefMut}; - -/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows -/// consumers to pass around an owned object and a dependent reference, -/// `OwningHandle` contains an owned object and a dependent _object_. -/// -/// `OwningHandle` can encapsulate a `RefMut` along with its associated -/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. -/// However, the API is completely generic and there are no restrictions on -/// what types of owning and dependent objects may be used. -/// -/// `OwningHandle` is created by passing an owner object (which dereferences -/// to a stable address) along with a callback which receives a pointer to -/// that stable location. The callback may then dereference the pointer and -/// mint a dependent object, with the guarantee that the returned object will -/// not outlive the referent of the pointer. -/// -/// Since the callback needs to dereference a raw pointer, it requires `unsafe` -/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is -/// implemented for common data structures. Types that implement `ToHandle` can -/// be wrapped into an `OwningHandle` without passing a callback. -pub struct OwningHandle<O, H> -where - O: StableAddress, - H: Deref, -{ - handle: H, - _owner: O, -} - -impl<O, H> Deref for OwningHandle<O, H> -where - O: StableAddress, - H: Deref, -{ - type Target = H::Target; - fn deref(&self) -> &H::Target { - self.handle.deref() - } -} - -unsafe impl<O, H> StableAddress for OwningHandle<O, H> -where - O: StableAddress, - H: StableAddress, -{ -} - -impl<O, H> DerefMut for OwningHandle<O, H> -where - O: StableAddress, - H: DerefMut, -{ - fn deref_mut(&mut self) -> &mut H::Target { - self.handle.deref_mut() - } -} - -/// Trait to implement the conversion of owner to handle for common types. -pub trait ToHandle { - /// The type of handle to be encapsulated by the OwningHandle. - type Handle: Deref; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle(x: *const Self) -> Self::Handle; -} - -/// Trait to implement the conversion of owner to mutable handle for common types. -pub trait ToHandleMut { - /// The type of handle to be encapsulated by the OwningHandle. - type HandleMut: DerefMut; - - /// Given an appropriately-long-lived pointer to ourselves, create a - /// mutable handle to be encapsulated by the `OwningHandle`. - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut; -} - -impl<O, H> OwningHandle<O, H> -where - O: StableAddress<Target: ToHandle<Handle = H>>, - H: Deref, -{ - /// Creates a new `OwningHandle` for a type that implements `ToHandle`. For types - /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts - /// a callback to perform the conversion. - pub fn new(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) }) - } -} - -impl<O, H> OwningHandle<O, H> -where - O: StableAddress<Target: ToHandleMut<HandleMut = H>>, - H: DerefMut, -{ - /// Creates a new mutable `OwningHandle` for a type that implements `ToHandleMut`. - pub fn new_mut(o: O) -> Self { - OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) }) - } -} - -impl<O, H> OwningHandle<O, H> -where - O: StableAddress, - H: Deref, -{ - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn new_with_fn<F>(o: O, f: F) -> Self - where - F: FnOnce(*const O::Target) -> H, - { - let h: H; - { - h = f(o.deref() as *const O::Target); - } - - OwningHandle { handle: h, _owner: o } - } - - /// Creates a new OwningHandle. The provided callback will be invoked with - /// a pointer to the object owned by `o`, and the returned value is stored - /// as the object to which this `OwningHandle` will forward `Deref` and - /// `DerefMut`. - pub fn try_new<F, E>(o: O, f: F) -> Result<Self, E> - where - F: FnOnce(*const O::Target) -> Result<H, E>, - { - let h: H; - { - h = f(o.deref() as *const O::Target)?; - } - - Ok(OwningHandle { handle: h, _owner: o }) - } -} - -///////////////////////////////////////////////////////////////////////////// -// std traits -///////////////////////////////////////////////////////////////////////////// - -use std::borrow::Borrow; -use std::cmp::Ordering; -use std::fmt::{self, Debug}; -use std::hash::{Hash, Hasher}; - -impl<O, T: ?Sized> Deref for OwningRef<O, T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl<O, T: ?Sized> Deref for OwningRefMut<O, T> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.reference } - } -} - -impl<O, T: ?Sized> DerefMut for OwningRefMut<O, T> { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.reference } - } -} - -unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {} - -impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> { - fn as_ref(&self) -> &T { - self - } -} - -impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> { - fn as_ref(&self) -> &T { - self - } -} - -impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> { - fn as_mut(&mut self) -> &mut T { - self - } -} - -impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> { - fn borrow(&self) -> &T { - self - } -} - -impl<O, T: ?Sized> From<O> for OwningRef<O, T> -where - O: StableAddress, - O: Deref<Target = T>, -{ - fn from(owner: O) -> Self { - OwningRef::new(owner) - } -} - -impl<O, T: ?Sized> From<O> for OwningRefMut<O, T> -where - O: StableAddress, - O: DerefMut<Target = T>, -{ - fn from(owner: O) -> Self { - OwningRefMut::new(owner) - } -} - -impl<O, T: ?Sized> From<OwningRefMut<O, T>> for OwningRef<O, T> -where - O: StableAddress, - O: DerefMut<Target = T>, -{ - fn from(other: OwningRefMut<O, T>) -> Self { - OwningRef { owner: other.owner, reference: other.reference } - } -} - -// ^ FIXME: Is an Into impl for calling into_inner() possible as well? - -impl<O, T: ?Sized> Debug for OwningRef<O, T> -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl<O, T: ?Sized> Debug for OwningRefMut<O, T> -where - O: Debug, - T: Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self) - } -} - -impl<O, T: ?Sized> Clone for OwningRef<O, T> -where - O: CloneStableAddress, -{ - fn clone(&self) -> Self { - OwningRef { owner: self.owner.clone(), reference: self.reference } - } -} - -unsafe impl<O, T: ?Sized> CloneStableAddress for OwningRef<O, T> where O: CloneStableAddress {} - -unsafe impl<O, T: ?Sized> Send for OwningRef<O, T> -where - O: Send, - for<'a> &'a T: Send, -{ -} -unsafe impl<O, T: ?Sized> Sync for OwningRef<O, T> -where - O: Sync, - for<'a> &'a T: Sync, -{ -} - -unsafe impl<O, T: ?Sized> Send for OwningRefMut<O, T> -where - O: Send, - for<'a> &'a mut T: Send, -{ -} -unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T> -where - O: Sync, - for<'a> &'a mut T: Sync, -{ -} - -impl Debug for dyn Erased { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "<Erased>",) - } -} - -impl<O, T: ?Sized> PartialEq for OwningRef<O, T> -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - self.deref().eq(other.deref()) - } -} - -impl<O, T: ?Sized> Eq for OwningRef<O, T> where T: Eq {} - -impl<O, T: ?Sized> PartialOrd for OwningRef<O, T> -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.deref().partial_cmp(other.deref()) - } -} - -impl<O, T: ?Sized> Ord for OwningRef<O, T> -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.deref().cmp(other.deref()) - } -} - -impl<O, T: ?Sized> Hash for OwningRef<O, T> -where - T: Hash, -{ - fn hash<H: Hasher>(&self, state: &mut H) { - self.deref().hash(state); - } -} - -impl<O, T: ?Sized> PartialEq for OwningRefMut<O, T> -where - T: PartialEq, -{ - fn eq(&self, other: &Self) -> bool { - self.deref().eq(other.deref()) - } -} - -impl<O, T: ?Sized> Eq for OwningRefMut<O, T> where T: Eq {} - -impl<O, T: ?Sized> PartialOrd for OwningRefMut<O, T> -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.deref().partial_cmp(other.deref()) - } -} - -impl<O, T: ?Sized> Ord for OwningRefMut<O, T> -where - T: Ord, -{ - fn cmp(&self, other: &Self) -> Ordering { - self.deref().cmp(other.deref()) - } -} - -impl<O, T: ?Sized> Hash for OwningRefMut<O, T> -where - T: Hash, -{ - fn hash<H: Hasher>(&self, state: &mut H) { - self.deref().hash(state); - } -} - -///////////////////////////////////////////////////////////////////////////// -// std types integration and convenience type defs -///////////////////////////////////////////////////////////////////////////// - -use std::cell::{Ref, RefCell, RefMut}; -use std::rc::Rc; -use std::sync::Arc; -use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard}; - -impl<T: 'static> ToHandle for RefCell<T> { - type Handle = Ref<'static, T>; - unsafe fn to_handle(x: *const Self) -> Self::Handle { - (*x).borrow() - } -} - -impl<T: 'static> ToHandleMut for RefCell<T> { - type HandleMut = RefMut<'static, T>; - unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut { - (*x).borrow_mut() - } -} - -// N.B., implementing ToHandle{,Mut} for Mutex and RwLock requires a decision -// about which handle creation to use (i.e., read() vs try_read()) as well as -// what to do with error results. - -/// Typedef of an owning reference that uses a `Box` as the owner. -pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>; -/// Typedef of an owning reference that uses a `Vec` as the owner. -pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>; -/// Typedef of an owning reference that uses a `String` as the owner. -pub type StringRef = OwningRef<String, str>; - -/// Typedef of an owning reference that uses an `Rc` as the owner. -pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>; -/// Typedef of an owning reference that uses an `Arc` as the owner. -pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>; - -/// Typedef of an owning reference that uses a `Ref` as the owner. -pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>; -/// Typedef of an owning reference that uses a `RefMut` as the owner. -pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>; -/// Typedef of an owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>; -/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner. -pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>; -/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>; - -/// Typedef of a mutable owning reference that uses a `Box` as the owner. -pub type BoxRefMut<T, U = T> = OwningRefMut<Box<T>, U>; -/// Typedef of a mutable owning reference that uses a `Vec` as the owner. -pub type VecRefMut<T, U = T> = OwningRefMut<Vec<T>, U>; -/// Typedef of a mutable owning reference that uses a `String` as the owner. -pub type StringRefMut = OwningRefMut<String, str>; - -/// Typedef of a mutable owning reference that uses a `RefMut` as the owner. -pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>; -/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner. -pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>; -/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner. -pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>; - -unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> { - type Erased = Box<dyn Erased + 'a>; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Rc<T> { - type Erased = Rc<dyn Erased + 'a>; - fn into_erased(self) -> Self::Erased { - self - } -} -unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> { - type Erased = Arc<dyn Erased + 'a>; - fn into_erased(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> { - type Erased = Box<dyn Erased + Send + 'a>; - fn into_erased_send(self) -> Self::Erased { - self - } -} - -unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> { - type Erased = Box<dyn Erased + Sync + Send + 'a>; - fn into_erased_send_sync(self) -> Self::Erased { - let result: Box<dyn Erased + Send + 'a> = self; - // This is safe since Erased can always implement Sync - // Only the destructor is available and it takes &mut self - unsafe { mem::transmute(result) } - } -} - -unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> { - type Erased = Arc<dyn Erased + Send + Sync + 'a>; - fn into_erased_send_sync(self) -> Self::Erased { - self - } -} - -/// Typedef of an owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRef<U> = OwningRef<Box<dyn Erased>, U>; -/// Typedef of an owning reference that uses an erased `Rc` as the owner. -pub type ErasedRcRef<U> = OwningRef<Rc<dyn Erased>, U>; -/// Typedef of an owning reference that uses an erased `Arc` as the owner. -pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>; - -/// Typedef of a mutable owning reference that uses an erased `Box` as the owner. -pub type ErasedBoxRefMut<U> = OwningRefMut<Box<dyn Erased>, U>; - -#[cfg(test)] -mod tests; diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs deleted file mode 100644 index a9b187c4ce0..00000000000 --- a/compiler/rustc_data_structures/src/owning_ref/tests.rs +++ /dev/null @@ -1,711 +0,0 @@ -// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. -#[cfg(not(miri))] -mod owning_ref { - use super::super::OwningRef; - use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; - use std::cmp::Ordering; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - use std::rc::Rc; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn into() { - let or: OwningRef<Box<()>, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &x.0); - assert_eq!(&*or, &42); - - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRef<Example> = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRef<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_chained() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or: BoxRef<_, str> = or.map(|x| &x[1..5]); - let or: BoxRef<_, str> = or.map(|x| &x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRef::new(Box::new(example().1)).map(|x| &x[..5]).map(|x| &x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn owner() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRef<String> = Box::new(example().1).into(); - let or = or.map(|x| &x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example())).map(|x| &x.1[..]); - - let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1)).map(|x| &x[..]); - - let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef}; - use super::super::{RefMutRef, RefRef}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefRef::new(a.borrow()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RefCell::new(1); - let a = { - let a = RefMutRef::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRef::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockReadGuardRef::new(a.read().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRef::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key = RcRef::<String>::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]); - - hash.insert(key.clone().map(|s| &s[..3]), 42); - hash.insert(key.clone().map(|s| &s[4..]), 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRef<Vec<u8>, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef<Box<[u8]>, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe { a.map_owner(Rc::new) }; - let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe { b.map_owner(Rc::new) }; - - let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner(); - let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner(); - - let _g = e.clone(); - let _h = f.clone(); - } - - #[test] - fn total_erase_box() { - let a: OwningRef<Vec<u8>, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]); - let b: OwningRef<Box<[u8]>, [u8]> = - OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]); - - let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box(); - let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); - - let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); - } -} - -mod owning_handle { - use super::super::OwningHandle; - use super::super::RcRef; - use std::cell::RefCell; - use std::rc::Rc; - use std::sync::Arc; - use std::sync::RwLock; - - #[test] - fn owning_handle() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = - OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_ok() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()) - }) - .unwrap(); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn try_owning_handle_err() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| { - if false { - return Ok(unsafe { x.as_ref() }.unwrap().borrow_mut()); - } - Err(()) - }); - assert!(handle.is_err()); - } - - #[test] - fn nested() { - use std::cell::RefCell; - use std::sync::{Arc, RwLock}; - - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } - - #[test] - fn owning_handle_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let handle = OwningHandle::new(cell_ref); - assert_eq!(*handle, 2); - } - - #[test] - fn owning_handle_mut_safe() { - use std::cell::RefCell; - let cell = Rc::new(RefCell::new(2)); - let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_mut(cell_ref); - assert_eq!(*handle, 2); - *handle = 3; - assert_eq!(*handle, 3); - } - - #[test] - fn owning_handle_safe_2() { - let result = { - let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); - let curr = RcRef::new(complex); - let curr = - OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| { - unsafe { x.as_ref() }.unwrap().try_write().unwrap() - }); - assert_eq!(*curr, "someString"); - *curr = "someOtherString"; - curr - }; - assert_eq!(*result, "someOtherString"); - } -} - -// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. -#[cfg(not(miri))] -mod owning_ref_mut { - use super::super::BoxRef; - use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; - use std::cmp::Ordering; - use std::collections::hash_map::DefaultHasher; - use std::collections::HashMap; - use std::hash::{Hash, Hasher}; - - #[derive(Debug, PartialEq)] - struct Example(u32, String, [u8; 3]); - fn example() -> Example { - Example(42, "hello world".to_string(), [1, 2, 3]) - } - - #[test] - fn new_deref() { - let or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&*or, &()); - } - - #[test] - fn new_deref_mut() { - let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(())); - assert_eq!(&mut *or, &mut ()); - } - - #[test] - fn mutate() { - let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0)); - assert_eq!(&*or, &0); - *or = 1; - assert_eq!(&*or, &1); - } - - #[test] - fn into() { - let or: OwningRefMut<Box<()>, ()> = Box::new(()).into(); - assert_eq!(&*or, &()); - } - - #[test] - fn map_offset_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, u32> = or.map(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_heap_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_static_ref() { - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<_, str> = or.map(|_| "hello"); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_offset_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0); - assert_eq!(&*or, &42); - - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]); - assert_eq!(&*or, &2); - } - - #[test] - fn map_mut_heap_ref() { - let or: BoxRefMut<Example> = Box::new(example()).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]); - assert_eq!(&*or, "hello"); - } - - #[test] - fn map_mut_static_ref() { - static mut MUT_S: [u8; 5] = *b"hello"; - - let mut_s: &'static mut [u8] = unsafe { &mut MUT_S }; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s); - assert_eq!(&*or, b"hello"); - } - - #[test] - fn map_mut_chained() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]); - let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]); - assert_eq!(&*or, "el"); - } - - #[test] - fn map_chained_inference() { - let or = BoxRefMut::new(Box::new(example().1)) - .map_mut(|x| &mut x[..5]) - .map_mut(|x| &mut x[1..3]); - assert_eq!(&*or, "el"); - } - - #[test] - fn try_map_mut() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5])); - assert_eq!(&*or.unwrap(), "ello"); - - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(())); - assert!(or.is_err()); - } - - #[test] - fn owner() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - assert_eq!(&**or.owner(), "hello world"); - } - - #[test] - fn into_inner() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - assert_eq!(&*or, "hello"); - let s = *or.into_inner(); - assert_eq!(&s, "hello world"); - } - - #[test] - fn fmt_debug() { - let or: BoxRefMut<String> = Box::new(example().1).into(); - let or = or.map_mut(|x| &mut x[..5]); - let s = format!("{:?}", or); - assert_eq!(&s, "OwningRefMut { owner: \"hello world\", reference: \"hello\" }"); - } - - #[test] - fn erased_owner() { - let o1: BoxRefMut<Example, str> = - BoxRefMut::new(Box::new(example())).map_mut(|x| &mut x.1[..]); - - let o2: BoxRefMut<String, str> = - BoxRefMut::new(Box::new(example().1)).map_mut(|x| &mut x[..]); - - let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()]; - assert!(os.iter().all(|e| &e[..] == "hello world")); - } - - #[test] - fn raii_locks() { - use super::super::RefMutRefMut; - use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut}; - use std::cell::RefCell; - use std::sync::{Mutex, RwLock}; - - { - let a = RefCell::new(1); - let a = { - let a = RefMutRefMut::new(a.borrow_mut()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = Mutex::new(1); - let a = { - let a = MutexGuardRefMut::new(a.lock().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - { - let a = RwLock::new(1); - let a = { - let a = RwLockWriteGuardRefMut::new(a.write().unwrap()); - assert_eq!(*a, 1); - a - }; - assert_eq!(*a, 1); - drop(a); - } - } - - #[test] - fn eq() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.eq(&or2), true); - } - - #[test] - fn cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - assert_eq!(or1.cmp(&or2), Ordering::Less); - } - - #[test] - fn partial_cmp() { - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater)); - } - - #[test] - fn hash() { - let mut h1 = DefaultHasher::new(); - let mut h2 = DefaultHasher::new(); - - let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice()); - - or1.hash(&mut h1); - or2.hash(&mut h2); - - assert_eq!(h1.finish(), h2.finish()); - } - - #[test] - fn borrow() { - let mut hash = HashMap::new(); - let key1 = BoxRefMut::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]); - let key2 = BoxRefMut::<String>::new(Box::new("bar".to_string())).map(|s| &s[..]); - - hash.insert(key1, 42); - hash.insert(key2, 23); - - assert_eq!(hash.get("foo"), Some(&42)); - assert_eq!(hash.get("bar"), Some(&23)); - } - - #[test] - fn total_erase() { - let a: OwningRefMut<Vec<u8>, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut<Box<[u8]>, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe { a.map_owner(Box::new) }; - let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe { b.map_owner(Box::new) }; - - let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn total_erase_box() { - let a: OwningRefMut<Vec<u8>, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]); - let b: OwningRefMut<Box<[u8]>, [u8]> = - OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]); - - let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box(); - let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box(); - - let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner(); - let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner(); - } - - #[test] - fn try_map1() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map2() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_err()); - } - - #[test] - fn try_map3() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok()); - } - - #[test] - fn try_map4() { - use std::any::Any; - - let x = Box::new(123_i32); - let y: Box<dyn Any> = x; - - assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err()); - } - - #[test] - fn into_owning_ref() { - use super::super::BoxRef; - - let or: BoxRefMut<()> = Box::new(()).into(); - let or: BoxRef<()> = or.into(); - assert_eq!(&*or, &()); - } - - struct Foo { - u: u32, - } - struct Bar { - f: Foo, - } - - #[test] - fn ref_mut() { - use std::cell::RefCell; - - let a = RefCell::new(Bar { f: Foo { u: 42 } }); - let mut b = OwningRefMut::new(a.borrow_mut()); - assert_eq!(b.f.u, 42); - b.f.u = 43; - let mut c = b.map_mut(|x| &mut x.f); - assert_eq!(c.u, 43); - c.u = 44; - let mut d = c.map_mut(|x| &mut x.u); - assert_eq!(*d, 44); - *d = 45; - assert_eq!(*d, 45); - } -} diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index e8ee4fb76cc..ef1da85198f 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -7,9 +7,6 @@ //! while the serial versions degenerate straightforwardly to serial execution. //! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`. //! -//! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the -//! serial version and `Erased + Send + Sync` for the parallel version. -//! //! Types //! ----- //! The parallel versions of types provide various kinds of synchronization, @@ -42,7 +39,7 @@ //! //! [^2] `MTLockRef` is a typedef. -use crate::owning_ref::{Erased, OwningRef}; +use crate::owned_slice::OwnedSlice; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use std::ops::{Deref, DerefMut}; @@ -57,18 +54,11 @@ mod vec; cfg_if! { if #[cfg(not(parallel_compiler))] { - pub auto trait Send {} - pub auto trait Sync {} - - impl<T> Send for T {} - impl<T> Sync for T {} + pub unsafe auto trait Send {} + pub unsafe auto trait Sync {} - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => { - $v.erase_owner() - } - } + unsafe impl<T> Send for T {} + unsafe impl<T> Sync for T {} use std::ops::Add; @@ -197,7 +187,7 @@ cfg_if! { } } - pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>; + pub type MetadataRef = OwnedSlice; pub use std::rc::Rc as Lrc; pub use std::rc::Weak as Weak; @@ -380,20 +370,11 @@ cfg_if! { }); } - pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>; + pub type MetadataRef = OwnedSlice; /// This makes locks panic if they are already held. /// It is only useful when you are running in a single thread const ERROR_CHECKING: bool = false; - - #[macro_export] - macro_rules! rustc_erase_owner { - ($v:expr) => {{ - let v = $v; - ::rustc_data_structures::sync::assert_send_val(&v); - v.erase_send_sync_owner() - }} - } } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 84114b27f41..426c6727adc 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -518,6 +518,8 @@ declare_features! ( /// Allows dyn upcasting trait objects via supertraits. /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. (active, trait_upcasting, "1.56.0", Some(65991), None), + /// Allows for transmuting between arrays with sizes that contain generic consts. + (active, transmute_generic_consts, "CURRENT_RUSTC_VERSION", Some(109929), None), /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), /// Allows inconsistent bounds in where clauses. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6727173cd88..acca3fa2641 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2336,10 +2336,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { FnMutDelegate { regions: &mut |_| tcx.lifetimes.re_erased, types: &mut |bv| { - tcx.mk_placeholder(ty::PlaceholderType { universe, name: bv.kind }) + tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv }) }, consts: &mut |bv, ty| { - tcx.mk_const(ty::PlaceholderConst { universe, name: bv }, ty) + tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty) }, }, ); @@ -2525,11 +2525,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { regions: &mut |_| tcx.lifetimes.re_erased, types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType { universe, - name: bv.kind, + bound: bv, }), consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst { universe, - name: bv + bound: bv, }, ty), }) ) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 1b7475486dc..854974d1605 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -139,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { let name_str = intrinsic_name.as_str(); let bound_vars = tcx.mk_bound_variable_kinds(&[ - ty::BoundVariableKind::Region(ty::BrAnon(0, None)), + ty::BoundVariableKind::Region(ty::BrAnon(None)), ty::BoundVariableKind::Region(ty::BrEnv), ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { let region = tcx.mk_re_late_bound( ty::INNERMOST, - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }, + ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }, ); let env_region = tcx.mk_re_late_bound( ty::INNERMOST, @@ -387,8 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ); let discriminant_def_id = assoc_items[0]; - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; ( 1, vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))], @@ -440,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), sym::raw_eq => { - let br = - ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) }; + let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) }; let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0)); (1, vec![param_ty; 2], tcx.types.bool) } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2a9025d60ab..27e56180349 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -70,7 +70,6 @@ This API is completely unstable and subject to change. #![feature(lazy_cell)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] -#![feature(is_some_and)] #![feature(type_alias_impl_trait)] #![recursion_limit = "256"] diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 9ecc870a70d..84ed8f3780e 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -240,7 +240,7 @@ pub fn resolve_interior<'a, 'tcx>( let mut counter = 0; let mut mk_bound_region = |span| { - let kind = ty::BrAnon(counter, span); + let kind = ty::BrAnon(span); let var = ty::BoundVar::from_u32(counter); counter += 1; ty::BoundRegion { var, kind } @@ -263,7 +263,7 @@ pub fn resolve_interior<'a, 'tcx>( } ty::ReLateBound(_, ty::BoundRegion { kind, .. }) | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind { - ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span), + ty::BoundRegionKind::BrAnon(span) => mk_bound_region(span), ty::BoundRegionKind::BrNamed(def_id, _) => { mk_bound_region(Some(fcx.tcx.def_span(def_id))) } @@ -294,7 +294,7 @@ pub fn resolve_interior<'a, 'tcx>( FnMutDelegate { regions: &mut |br| { let kind = match br.kind { - ty::BrAnon(_, span) => ty::BrAnon(counter, span), + ty::BrAnon(span) => ty::BrAnon(span), _ => br.kind, }; let var = ty::BoundVar::from_usize(bound_vars.len()); diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 901acffe1c8..106f5bcd755 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -84,6 +84,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let skeleton_string = |ty: Ty<'tcx>, sk| match sk { Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()), Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), + Ok(SizeSkeleton::Generic(size)) => { + if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) { + format!("{size} bytes") + } else { + format!("generic size {size}") + } + } Err(LayoutError::Unknown(bad)) => { if bad == ty { "this type does not have a fixed size".to_owned() diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 15780898dc6..1e43644be89 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -30,8 +30,8 @@ infer_source_kind_subdiag_let = {$kind -> }{$x_kind -> [has_name] , where the {$prefix_kind -> *[type] type for {$prefix} - [const_with_param] the value of const parameter - [const] the value of the constant + [const_with_param] value of const parameter + [const] value of the constant } `{$arg_name}` is specified [underscore] , where the placeholders `_` are specified *[empty] {""} diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index ef543b1fb93..30f6af74b83 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -90,9 +90,8 @@ impl<'a> DescriptionCtx<'a> { }; me.span = Some(sp); } - ty::BrAnon(idx, span) => { - me.kind = "anon_num_here"; - me.num_arg = idx+1; + ty::BrAnon(span) => { + me.kind = "defined_here"; me.span = match span { Some(_) => span, None => Some(tcx.def_span(scope)), diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 3bbd01f8273..e808911a38b 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -772,7 +772,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); - let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) }; + let br = ty::BoundRegion { var, kind: ty::BrAnon(None) }; self.interner().mk_re_late_bound(self.binder_index, br) } diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index ce230afdab3..fbb2257bf67 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -125,9 +125,9 @@ impl<'tcx> InferCtxt<'tcx> { ty.into() } - CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => { + CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => { let universe_mapped = universe_map(universe); - let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, name }; + let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound }; self.tcx.mk_placeholder(placeholder_mapped).into() } @@ -138,9 +138,9 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), - CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => { + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => { let universe_mapped = universe_map(universe); - let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name }; + let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound }; self.tcx.mk_re_placeholder(placeholder_mapped).into() } @@ -152,9 +152,9 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), - CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, name }, ty) => { + CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => { let universe_mapped = universe_map(universe); - let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name }; + let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound }; self.tcx.mk_const(placeholder_mapped, ty).into() } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index c9956b60a56..86fca9797d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -170,15 +170,15 @@ fn msg_span_from_named_region<'tcx>( } ty::ReStatic => ("the static lifetime".to_owned(), alt_span), ty::RePlaceholder(ty::PlaceholderRegion { - name: ty::BoundRegionKind::BrNamed(def_id, name), + bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. }, .. }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))), ty::RePlaceholder(ty::PlaceholderRegion { - name: ty::BoundRegionKind::BrAnon(_, Some(span)), + bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. }, .. }) => (format!("the anonymous lifetime defined here"), Some(span)), ty::RePlaceholder(ty::PlaceholderRegion { - name: ty::BoundRegionKind::BrAnon(_, None), + bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. }, .. }) => (format!("an anonymous lifetime"), None), _ => bug!("{:?}", region), @@ -226,8 +226,8 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>( }; (text, sp) } - ty::BrAnon(idx, span) => ( - format!("the anonymous lifetime #{} defined here", idx + 1), + ty::BrAnon(span) => ( + "the anonymous lifetime as defined here".to_string(), match span { Some(span) => span, None => tcx.def_span(scope) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bde16fad821..d7b900ca02d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { have_turbofish, } = args; let generics = tcx.generics_of(generics_def_id); - if let Some(argument_index) = generics + if let Some(mut argument_index) = generics .own_substs(substs) .iter() .position(|&arg| self.generic_arg_contains_target(arg)) { + if generics.parent.is_none() && generics.has_self { + argument_index += 1; + } let substs = self.infcx.resolve_vars_if_possible(substs); let generic_args = &generics.own_substs_no_defaults(tcx, substs) [generics.own_counts().lifetimes..]; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs index e8d94f0c04e..8a78a1956c9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs @@ -16,22 +16,34 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { match &self.error { Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::RelateRegionParamBound(span), - Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)), - Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)), + Region(Interned( + RePlaceholder(ty::Placeholder { + bound: ty::BoundRegion { kind: sub_name, .. }, + .. + }), + _, + )), + Region(Interned( + RePlaceholder(ty::Placeholder { + bound: ty::BoundRegion { kind: sup_name, .. }, + .. + }), + _, + )), )) => { let span = *span; let (sub_span, sub_symbol) = match sub_name { ty::BrNamed(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon(_, span) => (*span, None), + ty::BrAnon(span) => (*span, None), ty::BrEnv => (None, None), }; let (sup_span, sup_symbol) = match sup_name { ty::BrNamed(def_id, symbol) => { (Some(self.tcx().def_span(def_id)), Some(symbol)) } - ty::BrAnon(_, span) => (*span, None), + ty::BrAnon(span) => (*span, None), ty::BrEnv => (None, None), }; let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index d1897cf24b4..a63cfbc919c 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -82,20 +82,20 @@ impl<'tcx> InferCtxt<'tcx> { let delegate = FnMutDelegate { regions: &mut |br: ty::BoundRegion| { - self.tcx.mk_re_placeholder(ty::PlaceholderRegion { - universe: next_universe, - name: br.kind, - }) + self.tcx + .mk_re_placeholder(ty::PlaceholderRegion { universe: next_universe, bound: br }) }, types: &mut |bound_ty: ty::BoundTy| { self.tcx.mk_placeholder(ty::PlaceholderType { universe: next_universe, - name: bound_ty.kind, + bound: bound_ty, }) }, consts: &mut |bound_var: ty::BoundVar, ty| { - self.tcx - .mk_const(ty::PlaceholderConst { universe: next_universe, name: bound_var }, ty) + self.tcx.mk_const( + ty::PlaceholderConst { universe: next_universe, bound: bound_var }, + ty, + ) }, }; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9903ffa90ba..b4f2ad0bb34 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -2130,13 +2130,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if let ty::Infer(_) = t.kind() { + let idx = { + let idx = self.idx; + self.idx += 1; + idx + }; self.tcx.mk_placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, - name: ty::BoundTyKind::Anon({ - let idx = self.idx; - self.idx += 1; - idx - }), + bound: ty::BoundTy { + var: ty::BoundVar::from_u32(idx), + kind: ty::BoundTyKind::Anon, + }, }) } else { t.super_fold_with(self) @@ -2153,7 +2157,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( self.tcx.mk_const( ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, - name: ty::BoundVar::from_u32({ + bound: ty::BoundVar::from_u32({ let idx = self.idx; self.idx += 1; idx diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 7616a996da1..9f7b26b87f4 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -296,7 +296,7 @@ where universe }); - let placeholder = ty::PlaceholderRegion { universe, name: br.kind }; + let placeholder = ty::PlaceholderRegion { universe, bound: br }; debug!(?placeholder); let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); debug!(?placeholder_reg); diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 89ada23c667..b8ba98fc0a9 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -290,9 +290,9 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> { ) -> TypeError<'tcx> { debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region); if self.overly_polymorphic { - TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region) + TypeError::RegionsOverlyPolymorphic(placeholder.bound.kind, other_region) } else { - TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region) + TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region) } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 6a2fd5aa6e6..cadb6b1e23f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -152,10 +152,6 @@ LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) { nullptr)); } -extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) { - return wrap(Type::getMetadataTy(*unwrap(C))); -} - static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { switch (Kind) { case AlwaysInline: @@ -480,11 +476,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, #endif } -extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, - size_t AsmLen) { - unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen)); -} - typedef DIBuilder *LLVMRustDIBuilderRef; template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { @@ -753,10 +744,6 @@ extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name, return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr; } -extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) { - return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD))); -} - extern "C" void LLVMRustGlobalAddMetadata( LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) { unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD)); @@ -1153,6 +1140,8 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } // LLVMArrayType function does not support 64-bit ElementCount +// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17 +// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, uint64_t ElementCount) { return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); @@ -1408,61 +1397,6 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, return true; } -extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, - LLVMValueRef ParentPad, - unsigned ArgCount, - LLVMValueRef *LLArgs, - const char *Name) { - Value **Args = unwrap(LLArgs); - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCleanupPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B, - LLVMValueRef CleanupPad, - LLVMBasicBlockRef UnwindBB) { - CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad)); - return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB))); -} - -extern "C" LLVMValueRef -LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, - unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) { - Value **Args = unwrap(LLArgs); - return wrap(unwrap(B)->CreateCatchPad( - unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name)); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B, - LLVMValueRef Pad, - LLVMBasicBlockRef BB) { - return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)), - unwrap(BB))); -} - -extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B, - LLVMValueRef ParentPad, - LLVMBasicBlockRef BB, - unsigned NumHandlers, - const char *Name) { - if (ParentPad == nullptr) { - Type *Ty = Type::getTokenTy(unwrap(B)->getContext()); - ParentPad = wrap(Constant::getNullValue(Ty)); - } - return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB), - NumHandlers, Name)); -} - -extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef, - LLVMBasicBlockRef Handler) { - Value *CatchSwitch = unwrap(CatchSwitchRef); - cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler)); -} - extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name, LLVMValueRef *Inputs, unsigned NumInputs) { @@ -1627,6 +1561,7 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMSetLinkage(V, fromRust(RustLinkage)); } +// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal, LLVMValueRef *ConstantIndices, @@ -1704,12 +1639,6 @@ extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) { return toRust(LLVMGetVisibility(V)); } -// Oh hey, a binding that makes sense for once? (because LLVM’s own do not) -extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val, - LLVMTypeRef DestTy, bool isSigned) { - return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, "")); -} - extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMRustVisibility RustVisibility) { LLVMSetVisibility(V, fromRust(RustVisibility)); diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index 547c8debb50..745983e7e86 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -10,8 +10,8 @@ proc-macro = true annotate-snippets = "0.9" fluent-bundle = "0.15.2" fluent-syntax = "0.11" -synstructure = "0.12.1" -syn = { version = "1", features = ["full"] } +synstructure = "0.13.0" +syn = { version = "2", features = ["full"] } proc-macro2 = "1" quote = "1" unic-langid = { version = "0.9.0", features = ["macros"] } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 7fbe3bc2888..9b91627883a 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -1,8 +1,7 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - DiagnosticDeriveError, + span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, @@ -11,9 +10,8 @@ use crate::diagnostics::utils::{ }; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; -use syn::{ - parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, -}; +use syn::Token; +use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type}; use synstructure::{BindingInfo, Structure, VariantInfo}; /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? @@ -77,7 +75,7 @@ impl DiagnosticDeriveBuilder { match ast.data { syn::Data::Struct(..) | syn::Data::Enum(..) => (), syn::Data::Union(..) => { - span_err(span, "diagnostic derives can only be used on structs and enums"); + span_err(span, "diagnostic derives can only be used on structs and enums").emit(); } } @@ -160,8 +158,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { }; if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag { - let meta = attr.parse_meta()?; - throw_invalid_attr!(attr, &meta, |diag| diag + throw_invalid_attr!(attr, |diag| diag .help("consider creating a `Subdiagnostic` instead")); } @@ -191,71 +188,44 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(quote! {}); } - let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); - let meta = attr.parse_meta()?; - if name == "diag" { - let Meta::List(MetaList { ref nested, .. }) = meta else { - throw_invalid_attr!( - attr, - &meta - ); - }; + let mut first = true; - let mut nested_iter = nested.into_iter().peekable(); + if name == "diag" { + let mut tokens = TokenStream::new(); + attr.parse_nested_meta(|nested| { + let path = &nested.path; - match nested_iter.peek() { - Some(NestedMeta::Meta(Meta::Path(slug))) => { - self.slug.set_once(slug.clone(), slug.span().unwrap()); - nested_iter.next(); + if first && (nested.input.is_empty() || nested.input.peek(Token![,])) { + self.slug.set_once(path.clone(), path.span().unwrap()); + first = false; + return Ok(()) } - Some(NestedMeta::Meta(Meta::NameValue { .. })) => {} - Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag - .help("a diagnostic slug is required as the first argument")), - None => throw_invalid_attr!(attr, &meta, |diag| diag - .help("a diagnostic slug is required as the first argument")), - }; - // Remaining attributes are optional, only `code = ".."` at the moment. - let mut tokens = TokenStream::new(); - for nested_attr in nested_iter { - let (value, path) = match nested_attr { - NestedMeta::Meta(Meta::NameValue(MetaNameValue { - lit: syn::Lit::Str(value), - path, - .. - })) => (value, path), - NestedMeta::Meta(Meta::Path(_)) => { - invalid_nested_attr(attr, nested_attr) - .help("diagnostic slug must be the first argument") - .emit(); - continue; - } - _ => { - invalid_nested_attr(attr, nested_attr).emit(); - continue; - } + first = false; + + let Ok(nested) = nested.value() else { + span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit(); + return Ok(()) }; - let nested_name = path.segments.last().unwrap().ident.to_string(); - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - let span = value.span().unwrap(); - match nested_name.as_str() { - "code" => { - self.code.set_once((), span); - - let code = value.value(); - tokens.extend(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); - }); - } - _ => invalid_nested_attr(attr, nested_attr) - .help("only `code` is a valid nested attributes following the slug") - .emit(), + if path.is_ident("code") { + self.code.set_once((), path.span().unwrap()); + + let code = nested.parse::<syn::LitStr>()?; + tokens.extend(quote! { + #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + }); + } else { + span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit(); + + // consume the buffer so we don't have syntax errors from syn + let _ = nested.parse::<TokenStream>(); } - } + Ok(()) + })?; return Ok(tokens); } @@ -270,7 +240,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { Ok(self.add_subdiagnostic(&fn_ident, slug)) } SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { - throw_invalid_attr!(attr, &meta, |diag| diag + throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); } SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), @@ -309,7 +279,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return quote! {}; } - let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = attr.path().segments.last().unwrap().ident.to_string(); let needs_clone = name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_)); let (binding, needs_destructure) = if needs_clone { @@ -343,11 +313,10 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { binding: TokenStream, ) -> Result<TokenStream, DiagnosticDeriveError> { let diag = &self.parent.diag; - let meta = attr.parse_meta()?; - let ident = &attr.path.segments.last().unwrap().ident; + let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); - match (&meta, name.as_str()) { + match (&attr.meta, name.as_str()) { // Don't need to do anything - by virtue of the attribute existing, the // `set_arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), @@ -361,7 +330,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { }); } DiagnosticDeriveKind::LintDiagnostic => { - throw_invalid_attr!(attr, &meta, |diag| { + throw_invalid_attr!(attr, |diag| { diag.help("the `primary_span` field attribute is not valid for lint diagnostics") }) } @@ -378,26 +347,34 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(quote! { #diag.subdiagnostic(#binding); }); } } - (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => { - if nested.len() == 1 - && let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first() - && path.is_ident("eager") { - let handler = match &self.parent.kind { - DiagnosticDeriveKind::Diagnostic { handler } => handler, - DiagnosticDeriveKind::LintDiagnostic => { - throw_invalid_attr!(attr, &meta, |diag| { - diag.help("eager subdiagnostics are not supported on lints") - }) - } - }; - return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); }); - } else { - throw_invalid_attr!(attr, &meta, |diag| { - diag.help( - "`eager` is the only supported nested attribute for `subdiagnostic`", - ) - }) + (Meta::List(meta_list), "subdiagnostic") => { + let err = || { + span_err( + meta_list.span().unwrap(), + "`eager` is the only supported nested attribute for `subdiagnostic`", + ) + .emit(); + }; + + let Ok(p): Result<Path, _> = meta_list.parse_args() else { + err(); + return Ok(quote! {}); + }; + + if !p.is_ident("eager") { + err(); + return Ok(quote! {}); } + + let handler = match &self.parent.kind { + DiagnosticDeriveKind::Diagnostic { handler } => handler, + DiagnosticDeriveKind::LintDiagnostic => { + throw_invalid_attr!(attr, |diag| { + diag.help("eager subdiagnostics are not supported on lints") + }) + } + }; + return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); }); } _ => (), } @@ -432,7 +409,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { code_init, } => { if let FieldInnerTy::Vec(_) = info.ty { - throw_invalid_attr!(attr, &meta, |diag| { + throw_invalid_attr!(attr, |diag| { diag .note("`#[suggestion(...)]` applied to `Vec` field is ambiguous") .help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`") diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index 2d62d593163..b37dc826d28 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -1,7 +1,7 @@ use proc_macro::{Diagnostic, Level, MultiSpan}; use proc_macro2::TokenStream; use quote::quote; -use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta}; +use syn::{spanned::Spanned, Attribute, Error as SynError, Meta}; #[derive(Debug)] pub(crate) enum DiagnosticDeriveError { @@ -53,6 +53,7 @@ fn path_to_string(path: &syn::Path) -> String { } /// Returns an error diagnostic on span `span` with msg `msg`. +#[must_use] pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { Diagnostic::spanned(span, Level::Error, msg) } @@ -72,10 +73,10 @@ macro_rules! throw_span_err { pub(crate) use throw_span_err; /// Returns an error diagnostic for an invalid attribute. -pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { +pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic { let span = attr.span().unwrap(); - let path = path_to_string(&attr.path); - match meta { + let path = path_to_string(attr.path()); + match attr.meta { Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")), Meta::NameValue(_) => { span_err(span, &format!("`#[{path} = ...]` is not a valid attribute")) @@ -89,51 +90,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_attr { - ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }}; - ($attr:expr, $meta:expr, $f:expr) => {{ - let diag = crate::diagnostics::error::invalid_attr($attr, $meta); + ($attr:expr) => {{ throw_invalid_attr!($attr, |diag| diag) }}; + ($attr:expr, $f:expr) => {{ + let diag = crate::diagnostics::error::invalid_attr($attr); return Err(crate::diagnostics::error::_throw_err(diag, $f)); }}; } pub(crate) use throw_invalid_attr; - -/// Returns an error diagnostic for an invalid nested attribute. -pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diagnostic { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - - let span = nested.span().unwrap(); - let meta = match nested { - syn::NestedMeta::Meta(meta) => meta, - syn::NestedMeta::Lit(_) => { - return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute")); - } - }; - - let span = meta.span().unwrap(); - let path = path_to_string(meta.path()); - match meta { - Meta::NameValue(..) => { - span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute")) - } - Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")), - Meta::List(..) => { - span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute")) - } - } -} - -/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional -/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. -/// -/// For methods that return a `Result<_, DiagnosticDeriveError>`: -macro_rules! throw_invalid_nested_attr { - ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }}; - ($attr:expr, $nested_attr:expr, $f:expr) => {{ - let diag = crate::diagnostics::error::invalid_nested_attr($attr, $nested_attr); - return Err(crate::diagnostics::error::_throw_err(diag, $f)); - }}; -} - -pub(crate) use throw_invalid_nested_attr; diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 90660fc1f93..62d49c1c64e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,8 +1,7 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - DiagnosticDeriveError, + invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ build_field_mapping, is_doc_comment, new_code_ident, @@ -11,7 +10,7 @@ use crate::diagnostics::utils::{ }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::{build_suggestion_code, AllowMultipleAlternatives}; @@ -39,7 +38,8 @@ impl SubdiagnosticDeriveBuilder { span_err( span, "`#[derive(Subdiagnostic)]` can only be used on structs and enums", - ); + ) + .emit(); } } @@ -192,7 +192,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { }; let Some(slug) = slug else { - let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); throw_span_err!( @@ -265,17 +265,18 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { info: FieldInfo<'_>, clone_suggestion_code: bool, ) -> Result<TokenStream, DiagnosticDeriveError> { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path), - Meta::List(list @ MetaList { .. }) => self.generate_field_code_inner_list( + match &attr.meta { + Meta::Path(path) => { + self.generate_field_code_inner_path(kind_stats, attr, info, path.clone()) + } + Meta::List(list) => self.generate_field_code_inner_list( kind_stats, attr, info, list, clone_suggestion_code, ), - _ => throw_invalid_attr!(attr, &meta), + _ => throw_invalid_attr!(attr), } } @@ -296,7 +297,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { "skip_arg" => Ok(quote! {}), "primary_span" => { if kind_stats.has_multipart_suggestion { - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help( "multipart suggestions use one or more `#[suggestion_part]`s rather \ than one `#[primary_span]`", @@ -309,7 +310,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { // FIXME(#100717): support `Option<Span>` on `primary_span` like in the // diagnostic derive if !matches!(info.ty, FieldInnerTy::Plain(_)) { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + throw_invalid_attr!(attr, |diag| { let diag = diag.note("there must be exactly one primary span"); if kind_stats.has_normal_suggestion { @@ -335,7 +336,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); } else { - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help( "`#[suggestion_part(...)]` is only valid in multipart suggestions, \ use `#[primary_span]` instead", @@ -375,7 +376,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { span_attrs.push("primary_span") } - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help(format!( "only `{}`, `applicability` and `skip_arg` are valid field attributes", span_attrs.join(", ") @@ -394,7 +395,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { kind_stats: KindsStatistics, attr: &Attribute, info: FieldInfo<'_>, - list: MetaList, + list: &MetaList, clone_suggestion_code: bool, ) -> Result<TokenStream, DiagnosticDeriveError> { let span = attr.span().unwrap(); @@ -405,7 +406,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { match name { "suggestion_part" => { if !kind_stats.has_multipart_suggestion { - throw_invalid_attr!(attr, &Meta::List(list), |diag| { + throw_invalid_attr!(attr, |diag| { diag.help( "`#[suggestion_part(...)]` is only valid in multipart suggestions", ) @@ -417,31 +418,27 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { report_error_if_not_applied_to_span(attr, &info)?; let mut code = None; - for nested_attr in list.nested.iter() { - let NestedMeta::Meta(ref meta) = nested_attr else { - throw_invalid_nested_attr!(attr, nested_attr); - }; - - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - - match nested_name { - "code" => { - let code_field = new_code_ident(); - let formatting_init = build_suggestion_code( - &code_field, - meta, - self, - AllowMultipleAlternatives::No, - ); - code.set_once((code_field, formatting_init), span); - } - _ => throw_invalid_nested_attr!(attr, nested_attr, |diag| { - diag.help("`code` is the only valid nested attribute") - }), + + list.parse_nested_meta(|nested| { + if nested.path.is_ident("code") { + let code_field = new_code_ident(); + let span = nested.path.span().unwrap(); + let formatting_init = build_suggestion_code( + &code_field, + nested, + self, + AllowMultipleAlternatives::No, + ); + code.set_once((code_field, formatting_init), span); + } else { + span_err( + nested.path.span().unwrap(), + "`code` is the only valid nested attribute", + ) + .emit(); } - } + Ok(()) + })?; let Some((code_field, formatting_init)) = code.value() else { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") @@ -458,7 +455,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { }; Ok(quote! { suggestions.push((#binding, #code_field)); }) } - _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| { + _ => throw_invalid_attr!(attr, |diag| { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { span_attrs.push("suggestion_part"); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 65bb154d7f3..b9b09c66230 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,5 +1,5 @@ use crate::diagnostics::error::{ - span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, + span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use proc_macro::Span; use proc_macro2::{Ident, TokenStream}; @@ -8,11 +8,13 @@ use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; use std::fmt; use std::str::FromStr; +use syn::meta::ParseNestedMeta; +use syn::punctuated::Punctuated; +use syn::{parenthesized, LitStr, Path, Token}; use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple}; -use syn::{MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, VariantInfo}; -use super::error::{invalid_attr, invalid_nested_attr}; +use super::error::invalid_attr; thread_local! { pub static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0); @@ -60,8 +62,8 @@ pub(crate) fn report_type_error( attr: &Attribute, ty_name: &str, ) -> Result<!, DiagnosticDeriveError> { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let meta = attr.parse_meta()?; + let name = attr.path().segments.last().unwrap().ident.to_string(); + let meta = &attr.meta; throw_span_err!( attr.span().unwrap(), @@ -418,59 +420,62 @@ pub(super) enum AllowMultipleAlternatives { Yes, } +fn parse_suggestion_values( + nested: ParseNestedMeta<'_>, + allow_multiple: AllowMultipleAlternatives, +) -> syn::Result<Vec<LitStr>> { + let values = if let Ok(val) = nested.value() { + vec![val.parse()?] + } else { + let content; + parenthesized!(content in nested.input); + + if let AllowMultipleAlternatives::No = allow_multiple { + span_err( + nested.input.span().unwrap(), + "expected exactly one string literal for `code = ...`", + ) + .emit(); + vec![] + } else { + let literals = Punctuated::<LitStr, Token![,]>::parse_terminated(&content); + + match literals { + Ok(p) if p.is_empty() => { + span_err( + content.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } + Ok(p) => p.into_iter().collect(), + Err(_) => { + span_err( + content.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + vec![] + } + } + } + }; + + Ok(values) +} + /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or /// `#[suggestion*(code("foo", "bar"))]` attribute field pub(super) fn build_suggestion_code( code_field: &Ident, - meta: &Meta, + nested: ParseNestedMeta<'_>, fields: &impl HasFieldMap, allow_multiple: AllowMultipleAlternatives, ) -> TokenStream { - let values = match meta { - // `code = "foo"` - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s], - // `code("foo", "bar")` - Meta::List(MetaList { nested, .. }) => { - if let AllowMultipleAlternatives::No = allow_multiple { - span_err( - meta.span().unwrap(), - "expected exactly one string literal for `code = ...`", - ) - .emit(); - vec![] - } else if nested.is_empty() { - span_err( - meta.span().unwrap(), - "expected at least one string literal for `code(...)`", - ) - .emit(); - vec![] - } else { - nested - .into_iter() - .filter_map(|item| { - if let NestedMeta::Lit(syn::Lit::Str(s)) = item { - Some(s) - } else { - span_err( - item.span().unwrap(), - "`code(...)` must contain only string literals", - ) - .emit(); - None - } - }) - .collect() - } - } - _ => { - span_err( - meta.span().unwrap(), - r#"`code = "..."`/`code(...)` must contain only string literals"#, - ) - .emit(); - vec![] - } + let values = match parse_suggestion_values(nested, allow_multiple) { + Ok(x) => x, + Err(e) => return e.into_compile_error(), }; if let AllowMultipleAlternatives::Yes = allow_multiple { @@ -601,11 +606,9 @@ impl SubdiagnosticKind { let span = attr.span().unwrap(); - let name = attr.path.segments.last().unwrap().ident.to_string(); + let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); - let meta = attr.parse_meta()?; - let mut kind = match name { "label" => SubdiagnosticKind::Label, "note" => SubdiagnosticKind::Note, @@ -618,7 +621,7 @@ impl SubdiagnosticKind { name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix) { if suggestion_kind != SuggestionKind::Normal { - invalid_attr(attr, &meta) + invalid_attr(attr) .help(format!( r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"# )) @@ -635,7 +638,7 @@ impl SubdiagnosticKind { name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix) { if suggestion_kind != SuggestionKind::Normal { - invalid_attr(attr, &meta) + invalid_attr(attr) .help(format!( r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"# )) @@ -647,16 +650,16 @@ impl SubdiagnosticKind { applicability: None, } } else { - throw_invalid_attr!(attr, &meta); + throw_invalid_attr!(attr); } } }; - let nested = match meta { - Meta::List(MetaList { ref nested, .. }) => { + let list = match &attr.meta { + Meta::List(list) => { // An attribute with properties, such as `#[suggestion(code = "...")]` or // `#[error(some::slug)]` - nested + list } Meta::Path(_) => { // An attribute without a slug or other properties, such as `#[note]` - return @@ -678,69 +681,68 @@ impl SubdiagnosticKind { } } _ => { - throw_invalid_attr!(attr, &meta) + throw_invalid_attr!(attr) } }; let mut code = None; let mut suggestion_kind = None; - let mut nested_iter = nested.into_iter().peekable(); + let mut first = true; + let mut slug = None; - // Peek at the first nested attribute: if it's a slug path, consume it. - let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { - let path = path.clone(); - // Advance the iterator. - nested_iter.next(); - Some(path) - } else { - None - }; - - for nested_attr in nested_iter { - let meta = match nested_attr { - NestedMeta::Meta(ref meta) => meta, - NestedMeta::Lit(_) => { - invalid_nested_attr(attr, nested_attr).emit(); - continue; + list.parse_nested_meta(|nested| { + if nested.input.is_empty() || nested.input.peek(Token![,]) { + if first { + slug = Some(nested.path); + } else { + span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit(); } - }; - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + first = false; + return Ok(()); + } + + first = false; + + let nested_name = nested.path.segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let string_value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), + let path_span = nested.path.span().unwrap(); + let val_span = nested.input.span().unwrap(); - Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| { - diag.help("a diagnostic slug must be the first argument to the attribute") - }), - _ => None, - }; + macro_rules! get_string { + () => {{ + let Ok(value) = nested.value().and_then(|x| x.parse::<LitStr>()) else { + span_err(val_span, "expected `= \"xxx\"`").emit(); + return Ok(()); + }; + value + }}; + } + + let mut has_errors = false; + let input = nested.input; match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( code_field, - meta, + nested, fields, AllowMultipleAlternatives::Yes, ); - code.set_once(code_init, span); + code.set_once(code_init, path_span); } ( "applicability", SubdiagnosticKind::Suggestion { ref mut applicability, .. } | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { - let Some(value) = string_value else { - invalid_nested_attr(attr, nested_attr).emit(); - continue; - }; - + let value = get_string!(); let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(span, "invalid applicability").emit(); + span_err(value.span().unwrap(), "invalid applicability").emit(); + has_errors = true; Applicability::Unspecified }); applicability.set_once(value, span); @@ -750,15 +752,13 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { .. } | SubdiagnosticKind::MultipartSuggestion { .. }, ) => { - let Some(value) = string_value else { - invalid_nested_attr(attr, nested_attr).emit(); - continue; - }; + let value = get_string!(); let value = value.value().parse().unwrap_or_else(|()| { span_err(value.span().unwrap(), "invalid suggestion style") .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") .emit(); + has_errors = true; SuggestionKind::Normal }); @@ -767,22 +767,32 @@ impl SubdiagnosticKind { // Invalid nested attribute (_, SubdiagnosticKind::Suggestion { .. }) => { - invalid_nested_attr(attr, nested_attr) + span_err(path_span, "invalid nested attribute") .help( "only `style`, `code` and `applicability` are valid nested attributes", ) .emit(); + has_errors = true; } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { - invalid_nested_attr(attr, nested_attr) + span_err(path_span, "invalid nested attribute") .help("only `style` and `applicability` are valid nested attributes") - .emit() + .emit(); + has_errors = true; } _ => { - invalid_nested_attr(attr, nested_attr).emit(); + span_err(path_span, "invalid nested attribute").emit(); + has_errors = true; } } - } + + if has_errors { + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::<TokenStream>(); + } + + Ok(()) + })?; match kind { SubdiagnosticKind::Suggestion { @@ -845,5 +855,5 @@ pub(super) fn should_generate_set_arg(field: &Field) -> bool { } pub(super) fn is_doc_comment(attr: &Attribute) -> bool { - attr.path.segments.last().unwrap().ident == "doc" + attr.path().segments.last().unwrap().ident == "doc" } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 63bdcea87f8..75a2f7009c2 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -1,6 +1,6 @@ use proc_macro2::{self, Ident}; use quote::quote; -use syn::{self, parse_quote, Meta, NestedMeta}; +use syn::{self, parse_quote}; struct Attributes { ignore: bool, @@ -10,32 +10,29 @@ struct Attributes { fn parse_attributes(field: &syn::Field) -> Attributes { let mut attrs = Attributes { ignore: false, project: None }; for attr in &field.attrs { - if let Ok(meta) = attr.parse_meta() { - if !meta.path().is_ident("stable_hasher") { - continue; + let meta = &attr.meta; + if !meta.path().is_ident("stable_hasher") { + continue; + } + let mut any_attr = false; + let _ = attr.parse_nested_meta(|nested| { + if nested.path.is_ident("ignore") { + attrs.ignore = true; + any_attr = true; } - let mut any_attr = false; - if let Meta::List(list) = meta { - for nested in list.nested.iter() { - if let NestedMeta::Meta(meta) = nested { - if meta.path().is_ident("ignore") { - attrs.ignore = true; - any_attr = true; - } - if meta.path().is_ident("project") { - if let Meta::List(list) = meta { - if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() { - attrs.project = meta.path().get_ident().cloned(); - any_attr = true; - } - } - } + if nested.path.is_ident("project") { + let _ = nested.parse_nested_meta(|meta| { + if attrs.project.is_none() { + attrs.project = meta.path.get_ident().cloned(); } - } - } - if !any_attr { - panic!("error parsing stable_hasher"); + any_attr = true; + Ok(()) + }); } + Ok(()) + }); + if !any_attr { + panic!("error parsing stable_hasher"); } } attrs diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 89ea89cf502..78a6f74887d 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -25,7 +25,7 @@ impl Parse for Newtype { let mut encodable = true; let mut ord = true; - attrs.retain(|attr| match attr.path.get_ident() { + attrs.retain(|attr| match attr.path().get_ident() { Some(ident) => match &*ident.to_string() { "custom_encodable" => { encodable = false; @@ -36,22 +36,22 @@ impl Parse for Newtype { false } "max" => { - let Ok(Meta::NameValue(literal) )= attr.parse_meta() else { + let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else { panic!("#[max = NUMBER] attribute requires max value"); }; - if let Some(old) = max.replace(literal.lit) { + if let Some(old) = max.replace(lit.lit.clone()) { panic!("Specified multiple max: {old:?}"); } false } "debug_format" => { - let Ok(Meta::NameValue(literal) )= attr.parse_meta() else { + let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else { panic!("#[debug_format = FMT] attribute requires a format"); }; - if let Some(old) = debug_format.replace(literal.lit) { + if let Some(old) = debug_format.replace(lit.lit.clone()) { panic!("Specified multiple debug format options: {old:?}"); } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 08e42a8a08f..f85ba38003c 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -15,7 +15,7 @@ mod kw { /// Ensures only doc comment attributes are used fn check_attributes(attrs: Vec<Attribute>) -> Result<Vec<Attribute>> { let inner = |attr: Attribute| { - if !attr.path.is_ident("doc") { + if !attr.path().is_ident("doc") { Err(Error::new(attr.span(), "attributes not supported on queries")) } else if attr.style != AttrStyle::Outer { Err(Error::new( @@ -48,7 +48,7 @@ impl Parse for Query { let name: Ident = input.parse()?; let arg_content; parenthesized!(arg_content in input); - let key = arg_content.parse()?; + let key = Pat::parse_single(&arg_content)?; arg_content.parse::<Token![:]>()?; let arg = arg_content.parse()?; let result = input.parse()?; @@ -158,7 +158,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { } else { None }; - let list = attr_content.parse_terminated(Expr::parse)?; + let list = attr_content.parse_terminated(Expr::parse, Token![,])?; try_insert!(desc = (tcx, list)); } else if modifier == "cache_on_disk_if" { // Parse a cache modifier like: @@ -166,7 +166,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { let args = if input.peek(token::Paren) { let args; parenthesized!(args in input); - let tcx = args.parse()?; + let tcx = Pat::parse_single(&args)?; Some(tcx) } else { None diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 388e254cd64..5ee4d879313 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,5 +1,5 @@ use quote::{quote, ToTokens}; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; +use syn::parse_quote; pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { @@ -17,21 +17,20 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: vi.construct(|_, index| { let bind = &bindings[index]; + let mut fixed = false; + // retain value of fields with #[type_foldable(identity)] - let fixed = bind - .ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_foldable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"), - _ => false, + bind.ast().attrs.iter().for_each(|x| { + if !x.path().is_ident("type_foldable") { + return; + } + let _ = x.parse_nested_meta(|nested| { + if nested.path.is_ident("identity") { + fixed = true; + } + Ok(()) }); + }); if fixed { bind.to_token_stream() diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index f6f4c4779c3..dcd505a105e 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -1,5 +1,5 @@ use quote::quote; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; +use syn::parse_quote; pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { @@ -8,19 +8,21 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: // ignore fields with #[type_visitable(ignore)] s.filter(|bi| { - !bi.ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_visitable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"), - _ => false, - }) + let mut ignored = false; + + bi.ast().attrs.iter().for_each(|attr| { + if !attr.path().is_ident("type_visitable") { + return; + } + let _ = attr.parse_nested_meta(|nested| { + if nested.path.is_ident("ignore") { + ignored = true; + } + Ok(()) + }); + }); + + !ignored }); if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 880da5ca593..81e62eccb8a 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -22,8 +22,6 @@ extern crate proc_macro; extern crate rustc_macros; #[macro_use] extern crate rustc_middle; -#[macro_use] -extern crate rustc_data_structures; #[macro_use] extern crate tracing; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 79c42a128e7..2515269ea2f 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -218,7 +218,7 @@ use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg}; @@ -236,6 +236,7 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::borrow::Cow; use std::io::{Read, Result as IoResult, Write}; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt}; @@ -814,15 +815,14 @@ fn get_metadata_section<'p>( // Assume the decompressed data will be at least the size of the compressed data, so we // don't have to grow the buffer as much. let mut inflated = Vec::with_capacity(compressed_bytes.len()); - match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { - Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), - Err(_) => { - return Err(MetadataError::LoadFailure(format!( - "failed to decompress metadata: {}", - filename.display() - ))); - } - } + FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated).map_err(|_| { + MetadataError::LoadFailure(format!( + "failed to decompress metadata: {}", + filename.display() + )) + })?; + + slice_owned(inflated, Deref::deref) } CrateFlavor::Rmeta => { // mmap the file, because only a small fraction of it is read. @@ -840,7 +840,7 @@ fn get_metadata_section<'p>( )) })?; - rustc_erase_owner!(OwningRef::new(mmap).map_owner_box()) + slice_owned(mmap, Deref::deref) } }; let blob = MetadataBlob::new(raw_bytes); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 21ac7e201f9..852c6d96469 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -51,12 +51,6 @@ mod cstore_impl; #[derive(Clone)] pub(crate) struct MetadataBlob(Lrc<MetadataRef>); -// This is needed so we can create an OwningRef into the blob. -// The data behind a `MetadataBlob` has a stable address because it is -// contained within an Rc/Arc. -unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {} - -// This is needed so we can create an OwningRef into the blob. impl std::ops::Deref for MetadataBlob { type Target = [u8]; diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index a6133f1b417..02cab561b8f 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -1,14 +1,14 @@ use crate::rmeta::DecodeContext; use crate::rmeta::EncodeContext; -use crate::rmeta::MetadataBlob; -use rustc_data_structures::owning_ref::OwningRef; +use rustc_data_structures::owned_slice::slice_owned; +use rustc_data_structures::owned_slice::OwnedSlice; use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; use rustc_middle::parameterized_over_tcx; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::def_id::{DefIndex, DefPathHash}; pub(crate) enum DefPathHashMapRef<'tcx> { - OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>), + OwnedFromMetadata(odht::HashTable<HashMapConfig, OwnedSlice>), BorrowedFromTcx(&'tcx DefPathHashMap), } @@ -50,11 +50,11 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> let len = d.read_usize(); let pos = d.position(); - let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]); + let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); - // Although we already have the data we need via the OwningRef, we still need - // to advance the DecodeContext's position so it's in a valid state after - // the method. We use read_raw_bytes() for that. + // Although we already have the data we need via the `OwnedSlice`, we still need + // to advance the `DecodeContext`'s position so it's in a valid state after + // the method. We use `read_raw_bytes()` for that. let _ = d.read_raw_bytes(len); let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 2f42849f390..f668c4e77be 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -149,15 +149,15 @@ impl<'tcx> CanonicalVarInfo<'tcx> { } } - pub fn expect_anon_placeholder(self) -> u32 { + pub fn expect_placeholder_index(self) -> usize { match self.kind { CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"), - CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(), - CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(), - CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(), + CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(), + CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(), + CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(), } } } @@ -411,7 +411,7 @@ impl<'tcx> CanonicalVarValues<'tcx> { CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => { let br = ty::BoundRegion { var: ty::BoundVar::from_usize(i), - kind: ty::BrAnon(i as u32, None), + kind: ty::BrAnon(None), }; tcx.mk_re_late_bound(ty::INNERMOST, br).into() } diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index eb860c04de2..b898e85fa71 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -12,6 +12,9 @@ pub struct MirPatch<'tcx> { new_statements: Vec<(Location, StatementKind<'tcx>)>, new_locals: Vec<LocalDecl<'tcx>>, resume_block: Option<BasicBlock>, + // Only for unreachable in cleanup path. + unreachable_cleanup_block: Option<BasicBlock>, + terminate_block: Option<BasicBlock>, body_span: Span, next_local: usize, } @@ -25,14 +28,31 @@ impl<'tcx> MirPatch<'tcx> { new_locals: vec![], next_local: body.local_decls.len(), resume_block: None, + unreachable_cleanup_block: None, + terminate_block: None, body_span: body.span, }; - // Check if we already have a resume block for (bb, block) in body.basic_blocks.iter_enumerated() { + // Check if we already have a resume block if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() { result.resume_block = Some(bb); - break; + continue; + } + + // Check if we already have an unreachable block + if let TerminatorKind::Unreachable = block.terminator().kind + && block.statements.is_empty() + && block.is_cleanup + { + result.unreachable_cleanup_block = Some(bb); + continue; + } + + // Check if we already have a terminate block + if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() { + result.terminate_block = Some(bb); + continue; } } @@ -56,6 +76,40 @@ impl<'tcx> MirPatch<'tcx> { bb } + pub fn unreachable_cleanup_block(&mut self) -> BasicBlock { + if let Some(bb) = self.unreachable_cleanup_block { + return bb; + } + + let bb = self.new_block(BasicBlockData { + statements: vec![], + terminator: Some(Terminator { + source_info: SourceInfo::outermost(self.body_span), + kind: TerminatorKind::Unreachable, + }), + is_cleanup: true, + }); + self.unreachable_cleanup_block = Some(bb); + bb + } + + pub fn terminate_block(&mut self) -> BasicBlock { + if let Some(bb) = self.terminate_block { + return bb; + } + + let bb = self.new_block(BasicBlockData { + statements: vec![], + terminator: Some(Terminator { + source_info: SourceInfo::outermost(self.body_span), + kind: TerminatorKind::Terminate, + }), + is_cleanup: true, + }); + self.terminate_block = Some(bb); + bb + } + pub fn is_patched(&self, bb: BasicBlock) -> bool { self.patch_map[bb].is_some() } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 68561cf6dd7..cfdf1dcf5c0 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -411,10 +411,8 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { let inner = tcx.fold_regions(ty, |r, depth| match r.kind() { ty::ReVar(vid) => { - let br = ty::BoundRegion { - var: ty::BoundVar::new(vid.index()), - kind: ty::BrAnon(vid.as_u32(), None), - }; + let br = + ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) }; tcx.mk_re_late_bound(depth, br) } _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 1a23f9dadd4..2165403da26 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -262,7 +262,7 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str { Goto { .. } => "Goto", SwitchInt { .. } => "SwitchInt", Resume => "Resume", - Abort => "Abort", + Terminate => "Terminate", Return => "Return", Unreachable => "Unreachable", Drop { .. } => "Drop", diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index cc35e6106e2..135889d0da8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -515,15 +515,15 @@ pub struct CopyNonOverlapping<'tcx> { /// /// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the /// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such -/// terminators have a `cleanup: Option<BasicBlock>` field on them. If stack unwinding occurs, then -/// once the current function is reached, execution continues at the given basic block, if any. If -/// `cleanup` is `None` then no cleanup is performed, and the stack continues unwinding. This is -/// equivalent to the execution of a `Resume` terminator. +/// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then +/// once the current function is reached, an action will be taken based on the `unwind` field. +/// If the action is `Cleanup`, then the execution continues at the given basic block. If the +/// action is `Continue` then no cleanup is performed, and the stack continues unwinding. /// -/// The basic block pointed to by a `cleanup` field must have its `cleanup` flag set. `cleanup` -/// basic blocks have a couple restrictions: -/// 1. All `cleanup` fields in them must be `None`. -/// 2. `Return` terminators are not allowed in them. `Abort` and `Unwind` terminators are. +/// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set. +/// `cleanup` basic blocks have a couple restrictions: +/// 1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`. +/// 2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are. /// 3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks /// must also be `cleanup`. This is a part of the type system and checked statically, so it is /// still an error to have such an edge in the CFG even if it's known that it won't be taken at @@ -565,11 +565,11 @@ pub enum TerminatorKind<'tcx> { /// deaggregation runs. Resume, - /// Indicates that the landing pad is finished and that the process should abort. + /// Indicates that the landing pad is finished and that the process should terminate. /// /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in /// cleanup blocks. - Abort, + Terminate, /// Returns from the function. /// @@ -604,7 +604,7 @@ pub enum TerminatorKind<'tcx> { /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to /// > the place or one of its "parents" occurred more recently than a move out of it. This does not /// > consider indirect assignments. - Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> }, + Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction }, /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// the referred to function. The operand types must match the argument types of the function. @@ -628,8 +628,8 @@ pub enum TerminatorKind<'tcx> { destination: Place<'tcx>, /// Where to go after this call returns. If none, the call necessarily diverges. target: Option<BasicBlock>, - /// Cleanups to be done if the call unwinds. - cleanup: Option<BasicBlock>, + /// Action to be taken if the call unwinds. + unwind: UnwindAction, /// `true` if this is from a call in HIR rather than from an overloaded /// operator. True for overloaded function call. from_hir_call: bool, @@ -654,7 +654,7 @@ pub enum TerminatorKind<'tcx> { expected: bool, msg: AssertMessage<'tcx>, target: BasicBlock, - cleanup: Option<BasicBlock>, + unwind: UnwindAction, }, /// Marks a suspend point. @@ -720,9 +720,8 @@ pub enum TerminatorKind<'tcx> { /// in practice, but in order to avoid fragility we want to always /// consider it in borrowck. We don't want to accept programs which /// pass borrowck only when `panic=abort` or some assertions are disabled - /// due to release vs. debug mode builds. This needs to be an `Option` because - /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes. - unwind: Option<BasicBlock>, + /// due to release vs. debug mode builds. + unwind: UnwindAction, }, /// Block ends with an inline assembly block. This is a terminator since @@ -745,12 +744,31 @@ pub enum TerminatorKind<'tcx> { /// diverging (InlineAsmOptions::NORETURN). destination: Option<BasicBlock>, - /// Cleanup to be done if the inline assembly unwinds. This is present + /// Action to be taken if the inline assembly unwinds. This is present /// if and only if InlineAsmOptions::MAY_UNWIND is set. - cleanup: Option<BasicBlock>, + unwind: UnwindAction, }, } +/// Action to be taken when a stack unwind happens. +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum UnwindAction { + /// No action is to be taken. Continue unwinding. + /// + /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not + /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF. + Continue, + /// Triggers undefined behavior if unwind happens. + Unreachable, + /// Terminates the execution if unwind happens. + /// + /// Depending on the platform and situation this may cause a non-unwindable panic or abort. + Terminate, + /// Cleanups to be done. + Cleanup(BasicBlock), +} + /// Information about an assertion failure. #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] pub enum AssertKind<O> { diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cd970270727..2c6126cdd29 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,6 +1,6 @@ use smallvec::SmallVec; -use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind}; +use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction}; use rustc_ast::InlineAsmTemplatePiece; pub use rustc_ast::Mutability; use rustc_macros::HashStable; @@ -118,11 +118,11 @@ impl<'tcx> Terminator<'tcx> { self.kind.successors_mut() } - pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + pub fn unwind(&self) -> Option<&UnwindAction> { self.kind.unwind() } - pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { + pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> { self.kind.unwind_mut() } } @@ -135,33 +135,33 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { target: None, cleanup: None, .. } - | InlineAsm { destination: None, cleanup: None, .. } => { - None.into_iter().chain((&[]).into_iter().copied()) + Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } + | Yield { resume: t, drop: Some(ref u), .. } + | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. } + | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. } + | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) } + | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => { + Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) } Goto { target: t } - | Call { target: None, cleanup: Some(t), .. } - | Call { target: Some(t), cleanup: None, .. } + | Call { target: None, unwind: UnwindAction::Cleanup(t), .. } + | Call { target: Some(t), unwind: _, .. } | Yield { resume: t, drop: None, .. } - | Drop { target: t, unwind: None, .. } - | Assert { target: t, cleanup: None, .. } - | FalseUnwind { real_target: t, unwind: None } - | InlineAsm { destination: Some(t), cleanup: None, .. } - | InlineAsm { destination: None, cleanup: Some(t), .. } => { + | Drop { target: t, unwind: _, .. } + | Assert { target: t, unwind: _, .. } + | FalseUnwind { real_target: t, unwind: _ } + | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. } + | InlineAsm { destination: Some(t), unwind: _, .. } => { Some(t).into_iter().chain((&[]).into_iter().copied()) } - Call { target: Some(t), cleanup: Some(ref u), .. } - | Yield { resume: t, drop: Some(ref u), .. } - | Drop { target: t, unwind: Some(ref u), .. } - | Assert { target: t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: t, unwind: Some(ref u) } - | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => { - Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied()) + Resume + | Terminate + | GeneratorDrop + | Return + | Unreachable + | Call { target: None, unwind: _, .. } + | InlineAsm { destination: None, unwind: _, .. } => { + None.into_iter().chain((&[]).into_iter().copied()) } SwitchInt { ref targets, .. } => { None.into_iter().chain(targets.targets.iter().copied()) @@ -175,32 +175,34 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { use self::TerminatorKind::*; match *self { - Resume - | Abort - | GeneratorDrop - | Return - | Unreachable - | Call { target: None, cleanup: None, .. } - | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []), + Call { target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. } + | Yield { resume: ref mut t, drop: Some(ref mut u), .. } + | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } + | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. } + | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } + | InlineAsm { + destination: Some(ref mut t), + unwind: UnwindAction::Cleanup(ref mut u), + .. + } => Some(t).into_iter().chain(slice::from_mut(u)), Goto { target: ref mut t } - | Call { target: None, cleanup: Some(ref mut t), .. } - | Call { target: Some(ref mut t), cleanup: None, .. } + | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. } + | Call { target: Some(ref mut t), unwind: _, .. } | Yield { resume: ref mut t, drop: None, .. } - | Drop { target: ref mut t, unwind: None, .. } - | Assert { target: ref mut t, cleanup: None, .. } - | FalseUnwind { real_target: ref mut t, unwind: None } - | InlineAsm { destination: Some(ref mut t), cleanup: None, .. } - | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => { + | Drop { target: ref mut t, unwind: _, .. } + | Assert { target: ref mut t, unwind: _, .. } + | FalseUnwind { real_target: ref mut t, unwind: _ } + | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. } + | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => { Some(t).into_iter().chain(&mut []) } - Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. } - | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | Drop { target: ref mut t, unwind: Some(ref mut u), .. } - | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } - | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => { - Some(t).into_iter().chain(slice::from_mut(u)) - } + Resume + | Terminate + | GeneratorDrop + | Return + | Unreachable + | Call { target: None, unwind: _, .. } + | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []), SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets), FalseEdge { ref mut real_target, ref mut imaginary_target } => { Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) @@ -208,41 +210,41 @@ impl<'tcx> TerminatorKind<'tcx> { } } - pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + pub fn unwind(&self) -> Option<&UnwindAction> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } => None, - TerminatorKind::Call { cleanup: ref unwind, .. } - | TerminatorKind::Assert { cleanup: ref unwind, .. } + TerminatorKind::Call { ref unwind, .. } + | TerminatorKind::Assert { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. } - | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), + | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind), } } - pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { + pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> { match *self { TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdge { .. } => None, - TerminatorKind::Call { cleanup: ref mut unwind, .. } - | TerminatorKind::Assert { cleanup: ref mut unwind, .. } + TerminatorKind::Call { ref mut unwind, .. } + | TerminatorKind::Assert { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. } - | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), + | TerminatorKind::InlineAsm { ref mut unwind, .. } => Some(unwind), } } @@ -268,11 +270,17 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { let labels = self.fmt_successor_labels(); assert_eq!(successor_count, labels.len()); - match successor_count { - 0 => Ok(()), - - 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), - + let unwind = match self.unwind() { + // Not needed or included in successors + None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None, + Some(UnwindAction::Unreachable) => Some("unwind unreachable"), + Some(UnwindAction::Terminate) => Some("unwind terminate"), + }; + + match (successor_count, unwind) { + (0, None) => Ok(()), + (0, Some(unwind)) => write!(fmt, " -> {}", unwind), + (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; for (i, target) in self.successors().enumerate() { @@ -281,6 +289,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { } write!(fmt, "{}: {:?}", labels[i], target)?; } + if let Some(unwind) = unwind { + write!(fmt, ", {unwind}")?; + } write!(fmt, "]") } } @@ -299,7 +310,7 @@ impl<'tcx> TerminatorKind<'tcx> { Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), Resume => write!(fmt, "resume"), - Abort => write!(fmt, "abort"), + Terminate => write!(fmt, "abort"), Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({:?})", place), @@ -378,7 +389,7 @@ impl<'tcx> TerminatorKind<'tcx> { pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> { use self::TerminatorKind::*; match *self { - Return | Resume | Abort | Unreachable | GeneratorDrop => vec![], + Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![], Goto { .. } => vec!["".into()], SwitchInt { ref targets, .. } => targets .values @@ -386,31 +397,35 @@ impl<'tcx> TerminatorKind<'tcx> { .map(|&u| Cow::Owned(u.to_string())) .chain(iter::once("otherwise".into())) .collect(), - Call { target: Some(_), cleanup: Some(_), .. } => { + Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { vec!["return".into(), "unwind".into()] } - Call { target: Some(_), cleanup: None, .. } => vec!["return".into()], - Call { target: None, cleanup: Some(_), .. } => vec!["unwind".into()], - Call { target: None, cleanup: None, .. } => vec![], + Call { target: Some(_), unwind: _, .. } => vec!["return".into()], + Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()], + Call { target: None, unwind: _, .. } => vec![], Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], Yield { drop: None, .. } => vec!["resume".into()], - Drop { unwind: None, .. } => { - vec!["return".into()] - } - Drop { unwind: Some(_), .. } => { - vec!["return".into(), "unwind".into()] + Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()], + Drop { unwind: _, .. } => vec!["return".into()], + Assert { unwind: UnwindAction::Cleanup(_), .. } => { + vec!["success".into(), "unwind".into()] } - Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => vec!["success".into(), "unwind".into()], + Assert { unwind: _, .. } => vec!["success".into()], FalseEdge { .. } => vec!["real".into(), "imaginary".into()], - FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], - FalseUnwind { unwind: None, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), cleanup: Some(_), .. } => { + FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => { + vec!["real".into(), "unwind".into()] + } + FalseUnwind { unwind: _, .. } => vec!["real".into()], + InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => { vec!["return".into(), "unwind".into()] } - InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()], - InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], - InlineAsm { destination: None, cleanup: None, .. } => vec![], + InlineAsm { destination: Some(_), unwind: _, .. } => { + vec!["return".into()] + } + InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => { + vec!["unwind".into()] + } + InlineAsm { destination: None, unwind: _, .. } => vec![], } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 7aa446ae966..6c4ea065abe 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -462,7 +462,7 @@ macro_rules! make_mir_visitor { match kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume | - TerminatorKind::Abort | + TerminatorKind::Terminate | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } | @@ -509,7 +509,7 @@ macro_rules! make_mir_visitor { args, destination, target: _, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _ } => { @@ -529,7 +529,7 @@ macro_rules! make_mir_visitor { expected: _, msg, target: _, - cleanup: _, + unwind: _, } => { self.visit_operand(cond, location); self.visit_assert_message(msg, location); @@ -555,7 +555,7 @@ macro_rules! make_mir_visitor { options: _, line_spans: _, destination: _, - cleanup: _, + unwind: _, } => { for op in operands { match op { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8d0aa622244..299b1bf1d96 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -311,7 +311,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec<Region<'tcx>>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })` + /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })` /// for small values of `i` and `v`. pub re_late_bounds: Vec<Vec<Region<'tcx>>>, } @@ -386,10 +386,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|v| { mk(ty::ReLateBound( ty::DebruijnIndex::from(i), - ty::BoundRegion { - var: ty::BoundVar::from(v), - kind: ty::BrAnon(v, None), - }, + ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) }, )) }) .collect() @@ -2075,10 +2072,9 @@ impl<'tcx> TyCtxt<'tcx> { bound_region: ty::BoundRegion, ) -> Region<'tcx> { // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region - && var.as_u32() == v + if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize()) - && let Some(re) = inner.get(v as usize).copied() + && let Some(re) = inner.get(var.as_usize()).copied() { re } else { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 6205e2bf24d..203e16bea27 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -379,9 +379,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| { - ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None)) - }) + .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None))) .expect_region(); let br = ty::BoundRegion { var, kind }; self.tcx.mk_re_late_bound(ty::INNERMOST, br) @@ -391,9 +389,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| { - ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32)) - }) + .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon)) .expect_ty(); self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8af9acfadde..2328a1324fc 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -281,6 +281,12 @@ pub enum SizeSkeleton<'tcx> { /// Any statically computable Layout. Known(Size), + /// This is a generic const expression (i.e. N * 2), which may contain some parameters. + /// It must be of type usize, and represents the size of a type in bytes. + /// It is not required to be evaluatable to a concrete value, but can be used to check + /// that another SizeSkeleton is of equal size. + Generic(ty::Const<'tcx>), + /// A potentially-fat pointer. Pointer { /// If true, this pointer is never null. @@ -326,6 +332,37 @@ impl<'tcx> SizeSkeleton<'tcx> { ), } } + ty::Array(inner, len) + if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts => + { + match SizeSkeleton::compute(inner, tcx, param_env)? { + // This may succeed because the multiplication of two types may overflow + // but a single size of a nested array will not. + SizeSkeleton::Known(s) => { + if let Some(c) = len.try_eval_target_usize(tcx, param_env) { + let size = s + .bytes() + .checked_mul(c) + .ok_or_else(|| LayoutError::SizeOverflow(ty))?; + return Ok(SizeSkeleton::Known(Size::from_bytes(size))); + } + let len = tcx.expand_abstract_consts(len); + let prev = ty::Const::from_target_usize(tcx, s.bytes()); + let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else { + return Err(LayoutError::SizeOverflow(ty)); + }; + Ok(SizeSkeleton::Generic(gen_size)) + } + SizeSkeleton::Pointer { .. } => Err(err), + SizeSkeleton::Generic(g) => { + let len = tcx.expand_abstract_consts(len); + let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else { + return Err(LayoutError::SizeOverflow(ty)); + }; + Ok(SizeSkeleton::Generic(gen_size)) + } + } + } ty::Adt(def, substs) => { // Only newtypes and enums w/ nullable pointer optimization. @@ -355,6 +392,9 @@ impl<'tcx> SizeSkeleton<'tcx> { } ptr = Some(field); } + SizeSkeleton::Generic(_) => { + return Err(err); + } } } Ok(ptr) @@ -410,11 +450,66 @@ impl<'tcx> SizeSkeleton<'tcx> { (SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => { a == b } + // constants are always pre-normalized into a canonical form so this + // only needs to check if their pointers are identical. + (SizeSkeleton::Generic(a), SizeSkeleton::Generic(b)) => a == b, _ => false, } } } +/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]), +/// to ensure that they have a canonical order and can be compared directly we combine all +/// constants, and sort the other terms. This allows comparison of expressions of sizes, +/// allowing for things like transmutating between types that depend on generic consts. +/// This returns `None` if multiplication of constants overflows. +fn mul_sorted_consts<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, +) -> Option<ty::Const<'tcx>> { + use crate::mir::BinOp::Mul; + use ty::ConstKind::Expr; + use ty::Expr::Binop; + + let mut work = vec![a, b]; + let mut done = vec![]; + while let Some(n) = work.pop() { + if let Expr(Binop(Mul, l, r)) = n.kind() { + work.push(l); + work.push(r) + } else { + done.push(n); + } + } + let mut k = 1; + let mut overflow = false; + done.retain(|c| { + let Some(c) = c.try_eval_target_usize(tcx, param_env) else { + return true; + }; + let Some(next) = c.checked_mul(k) else { + overflow = true; + return false; + }; + k = next; + false + }); + if overflow { + return None; + } + if k != 1 { + done.push(ty::Const::from_target_usize(tcx, k)); + } else if k == 0 { + return Some(ty::Const::from_target_usize(tcx, 0)); + } + done.sort_unstable(); + + // create a single tree from the buffer + done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty())) +} + pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 800a230b654..c856bb25e14 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1454,12 +1454,12 @@ impl<'tcx> OpaqueHiddenType<'tcx> { #[derive(HashStable, TyEncodable, TyDecodable)] pub struct Placeholder<T> { pub universe: UniverseIndex, - pub name: T, + pub bound: T, } -pub type PlaceholderRegion = Placeholder<BoundRegionKind>; +pub type PlaceholderRegion = Placeholder<BoundRegion>; -pub type PlaceholderType = Placeholder<BoundTyKind>; +pub type PlaceholderType = Placeholder<BoundTy>; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index de4c703107e..bc0ccc1ebc3 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -701,9 +701,7 @@ pub trait PrettyPrinter<'tcx>: ty::Error(_) => p!("[type error]"), ty::Param(ref param_ty) => p!(print(param_ty)), ty::Bound(debruijn, bound_ty) => match bound_ty.kind { - ty::BoundTyKind::Anon(bv) => { - self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))? - } + ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?, ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() { true if debruijn == ty::INNERMOST => p!(write("^{}", s)), true => p!(write("^{}_{}", debruijn.index(), s)), @@ -739,8 +737,8 @@ pub trait PrettyPrinter<'tcx>: p!(print(data)) } } - ty::Placeholder(placeholder) => match placeholder.name { - ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)), + ty::Placeholder(placeholder) => match placeholder.bound.kind { + ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)), ty::BoundTyKind::Param(_, name) => p!(write("{}", name)), }, ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { @@ -2104,7 +2102,9 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) - | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + | ty::RePlaceholder(ty::Placeholder { + bound: ty::BoundRegion { kind: br, .. }, .. + }) => { if br.is_named() { return true; } @@ -2181,7 +2181,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) - | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + | ty::RePlaceholder(ty::Placeholder { + bound: ty::BoundRegion { kind: br, .. }, .. + }) => { if let ty::BrNamed(_, name) = br && br.is_named() { p!(write("{}", name)); return Ok(self); @@ -2259,7 +2261,10 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { ty::ReLateBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } - ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => { + ty::RePlaceholder(ty::PlaceholderRegion { + bound: ty::BoundRegion { kind, .. }, + .. + }) => { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index d4f058440b9..5c604bb6db2 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"), + ty::BrAnon(span) => write!(f, "BrAnon({span:?})"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({})", name) @@ -254,8 +254,8 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::AssocKind, crate::ty::AliasKind, crate::ty::AliasRelationDirection, - crate::ty::Placeholder<crate::ty::BoundRegionKind>, - crate::ty::Placeholder<crate::ty::BoundTyKind>, + crate::ty::Placeholder<crate::ty::BoundRegion>, + crate::ty::Placeholder<crate::ty::BoundTy>, crate::ty::ClosureKind, crate::ty::FreeRegion, crate::ty::InferTy, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5ea77833af2..0e2e2a956ec 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -60,7 +60,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(u32, Option<Span>), + BrAnon(Option<Span>), /// Named region parameters for functions (a in &'a T) /// @@ -107,15 +107,6 @@ impl BoundRegionKind { _ => None, } } - - pub fn expect_anon(&self) -> u32 { - match *self { - BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => { - bug!("expected anon region: {self:?}") - } - BoundRegionKind::BrAnon(idx, _) => idx, - } - } } pub trait Article { @@ -136,10 +127,6 @@ impl<'tcx> Article for TyKind<'tcx> { } } -// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyKind<'_>, 32); - /// A closure can be modeled as a struct that looks like: /// ```ignore (illustrative) /// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U); @@ -1533,22 +1520,13 @@ pub struct BoundTy { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundTyKind { - Anon(u32), + Anon, Param(DefId, Symbol), } -impl BoundTyKind { - pub fn expect_anon(self) -> u32 { - match self { - BoundTyKind::Anon(i) => i, - _ => bug!(), - } - } -} - impl From<BoundVar> for BoundTy { fn from(var: BoundVar) -> Self { - BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) } + BoundTy { var, kind: BoundTyKind::Anon } } } @@ -1632,7 +1610,7 @@ impl<'tcx> Region<'tcx> { ty::ReLateBound(_, br) => br.kind.get_name(), ty::ReFree(fr) => fr.bound_region.get_name(), ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.name.get_name(), + ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), _ => None, }; @@ -1650,7 +1628,7 @@ impl<'tcx> Region<'tcx> { ty::ReFree(fr) => fr.bound_region.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.name.is_named(), + ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), ty::ReErased => false, ty::ReError(_) => false, } @@ -2514,3 +2492,14 @@ impl<'tcx> VarianceDiagInfo<'tcx> { } } } + +// Some types are used a lot. Make sure they don't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +mod size_asserts { + use super::*; + use rustc_data_structures::static_assert_size; + // tidy-alphabetical-start + static_assert_size!(RegionKind<'_>, 28); + static_assert_size!(TyKind<'_>, 32); + // tidy-alphabetical-end +} diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 33b73928704..54028dfe87b 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -56,7 +56,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { Ok(TerminatorKind::Drop { place: self.parse_place(args[0])?, target: self.parse_block(args[1])?, - unwind: None, + unwind: UnwindAction::Continue, }) }, @call("mir_call", args) => { @@ -126,7 +126,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { args, destination, target: Some(target), - cleanup: None, + unwind: UnwindAction::Continue, from_hir_call: *from_hir_call, fn_span: *fn_span, }) diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index baa12ec11c3..8631749a524 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -171,7 +171,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args: vec![Operand::Move(size), Operand::Move(align)], destination: storage, target: Some(success), - cleanup: None, + unwind: UnwindAction::Continue, from_hir_call: false, fn_span: expr_span, }, @@ -702,7 +702,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.terminate( block, outer_source_info, - TerminatorKind::Drop { place: to_drop, target: success, unwind: None }, + TerminatorKind::Drop { + place: to_drop, + target: success, + unwind: UnwindAction::Continue, + }, ); this.diverge_from(block); block = success; diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 8efaba1f602..05a723a6b67 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -228,7 +228,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.terminate( loop_block, source_info, - TerminatorKind::FalseUnwind { real_target: body_block, unwind: None }, + TerminatorKind::FalseUnwind { + real_target: body_block, + unwind: UnwindAction::Continue, + }, ); this.diverge_from(loop_block); @@ -264,7 +267,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::Call { func: fun, args, - cleanup: None, + unwind: UnwindAction::Continue, destination, // The presence or absence of a return edge affects control-flow sensitive // MIR checks and ultimately whether code is accepted or not. We can only @@ -466,7 +469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { Some(destination_block) }, - cleanup: None, + unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) { + UnwindAction::Continue + } else { + UnwindAction::Unreachable + }, }, ); if options.contains(InlineAsmOptions::MAY_UNWIND) { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 2de89f67dfd..8a03ea7e2cc 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -263,7 +263,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args: vec![Operand::Move(ref_string)], destination: ref_str, target: Some(eq_block), - cleanup: None, + unwind: UnwindAction::Continue, from_hir_call: false, fn_span: source_info.span } @@ -466,7 +466,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args: vec![val, expect], destination: eq_result, target: Some(eq_block), - cleanup: None, + unwind: UnwindAction::Continue, from_hir_call: false, fn_span: source_info.span, }, diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 25af221bf36..f32d2db4e71 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -369,7 +369,7 @@ impl DropTree { let terminator = TerminatorKind::Drop { target: blocks[drop_data.1].unwrap(), // The caller will handle this if needed. - unwind: None, + unwind: UnwindAction::Terminate, place: drop_data.0.local.into(), }; cfg.terminate(block, drop_data.0.source_info, terminator); @@ -1141,7 +1141,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate( block, source_info, - TerminatorKind::Drop { place, target: assign, unwind: Some(assign_unwind) }, + TerminatorKind::Drop { + place, + target: assign, + unwind: UnwindAction::Cleanup(assign_unwind), + }, ); self.diverge_from(block); @@ -1165,7 +1169,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate( block, source_info, - TerminatorKind::Assert { cond, expected, msg, target: success_block, cleanup: None }, + TerminatorKind::Assert { + cond, + expected, + msg, + target: success_block, + unwind: UnwindAction::Continue, + }, ); self.diverge_from(block); @@ -1244,7 +1254,11 @@ fn build_scope_drops<'tcx>( cfg.terminate( block, source_info, - TerminatorKind::Drop { place: local.into(), target: next, unwind: None }, + TerminatorKind::Drop { + place: local.into(), + target: next, + unwind: UnwindAction::Continue, + }, ); block = next; } @@ -1424,23 +1438,23 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { let term = &mut cfg.block_data_mut(from).terminator_mut(); match &mut term.kind { TerminatorKind::Drop { unwind, .. } => { - if let Some(unwind) = *unwind { + if let UnwindAction::Cleanup(unwind) = *unwind { let source_info = term.source_info; cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to }); } else { - *unwind = Some(to); + *unwind = UnwindAction::Cleanup(to); } } TerminatorKind::FalseUnwind { unwind, .. } - | TerminatorKind::Call { cleanup: unwind, .. } - | TerminatorKind::Assert { cleanup: unwind, .. } - | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { - *unwind = Some(to); + | TerminatorKind::Call { unwind, .. } + | TerminatorKind::Assert { unwind, .. } + | TerminatorKind::InlineAsm { unwind, .. } => { + *unwind = UnwindAction::Cleanup(to); } TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 8937b78fe34..8e41957af0e 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::def::DefKind; -use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind}; +use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Operand, TerminatorKind}; use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; @@ -108,7 +108,7 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { match self.body[bb].terminator().kind { // These terminators return control flow to the caller. - TerminatorKind::Abort + TerminatorKind::Terminate | TerminatorKind::GeneratorDrop | TerminatorKind::Resume | TerminatorKind::Return @@ -149,7 +149,9 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool { let terminator = self.body[bb].terminator(); - if terminator.unwind() == Some(&Some(target)) && terminator.successors().count() > 1 { + if terminator.unwind() == Some(&mir::UnwindAction::Cleanup(target)) + && terminator.successors().count() > 1 + { return true; } // Don't traverse successors of recursive calls or false CFG edges. diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 7ef3d41ac48..bd8ec82dffd 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -77,10 +77,10 @@ impl Unwind { } } - fn into_option(self) -> Option<BasicBlock> { + fn into_action(self) -> UnwindAction { match self { - Unwind::To(bb) => Some(bb), - Unwind::InCleanup => None, + Unwind::To(bb) => UnwindAction::Cleanup(bb), + Unwind::InCleanup => UnwindAction::Terminate, } } @@ -236,7 +236,7 @@ where TerminatorKind::Drop { place: self.place, target: self.succ, - unwind: self.unwind.into_option(), + unwind: self.unwind.into_action(), }, ); } @@ -640,7 +640,7 @@ where args: vec![Operand::Move(Place::from(ref_place))], destination: unit_temp, target: Some(succ), - cleanup: unwind.into_option(), + unwind: unwind.into_action(), from_hir_call: true, fn_span: self.source_info.span, }, @@ -717,7 +717,7 @@ where TerminatorKind::Drop { place: tcx.mk_place_deref(ptr), target: loop_block, - unwind: unwind.into_option(), + unwind: unwind.into_action(), }, ); @@ -946,7 +946,11 @@ where args, destination: unit_temp, target: Some(target), - cleanup: None, + unwind: if unwind.is_cleanup() { + UnwindAction::Terminate + } else { + UnwindAction::Continue + }, from_hir_call: false, fn_span: self.source_info.span, }; // FIXME(#43234) @@ -959,7 +963,7 @@ where fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { let block = - TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_option() }; + TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() }; self.new_block(unwind, block) } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index a40c38aa4c3..c8fe1af6674 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets}; +use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction}; use rustc_middle::ty::TyCtxt; use std::ops::RangeInclusive; @@ -474,14 +474,14 @@ impl Direction for Forward { { use mir::TerminatorKind::*; match bb_data.terminator().kind { - Return | Resume | Abort | GeneratorDrop | Unreachable => {} + Return | Resume | Terminate | GeneratorDrop | Unreachable => {} Goto { target } => propagate(target, exit_state), - Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } + Assert { target, unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _ } | FalseUnwind { real_target: target, unwind } => { - if let Some(unwind) = unwind { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } @@ -503,7 +503,7 @@ impl Direction for Forward { } Call { - cleanup, + unwind, destination, target, func: _, @@ -511,7 +511,7 @@ impl Direction for Forward { from_hir_call: _, fn_span: _, } => { - if let Some(unwind) = cleanup { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } @@ -533,9 +533,9 @@ impl Direction for Forward { options: _, line_spans: _, destination, - cleanup, + unwind, } => { - if let Some(unwind) = cleanup { + if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 17102454a88..60679b17d6c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -39,7 +39,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { args: vec![], destination: dummy_place.clone(), target: Some(mir::START_BLOCK), - cleanup: None, + unwind: mir::UnwindAction::Continue, from_hir_call: false, fn_span: DUMMY_SP, }, @@ -53,7 +53,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { args: vec![], destination: dummy_place.clone(), target: Some(mir::START_BLOCK), - cleanup: None, + unwind: mir::UnwindAction::Continue, from_hir_call: false, fn_span: DUMMY_SP, }, diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 08fadfe68a1..92d30f254a6 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -125,7 +125,7 @@ where } } - TerminatorKind::Abort + TerminatorKind::Terminate | 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 99988b29e8a..4a5d9d52010 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -200,7 +200,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. - TerminatorKind::Abort + TerminatorKind::Terminate | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { .. } @@ -237,7 +237,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Yield { .. } - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 d9ceac1154f..64ed7a29f6f 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -375,7 +375,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // need recording. | TerminatorKind::Return | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } => {} @@ -398,7 +398,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { ref args, destination, target, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } => { @@ -417,7 +417,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { options: _, line_spans: _, destination: _, - cleanup: _, + unwind: _, } => { for op in operands { match *op { diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 33a15a8d224..98bebc9b13b 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -238,7 +238,7 @@ pub trait ValueAnalysis<'tcx> { TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 893018e0d8e..5aed89139e2 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -34,11 +34,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { return; } - // This pass only runs on functions which themselves cannot unwind, - // forcibly changing the body of the function to structurally provide - // this guarantee by aborting on an unwind. If this function can unwind, - // then there's nothing to do because it already should work correctly. - // // Here we test for this function itself whether its ABI allows // unwinding or not. let body_ty = tcx.type_of(def_id).skip_binder(); @@ -107,31 +102,14 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { } } - // For call instructions which need to be terminated, we insert a - // singular basic block which simply terminates, and then configure the - // `cleanup` attribute for all calls we found to this basic block we - // insert which means that any unwinding that happens in the functions - // will force an abort of the process. - if !calls_to_terminate.is_empty() { - let bb = BasicBlockData { - statements: Vec::new(), - is_cleanup: true, - terminator: Some(Terminator { - source_info: SourceInfo::outermost(body.span), - kind: TerminatorKind::Abort, - }), - }; - let abort_bb = body.basic_blocks_mut().push(bb); - - for bb in calls_to_terminate { - let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap(); - *cleanup = Some(abort_bb); - } + for id in calls_to_terminate { + let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); + *cleanup = UnwindAction::Terminate; } for id in cleanups_to_remove { let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = None; + *cleanup = UnwindAction::Unreachable; } // We may have invalidated some `cleanup` blocks so clean those up now. diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 30966d22e2f..e1e354efa1c 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -50,10 +50,11 @@ impl AddCallGuards { for block in body.basic_blocks_mut() { match block.terminator { Some(Terminator { - kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. }, + kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. }, source_info, }) if pred_count[*destination] > 1 - && (cleanup.is_some() || 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_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 5815887e5bb..8086a4557b7 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -221,7 +221,7 @@ fn insert_alignment_check<'tcx>( required: Operand::Copy(alignment), found: Operand::Copy(addr), }, - cleanup: None, + unwind: UnwindAction::Terminate, }, }); } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index c4d058e8ecb..d908f6b3a9b 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -57,7 +57,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 839d5422ad1..79a9ac7d20c 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -24,7 +24,7 @@ use crate::MirPass; use rustc_const_eval::interpret::{ self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame, ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, - Scalar, StackPopCleanup, StackPopUnwind, + Scalar, StackPopCleanup, }; /// The maximum number of bytes that we'll allocate space for a local or the return value. @@ -206,7 +206,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> _args: &[OpTy<'tcx>], _destination: &PlaceTy<'tcx>, _target: Option<BasicBlock>, - _unwind: StackPopUnwind, + _unwind: UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { Ok(None) } @@ -217,7 +217,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> _args: &[OpTy<'tcx>], _destination: &PlaceTy<'tcx>, _target: Option<BasicBlock>, - _unwind: StackPopUnwind, + _unwind: UnwindAction, ) -> InterpResult<'tcx> { throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp") } @@ -225,7 +225,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &rustc_middle::mir::AssertMessage<'tcx>, - _unwind: Option<rustc_middle::mir::BasicBlock>, + _unwind: rustc_middle::mir::UnwindAction, ) -> InterpResult<'tcx> { bug!("panics terminators are not evaluated in ConstProp") } @@ -956,7 +956,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 85e229b694c..699fe44892b 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -683,7 +683,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 0e7dc171a5d..725883b83fa 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -818,7 +818,7 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", TerminatorKind::Resume => "Resume", - TerminatorKind::Abort => "Abort", + TerminatorKind::Terminate => "Terminate", TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 6a73f2a6578..7391a77b0a6 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -122,7 +122,7 @@ impl CoverageGraph { match term.kind { TerminatorKind::Return { .. } - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } => { // The `bb` has more than one _outgoing_ edge, or exits the function. Save the @@ -136,7 +136,7 @@ impl CoverageGraph { debug!(" because term.kind = {:?}", term.kind); // Note that this condition is based on `TerminatorKind`, even though it // theoretically boils down to `successors().len() != 1`; that is, either zero - // (e.g., `Return`, `Abort`) or multiple successors (e.g., `SwitchInt`), but + // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but // since the BCB CFG ignores things like unwind branches (which exist in the // `Terminator`s `successors()` list) checking the number of successors won't // work. diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 2f120258659..287ae217087 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -869,7 +869,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp // Retain spans from all other terminators TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 59b506e7345..0f6c06e370b 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -140,7 +140,7 @@ impl<'tcx> MockBlocks<'tcx> { args: vec![], destination: self.dummy_place.clone(), target: Some(TEMP_BLOCK), - cleanup: None, + unwind: UnwindAction::Continue, from_hir_call: false, fn_span: DUMMY_SP, }, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 15f5df41153..d4db7e2de40 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -567,7 +567,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, - _unwind: rustc_const_eval::interpret::StackPopUnwind, + _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { unimplemented!() } @@ -578,7 +578,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>], _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, - _unwind: rustc_const_eval::interpret::StackPopUnwind, + _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx> { unimplemented!() } @@ -586,7 +586,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &rustc_middle::mir::AssertMessage<'tcx>, - _unwind: Option<BasicBlock>, + _unwind: UnwindAction, ) -> interpret::InterpResult<'tcx> { unimplemented!() } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 35e7efed87a..811935aa990 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -645,8 +645,8 @@ impl WriteInfo { } } TerminatorKind::Goto { .. } - | TerminatorKind::Resume { .. } - | TerminatorKind::Abort { .. } + | TerminatorKind::Resume + | TerminatorKind::Terminate | 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 a028d6356d5..a702113bd99 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -120,7 +120,7 @@ fn remove_dead_unwinds<'tcx>( .into_results_cursor(body); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { let place = match bb_data.terminator().kind { - TerminatorKind::Drop { ref place, unwind: Some(_), .. } => { + TerminatorKind::Drop { ref place, unwind: UnwindAction::Cleanup(_), .. } => { und.derefer(place.as_ref(), body).unwrap_or(*place) } _ => continue, @@ -160,7 +160,7 @@ fn remove_dead_unwinds<'tcx>( let basic_blocks = body.basic_blocks.as_mut(); for &bb in dead_unwinds.iter() { if let Some(unwind) = basic_blocks[bb].terminator_mut().unwind_mut() { - *unwind = None; + *unwind = UnwindAction::Unreachable; } } } @@ -399,7 +399,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let loc = Location { block: bb, statement_index: data.statements.len() }; let terminator = data.terminator(); - let resume_block = self.patch.resume_block(); match terminator.kind { TerminatorKind::Drop { mut place, target, unwind } => { if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) { @@ -408,19 +407,31 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { self.init_data.seek_before(loc); match self.move_data().rev_lookup.find(place.as_ref()) { - LookupResult::Exact(path) => elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - if data.is_cleanup { + LookupResult::Exact(path) => { + let unwind = if data.is_cleanup { Unwind::InCleanup } else { - Unwind::To(Option::unwrap_or(unwind, resume_block)) - }, - bb, - ), + match unwind { + UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup), + UnwindAction::Continue => Unwind::To(self.patch.resume_block()), + UnwindAction::Unreachable => { + Unwind::To(self.patch.unreachable_cleanup_block()) + } + UnwindAction::Terminate => { + Unwind::To(self.patch.terminate_block()) + } + } + }; + elaborate_drop( + &mut Elaborator { ctxt: self }, + terminator.source_info, + place, + path, + target, + unwind, + bb, + ) + } LookupResult::Parent(..) => { if !matches!( terminator.source_info.span.desugaring_kind(), @@ -474,7 +485,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { continue; } if let TerminatorKind::Call { - destination, target: Some(tgt), cleanup: Some(_), .. + destination, + target: Some(tgt), + unwind: UnwindAction::Cleanup(_), + .. } = data.terminator().kind { assert!(!self.patch.is_patched(bb)); @@ -543,8 +557,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // There may be a critical edge after this call, // so mark the return as initialized *before* the // call. - if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } = - data.terminator().kind + if let TerminatorKind::Call { + destination, + target: Some(_), + unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate, + .. + } = data.terminator().kind { assert!(!self.patch.is_patched(bb)); diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 66d32b954e4..8601c1b2d71 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -34,7 +34,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { args, destination: _, target: _, - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } = &terminator.kind diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 8f29066b6e2..159780319ba 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1060,7 +1060,12 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let unwind = if block_data.is_cleanup { Unwind::InCleanup } else { - Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block())) + Unwind::To(match *unwind { + UnwindAction::Cleanup(tgt) => tgt, + UnwindAction::Continue => elaborator.patch.resume_block(), + UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(), + UnwindAction::Terminate => elaborator.patch.terminate_block(), + }) }; elaborate_drop( &mut elaborator, @@ -1147,7 +1152,7 @@ fn insert_panic_block<'tcx>( expected: true, msg: message, target: assert_block, - cleanup: None, + unwind: UnwindAction::Continue, }; let source_info = SourceInfo::outermost(body.span); @@ -1189,7 +1194,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These never unwind. TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop @@ -1248,8 +1253,8 @@ fn create_generator_resume_function<'tcx>( } else if !block.is_cleanup { // Any terminators that *can* unwind but don't have an unwind target set are also // pointed at our poisoning block (unless they're part of the cleanup path). - if let Some(unwind @ None) = block.terminator_mut().unwind_mut() { - *unwind = Some(poison_block); + if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() { + *unwind = UnwindAction::Cleanup(poison_block); } } } @@ -1294,8 +1299,11 @@ fn create_generator_resume_function<'tcx>( fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { let return_block = insert_term_block(body, TerminatorKind::Return); - let term = - TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None }; + let term = TerminatorKind::Drop { + place: Place::from(SELF_ARG), + target: return_block, + unwind: UnwindAction::Continue, + }; let source_info = SourceInfo::outermost(body.span); // Create a block to destroy an unresumed generators. This can only destroy upvars. @@ -1670,7 +1678,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { args, destination, target: Some(_), - cleanup: _, + unwind: _, from_hir_call: _, fn_span: _, } => { @@ -1693,7 +1701,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 15b31d38394..f0cb317f449 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -453,7 +453,7 @@ impl<'tcx> Inliner<'tcx> { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty); - if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind { + if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); } } else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set @@ -500,7 +500,7 @@ impl<'tcx> Inliner<'tcx> { ) { let terminator = caller_body[callsite.block].terminator.take().unwrap(); match terminator.kind { - TerminatorKind::Call { args, destination, cleanup, .. } => { + TerminatorKind::Call { args, destination, unwind, .. } => { // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` // Place could result in two different locations if `f` @@ -571,7 +571,7 @@ impl<'tcx> Inliner<'tcx> { destination: destination_local, callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(), callsite, - cleanup_block: cleanup, + cleanup_block: unwind, in_cleanup_block: false, tcx: self.tcx, expn_data, @@ -813,14 +813,14 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty); if ty.needs_drop(tcx, self.param_env) { self.cost += CALL_PENALTY; - if unwind.is_some() { + if let UnwindAction::Cleanup(_) = unwind { self.cost += LANDINGPAD_PENALTY; } } else { self.cost += INSTR_COST; } } - TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { + TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { let fn_ty = self.instance.subst_mir(tcx, &f.literal.ty()); self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { // Don't give intrinsics the extra penalty for calls @@ -828,20 +828,20 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } else { CALL_PENALTY }; - if cleanup.is_some() { + if let UnwindAction::Cleanup(_) = unwind { self.cost += LANDINGPAD_PENALTY; } } - TerminatorKind::Assert { cleanup, .. } => { + TerminatorKind::Assert { unwind, .. } => { self.cost += CALL_PENALTY; - if cleanup.is_some() { + if let UnwindAction::Cleanup(_) = unwind { self.cost += LANDINGPAD_PENALTY; } } TerminatorKind::Resume => self.cost += RESUME_PENALTY, - TerminatorKind::InlineAsm { cleanup, .. } => { + TerminatorKind::InlineAsm { unwind, .. } => { self.cost += INSTR_COST; - if cleanup.is_some() { + if let UnwindAction::Cleanup(_) = unwind { self.cost += LANDINGPAD_PENALTY; } } @@ -979,7 +979,7 @@ struct Integrator<'a, 'tcx> { destination: Local, callsite_scope: SourceScopeData<'tcx>, callsite: &'a CallSite<'tcx>, - cleanup_block: Option<BasicBlock>, + cleanup_block: UnwindAction, in_cleanup_block: bool, tcx: TyCtxt<'tcx>, expn_data: LocalExpnId, @@ -1014,18 +1014,21 @@ impl Integrator<'_, '_> { new } - fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> { + fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction { if self.in_cleanup_block { - if unwind.is_some() { - bug!("cleanup on cleanup block"); + match unwind { + UnwindAction::Cleanup(_) | UnwindAction::Continue => { + bug!("cleanup on cleanup block"); + } + UnwindAction::Unreachable | UnwindAction::Terminate => return unwind, } - return unwind; } match unwind { - Some(target) => Some(self.map_block(target)), + 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 - None => self.cleanup_block, + UnwindAction::Continue => self.cleanup_block, } } } @@ -1116,15 +1119,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { *target = self.map_block(*target); *unwind = self.map_unwind(*unwind); } - TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => { + TerminatorKind::Call { ref mut target, ref mut unwind, .. } => { if let Some(ref mut tgt) = *target { *tgt = self.map_block(*tgt); } - *cleanup = self.map_unwind(*cleanup); + *unwind = self.map_unwind(*unwind); } - TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => { + TerminatorKind::Assert { ref mut target, ref mut unwind, .. } => { *target = self.map_block(*target); - *cleanup = self.map_unwind(*cleanup); + *unwind = self.map_unwind(*unwind); } TerminatorKind::Return => { terminator.kind = if let Some(tgt) = self.callsite.target { @@ -1134,11 +1137,14 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { } } TerminatorKind::Resume => { - if let Some(tgt) = self.cleanup_block { - terminator.kind = TerminatorKind::Goto { target: tgt } - } + terminator.kind = match self.cleanup_block { + UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt }, + UnwindAction::Continue => TerminatorKind::Resume, + UnwindAction::Unreachable => TerminatorKind::Unreachable, + UnwindAction::Terminate => TerminatorKind::Terminate, + }; } - TerminatorKind::Abort => {} + TerminatorKind::Terminate => {} TerminatorKind::Unreachable => {} TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => { *real_target = self.map_block(*real_target); @@ -1149,11 +1155,11 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { { bug!("False unwinds should have been removed before inlining") } - TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => { + TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => { if let Some(ref mut tgt) = *destination { *tgt = self.map_block(*tgt); } - *cleanup = self.map_unwind(*cleanup); + *unwind = self.map_unwind(*unwind); } } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b52de4b72c9..2e418c1dafc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -159,7 +159,7 @@ fn remap_mir_for_const_eval_select<'tcx>( ref mut args, destination, target, - cleanup, + unwind, fn_span, .. } if let ty::FnDef(def_id, _) = *literal.ty().kind() @@ -196,7 +196,7 @@ fn remap_mir_for_const_eval_select<'tcx>( }; method(place) }).collect(); - terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span }; + terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, from_hir_call: false, fn_span }; } _ => {} } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 101fae2f08c..7dc5878e047 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -54,7 +54,6 @@ fn lower_slice_len_call<'tcx>( args, destination, target: Some(bb), - cleanup: None, from_hir_call: true, .. } => { 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 e962819b691..4941c9edce3 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::Abort + | TerminatorKind::Terminate | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } @@ -103,11 +103,11 @@ impl RemoveNoopLandingPads { for bb in postorder { debug!(" processing {:?}", bb); if let Some(unwind) = body[bb].terminator_mut().unwind_mut() { - if let Some(unwind_bb) = *unwind { + if let UnwindAction::Cleanup(unwind_bb) = *unwind { if nop_landing_pads.contains(unwind_bb) { debug!(" removing noop landing pad"); landing_pads_removed += 1; - *unwind = None; + *unwind = UnwindAction::Continue; } } } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index d76ab95faba..ef367faf6a7 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -112,7 +112,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield { .. } - | TerminatorKind::Abort + | TerminatorKind::Terminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::InlineAsm { .. } @@ -164,7 +164,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { } TerminatorKind::Resume - | TerminatorKind::Abort + | TerminatorKind::Terminate | 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 9e406eba0fc..2787fe2ce42 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -499,7 +499,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { args: vec![Operand::Move(ref_loc)], destination: dest, target: Some(next), - cleanup: Some(cleanup), + unwind: UnwindAction::Cleanup(cleanup), from_hir_call: true, fn_span: self.span, }, @@ -540,7 +540,11 @@ impl<'tcx> CloneShimBuilder<'tcx> { self.make_clone_call(dest_field, src_field, ity, next_block, unwind); self.block( vec![], - TerminatorKind::Drop { place: dest_field, target: unwind, unwind: None }, + TerminatorKind::Drop { + place: dest_field, + target: unwind, + unwind: UnwindAction::Terminate, + }, true, ); unwind = next_unwind; @@ -776,10 +780,10 @@ fn build_call_shim<'tcx>( args, destination: Place::return_place(), target: Some(BasicBlock::new(1)), - cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment { - Some(BasicBlock::new(3)) + unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment { + UnwindAction::Cleanup(BasicBlock::new(3)) } else { - None + UnwindAction::Continue }, from_hir_call: true, fn_span: span, @@ -792,7 +796,11 @@ fn build_call_shim<'tcx>( block( &mut blocks, vec![], - TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(2), unwind: None }, + TerminatorKind::Drop { + place: rcvr_place(), + target: BasicBlock::new(2), + unwind: UnwindAction::Continue, + }, false, ); } @@ -803,7 +811,11 @@ fn build_call_shim<'tcx>( block( &mut blocks, vec![], - TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), unwind: None }, + TerminatorKind::Drop { + place: rcvr_place(), + target: BasicBlock::new(4), + unwind: UnwindAction::Terminate, + }, true, ); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index f41edff8513..7bcff7e07fb 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -852,7 +852,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(create_fn_mono_item(tcx, instance, source)); } } - mir::TerminatorKind::Abort { .. } => { + mir::TerminatorKind::Terminate { .. } => { let instance = Instance::mono( tcx, tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), @@ -872,6 +872,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'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)); + } + } + self.super_terminator(terminator, location); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 5210b8fe69d..e03ce5d7120 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -423,11 +423,11 @@ impl<'a> Parser<'a> { if let token::Literal(Lit { kind: token::LitKind::Integer | token::LitKind::Float, symbol, - suffix, + suffix: Some(suffix), // no suffix makes it a valid literal }) = self.token.kind && rustc_ast::MetaItemLit::from_token(&self.token).is_none() { - Some((symbol.as_str().len(), suffix.unwrap())) + Some((symbol.as_str().len(), suffix)) } else { None } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e69a9d0aeca..0c9d306081e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1607,7 +1607,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident); err.span_label(ident.span, &format!("private {}", descr)); - if let Some(span) = ctor_fields_span { + + let mut non_exhaustive = None; + // If an ADT is foreign and marked as `non_exhaustive`, then that's + // probably why we have the privacy error. + // Otherwise, point out if the struct has any private fields. + if let Some(def_id) = res.opt_def_id() + && !def_id.is_local() + && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive) + { + non_exhaustive = Some(attr.span); + } else if let Some(span) = ctor_fields_span { err.span_label(span, "a constructor is private if any of the fields is private"); if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) { err.multipart_suggestion_verbose( @@ -1656,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !first && binding.vis.is_public() { note_span.push_span_label(def_span, "consider importing it directly"); } + // Final step in the import chain, point out if the ADT is `non_exhaustive` + // which is probably why this privacy violation occurred. + if next_binding.is_none() && let Some(span) = non_exhaustive { + note_span.push_span_label( + span, + format!("cannot be constructed because it is `#[non_exhaustive]`"), + ); + } err.span_note(note_span, &msg); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 19f46d45af6..b1a696d093e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -122,6 +122,12 @@ pub(crate) enum ConstantItemKind { Static, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum RecordPartialRes { + Yes, + No, +} + /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -2682,6 +2688,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &path, PathSource::Trait(AliasPossibility::No), Finalize::new(trait_ref.ref_id, trait_ref.path.span), + RecordPartialRes::Yes, ); self.diagnostic_metadata.currently_processing_impl_trait = None; if let Some(def_id) = res.expect_full_res().opt_def_id() { @@ -3420,6 +3427,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &Segment::from_path(path), source, Finalize::new(id, path.span), + RecordPartialRes::Yes, ); } @@ -3430,6 +3438,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], source: PathSource<'ast>, finalize: Finalize, + record_partial_res: RecordPartialRes, ) -> PartialRes { let ns = source.namespace(); @@ -3636,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { _ => report_errors(self, None), }; - if !matches!(source, PathSource::TraitItem(..)) { + if record_partial_res == RecordPartialRes::Yes { // Avoid recording definition of `A::B` in `<T as A>::B::C`. self.r.record_partial_res(node_id, partial_res); self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); @@ -3740,7 +3749,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ))); } - // Make sure `A::B` in `<T as A::B>::C` is a trait item. + let num_privacy_errors = self.r.privacy_errors.len(); + // Make sure that `A` in `<T as A>::B::C` is a trait. + let trait_res = self.smart_resolve_path_fragment( + &None, + &path[..qself.position], + PathSource::Trait(AliasPossibility::No), + Finalize::new(finalize.node_id, qself.path_span), + RecordPartialRes::No, + ); + + if trait_res.expect_full_res() == Res::Err { + return Ok(Some(trait_res)); + } + + // Truncate additional privacy errors reported above, + // because they'll be recomputed below. + self.r.privacy_errors.truncate(num_privacy_errors); + + // Make sure `A::B` in `<T as A>::B::C` is a trait item. // // Currently, `path` names the full item (`A::B::C`, in // our example). so we extract the prefix of that that is @@ -3753,6 +3780,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &path[..=qself.position], PathSource::TraitItem(ns), Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), + RecordPartialRes::No, ); // The remaining segments (the `C` in our example) will diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 86e30dd0f6a..0befff894ef 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -143,7 +143,7 @@ fn rustc_terminator_to_terminator( otherwise: targets.otherwise().as_usize(), }, Resume => Terminator::Resume, - Abort => Terminator::Abort, + Terminate => Terminator::Abort, Return => Terminator::Return, Unreachable => Terminator::Unreachable, Drop { .. } => todo!(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0e55e81143d..7affad9aa01 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1496,6 +1496,7 @@ symbols! { trait_alias, trait_upcasting, transmute, + transmute_generic_consts, transmute_opts, transmute_trait, transparent, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index cac7ff72267..ee883285531 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,5 +1,5 @@ use rustc_data_structures::base_n; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -81,9 +81,9 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>( struct BinderLevel { /// The range of distances from the root of what's /// being printed, to the lifetimes in a binder. - /// Specifically, a `BrAnon(i)` lifetime has depth - /// `lifetime_depths.start + i`, going away from the - /// the root and towards its use site, as `i` increases. + /// Specifically, a `BrAnon` lifetime has depth + /// `lifetime_depths.start + index`, going away from the + /// the root and towards its use site, as the var index increases. /// This is used to flatten rustc's pairing of `BrAnon` /// (intra-binder disambiguation) with a `DebruijnIndex` /// (binder addressing), to "true" de Bruijn indices, @@ -208,24 +208,15 @@ impl<'tcx> SymbolMangler<'tcx> { where T: TypeVisitable<TyCtxt<'tcx>>, { - // FIXME(non-lifetime-binders): What to do here? - let regions = if value.has_late_bound_regions() { - self.tcx.collect_referenced_late_bound_regions(value) - } else { - FxHashSet::default() - }; - let mut lifetime_depths = self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i); - let lifetimes = regions - .into_iter() - .map(|br| match br { - ty::BrAnon(i, _) => i, - _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), - }) - .max() - .map_or(0, |max| max + 1); + // FIXME(non-lifetime-binders): What to do here? + let lifetimes = value + .bound_vars() + .iter() + .filter(|var| matches!(var, ty::BoundVariableKind::Region(..))) + .count() as u32; self.push_opt_integer_62("G", lifetimes as u64); lifetime_depths.end += lifetimes; @@ -338,9 +329,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. - ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => { + ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon(_) }) => { let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; - let depth = binder.lifetime_depths.start + i; + let depth = binder.lifetime_depths.start + var.as_u32(); 1 + (self.binders.last().unwrap().lifetime_depths.end - 1 - depth) } diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 2e5a8b7debc..55025e2e72b 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -257,7 +257,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { self.primitive_var_infos.push(CanonicalVarInfo { kind }); var }); - let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) }; + let br = ty::BoundRegion { var, kind: BrAnon(None) }; self.interner().mk_re_late_bound(self.binder_index, br) } @@ -300,14 +300,20 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { ty::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: placeholder.universe, - name: BoundTyKind::Anon(self.variables.len() as u32), + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(self.variables.len()), + kind: ty::BoundTyKind::Anon, + }, }), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ty::UniverseIndex::ROOT, - name: ty::BoundTyKind::Anon(self.variables.len() as u32), + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(self.variables.len()), + kind: ty::BoundTyKind::Anon, + }, }), CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"), }, @@ -345,7 +351,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { var }), ); - let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) }; + let bt = ty::BoundTy { var, kind: BoundTyKind::Anon }; self.interner().mk_bound(self.binder_index, bt) } @@ -373,7 +379,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( ty::Placeholder { universe: placeholder.universe, - name: ty::BoundVar::from(self.variables.len()), + bound: ty::BoundVar::from(self.variables.len()), }, c.ty(), ), @@ -385,7 +391,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( ty::Placeholder { universe: ty::UniverseIndex::ROOT, - name: ty::BoundVar::from(self.variables.len()), + bound: ty::BoundVar::from(self.variables.len()), }, c.ty(), ), diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index ee90488730a..714b6dfb717 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -188,7 +188,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } else { // For placeholders which were already part of the input, we simply map this // universal bound variable back the placeholder of the input. - original_values[info.expect_anon_placeholder() as usize] + original_values[info.expect_placeholder_index()] } }, )); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index 4a3b7e42bac..9e851b788a5 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -95,17 +95,15 @@ fn replace_erased_lifetimes_with_bound_vars<'tcx>( let mut counter = 0; let ty = tcx.fold_regions(ty, |mut r, current_depth| { if let ty::ReErased = r.kind() { - let br = ty::BoundRegion { - var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter, None), - }; + let br = + ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) }; counter += 1; r = tcx.mk_re_late_bound(current_depth, br); } r }); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), + (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))), ); ty::Binder::bind_with_vars(ty, bound_vars) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b8d9cff9c48..826fc63ca06 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -772,7 +772,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { } ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = ty::PlaceholderRegion { universe, name: br.kind }; + let p = ty::PlaceholderRegion { universe, bound: br }; self.mapped_regions.insert(p, br); self.infcx.tcx.mk_re_placeholder(p) } @@ -790,7 +790,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { } ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = ty::PlaceholderType { universe, name: bound_ty.kind }; + let p = ty::PlaceholderType { universe, bound: bound_ty }; self.mapped_types.insert(p, bound_ty); self.infcx.tcx.mk_placeholder(p) } @@ -809,7 +809,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> { } ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = ty::PlaceholderConst { universe, name: bound_const }; + let p = ty::PlaceholderConst { universe, bound: bound_const }; self.mapped_consts.insert(p, bound_const); self.infcx.tcx.mk_const(p, ct.ty()) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b58e62536d6..6bb53418bea 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2,12 +2,6 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection -// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to -// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be -// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap` -// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242 -#![allow(rustc::potential_query_instability)] - use self::EvaluationResult::*; use self::SelectionCandidate::*; @@ -32,8 +26,7 @@ use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; use crate::traits::Unimplemented; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Diagnostic; use rustc_hir as hir; @@ -2782,7 +2775,7 @@ struct ProvisionalEvaluationCache<'tcx> { /// - then we determine that `E` is in error -- we will then clear /// all cache values whose DFN is >= 4 -- in this case, that /// means the cached value for `F`. - map: RefCell<FxHashMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>, + map: RefCell<FxIndexMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>, /// The stack of args that we assume to be true because a `WF(arg)` predicate /// is on the stack above (and because of wellformedness is coinductive). @@ -2930,12 +2923,13 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// have a performance impact in practice. fn on_completion(&self, dfn: usize) { debug!(?dfn, "on_completion"); - - for (fresh_trait_pred, eval) in - self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn) - { - debug!(?fresh_trait_pred, ?eval, "on_completion"); - } + self.map.borrow_mut().retain(|fresh_trait_pred, eval| { + if eval.from_dfn >= dfn { + debug!(?fresh_trait_pred, ?eval, "on_completion"); + return false; + } + true + }); } } @@ -3017,7 +3011,7 @@ fn bind_generator_hidden_types_above<'tcx>( if let ty::ReErased = r.kind() { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter, None), + kind: ty::BrAnon(None), }; counter += 1; r = tcx.mk_re_late_bound(current_depth, br); @@ -3033,7 +3027,7 @@ fn bind_generator_hidden_types_above<'tcx>( debug_assert!(!hidden_types.has_erased_regions()); } let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain( - (num_bound_variables..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), + (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))), )); ty::Binder::bind_with_vars(hidden_types, bound_vars) } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index f8c8f744e6d..9683e48478e 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -730,7 +730,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> { ty::GenericParamDefKind::Lifetime => { let br = ty::BoundRegion { var: ty::BoundVar::from_usize(substs.len()), - kind: ty::BrAnon(substs.len() as u32, None), + kind: ty::BrAnon(None), }; tcx.mk_re_late_bound(ty::INNERMOST, br).into() } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 527f6013a15..2be72879b7b 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -376,7 +376,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> { ty::Placeholder(_placeholder) => { chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex { ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() }, - idx: _placeholder.name.expect_anon() as usize, + idx: _placeholder.bound.var.as_usize(), }) } ty::Infer(_infer) => unimplemented!(), @@ -479,12 +479,15 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> { ty::DebruijnIndex::from_usize(bound.debruijn.depth() as usize), ty::BoundTy { var: ty::BoundVar::from_usize(bound.index), - kind: ty::BoundTyKind::Anon(bound.index as u32), + kind: ty::BoundTyKind::Anon, }, ), TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder { universe: ty::UniverseIndex::from_usize(placeholder.ui.counter), - name: ty::BoundTyKind::Anon(placeholder.idx as u32), + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(placeholder.idx), + kind: ty::BoundTyKind::Anon, + }, }), TyKind::InferenceVar(_, _) => unimplemented!(), TyKind::Dyn(_) => unimplemented!(), @@ -530,13 +533,16 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t ty::DebruijnIndex::from_u32(var.debruijn.depth()), ty::BoundRegion { var: ty::BoundVar::from_usize(var.index), - kind: ty::BrAnon(var.index as u32, None), + kind: ty::BrAnon(None), }, ), chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(), chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder { universe: ty::UniverseIndex::from_usize(p.ui.counter), - name: ty::BoundRegionKind::BrAnon(p.idx as u32, None), + bound: ty::BoundRegion { + var: ty::BoundVar::from_usize(p.idx), + kind: ty::BoundRegionKind::BrAnon(None), + }, }), chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static, chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased, @@ -685,7 +691,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru let self_ty = interner.tcx.mk_bound( // This is going to be wrapped in a binder ty::DebruijnIndex::from_usize(1), - ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon(0) }, + ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon }, ); let where_clauses = predicates.into_iter().map(|predicate| { let (predicate, binders, _named_regions) = @@ -970,7 +976,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for BoundVarsCollector<'tcx> { } } - ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) { + ty::BoundRegionKind::BrAnon(_) => match self.parameters.entry(br.var.as_u32()) { Entry::Vacant(entry) => { entry.insert(chalk_ir::VariableKind::Lifetime); } @@ -1030,8 +1036,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> { match *r { ty::ReLateBound(index, br) if index == self.binder_index => match br.kind { ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) { - Some(idx) => { - let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) }; + Some(_) => { + let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(None) }; return self.tcx.mk_re_late_bound(index, new_br); } None => panic!("Missing `BrNamed`."), @@ -1090,7 +1096,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> { ty::Param(param) => match self.list.iter().position(|r| r == ¶m) { Some(idx) => self.tcx.mk_placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::from_usize(0), - name: ty::BoundTyKind::Anon(idx as u32), + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(idx), + kind: ty::BoundTyKind::Anon, + }, }), None => { self.list.push(param); @@ -1098,7 +1107,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> { self.params.insert(idx as u32, param); self.tcx.mk_placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::from_usize(0), - name: ty::BoundTyKind::Anon(idx as u32), + bound: ty::BoundTy { + var: ty::BoundVar::from_usize(idx), + kind: ty::BoundTyKind::Anon, + }, }) } }, @@ -1115,7 +1127,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> { Some(idx) => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(*idx), - kind: ty::BrAnon(*idx, None), + kind: ty::BrAnon(None), }; self.tcx.mk_re_late_bound(self.binder_index, br) } @@ -1123,7 +1135,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> { let idx = self.named_regions.len() as u32; let br = ty::BoundRegion { var: ty::BoundVar::from_u32(idx), - kind: ty::BrAnon(idx, None), + kind: ty::BrAnon(None), }; self.named_regions.insert(_re.def_id, idx); self.tcx.mk_re_late_bound(self.binder_index, br) @@ -1156,8 +1168,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseParamsSubstitutor<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match *t.kind() { - ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => { - match self.params.get(&name.expect_anon()) { + ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, bound }) => { + match self.params.get(&bound.var.as_u32()) { Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name), None => t, } @@ -1189,8 +1201,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match t.kind() { ty::Placeholder(p) if p.universe == self.universe_index => { - self.next_ty_placeholder = - self.next_ty_placeholder.max(p.name.expect_anon() as usize + 1); + self.next_ty_placeholder = self.next_ty_placeholder.max(p.bound.var.as_usize() + 1); } _ => (), @@ -1202,8 +1213,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector { fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { ty::RePlaceholder(p) if p.universe == self.universe_index => { - if let ty::BoundRegionKind::BrAnon(anon, _) = p.name { - self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon); + if let ty::BoundRegionKind::BrAnon(_) = p.bound.kind { + self.next_anon_region_placeholder = + self.next_anon_region_placeholder.max(p.bound.var.as_u32()); } // FIXME: This doesn't seem to handle BrNamed at all? } diff --git a/config.example.toml b/config.example.toml index 5ef83760aed..15c6bc0f123 100644 --- a/config.example.toml +++ b/config.example.toml @@ -16,7 +16,7 @@ # Use different pre-set defaults than the global defaults. # # See `src/bootstrap/defaults` for more information. -# Note that this has no default value (x.py uses the defaults in `config.toml.example`). +# Note that this has no default value (x.py uses the defaults in `config.example.toml`). #profile = <none> # Keeps track of the last version of `x.py` used. diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 8a8d4caf96f..5888e2960bb 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -764,6 +764,7 @@ where { type Error = U::Error; + #[inline] fn try_into(self) -> Result<U, U::Error> { U::try_from(self) } @@ -779,6 +780,7 @@ where { type Error = Infallible; + #[inline] fn try_from(value: U) -> Result<Self, Self::Error> { Ok(U::into(value)) } diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs index b203806f460..7394977e507 100644 --- a/library/core/src/num/shells/u16.rs +++ b/library/core/src/num/shells/u16.rs @@ -1,4 +1,4 @@ -//! Redundant constants module for the [`i16` primitive type][i16]. +//! Redundant constants module for the [`u16` primitive type][u16]. //! //! New code should use the associated constants directly on the primitive type. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index fcf9707b74d..057053297cd 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -605,8 +605,6 @@ impl<T> Option<T> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] - /// /// let x: Option<u32> = Some(2); /// assert_eq!(x.is_some_and(|x| x > 1), true); /// @@ -618,7 +616,7 @@ impl<T> Option<T> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")] pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool { match self { None => false, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 76d9b0385d0..241602c0e18 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -545,8 +545,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] - /// /// let x: Result<u32, &str> = Ok(2); /// assert_eq!(x.is_ok_and(|x| x > 1), true); /// @@ -558,7 +556,7 @@ impl<T, E> Result<T, E> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")] pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool { match self { Err(_) => false, @@ -590,7 +588,6 @@ impl<T, E> Result<T, E> { /// # Examples /// /// ``` - /// #![feature(is_some_and)] /// use std::io::{Error, ErrorKind}; /// /// let x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, "!")); @@ -604,7 +601,7 @@ impl<T, E> Result<T, E> { /// ``` #[must_use] #[inline] - #[unstable(feature = "is_some_and", issue = "93050")] + #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")] pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool { match self { Ok(_) => false, diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 6acb937e784..14c455d4fa3 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -339,7 +339,7 @@ impl<W: Write> BufWriter<W> { let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; // SAFETY: forget(self) prevents double dropping inner - let inner = unsafe { ptr::read(&mut self.inner) }; + let inner = unsafe { ptr::read(&self.inner) }; mem::forget(self); (inner, buf) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8c118b95b0a..736b3c0497c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -289,7 +289,6 @@ #![feature(hashmap_internals)] #![feature(ip)] #![feature(ip_in_core)] -#![feature(is_some_and)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_write_slice)] #![feature(panic_can_unwind)] diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 3982d363661..4b42ad65ee6 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -869,7 +869,7 @@ impl TcpListener { /// use std::net::{TcpListener, TcpStream}; /// /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> { - /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); + /// let listener = TcpListener::bind(("127.0.0.1", port)).unwrap(); /// listener.into_incoming() /// .filter_map(Result::ok) /* Ignore failed connections */ /// } diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs index ce74ad3486e..1442a397e76 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -49,7 +49,9 @@ macro_rules! __thread_local_inner { #[inline] fn __init() -> $t { $init } - #[cfg_attr(not(bootstrap), inline)] + // `#[inline] does not work on windows-gnu due to linking errors around dllimports. + // See https://github.com/rust-lang/rust/issues/109797. + #[cfg_attr(not(windows), inline)] unsafe fn __getit( init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 373157bd9e8..956db577d53 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> { opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); let f = File::open(junction, &opts)?; let h = f.as_inner().as_raw_handle(); - unsafe { let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]); let data_ptr = data.0.as_mut_ptr(); + let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE); let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>(); // Zero the header to ensure it's fully initialized, including reserved parameters. *db = mem::zeroed(); - let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>(); - let mut i = 0; + let reparse_target_slice = { + let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>(); + // Compute offset in bytes and then divide so that we round down + // rather than hit any UB (admittedly this arithmetic should work + // out so that this isn't necessary) + let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap(); + let buf_len_wchars = buf_len_bytes / core::mem::size_of::<c::WCHAR>(); + core::slice::from_raw_parts_mut(buf_start, buf_len_wchars) + }; + // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(original.as_os_str().encode_wide()) { - *buf.add(i) = c; + let iter = br"\??\" + .iter() + .map(|x| *x as u16) + .chain(original.as_os_str().encode_wide()) + .chain(core::iter::once(0)); + let mut i = 0; + for c in iter { + if i >= reparse_target_slice.len() { + return Err(crate::io::const_io_error!( + crate::io::ErrorKind::InvalidFilename, + "Input filename is too long" + )); + } + reparse_target_slice[i] = c; i += 1; } - *buf.add(i) = 0; - i += 1; (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT; (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD; (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD; diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 965dfa5f398..a158d1f718e 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -45,6 +45,7 @@ dependencies = [ "hex", "ignore", "is-terminal", + "junction", "libc", "object", "once_cell", @@ -350,6 +351,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] +name = "junction" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca39ef0d69b18e6a2fd14c2f0a1d593200f4a4ed949b240b5917ab51fac754cb" +dependencies = [ + "scopeguard", + "winapi", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2fbe7aa57aa..eeda6d7c121 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -61,6 +61,9 @@ sysinfo = { version = "0.26.0", optional = true } [target.'cfg(not(target_os = "solaris"))'.dependencies] fd-lock = "3.0.8" +[target.'cfg(windows)'.dependencies.junction] +version = "1.0.0" + [target.'cfg(windows)'.dependencies.windows] version = "0.46.0" features = [ diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index b8b6b7b2d4e..f038aceb34c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -227,27 +227,36 @@ pub struct Config { pub reuse: Option<PathBuf>, pub cargo_native_static: bool, pub configure_args: Vec<String>, + pub out: PathBuf, + pub rust_info: channel::GitInfo, // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + #[cfg(not(test))] initial_rustfmt: RefCell<RustfmtState>, #[cfg(test)] pub initial_rustfmt: RefCell<RustfmtState>, - pub out: PathBuf, - pub rust_info: channel::GitInfo, } #[derive(Default, Deserialize)] #[cfg_attr(test, derive(Clone))] pub struct Stage0Metadata { + pub compiler: CompilerMetadata, pub config: Stage0Config, pub checksums_sha256: HashMap<String, String>, pub rustfmt: Option<RustfmtMetadata>, } #[derive(Default, Deserialize)] #[cfg_attr(test, derive(Clone))] +pub struct CompilerMetadata { + pub date: String, + pub version: String, +} + +#[derive(Default, Deserialize)] +#[cfg_attr(test, derive(Clone))] pub struct Stage0Config { pub dist_server: String, pub artifacts_server: String, @@ -1000,10 +1009,10 @@ impl Config { config.out = crate::util::absolute(&config.out); } - config.initial_rustc = build - .rustc - .map(PathBuf::from) - .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc")); + config.initial_rustc = build.rustc.map(PathBuf::from).unwrap_or_else(|| { + config.download_beta_toolchain(); + config.out.join(config.build.triple).join("stage0/bin/rustc") + }); config.initial_cargo = build .cargo .map(PathBuf::from) diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs index 5cea143e0a7..50569eb4f37 100644 --- a/src/bootstrap/config/tests.rs +++ b/src/bootstrap/config/tests.rs @@ -33,35 +33,58 @@ fn download_ci_llvm() { )); } +// FIXME(ozkanonur): extend scope of the test +// refs: +// - https://github.com/rust-lang/rust/issues/109120 +// - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487 #[test] fn detect_src_and_out() { - let cfg = parse(""); + fn test(cfg: Config, build_dir: Option<&str>) { + // This will bring absolute form of `src/bootstrap` path + let current_dir = std::env::current_dir().unwrap(); - // This will bring absolute form of `src/bootstrap` path - let current_dir = std::env::current_dir().unwrap(); + // get `src` by moving into project root path + let expected_src = current_dir.ancestors().nth(2).unwrap(); + assert_eq!(&cfg.src, expected_src); - // get `src` by moving into project root path - let expected_src = current_dir.ancestors().nth(2).unwrap(); + // Sanity check for `src` + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let expected_src = manifest_dir.ancestors().nth(2).unwrap(); + assert_eq!(&cfg.src, expected_src); - assert_eq!(&cfg.src, expected_src); + // test if build-dir was manually given in config.toml + if let Some(custom_build_dir) = build_dir { + assert_eq!(&cfg.out, Path::new(custom_build_dir)); + } + // test the native bootstrap way + else { + // This should bring output path of bootstrap in absolute form + let cargo_target_dir = env::var_os("CARGO_TARGET_DIR").expect( + "CARGO_TARGET_DIR must been provided for the test environment from bootstrap", + ); - // This should bring output path of bootstrap in absolute form - let cargo_target_dir = env::var_os("CARGO_TARGET_DIR") - .expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap"); + // Move to `build` from `build/bootstrap` + let expected_out = Path::new(&cargo_target_dir).parent().unwrap(); + assert_eq!(&cfg.out, expected_out); - // Move to `build` from `build/bootstrap` - let expected_out = Path::new(&cargo_target_dir).parent().unwrap(); - assert_eq!(&cfg.out, expected_out); + let args: Vec<String> = env::args().collect(); - let args: Vec<String> = env::args().collect(); + // Another test for `out` as a sanity check + // + // This will bring something similar to: + // `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804` + // `{build-dir}` can be anywhere, not just in the rust project directory. + let dep = Path::new(args.first().unwrap()); + let expected_out = dep.ancestors().nth(4).unwrap(); - // Another test for `out` as a sanity check - // - // This will bring something similar to: - // `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804` - // `{config_toml_place}` can be anywhere, not just in the rust project directory. - let dep = Path::new(args.first().unwrap()); - let expected_out = dep.ancestors().nth(4).unwrap(); + assert_eq!(&cfg.out, expected_out); + } + } + + test(parse(""), None); - assert_eq!(&cfg.out, expected_out); + { + let build_dir = if cfg!(windows) { Some("C:\\tmp") } else { Some("/tmp") }; + test(parse("build.build-dir = \"/tmp\""), build_dir); + } } diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 8fbc034965a..24251556584 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -367,26 +367,70 @@ impl Config { pub(crate) fn download_ci_rustc(&self, commit: &str) { self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})")); + let version = self.artifact_version_part(commit); + // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the + // `rustc_private` crates for tools. + let extra_components = ["rustc-dev"]; + + self.download_toolchain( + &version, + "ci-rustc", + commit, + &extra_components, + Self::download_ci_component, + ); + } + + pub(crate) fn download_beta_toolchain(&self) { + self.verbose(&format!("downloading stage0 beta artifacts")); + + let date = &self.stage0_metadata.compiler.date; + let version = &self.stage0_metadata.compiler.version; + let extra_components = ["cargo"]; + + let download_beta_component = |config: &Config, filename, prefix: &_, date: &_| { + config.download_component(DownloadSource::Dist, filename, prefix, date, "stage0") + }; + + self.download_toolchain( + version, + "stage0", + date, + &extra_components, + download_beta_component, + ); + } + + fn download_toolchain( + &self, + // FIXME(ozkanonur) use CompilerMetadata instead of `version: &str` + version: &str, + sysroot: &str, + stamp_key: &str, + extra_components: &[&str], + download_component: fn(&Config, String, &str, &str), + ) { let host = self.build.triple; - let bin_root = self.out.join(host).join("ci-rustc"); + let bin_root = self.out.join(host).join(sysroot); let rustc_stamp = bin_root.join(".rustc-stamp"); - if !bin_root.join("bin").join("rustc").exists() || program_out_of_date(&rustc_stamp, commit) + if !bin_root.join("bin").join(exe("rustc", self.build)).exists() + || program_out_of_date(&rustc_stamp, stamp_key) { if bin_root.exists() { t!(fs::remove_dir_all(&bin_root)); } let filename = format!("rust-std-{version}-{host}.tar.xz"); let pattern = format!("rust-std-{host}"); - self.download_ci_component(filename, &pattern, commit); + download_component(self, filename, &pattern, stamp_key); let filename = format!("rustc-{version}-{host}.tar.xz"); - self.download_ci_component(filename, "rustc", commit); - // download-rustc doesn't need its own cargo, it can just use beta's. - let filename = format!("rustc-dev-{version}-{host}.tar.xz"); - self.download_ci_component(filename, "rustc-dev", commit); - let filename = format!("rust-src-{version}.tar.xz"); - self.download_ci_component(filename, "rust-src", commit); + download_component(self, filename, "rustc", stamp_key); + + for component in extra_components { + let filename = format!("{component}-{version}-{host}.tar.xz"); + download_component(self, filename, component, stamp_key); + } if self.should_fix_bins_and_dylibs() { self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc")); @@ -403,7 +447,7 @@ impl Config { } } - t!(fs::write(rustc_stamp, commit)); + t!(fs::write(rustc_stamp, stamp_key)); } } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 84afddbf979..058ff429e80 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1133,7 +1133,7 @@ impl Step for Tidy { if builder.config.channel == "dev" || builder.config.channel == "nightly" { builder.info("fmt check"); if builder.initial_rustfmt().is_none() { - let inferred_rustfmt_dir = builder.config.initial_rustc.parent().unwrap(); + let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap(); eprintln!( "\ error: no `rustfmt` binary found in {PATH} diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 9a6aaffe22b..2e1adbf63bb 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -146,106 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { fs::symlink(src, dest) } - // Creating a directory junction on windows involves dealing with reparse - // points and the DeviceIoControl function, and this code is a skeleton of - // what can be found here: - // - // http://www.flexhex.com/docs/articles/hard-links.phtml #[cfg(windows)] fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> { - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - - use windows::{ - core::PCWSTR, - Win32::Foundation::{CloseHandle, HANDLE}, - Win32::Storage::FileSystem::{ - CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS, - FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, - MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING, - }, - Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT, - Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT}, - Win32::System::IO::DeviceIoControl, - }; - - #[allow(non_snake_case)] - #[repr(C)] - struct REPARSE_MOUNTPOINT_DATA_BUFFER { - ReparseTag: u32, - ReparseDataLength: u32, - Reserved: u16, - ReparseTargetLength: u16, - ReparseTargetMaximumLength: u16, - Reserved1: u16, - ReparseTarget: u16, - } - - fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> { - Ok(s.as_ref().encode_wide().chain(Some(0)).collect()) - } - - // We're using low-level APIs to create the junction, and these are more - // picky about paths. For example, forward slashes cannot be used as a - // path separator, so we should try to canonicalize the path first. - let target = fs::canonicalize(target)?; - - fs::create_dir(junction)?; - - let path = to_u16s(junction)?; - - let h = unsafe { - CreateFileW( - PCWSTR(path.as_ptr()), - FILE_ACCESS_FLAGS(GENERIC_WRITE), - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - None, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - HANDLE::default(), - ) - } - .map_err(|_| io::Error::last_os_error())?; - - unsafe { - #[repr(C, align(8))] - struct Align8<T>(T); - let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); - let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER; - let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16; - let mut i = 0; - // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(target.as_os_str().encode_wide().skip(4)) { - *buf.offset(i) = c; - i += 1; - } - *buf.offset(i) = 0; - i += 1; - - (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - (*db).ReparseTargetMaximumLength = (i * 2) as u16; - (*db).ReparseTargetLength = ((i - 1) * 2) as u16; - (*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32; - - let mut ret = 0u32; - DeviceIoControl( - h, - FSCTL_SET_REPARSE_POINT, - Some(db.cast()), - (*db).ReparseDataLength + 8, - None, - 0, - Some(&mut ret), - None, - ) - .ok() - .map_err(|_| io::Error::last_os_error())?; - } - - unsafe { CloseHandle(h) }; - Ok(()) + junction::create(&target, &junction) } } diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 960c1de1782..ae180439d23 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -38,6 +38,15 @@ future. Attempting to use these error numbers on stable will result in the code sample being interpreted as plain text. +### `missing_doc_code_examples` lint + +This lint will emit a warning if an item doesn't have a code example in its documentation. +It can be enabled using: + +```rust,ignore (nightly) +#![deny(rustdoc::missing_doc_code_examples)] +``` + ## Extensions to the `#[doc]` attribute These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md index cf1e6a8d3ca..16457ed0ff8 100644 --- a/src/doc/rustdoc/src/write-documentation/what-to-include.md +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -39,9 +39,7 @@ warning: 1 warning emitted As a library author, adding the lint `#![deny(missing_docs)]` is a great way to ensure the project does not drift away from being documented well, and `#![warn(missing_docs)]` is a good way to move towards comprehensive -documentation. In addition to docs, `#![deny(rustdoc::missing_doc_code_examples)]` -ensures each function contains a usage example. In our example above, the -warning is resolved by adding crate level documentation. +documentation. There are more lints in the upcoming chapter [Lints][rustdoc-lints]. diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 02b358e863b..7a2449cbe9a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -136,10 +136,6 @@ impl Buffer { self.into_inner() } - pub(crate) fn is_for_html(&self) -> bool { - self.for_html - } - pub(crate) fn reserve(&mut self, additional: usize) { self.buffer.reserve(additional) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index d75d03071f8..1e3cd266850 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -50,6 +50,7 @@ use std::string::ToString; use askama::Template; use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; @@ -69,7 +70,7 @@ use crate::formats::item_type::ItemType; use crate::formats::{AssocItemRender, Impl, RenderMode}; use crate::html::escape::Escape; use crate::html::format::{ - href, join_with_double_colon, print_abi_with_space, print_constness_with_space, + display_fn, href, join_with_double_colon, print_abi_with_space, print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space, Buffer, Ending, HrefError, PrintWithSpace, }; @@ -408,128 +409,134 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { ) } -fn document( - w: &mut Buffer, - cx: &mut Context<'_>, - item: &clean::Item, - parent: Option<&clean::Item>, +fn document<'a, 'cx: 'a>( + cx: &'a mut Context<'cx>, + item: &'a clean::Item, + parent: Option<&'a clean::Item>, heading_offset: HeadingOffset, -) { +) -> impl fmt::Display + 'a + Captures<'cx> { if let Some(ref name) = item.name { info!("Documenting {}", name); } - document_item_info(cx, item, parent).render_into(w).unwrap(); - if parent.is_none() { - document_full_collapsible(w, item, cx, heading_offset); - } else { - document_full(w, item, cx, heading_offset); - } + + display_fn(move |f| { + document_item_info(cx, item, parent).render_into(f).unwrap(); + if parent.is_none() { + write!(f, "{}", document_full_collapsible(item, cx, heading_offset))?; + } else { + write!(f, "{}", document_full(item, cx, heading_offset))?; + } + Ok(()) + }) } /// Render md_text as markdown. -fn render_markdown( - w: &mut Buffer, - cx: &mut Context<'_>, - md_text: &str, +fn render_markdown<'a, 'cx: 'a>( + cx: &'a mut Context<'cx>, + md_text: &'a str, links: Vec<RenderedLink>, heading_offset: HeadingOffset, -) { - write!( - w, - "<div class=\"docblock\">{}</div>", - Markdown { - content: md_text, - links: &links, - ids: &mut cx.id_map, - error_codes: cx.shared.codes, - edition: cx.shared.edition(), - playground: &cx.shared.playground, - heading_offset, - } - .into_string() - ) +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + write!( + f, + "<div class=\"docblock\">{}</div>", + Markdown { + content: md_text, + links: &links, + ids: &mut cx.id_map, + error_codes: cx.shared.codes, + edition: cx.shared.edition(), + playground: &cx.shared.playground, + heading_offset, + } + .into_string() + ) + }) } /// Writes a documentation block containing only the first paragraph of the documentation. If the /// docs are longer, a "Read more" link is appended to the end. -fn document_short( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, - link: AssocItemLink<'_>, - parent: &clean::Item, +fn document_short<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, + link: AssocItemLink<'a>, + parent: &'a clean::Item, show_def_docs: bool, -) { - document_item_info(cx, item, Some(parent)).render_into(w).unwrap(); - if !show_def_docs { - return; - } - if let Some(s) = item.doc_value() { - let (mut summary_html, has_more_content) = - MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + document_item_info(cx, item, Some(parent)).render_into(f).unwrap(); + if !show_def_docs { + return Ok(()); + } + if let Some(s) = item.doc_value() { + let (mut summary_html, has_more_content) = + MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content(); - if has_more_content { - let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx)); + if has_more_content { + let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx)); - if let Some(idx) = summary_html.rfind("</p>") { - summary_html.insert_str(idx, &link); - } else { - summary_html.push_str(&link); + if let Some(idx) = summary_html.rfind("</p>") { + summary_html.insert_str(idx, &link); + } else { + summary_html.push_str(&link); + } } - } - write!(w, "<div class='docblock'>{}</div>", summary_html,); - } + write!(f, "<div class='docblock'>{}</div>", summary_html)?; + } + Ok(()) + }) } -fn document_full_collapsible( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, +fn document_full_collapsible<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, heading_offset: HeadingOffset, -) { - document_full_inner(w, item, cx, true, heading_offset); +) -> impl fmt::Display + 'a + Captures<'cx> { + document_full_inner(item, cx, true, heading_offset) } -fn document_full( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, +fn document_full<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, heading_offset: HeadingOffset, -) { - document_full_inner(w, item, cx, false, heading_offset); +) -> impl fmt::Display + 'a + Captures<'cx> { + document_full_inner(item, cx, false, heading_offset) } -fn document_full_inner( - w: &mut Buffer, - item: &clean::Item, - cx: &mut Context<'_>, +fn document_full_inner<'a, 'cx: 'a>( + item: &'a clean::Item, + cx: &'a mut Context<'cx>, is_collapsible: bool, heading_offset: HeadingOffset, -) { - if let Some(s) = item.collapsed_doc_value() { - debug!("Doc block: =====\n{}\n=====", s); - if is_collapsible { - w.write_str( - "<details class=\"toggle top-doc\" open>\ - <summary class=\"hideme\">\ - <span>Expand description</span>\ - </summary>", - ); - render_markdown(w, cx, &s, item.links(cx), heading_offset); - w.write_str("</details>"); - } else { - render_markdown(w, cx, &s, item.links(cx), heading_offset); +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |f| { + if let Some(s) = item.collapsed_doc_value() { + debug!("Doc block: =====\n{}\n=====", s); + if is_collapsible { + write!( + f, + "<details class=\"toggle top-doc\" open>\ + <summary class=\"hideme\">\ + <span>Expand description</span>\ + </summary>{}</details>", + render_markdown(cx, &s, item.links(cx), heading_offset) + )?; + } else { + write!(f, "{}", render_markdown(cx, &s, item.links(cx), heading_offset))?; + } } - } - let kind = match &*item.kind { - clean::ItemKind::StrippedItem(box kind) | kind => kind, - }; + let kind = match &*item.kind { + clean::ItemKind::StrippedItem(box kind) | kind => kind, + }; - if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind { - render_call_locations(w, cx, item); - } + if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind { + render_call_locations(f, cx, item); + } + Ok(()) + }) } #[derive(Template)] @@ -653,7 +660,7 @@ fn short_item_info( // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). pub(crate) fn render_impls( cx: &mut Context<'_>, - w: &mut Buffer, + mut w: impl Write, impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, @@ -665,7 +672,7 @@ pub(crate) fn render_impls( let did = i.trait_did().unwrap(); let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx); let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); - let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; + let mut buffer = Buffer::new(); render_impl( &mut buffer, cx, @@ -686,7 +693,7 @@ pub(crate) fn render_impls( }) .collect::<Vec<_>>(); rendered_impls.sort(); - w.write_str(&rendered_impls.join("")); + w.write_str(&rendered_impls.join("")).unwrap(); } /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item. @@ -842,7 +849,7 @@ fn assoc_method( let (indent, indent_str, end_newline) = if parent == ItemType::Trait { header_len += 4; let indent_str = " "; - render_attributes_in_pre(w, meth, indent_str); + write!(w, "{}", render_attributes_in_pre(meth, indent_str)); (4, indent_str, Ending::NoNewline) } else { render_attributes_in_code(w, meth); @@ -1038,10 +1045,16 @@ fn attributes(it: &clean::Item) -> Vec<String> { // When an attribute is rendered inside a `<pre>` tag, it is formatted using // a whitespace prefix and newline. -fn render_attributes_in_pre(w: &mut Buffer, it: &clean::Item, prefix: &str) { - for a in attributes(it) { - writeln!(w, "{}{}", prefix, a); - } +fn render_attributes_in_pre<'a>( + it: &'a clean::Item, + prefix: &'a str, +) -> impl fmt::Display + Captures<'a> { + crate::html::format::display_fn(move |f| { + for a in attributes(it) { + writeln!(f, "{}{}", prefix, a)?; + } + Ok(()) + }) } // When an attribute is rendered inside a <code> tag, it is formatted using @@ -1067,61 +1080,68 @@ impl<'a> AssocItemLink<'a> { } } -fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) { +fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) { write!( w, "<h2 id=\"{id}\" class=\"small-section-header\">\ {title}\ <a href=\"#{id}\" class=\"anchor\">§</a>\ </h2>" - ); + ) + .unwrap(); } pub(crate) fn render_all_impls( - w: &mut Buffer, + mut w: impl Write, cx: &mut Context<'_>, containing_item: &clean::Item, concrete: &[&Impl], synthetic: &[&Impl], blanket_impl: &[&Impl], ) { - let mut impls = Buffer::empty_from(w); + let mut impls = Buffer::html(); render_impls(cx, &mut impls, concrete, containing_item, true); let impls = impls.into_inner(); if !impls.is_empty() { - write_impl_section_heading(w, "Trait Implementations", "trait-implementations"); - write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls); + write_impl_section_heading(&mut w, "Trait Implementations", "trait-implementations"); + write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls).unwrap(); } if !synthetic.is_empty() { - write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations"); - w.write_str("<div id=\"synthetic-implementations-list\">"); - render_impls(cx, w, synthetic, containing_item, false); - w.write_str("</div>"); + write_impl_section_heading( + &mut w, + "Auto Trait Implementations", + "synthetic-implementations", + ); + w.write_str("<div id=\"synthetic-implementations-list\">").unwrap(); + render_impls(cx, &mut w, synthetic, containing_item, false); + w.write_str("</div>").unwrap(); } if !blanket_impl.is_empty() { - write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations"); - w.write_str("<div id=\"blanket-implementations-list\">"); - render_impls(cx, w, blanket_impl, containing_item, false); - w.write_str("</div>"); + write_impl_section_heading(&mut w, "Blanket Implementations", "blanket-implementations"); + w.write_str("<div id=\"blanket-implementations-list\">").unwrap(); + render_impls(cx, &mut w, blanket_impl, containing_item, false); + w.write_str("</div>").unwrap(); } } -fn render_assoc_items( - w: &mut Buffer, - cx: &mut Context<'_>, - containing_item: &clean::Item, +fn render_assoc_items<'a, 'cx: 'a>( + cx: &'a mut Context<'cx>, + containing_item: &'a clean::Item, it: DefId, - what: AssocItemRender<'_>, -) { + what: AssocItemRender<'a>, +) -> impl fmt::Display + 'a + Captures<'cx> { let mut derefs = DefIdSet::default(); derefs.insert(it); - render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs) + display_fn(move |f| { + render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs); + Ok(()) + }) } fn render_assoc_items_inner( - w: &mut Buffer, + mut w: &mut dyn fmt::Write, cx: &mut Context<'_>, containing_item: &clean::Item, it: DefId, @@ -1134,7 +1154,7 @@ fn render_assoc_items_inner( let Some(v) = cache.impls.get(&it) else { return }; let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { - let mut tmp_buf = Buffer::empty_from(w); + let mut tmp_buf = Buffer::html(); let (render_mode, id) = match what { AssocItemRender::All => { write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations"); @@ -1158,7 +1178,7 @@ fn render_assoc_items_inner( (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } }; - let mut impls_buf = Buffer::empty_from(w); + let mut impls_buf = Buffer::html(); for i in &non_trait { render_impl( &mut impls_buf, @@ -1178,10 +1198,10 @@ fn render_assoc_items_inner( ); } if !impls_buf.is_empty() { - w.push_buffer(tmp_buf); - write!(w, "<div id=\"{}\">", id); - w.push_buffer(impls_buf); - w.write_str("</div>"); + write!(w, "{}", tmp_buf.into_inner()).unwrap(); + write!(w, "<div id=\"{}\">", id).unwrap(); + write!(w, "{}", impls_buf.into_inner()).unwrap(); + w.write_str("</div>").unwrap(); } } @@ -1191,7 +1211,7 @@ fn render_assoc_items_inner( if let Some(impl_) = deref_impl { let has_deref_mut = traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); - render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs); + render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs); } // If we were already one level into rendering deref methods, we don't want to render @@ -1210,7 +1230,7 @@ fn render_assoc_items_inner( } fn render_deref_methods( - w: &mut Buffer, + mut w: impl Write, cx: &mut Context<'_>, impl_: &Impl, container_item: &clean::Item, @@ -1242,10 +1262,10 @@ fn render_deref_methods( return; } } - render_assoc_items_inner(w, cx, container_item, did, what, derefs); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } else if let Some(prim) = target.primitive_type() { if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items_inner(w, cx, container_item, did, what, derefs); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } } } @@ -1478,18 +1498,25 @@ fn render_impl( document_item_info(cx, it, Some(parent)) .render_into(&mut info_buffer) .unwrap(); - document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); + write!( + &mut doc_buffer, + "{}", + document_full(item, cx, HeadingOffset::H5) + ); short_documented = false; } else { // In case the item isn't documented, // provide short documentation from the trait. - document_short( + write!( &mut doc_buffer, - it, - cx, - link, - parent, - rendering_params.show_def_docs, + "{}", + document_short( + it, + cx, + link, + parent, + rendering_params.show_def_docs, + ) ); } } @@ -1498,18 +1525,15 @@ fn render_impl( .render_into(&mut info_buffer) .unwrap(); if rendering_params.show_def_docs { - document_full(&mut doc_buffer, item, cx, HeadingOffset::H5); + write!(&mut doc_buffer, "{}", document_full(item, cx, HeadingOffset::H5)); short_documented = false; } } } else { - document_short( + write!( &mut doc_buffer, - item, - cx, - link, - parent, - rendering_params.show_def_docs, + "{}", + document_short(item, cx, link, parent, rendering_params.show_def_docs,) ); } } @@ -2206,7 +2230,7 @@ const MAX_FULL_EXAMPLES: usize = 5; const NUM_VISIBLE_LINES: usize = 10; /// Generates the HTML for example call locations generated via the --scrape-examples flag. -fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item) { +fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) { let tcx = cx.tcx(); let def_id = item.item_id.expect_def_id(); let key = tcx.def_path_hash(def_id); @@ -2215,7 +2239,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // Generate a unique ID so users can link to this section for a given method let id = cx.id_map.derive("scraped-examples"); write!( - w, + &mut w, "<div class=\"docblock scraped-example-list\">\ <span></span>\ <h5 id=\"{id}\">\ @@ -2224,7 +2248,8 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite </h5>", root_path = cx.root_path(), id = id - ); + ) + .unwrap(); // Create a URL to a particular location in a reverse-dependency's source file let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) { @@ -2242,7 +2267,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite }; // Generate the HTML for a single example, being the title and code block - let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool { + let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool { let contents = match fs::read_to_string(&path) { Ok(contents) => contents, Err(err) => { @@ -2290,7 +2315,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); write!( - w, + &mut w, "<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\ <div class=\"scraped-example-title\">\ {name} (<a href=\"{url}\">{title}</a>)\ @@ -2303,10 +2328,12 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // The locations are encoded as a data attribute, so they can be read // later by the JS for interactions. locations = Escape(&locations_encoded) - ); + ) + .unwrap(); if line_ranges.len() > 1 { - write!(w, r#"<button class="prev">≺</button> <button class="next">≻</button>"#); + write!(w, r#"<button class="prev">≺</button> <button class="next">≻</button>"#) + .unwrap(); } // Look for the example file in the source map if it exists, otherwise return a dummy span @@ -2333,7 +2360,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite decoration_info.insert("highlight", byte_ranges); sources::print_src( - w, + &mut w, contents_subset, file_span, cx, @@ -2341,7 +2368,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite highlight::DecorationInfo(decoration_info), sources::SourceContext::Embedded { offset: line_min, needs_expansion }, ); - write!(w, "</div></div>"); + write!(w, "</div></div>").unwrap(); true }; @@ -2375,7 +2402,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite // An example may fail to write if its source can't be read for some reason, so this method // continues iterating until a write succeeds - let write_and_skip_failure = |w: &mut Buffer, it: &mut Peekable<_>| { + let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| { while let Some(example) = it.next() { if write_example(&mut *w, example) { break; @@ -2384,7 +2411,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite }; // Write just one example that's visible by default in the method's description. - write_and_skip_failure(w, &mut it); + write_and_skip_failure(&mut w, &mut it); // Then add the remaining examples in a hidden section. if it.peek().is_some() { @@ -2397,17 +2424,19 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite <div class=\"hide-more\">Hide additional examples</div>\ <div class=\"more-scraped-examples\">\ <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>" - ); + ) + .unwrap(); // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could // make the page arbitrarily huge! for _ in 0..MAX_FULL_EXAMPLES { - write_and_skip_failure(w, &mut it); + write_and_skip_failure(&mut w, &mut it); } // For the remaining examples, generate a <ul> containing links to the source files. if it.peek().is_some() { - write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#); + write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#) + .unwrap(); it.for_each(|(_, call_data)| { let (url, _) = link_to_loc(call_data, &call_data.locations[0]); write!( @@ -2415,13 +2444,14 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite r#"<li><a href="{url}">{name}</a></li>"#, url = url, name = call_data.display_name - ); + ) + .unwrap(); }); - write!(w, "</ul></div>"); + write!(w, "</ul></div>").unwrap(); } - write!(w, "</div></details>"); + write!(w, "</div></details>").unwrap(); } - write!(w, "</div>"); + write!(w, "</div>").unwrap(); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 674cd0d62d4..6bce5734004 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -202,7 +202,7 @@ fn should_hide_fields(n_fields: usize) -> bool { n_fields > 12 } -fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { +fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) { write!( w, "<details class=\"toggle type-contents-toggle\">\ @@ -210,15 +210,16 @@ fn toggle_open(w: &mut Buffer, text: impl fmt::Display) { <span>Show {}</span>\ </summary>", text - ); + ) + .unwrap(); } -fn toggle_close(w: &mut Buffer) { - w.write_str("</details>"); +fn toggle_close(mut w: impl fmt::Write) { + w.write_str("</details>").unwrap(); } fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { - document(w, cx, item, None, HeadingOffset::H2); + write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>(); @@ -544,12 +545,12 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx)); wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); w.reserve(header_len); write!( w, - "{vis}{constness}{asyncness}{unsafety}{abi}fn \ + "{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{notable_traits}{where_clause}", + attrs = render_attributes_in_pre(it, ""), vis = visibility, constness = constness, asyncness = asyncness, @@ -562,7 +563,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle notable_traits = notable_traits.unwrap_or_default(), ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); } fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) { @@ -580,17 +581,17 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone(); // Output the trait definition - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); + wrap_item(w, |mut w| { write!( w, - "{}{}{}trait {}{}{}", + "{attrs}{}{}{}trait {}{}{}", visibility_print_with_space(it.visibility(tcx), it.item_id, cx), t.unsafety(tcx).print_with_space(), if t.is_auto(tcx) { "auto " } else { "" }, it.name.unwrap(), t.generics.print(cx), - bounds + bounds, + attrs = render_attributes_in_pre(it, ""), ); if !t.generics.where_predicates.is_empty() { @@ -610,7 +611,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if should_hide_fields(count_types) { toggle = true; toggle_open( - w, + &mut w, format_args!("{} associated items", count_types + count_consts + count_methods), ); } @@ -634,7 +635,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: if !toggle && should_hide_fields(count_types + count_consts) { toggle = true; toggle_open( - w, + &mut w, format_args!( "{} associated constant{} and {} method{}", count_consts, @@ -662,7 +663,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } if !toggle && should_hide_fields(count_methods) { toggle = true; - toggle_open(w, format_args!("{} methods", count_methods)); + toggle_open(&mut w, format_args!("{} methods", count_methods)); } if count_consts != 0 && count_methods != 0 { w.write_str("\n"); @@ -710,14 +711,14 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } }); // Trait documentation - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) { write!( @@ -735,7 +736,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let item_type = m.type_(); let id = cx.derive_id(format!("{}.{}", item_type, name)); let mut content = Buffer::empty_from(w); - document(&mut content, cx, m, Some(t), HeadingOffset::H5); + write!(&mut content, "{}", document(cx, m, Some(t), HeadingOffset::H5)); let toggled = !content.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; @@ -847,7 +848,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); let cloned_shared = Rc::clone(&cx.shared); let cache = &cloned_shared.cache; @@ -1057,147 +1058,201 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) { wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); write!( w, - "trait {}{}{} = {};", + "{attrs}trait {}{}{} = {};", it.name.unwrap(), t.generics.print(cx), print_where_clause(&t.generics, cx, 0, Ending::Newline), - bounds(&t.bounds, true, cx) + bounds(&t.bounds, true, cx), + attrs = render_attributes_in_pre(it, ""), ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); write!( w, - "type {}{}{where_clause} = impl {bounds};", + "{attrs}type {}{}{where_clause} = impl {bounds};", it.name.unwrap(), t.generics.print(cx), where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), bounds = bounds(&t.bounds, false, cx), + attrs = render_attributes_in_pre(it, ""), ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); write!( w, - "{}type {}{}{where_clause} = {type_};", + "{attrs}{}type {}{}{where_clause} = {type_};", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), it.name.unwrap(), t.generics.print(cx), where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), type_ = t.type_.print(cx), + attrs = render_attributes_in_pre(it, ""), ); }); } write_content(w, cx, it, t); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let def_id = it.item_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); - render_union(w, it, Some(&s.generics), &s.fields, cx); - }); + #[derive(Template)] + #[template(path = "item_union.html")] + struct ItemUnion<'a, 'cx> { + cx: std::cell::RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + s: &'a clean::Union, + } - document(w, cx, it, None, HeadingOffset::H2); + impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { + fn render_assoc_items<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let def_id = self.it.item_id.expect_def_id(); + let mut cx = self.cx.borrow_mut(); + let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); + write!(f, "{v}") + }) + } + fn document_type_layout<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let def_id = self.it.item_id.expect_def_id(); + let cx = self.cx.borrow_mut(); + let v = document_type_layout(*cx, def_id); + write!(f, "{v}") + }) + } + fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow_mut(); + let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx); + write!(f, "{v}") + }) + } + fn render_attributes_in_pre<'b>( + &'b self, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let v = render_attributes_in_pre(self.it, ""); + write!(f, "{v}") + }) + } + fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, self.it, None, HeadingOffset::H2); + write!(f, "{v}") + }) + } + fn document_field<'b>( + &'b self, + field: &'a clean::Item, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let mut cx = self.cx.borrow_mut(); + let v = document(*cx, field, Some(self.it), HeadingOffset::H3); + write!(f, "{v}") + }) + } + fn stability_field(&self, field: &clean::Item) -> Option<String> { + let cx = self.cx.borrow(); + field.stability_class(cx.tcx()) + } + fn print_ty<'b>( + &'b self, + ty: &'a clean::Type, + ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow(); + let v = ty.print(*cx); + write!(f, "{v}") + }) + } - let mut fields = s - .fields - .iter() - .filter_map(|f| match *f.kind { - clean::StructFieldItem(ref ty) => Some((f, ty)), - _ => None, - }) - .peekable(); - if fields.peek().is_some() { - write!( - w, - "<h2 id=\"fields\" class=\"fields small-section-header\">\ - Fields<a href=\"#fields\" class=\"anchor\">§</a>\ - </h2>" - ); - for (field, ty) in fields { - let name = field.name.expect("union field name"); - let id = format!("{}.{}", ItemType::StructField, name); - write!( - w, - "<span id=\"{id}\" class=\"{shortty} small-section-header\">\ - <a href=\"#{id}\" class=\"anchor field\">§</a>\ - <code>{name}: {ty}</code>\ - </span>", - shortty = ItemType::StructField, - ty = ty.print(cx), - ); - if let Some(stability_class) = field.stability_class(cx.tcx()) { - write!(w, "<span class=\"stab {stability_class}\"></span>"); - } - document(w, cx, field, Some(it), HeadingOffset::H3); + fn fields_iter( + &self, + ) -> std::iter::Peekable<impl Iterator<Item = (&'a clean::Item, &'a clean::Type)>> { + self.s + .fields + .iter() + .filter_map(|f| match *f.kind { + clean::StructFieldItem(ref ty) => Some((f, ty)), + _ => None, + }) + .peekable() } } - let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + + ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap(); } -fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) { - for (i, ty) in s.iter().enumerate() { - if i > 0 { - w.write_str(", "); - } - match *ty.kind { - clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"), - clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)), - _ => unreachable!(), +fn print_tuple_struct_fields<'a, 'cx: 'a>( + cx: &'a Context<'cx>, + s: &'a [clean::Item], +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(|f| { + for (i, ty) in s.iter().enumerate() { + if i > 0 { + f.write_str(", ")?; + } + match *ty.kind { + clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?, + clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?, + _ => unreachable!(), + } } - } + Ok(()) + }) } fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) { let tcx = cx.tcx(); let count_variants = e.variants().count(); - wrap_item(w, |w| { - render_attributes_in_pre(w, it, ""); + wrap_item(w, |mut w| { write!( w, - "{}enum {}{}", + "{attrs}{}enum {}{}", visibility_print_with_space(it.visibility(tcx), it.item_id, cx), it.name.unwrap(), e.generics.print(cx), + attrs = render_attributes_in_pre(it, ""), ); if !print_where_clause_and_check(w, &e.generics, cx) { // If there wasn't a `where` clause, we add a whitespace. @@ -1211,7 +1266,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str("{\n"); let toggle = should_hide_fields(count_variants); if toggle { - toggle_open(w, format_args!("{} variants", count_variants)); + toggle_open(&mut w, format_args!("{} variants", count_variants)); } for v in e.variants() { w.write_str(" "); @@ -1221,9 +1276,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: clean::VariantItem(ref var) => match var.kind { clean::VariantKind::CLike => write!(w, "{}", name), clean::VariantKind::Tuple(ref s) => { - write!(w, "{}(", name); - print_tuple_struct_fields(w, cx, s); - w.write_str(")"); + write!(w, "{name}({})", print_tuple_struct_fields(cx, s),); } clean::VariantKind::Struct(ref s) => { render_struct(w, v, None, None, &s.fields, " ", false, cx); @@ -1238,24 +1291,25 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(" // some variants omitted\n"); } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if count_variants != 0 { write!( w, "<h2 id=\"variants\" class=\"variants small-section-header\">\ Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\ - </h2>", - document_non_exhaustive_header(it) + </h2>\ + {}\ + <div class=\"variants\">", + document_non_exhaustive_header(it), + document_non_exhaustive(it) ); - document_non_exhaustive(w, it); - write!(w, "<div class=\"variants\">"); for variant in e.variants() { let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap())); write!( @@ -1276,9 +1330,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; if let clean::VariantKind::Tuple(ref s) = variant_data.kind { - w.write_str("("); - print_tuple_struct_fields(w, cx, s); - w.write_str(")"); + write!(w, "({})", print_tuple_struct_fields(cx, s),); } w.write_str("</h3></section>"); @@ -1302,9 +1354,10 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!( w, "<div class=\"sub-variant\" id=\"{variant_id}\">\ - <h4>{heading}</h4>", + <h4>{heading}</h4>\ + {}", + document_non_exhaustive(variant) ); - document_non_exhaustive(w, variant); for field in fields { match *field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} @@ -1322,10 +1375,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: <code>{f}: {t}</code>\ </span>", f = field.name.unwrap(), - t = ty.print(cx) + t = ty.print(cx), + ); + write!( + w, + "{}</div>", + document(cx, field, Some(variant), HeadingOffset::H5) ); - document(w, cx, field, Some(variant), HeadingOffset::H5); - write!(w, "</div>"); } _ => unreachable!(), } @@ -1333,18 +1389,18 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str("</div>"); } - document(w, cx, variant, Some(it), HeadingOffset::H4); + write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4)); } write!(w, "</div>"); } let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) { highlight::render_item_decl_with_highlighting(&t.source, w); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { @@ -1370,14 +1426,14 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c } } }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { let def_id = it.item_id.expect_def_id(); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. @@ -1433,7 +1489,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle } }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) { @@ -1442,7 +1498,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let mut fields = s .fields @@ -1458,11 +1514,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean w, "<h2 id=\"fields\" class=\"fields small-section-header\">\ {}{}<a href=\"#fields\" class=\"anchor\">§</a>\ - </h2>", + </h2>\ + {}", if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" }, - document_non_exhaustive_header(it) + document_non_exhaustive_header(it), + document_non_exhaustive(it) ); - document_non_exhaustive(w, it); for (index, (field, ty)) in fields.enumerate() { let field_name = field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string()); @@ -1476,13 +1533,13 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean item_type = ItemType::StructField, ty = ty.print(cx) ); - document(w, cx, field, Some(it), HeadingOffset::H3); + write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3)); } } } let def_id = it.item_id.expect_def_id(); - render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_type_layout(w, cx, def_id); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); + write!(w, "{}", document_type_layout(cx, def_id)); } fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1497,7 +1554,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean typ = s.type_.print(cx) ); }); - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { @@ -1512,13 +1569,13 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { ); }); - document(w, cx, it, None, HeadingOffset::H2); + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { - document(w, cx, it, None, HeadingOffset::H2) + write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) } /// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order). @@ -1655,64 +1712,69 @@ fn render_implementor( ); } -fn render_union( - w: &mut Buffer, - it: &clean::Item, - g: Option<&clean::Generics>, - fields: &[clean::Item], - cx: &Context<'_>, -) { - let tcx = cx.tcx(); - write!( - w, - "{}union {}", - visibility_print_with_space(it.visibility(tcx), it.item_id, cx), - it.name.unwrap(), - ); - - let where_displayed = g - .map(|g| { - write!(w, "{}", g.print(cx)); - print_where_clause_and_check(w, g, cx) - }) - .unwrap_or(false); +fn render_union<'a, 'cx: 'a>( + it: &'a clean::Item, + g: Option<&'a clean::Generics>, + fields: &'a [clean::Item], + cx: &'a Context<'cx>, +) -> impl fmt::Display + 'a + Captures<'cx> { + display_fn(move |mut f| { + let tcx = cx.tcx(); + write!( + f, + "{}union {}", + visibility_print_with_space(it.visibility(tcx), it.item_id, cx), + it.name.unwrap(), + )?; + + let where_displayed = g + .map(|g| { + let mut buf = Buffer::html(); + write!(buf, "{}", g.print(cx)); + let where_displayed = print_where_clause_and_check(&mut buf, g, cx); + write!(f, "{buf}", buf = buf.into_inner()).unwrap(); + where_displayed + }) + .unwrap_or(false); - // If there wasn't a `where` clause, we add a whitespace. - if !where_displayed { - w.write_str(" "); - } + // If there wasn't a `where` clause, we add a whitespace. + if !where_displayed { + f.write_str(" ")?; + } - write!(w, "{{\n"); - let count_fields = - fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); - let toggle = should_hide_fields(count_fields); - if toggle { - toggle_open(w, format_args!("{} fields", count_fields)); - } + write!(f, "{{\n")?; + let count_fields = + fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); + let toggle = should_hide_fields(count_fields); + if toggle { + toggle_open(&mut f, format_args!("{} fields", count_fields)); + } - for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { - write!( - w, - " {}{}: {},\n", - visibility_print_with_space(field.visibility(tcx), field.item_id, cx), - field.name.unwrap(), - ty.print(cx) - ); + for field in fields { + if let clean::StructFieldItem(ref ty) = *field.kind { + write!( + f, + " {}{}: {},\n", + visibility_print_with_space(field.visibility(tcx), field.item_id, cx), + field.name.unwrap(), + ty.print(cx) + )?; + } } - } - if it.has_stripped_entries().unwrap() { - write!(w, " /* private fields */\n"); - } - if toggle { - toggle_close(w); - } - w.write_str("}"); + if it.has_stripped_entries().unwrap() { + write!(f, " /* private fields */\n")?; + } + if toggle { + toggle_close(&mut f); + } + f.write_str("}").unwrap(); + Ok(()) + }) } fn render_struct( - w: &mut Buffer, + mut w: &mut Buffer, it: &clean::Item, g: Option<&clean::Generics>, ty: Option<CtorKind>, @@ -1747,7 +1809,7 @@ fn render_struct( let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { - toggle_open(w, format_args!("{} fields", count_fields)); + toggle_open(&mut w, format_args!("{} fields", count_fields)); } for field in fields { if let clean::StructFieldItem(ref ty) = *field.kind { @@ -1771,7 +1833,7 @@ fn render_struct( write!(w, " /* private fields */ "); } if toggle { - toggle_close(w); + toggle_close(&mut w); } w.write_str("}"); } @@ -1817,161 +1879,169 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { - if item.is_non_exhaustive() { - write!( - w, - "<details class=\"toggle non-exhaustive\">\ - <summary class=\"hideme\"><span>{}</span></summary>\ - <div class=\"docblock\">", - { - if item.is_struct() { - "This struct is marked as non-exhaustive" - } else if item.is_enum() { - "This enum is marked as non-exhaustive" - } else if item.is_variant() { - "This variant is marked as non-exhaustive" - } else { - "This type is marked as non-exhaustive" +fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a { + display_fn(|f| { + if item.is_non_exhaustive() { + write!( + f, + "<details class=\"toggle non-exhaustive\">\ + <summary class=\"hideme\"><span>{}</span></summary>\ + <div class=\"docblock\">", + { + if item.is_struct() { + "This struct is marked as non-exhaustive" + } else if item.is_enum() { + "This enum is marked as non-exhaustive" + } else if item.is_variant() { + "This variant is marked as non-exhaustive" + } else { + "This type is marked as non-exhaustive" + } } + )?; + + if item.is_struct() { + f.write_str( + "Non-exhaustive structs could have additional fields added in future. \ + Therefore, non-exhaustive structs cannot be constructed in external crates \ + using the traditional <code>Struct { .. }</code> syntax; cannot be \ + matched against without a wildcard <code>..</code>; and \ + struct update syntax will not work.", + )?; + } else if item.is_enum() { + f.write_str( + "Non-exhaustive enums could have additional variants added in future. \ + Therefore, when matching against variants of non-exhaustive enums, an \ + extra wildcard arm must be added to account for any future variants.", + )?; + } else if item.is_variant() { + f.write_str( + "Non-exhaustive enum variants could have additional fields added in future. \ + Therefore, non-exhaustive enum variants cannot be constructed in external \ + crates and cannot be matched against.", + )?; + } else { + f.write_str( + "This type will require a wildcard arm in any match statements or constructors.", + )?; } - ); - if item.is_struct() { - w.write_str( - "Non-exhaustive structs could have additional fields added in future. \ - Therefore, non-exhaustive structs cannot be constructed in external crates \ - using the traditional <code>Struct { .. }</code> syntax; cannot be \ - matched against without a wildcard <code>..</code>; and \ - struct update syntax will not work.", - ); - } else if item.is_enum() { - w.write_str( - "Non-exhaustive enums could have additional variants added in future. \ - Therefore, when matching against variants of non-exhaustive enums, an \ - extra wildcard arm must be added to account for any future variants.", - ); - } else if item.is_variant() { - w.write_str( - "Non-exhaustive enum variants could have additional fields added in future. \ - Therefore, non-exhaustive enum variants cannot be constructed in external \ - crates and cannot be matched against.", - ); - } else { - w.write_str( - "This type will require a wildcard arm in any match statements or constructors.", - ); + f.write_str("</div></details>")?; } - - w.write_str("</div></details>"); - } + Ok(()) + }) } -fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { - fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS, tag_size: u64) { +fn document_type_layout<'a, 'cx: 'a>( + cx: &'a Context<'cx>, + ty_def_id: DefId, +) -> impl fmt::Display + 'a + Captures<'cx> { + fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) { if layout.abi.is_unsized() { - write!(w, "(unsized)"); + write!(w, "(unsized)").unwrap(); } else { let size = layout.size.bytes() - tag_size; - write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },); + write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap(); if layout.abi.is_uninhabited() { write!( w, " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)" - ); + ).unwrap(); } } } - if !cx.shared.show_type_layout { - return; - } - - writeln!( - w, - "<h2 id=\"layout\" class=\"small-section-header\"> \ - Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>" - ); - writeln!(w, "<div class=\"docblock\">"); - - let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); - let ty = tcx.type_of(ty_def_id).subst_identity(); - match tcx.layout_of(param_env.and(ty)) { - Ok(ty_layout) => { - writeln!( - w, - "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \ - <strong>completely unstable</strong> and may even differ between compilations. \ - The only exception is types with certain <code>repr(...)</code> attributes. \ - Please see the Rust Reference’s \ - <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \ - chapter for details on type layout guarantees.</p></div>" - ); - w.write_str("<p><strong>Size:</strong> "); - write_size_of_layout(w, &ty_layout.layout.0, 0); - writeln!(w, "</p>"); - if let Variants::Multiple { variants, tag, tag_encoding, .. } = - &ty_layout.layout.variants() - { - if !variants.is_empty() { - w.write_str( - "<p><strong>Size for each variant:</strong></p>\ - <ul>", - ); - - let Adt(adt, _) = ty_layout.ty.kind() else { - span_bug!(tcx.def_span(ty_def_id), "not an adt") - }; + display_fn(move |mut f| { + if !cx.shared.show_type_layout { + return Ok(()); + } - let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { - 0 - } else if let Primitive::Int(i, _) = tag.primitive() { - i.size().bytes() - } else { - span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") - }; + writeln!( + f, + "<h2 id=\"layout\" class=\"small-section-header\"> \ + Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>" + )?; + writeln!(f, "<div class=\"docblock\">")?; - for (index, layout) in variants.iter_enumerated() { - let name = adt.variant(index).name; - write!(w, "<li><code>{name}</code>: "); - write_size_of_layout(w, layout, tag_size); - writeln!(w, "</li>"); + let tcx = cx.tcx(); + let param_env = tcx.param_env(ty_def_id); + let ty = tcx.type_of(ty_def_id).subst_identity(); + match tcx.layout_of(param_env.and(ty)) { + Ok(ty_layout) => { + writeln!( + f, + "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \ + <strong>completely unstable</strong> and may even differ between compilations. \ + The only exception is types with certain <code>repr(...)</code> attributes. \ + Please see the Rust Reference’s \ + <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \ + chapter for details on type layout guarantees.</p></div>" + )?; + f.write_str("<p><strong>Size:</strong> ")?; + write_size_of_layout(&mut f, &ty_layout.layout.0, 0); + writeln!(f, "</p>")?; + if let Variants::Multiple { variants, tag, tag_encoding, .. } = + &ty_layout.layout.variants() + { + if !variants.is_empty() { + f.write_str( + "<p><strong>Size for each variant:</strong></p>\ + <ul>", + )?; + + let Adt(adt, _) = ty_layout.ty.kind() else { + span_bug!(tcx.def_span(ty_def_id), "not an adt") + }; + + let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.primitive() { + i.size().bytes() + } else { + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") + }; + + for (index, layout) in variants.iter_enumerated() { + let name = adt.variant(index).name; + write!(&mut f, "<li><code>{name}</code>: ")?; + write_size_of_layout(&mut f, layout, tag_size); + writeln!(&mut f, "</li>")?; + } + f.write_str("</ul>")?; } - w.write_str("</ul>"); } } + // This kind of layout error can occur with valid code, e.g. if you try to + // get the layout of a generic type such as `Vec<T>`. + Err(LayoutError::Unknown(_)) => { + writeln!( + f, + "<p><strong>Note:</strong> Unable to compute type layout, \ + possibly due to this type having generic parameters. \ + Layout can only be computed for concrete, fully-instantiated types.</p>" + )?; + } + // This kind of error probably can't happen with valid code, but we don't + // want to panic and prevent the docs from building, so we just let the + // user know that we couldn't compute the layout. + Err(LayoutError::SizeOverflow(_)) => { + writeln!( + f, + "<p><strong>Note:</strong> Encountered an error during type layout; \ + the type was too big.</p>" + )?; + } + Err(LayoutError::NormalizationFailure(_, _)) => { + writeln!( + f, + "<p><strong>Note:</strong> Encountered an error during type layout; \ + the type failed to be normalized.</p>" + )?; + } } - // This kind of layout error can occur with valid code, e.g. if you try to - // get the layout of a generic type such as `Vec<T>`. - Err(LayoutError::Unknown(_)) => { - writeln!( - w, - "<p><strong>Note:</strong> Unable to compute type layout, \ - possibly due to this type having generic parameters. \ - Layout can only be computed for concrete, fully-instantiated types.</p>" - ); - } - // This kind of error probably can't happen with valid code, but we don't - // want to panic and prevent the docs from building, so we just let the - // user know that we couldn't compute the layout. - Err(LayoutError::SizeOverflow(_)) => { - writeln!( - w, - "<p><strong>Note:</strong> Encountered an error during type layout; \ - the type was too big.</p>" - ); - } - Err(LayoutError::NormalizationFailure(_, _)) => { - writeln!( - w, - "<p><strong>Note:</strong> Encountered an error during type layout; \ - the type failed to be normalized.</p>" - ) - } - } - writeln!(w, "</div>"); + writeln!(f, "</div>") + }) } fn pluralize(count: usize) -> &'static str { diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 1d298f52f75..c8397967c87 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -2,7 +2,6 @@ use crate::clean; use crate::docfs::PathError; use crate::error::Error; use crate::html::format; -use crate::html::format::Buffer; use crate::html::highlight; use crate::html::layout; use crate::html::render::Context; @@ -17,6 +16,7 @@ use rustc_span::source_map::FileName; use std::cell::RefCell; use std::ffi::OsStr; +use std::fmt; use std::fs; use std::ops::RangeInclusive; use std::path::{Component, Path, PathBuf}; @@ -294,7 +294,7 @@ pub(crate) enum SourceContext { /// Wrapper struct to render the source code of a file. This will do things like /// adding line numbers to the left-hand side. pub(crate) fn print_src( - buf: &mut Buffer, + mut writer: impl fmt::Write, s: &str, file_span: rustc_span::Span, context: &Context<'_>, @@ -329,5 +329,5 @@ pub(crate) fn print_src( ); Ok(()) }); - Source { embedded, needs_expansion, lines, code_html: code }.render_into(buf).unwrap(); + Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap(); } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 45c0360a49e..56ee4c1510e 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -332,13 +332,7 @@ function preLoadCss(cssUrl) { }; function getPageId() { - if (window.location.hash) { - const tmp = window.location.hash.replace(/^#/, ""); - if (tmp.length > 0) { - return tmp; - } - } - return null; + return window.location.hash.replace(/^#/, ""); } const toggleAllDocsId = "toggle-all-docs"; @@ -707,7 +701,7 @@ function preLoadCss(cssUrl) { }); const pageId = getPageId(); - if (pageId !== null) { + if (pageId !== "") { expandSection(pageId); } }()); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 1cd552e7f25..ebbe6c1ca9a 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -86,12 +86,8 @@ if (settingId === "theme") { const useSystem = getSettingValue("use-system-theme"); if (useSystem === "true" || settingValue === null) { - if (useSystem !== "false") { - settingValue = "system preference"; - } else { - // This is the default theme. - settingValue = "light"; - } + // "light" is the default theme + settingValue = useSystem === "false" ? "light" : "system preference"; } } if (settingValue !== null && settingValue !== "null") { diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 8d82b5b78ed..93979a94418 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -53,10 +53,9 @@ function removeClass(elem, className) { * @param {boolean} [reversed] - Whether to iterate in reverse */ function onEach(arr, func, reversed) { - if (arr && arr.length > 0 && func) { + if (arr && arr.length > 0) { if (reversed) { - const length = arr.length; - for (let i = length - 1; i >= 0; --i) { + for (let i = arr.length - 1; i >= 0; --i) { if (func(arr[i])) { return true; } @@ -150,26 +149,19 @@ const updateTheme = (function() { * … dictates that it should be. */ function updateTheme() { - const use = (theme, saveTheme) => { - switchTheme(theme, saveTheme); - }; - // maybe the user has disabled the setting in the meantime! if (getSettingValue("use-system-theme") !== "false") { const lightTheme = getSettingValue("preferred-light-theme") || "light"; const darkTheme = getSettingValue("preferred-dark-theme") || "dark"; + updateLocalStorage("use-system-theme", "true"); - if (mql.matches) { - use(darkTheme, true); - } else { - // prefers a light theme, or has no preference - use(lightTheme, true); - } + // use light theme if user prefers it, or has no preference + switchTheme(mql.matches ? darkTheme : lightTheme, true); // note: we save the theme so that it doesn't suddenly change when // the user disables "use-system-theme" and reloads the page or // navigates to another page } else { - use(getSettingValue("theme"), false); + switchTheme(getSettingValue("theme"), false); } } diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html new file mode 100644 index 00000000000..a01457971c1 --- /dev/null +++ b/src/librustdoc/html/templates/item_union.html @@ -0,0 +1,23 @@ +<pre class="rust item-decl"><code> + {{ self.render_attributes_in_pre() | safe }} + {{ self.render_union() | safe }} +</code></pre> +{{ self.document() | safe }} +{% if self.fields_iter().peek().is_some() %} + <h2 id="fields" class="fields small-section-header"> + Fields<a href="#fields" class="anchor">§</a> + </h2> + {% for (field, ty) in self.fields_iter() %} + {% let name = field.name.expect("union field name") %} + <span id="structfield.{{ name }}" class="{{ ItemType::StructField }} small-section-header"> + <a href="#structfield.{{ name }}" class="anchor field">§</a> + <code>{{ name }}: {{ self.print_ty(ty) | safe }}</code> + </span> + {% if let Some(stability_class) = self.stability_field(field) %} + <span class="stab {{ stability_class }}"></span> + {% endif %} + {{ self.document_field(field) | safe }} + {% endfor %} +{% endif %} +{{ self.render_assoc_items() | safe }} +{{ self.document_type_layout() | safe }} 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 d66640ba0b7..354b6d71aa4 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 @@ -301,13 +301,13 @@ fn check_terminator<'tcx>( | TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume + | TerminatorKind::Terminate | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), - TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())), TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn generators are unstable".into())) }, @@ -318,7 +318,7 @@ fn check_terminator<'tcx>( from_hir_call: _, destination: _, target: _, - cleanup: _, + unwind: _, fn_span: _, } => { let fn_ty = func.ty(body, tcx); @@ -361,7 +361,7 @@ fn check_terminator<'tcx>( expected: _, msg: _, target: _, - cleanup: _, + unwind: _, } => check_operand(tcx, cond, span, body), TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 21a413002d0..8f6ae729491 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -951,7 +951,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if this.machine.panic_on_unsupported { // message is slightly different here to make automated analysis easier let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref()); - this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?; + this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?; Ok(()) } else { throw_unsup_format!("{}", error_msg.as_ref()); diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 01d0f01d319..fb4e59acd00 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -5,7 +5,6 @@ #![feature(io_error_more)] #![feature(variant_count)] #![feature(yeet_expr)] -#![feature(is_some_and)] #![feature(nonzero_ops)] #![feature(local_key_cell_methods)] #![feature(is_terminal)] diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index cc1964de332..477d8d33ebb 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -834,7 +834,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind) } @@ -847,7 +847,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - _unwind: StackPopUnwind, + _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { ecx.call_dlsym(fn_val, abi, args, dest, ret) } @@ -859,7 +859,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { ecx.call_intrinsic(instance, args, dest, ret, unwind) } @@ -868,7 +868,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { fn assert_panic( ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: &mir::AssertMessage<'tcx>, - unwind: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { ecx.assert_panic(msg, unwind) } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 73439133af2..fcee381ff71 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { let this = self.eval_context_mut(); let link_name = this.item_link_name(def_id); diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 9ecbb18ef5a..ca2c1652dc1 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - _unwind: StackPopUnwind, + _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index dbc48876a4b..918efda3777 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { args: &[OpTy<'tcx, Provenance>], dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { let this = self.eval_context_mut(); trace!("eval_fn_call: {:#?}, {:?}", instance, dest); @@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { align_op: &OpTy<'tcx, Provenance>, dest: &PlaceTy<'tcx, Provenance>, ret: Option<mir::BasicBlock>, - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); let ret = ret.unwrap(); diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index acc97c4b8a0..2cca2f3f391 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -53,7 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, link_name: Symbol, args: &[OpTy<'tcx, Provenance>], - unwind: StackPopUnwind, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -106,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[data.into()], None, // Directly return to caller. - StackPopCleanup::Goto { ret: Some(ret), unwind: StackPopUnwind::Skip }, + StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue }, )?; // We ourselves will return `0`, eventually (will be overwritten if we catch a panic). @@ -157,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[catch_unwind.data.into(), payload.into()], None, // Directly return to caller of `try`. - StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: StackPopUnwind::Skip }, + StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue }, )?; // We pushed a new stack frame, the engine should not do any jumping now! @@ -168,7 +168,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Start a panic in the interpreter with the given message as payload. - fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> { + fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // First arg: message. @@ -189,7 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn assert_panic( &mut self, msg: &mir::AssertMessage<'tcx>, - unwind: Option<mir::BasicBlock>, + unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { use rustc_middle::mir::AssertKind::*; let this = self.eval_context_mut(); @@ -213,10 +213,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { None, StackPopCleanup::Goto { ret: None, - unwind: match unwind { - Some(cleanup) => StackPopUnwind::Cleanup(cleanup), - None => StackPopUnwind::Skip, - }, + unwind, }, )?; } @@ -240,10 +237,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { None, StackPopCleanup::Goto { ret: None, - unwind: match unwind { - Some(cleanup) => StackPopUnwind::Cleanup(cleanup), - None => StackPopUnwind::Skip, - }, + unwind, }, )?; } @@ -252,10 +246,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Forward everything else to `panic` lang item. this.start_panic( msg.description(), - match unwind { - Some(cleanup) => StackPopUnwind::Cleanup(cleanup), - None => StackPopUnwind::Skip, - }, + unwind, )?; } } diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index 484f703f9c1..e1631471ae2 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -1,6 +1,6 @@ thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -error: abnormal termination: the program aborted execution +error: abnormal termination: panic in a function that cannot unwind --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC | LL | / extern "C-unwind" fn nounwind() { @@ -8,7 +8,7 @@ LL | | LL | | LL | | panic!(); LL | | } - | |_^ the program aborted execution + | |_^ panic in a function that cannot unwind | = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index 484f703f9c1..e1631471ae2 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -1,6 +1,6 @@ thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -error: abnormal termination: the program aborted execution +error: abnormal termination: panic in a function that cannot unwind --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC | LL | / extern "C-unwind" fn nounwind() { @@ -8,7 +8,7 @@ LL | | LL | | LL | | panic!(); LL | | } - | |_^ the program aborted execution + | |_^ panic in a function that cannot unwind | = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs index 554cbe09cf0..65ba3433c28 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs @@ -4,8 +4,8 @@ #[cfg_attr(any(definition, both), rustc_nounwind)] #[no_mangle] extern "C-unwind" fn nounwind() { - //~[definition]^ ERROR: abnormal termination: the program aborted execution - //~[both]^^ ERROR: abnormal termination: the program aborted execution + //~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind + //~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind panic!(); } diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs new file mode 100644 index 00000000000..f4931659fc8 --- /dev/null +++ b/src/tools/miri/tests/fail/terminate-terminator.rs @@ -0,0 +1,27 @@ +//@compile-flags: -Zmir-opt-level=3 +// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated +// instead of just `UnwindAction::Terminate`. + +#![feature(c_unwind)] + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +#[inline(always)] +fn has_cleanup() { + //~^ ERROR: panic in a function that cannot unwind + // FIXME(nbdd0121): The error should be reported at the call site. + let _f = Foo; + panic!(); +} + +extern "C" fn panic_abort() { + has_cleanup(); +} + +fn main() { + panic_abort(); +} diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr new file mode 100644 index 00000000000..3befd83007b --- /dev/null +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -0,0 +1,27 @@ +thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +error: abnormal termination: panic in a function that cannot unwind + --> $DIR/terminate-terminator.rs:LL:CC + | +LL | / fn has_cleanup() { +LL | | +LL | | // FIXME(nbdd0121): The error should be reported at the call site. +LL | | let _f = Foo; +LL | | panic!(); +LL | | } + | |_^ panic in a function that cannot unwind +... +LL | has_cleanup(); + | ------------- in this inlined function call + | + = note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC +note: inside `main` + --> $DIR/terminate-terminator.rs:LL:CC + | +LL | panic_abort(); + | ^^^^^^^^^^^^^ + +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/abort-terminator.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs index c954443a276..876b9a9ab0a 100644 --- a/src/tools/miri/tests/fail/abort-terminator.rs +++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs @@ -1,7 +1,7 @@ #![feature(c_unwind)] extern "C" fn panic_abort() { - //~^ ERROR: the program aborted + //~^ ERROR: panic in a function that cannot unwind panic!() } diff --git a/src/tools/miri/tests/fail/abort-terminator.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 2d3275f6b19..52a1879cb5f 100644 --- a/src/tools/miri/tests/fail/abort-terminator.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -1,17 +1,17 @@ -thread 'main' panicked at 'explicit panic', $DIR/abort-terminator.rs:LL:CC +thread 'main' panicked at 'explicit panic', $DIR/unwind-action-terminate.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -error: abnormal termination: the program aborted execution - --> $DIR/abort-terminator.rs:LL:CC +error: abnormal termination: panic in a function that cannot unwind + --> $DIR/unwind-action-terminate.rs:LL:CC | LL | / extern "C" fn panic_abort() { LL | | LL | | panic!() LL | | } - | |_^ the program aborted execution + | |_^ panic in a function that cannot unwind | - = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC + = note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC note: inside `main` - --> $DIR/abort-terminator.rs:LL:CC + --> $DIR/unwind-action-terminate.rs:LL:CC | LL | panic_abort(); | ^^^^^^^^^^^^^ diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir index af5178d4079..4be382fac8c 100644 --- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir @@ -38,7 +38,7 @@ fn main() -> () { _6 = _3; // scope 4 at $DIR/array_index_is_temporary.rs:+4:25: +4:26 _5 = foo(move _6) -> bb1; // scope 4 at $DIR/array_index_is_temporary.rs:+4:21: +4:27 // mir::Constant - // + span: $DIR/array_index_is_temporary.rs:16:21: 16:24 + // + span: $DIR/array_index_is_temporary.rs:17:21: 17:24 // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs index e7bde81d4ca..702b9c70e59 100644 --- a/tests/mir-opt/array_index_is_temporary.rs +++ b/tests/mir-opt/array_index_is_temporary.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Retagging (from Stacked Borrows) relies on the array index being a fresh // temporary, so that side-effects cannot change it. // Test that this is indeed the case. 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 2487ef5c215..f6954ab3526 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); // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49 _1 = const (); // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49 - asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49 + asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49 } bb1: { @@ -17,8 +17,4 @@ fn main() -> () { _0 = const (); // scope 1 at $DIR/asm_unwind_panic_abort.rs:+1:5: +3:6 return; // scope 0 at $DIR/asm_unwind_panic_abort.rs:+4:2: +4:2 } - - bb2 (cleanup): { - abort; // scope 0 at $DIR/asm_unwind_panic_abort.rs:+0:1: +4:2 - } } diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff index 61a934685cd..d663c343515 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; // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11 - drop(_6) -> bb6; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20 + drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20 } bb3: { @@ -70,16 +70,20 @@ } bb6 (cleanup): { - drop(_5) -> bb7; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2 + drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2 } bb7 (cleanup): { -- drop(_4) -> bb8; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2 +- drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2 + goto -> bb8; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2 } bb8 (cleanup): { resume; // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2 ++ } ++ ++ bb9 (cleanup): { ++ unreachable; // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2 } } 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 6d1c7bd18dc..d63497e3a98 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; // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11 - drop(_6) -> bb6; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20 + drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20 } bb3: { @@ -73,11 +73,11 @@ fn main() -> () { } bb6 (cleanup): { - drop(_5) -> bb7; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2 + drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2 } bb7 (cleanup): { - drop(_4) -> bb8; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2 + drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2 } bb8 (cleanup): { diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir index 1bbf8f37f29..bac5b21dfad 100644 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -63,15 +63,15 @@ fn main() -> () { } bb6 (cleanup): { - drop(_7) -> bb7; // scope 1 at $DIR/box_expr.rs:+3:11: +3:12 + drop(_7) -> [return: bb7, unwind terminate]; // scope 1 at $DIR/box_expr.rs:+3:11: +3:12 } bb7 (cleanup): { - drop(_1) -> bb9; // scope 0 at $DIR/box_expr.rs:+4:1: +4:2 + drop(_1) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+4:1: +4:2 } bb8 (cleanup): { - drop(_5) -> bb9; // scope 0 at $DIR/box_expr.rs:+2:22: +2:23 + drop(_5) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+2:22: +2:23 } bb9 (cleanup): { diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index fd6485de863..7cce3415fa1 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -98,14 +98,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_3); // scope 0 at $DIR/async_await.rs:+1:5: +1:14 StorageLive(_4); // scope 0 at $DIR/async_await.rs:+1:8: +1:14 StorageLive(_5); // scope 0 at $DIR/async_await.rs:+1:5: +1:8 - _5 = a() -> bb2; // scope 0 at $DIR/async_await.rs:+1:5: +1:8 + _5 = a() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:5: +1:8 // mir::Constant // + span: $DIR/async_await.rs:15:5: 15:6 // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) } } bb2: { - _4 = <impl Future<Output = ()> as IntoFuture>::into_future(move _5) -> bb3; // scope 0 at $DIR/async_await.rs:+1:8: +1:14 + _4 = <impl Future<Output = ()> as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:8: +1:14 // mir::Constant // + span: $DIR/async_await.rs:15:8: 15:14 // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) } @@ -126,7 +126,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_12); // scope 2 at $DIR/async_await.rs:+1:8: +1:14 _12 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future<Output = ()>); // scope 2 at $DIR/async_await.rs:+1:8: +1:14 _11 = &mut (*_12); // scope 2 at $DIR/async_await.rs:+1:8: +1:14 - _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> bb5; // scope 2 at $DIR/async_await.rs:+1:8: +1:14 + _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14 // mir::Constant // + span: $DIR/async_await.rs:15:8: 15:14 // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) } @@ -145,7 +145,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, bb6: { _13 = &mut (*_14); // scope 2 at $DIR/async_await.rs:+1:5: +1:14 StorageDead(_15); // scope 2 at $DIR/async_await.rs:+1:13: +1:14 - _9 = <impl Future<Output = ()> as Future>::poll(move _10, move _13) -> bb7; // scope 2 at $DIR/async_await.rs:+1:8: +1:14 + _9 = <impl Future<Output = ()> as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14 // mir::Constant // + span: $DIR/async_await.rs:15:8: 15:14 // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) } @@ -206,14 +206,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageDead(_3); // scope 0 at $DIR/async_await.rs:+1:14: +1:15 StorageLive(_21); // scope 0 at $DIR/async_await.rs:+2:8: +2:14 StorageLive(_22); // scope 0 at $DIR/async_await.rs:+2:5: +2:8 - _22 = a() -> bb14; // scope 0 at $DIR/async_await.rs:+2:5: +2:8 + _22 = a() -> [return: bb14, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:5: +2:8 // mir::Constant // + span: $DIR/async_await.rs:16:5: 16:6 // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) } } bb14: { - _21 = <impl Future<Output = ()> as IntoFuture>::into_future(move _22) -> bb15; // scope 0 at $DIR/async_await.rs:+2:8: +2:14 + _21 = <impl Future<Output = ()> as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:8: +2:14 // mir::Constant // + span: $DIR/async_await.rs:16:8: 16:14 // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) } @@ -234,7 +234,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, StorageLive(_28); // scope 5 at $DIR/async_await.rs:+2:8: +2:14 _28 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future<Output = ()>); // scope 5 at $DIR/async_await.rs:+2:8: +2:14 _27 = &mut (*_28); // scope 5 at $DIR/async_await.rs:+2:8: +2:14 - _26 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _27) -> bb17; // scope 5 at $DIR/async_await.rs:+2:8: +2:14 + _26 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14 // mir::Constant // + span: $DIR/async_await.rs:16:8: 16:14 // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) } @@ -253,7 +253,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>, bb18: { _29 = &mut (*_30); // scope 5 at $DIR/async_await.rs:+2:5: +2:14 StorageDead(_31); // scope 5 at $DIR/async_await.rs:+2:13: +2:14 - _25 = <impl Future<Output = ()> as Future>::poll(move _26, move _29) -> bb19; // scope 5 at $DIR/async_await.rs:+2:8: +2:14 + _25 = <impl Future<Output = ()> as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14 // mir::Constant // + span: $DIR/async_await.rs:16:8: 16:14 // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) } 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 5231c2eab95..1112177fbbf 100644 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir @@ -63,7 +63,7 @@ fn droppy() -> () { } bb4 (cleanup): { - drop(_2) -> bb5; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 + drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6 } bb5 (cleanup): { diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir index de5e4c0f6ed..cc135f41721 100644 --- a/tests/mir-opt/building/issue_49232.main.built.after.mir +++ b/tests/mir-opt/building/issue_49232.main.built.after.mir @@ -17,7 +17,7 @@ fn main() -> () { } bb1: { - falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6 + falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6 } bb2: { 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 ed72726c5ae..54f0ea2d894 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 @@ -95,15 +95,15 @@ fn move_out_by_subslice() -> () { } bb9 (cleanup): { - drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2 + drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2 } bb10 (cleanup): { - drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 + drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 } bb11 (cleanup): { - drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 + drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 } 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 eca874130f6..5090a4ba675 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 @@ -95,15 +95,15 @@ fn move_out_from_end() -> () { } bb9 (cleanup): { - drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2 + drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2 } bb10 (cleanup): { - drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 + drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 } bb11 (cleanup): { - drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 + drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6 } bb12 (cleanup): { diff --git a/tests/mir-opt/combine_array_len.rs b/tests/mir-opt/combine_array_len.rs index 3ef3bd09afd..08c5f1a1fc5 100644 --- a/tests/mir-opt/combine_array_len.rs +++ b/tests/mir-opt/combine_array_len.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: InstCombine // EMIT_MIR combine_array_len.norm2.InstCombine.diff diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff index 20b0fb9643e..b715a544ffe 100644 --- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff +++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff @@ -72,7 +72,7 @@ } bb4 (cleanup): { - drop(_2) -> bb5; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15 + drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15 } bb5 (cleanup): { diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff index c44a14075ef..168e8c61031 100644 --- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff +++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff @@ -128,7 +128,7 @@ StorageDead(_22); // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48 StorageLive(_23); // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11 StorageLive(_24); // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77 - _24 = MaybeUninit::<String>::uninit() -> bb1; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77 + _24 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77 // mir::Constant // + span: $DIR/combine_transmutes.rs:46:46: 46:75 // + user_ty: UserType(23) diff --git a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff index c83c9f5acf4..ae1185c7f71 100644 --- a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff +++ b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff @@ -19,7 +19,7 @@ + _1 = const 1_i32; // scope 0 at $DIR/combine_transmutes.rs:+2:14: +2:38 StorageLive(_2); // scope 1 at $DIR/combine_transmutes.rs:+3:9: +3:11 StorageLive(_3); // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56 - _3 = Vec::<i32>::new() -> bb1; // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56 + _3 = Vec::<i32>::new() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56 // mir::Constant // + span: $DIR/combine_transmutes.rs:15:46: 15:54 // + user_ty: UserType(0) @@ -31,7 +31,7 @@ + _2 = move _3; // scope 1 at $DIR/combine_transmutes.rs:+3:14: +3:57 StorageDead(_3); // scope 1 at $DIR/combine_transmutes.rs:+3:56: +3:57 _0 = const (); // scope 0 at $DIR/combine_transmutes.rs:+0:37: +4:2 - drop(_2) -> bb2; // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2 + drop(_2) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2 } bb2: { diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff index f6e58955b4f..0411972661e 100644 --- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -29,7 +29,7 @@ + _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 // mir::Constant - // + span: $DIR/aggregate.rs:8:5: 8:8 + // + span: $DIR/aggregate.rs:9:5: 9:8 // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir index 4706af92cba..05d4bf8b52e 100644 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir +++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir @@ -25,7 +25,7 @@ fn main() -> () { _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10 _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11 // mir::Constant - // + span: $DIR/aggregate.rs:8:5: 8:8 + // + span: $DIR/aggregate.rs:9:5: 9:8 // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs index aa123b7a866..ed5a4ab594d 100644 --- a/tests/mir-opt/const_prop/aggregate.rs +++ b/tests/mir-opt/const_prop/aggregate.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -O diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs index d31c2827b4e..f36cf221348 100644 --- a/tests/mir-opt/const_prop/array_index.rs +++ b/tests/mir-opt/const_prop/array_index.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs index a6fd325ece0..38f1a993dc0 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff #[allow(unconditional_panic)] diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs index cc16a4a5aa7..a1078472cbf 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff #[allow(unconditional_panic)] fn main() { diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 38d402b8f21..e711babf035 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -25,7 +25,7 @@ StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _2 = &raw const (*_8); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 38d402b8f21..e711babf035 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -25,7 +25,7 @@ StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant - // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 + // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _2 = &raw const (*_8); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs index cf22b06d5e5..3d252f2d221 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff #[allow(unconditional_panic)] diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs index b9860da4c82..007defd1037 100644 --- a/tests/mir-opt/const_prop/checked_add.rs +++ b/tests/mir-opt/const_prop/checked_add.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -C overflow-checks=on diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index bea7114c7df..d75fae30b53 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -18,7 +18,7 @@ StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 _3 = const _; // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16 + // + span: $DIR/const_prop_fails_gracefully.rs:9:13: 9:16 // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16 _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39 @@ -29,7 +29,7 @@ _5 = _1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11 _4 = read(move _5) -> bb1; // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12 // mir::Constant - // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9 + // + span: $DIR/const_prop_fails_gracefully.rs:10:5: 10:9 // + literal: Const { ty: fn(usize) {read}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs index 0a3dcbd380f..44d4878424d 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp #[inline(never)] fn read(_: usize) { } diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs index 7dbe8e7344b..b2ca045e89f 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.rs +++ b/tests/mir-opt/const_prop/control_flow_simplification.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -Zmir-opt-level=1 diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs index 44916cbfe74..46fd8082d30 100644 --- a/tests/mir-opt/const_prop/indirect.rs +++ b/tests/mir-opt/const_prop/indirect.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -C overflow-checks=on diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff index d03c23a3fb5..0ac7fa43d5b 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff @@ -8,7 +8,7 @@ let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 scope 1 { } - scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47 + scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47 debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL let mut _4: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs index 541a8c5c3af..4e905d00d4d 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.rs +++ b/tests/mir-opt/const_prop/inherit_overflow.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -Zmir-enable-passes=+Inline diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff index a4f9003e140..2652694097c 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -11,7 +11,7 @@ _2 = (const (), const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 // mir::Constant - // + span: $DIR/issue_66971.rs:17:5: 17:11 + // + span: $DIR/issue_66971.rs:18:5: 18:11 // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs index 6ca03438ef3..af95c9ca283 100644 --- a/tests/mir-opt/const_prop/issue_66971.rs +++ b/tests/mir-opt/const_prop/issue_66971.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -Z mir-opt-level=3 diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff index f456a321204..54c9200d672 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -16,7 +16,7 @@ StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19 _1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20 // mir::Constant - // + span: $DIR/issue_67019.rs:12:5: 12:9 + // + span: $DIR/issue_67019.rs:13:5: 13:9 // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs index ffc6fa1f290..08c7d4805d6 100644 --- a/tests/mir-opt/const_prop/issue_67019.rs +++ b/tests/mir-opt/const_prop/issue_67019.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -Z mir-opt-level=3 diff --git a/tests/mir-opt/const_prop/large_array_index.rs b/tests/mir-opt/const_prop/large_array_index.rs index 48d134376db..073f9849568 100644 --- a/tests/mir-opt/const_prop/large_array_index.rs +++ b/tests/mir-opt/const_prop/large_array_index.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR large_array_index.main.ConstProp.diff diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff index 149aa6290d0..75f6ebc58c7 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34 // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32 + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:29: 7:32 // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs index cb59509ff10..70a287cf381 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test // compile-flags: -O diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 4010dd6c6d0..9582504b25e 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -26,7 +26,7 @@ StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 _1 = foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18 // mir::Constant - // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16 + // + span: $DIR/mutable_variable_unprop_assign.rs:7:13: 7:16 // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs index b077cfd3e0a..fabd04e9bd2 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test // compile-flags: -O diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.rs b/tests/mir-opt/const_prop/optimizes_into_variable.rs index abea07e2025..5ffa153476d 100644 --- a/tests/mir-opt/const_prop/optimizes_into_variable.rs +++ b/tests/mir-opt/const_prop/optimizes_into_variable.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test // compile-flags: -C overflow-checks=on diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs index 36d9b9fc62d..2f3b7d2c502 100644 --- a/tests/mir-opt/const_prop/repeat.rs +++ b/tests/mir-opt/const_prop/repeat.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -O // EMIT_MIR_FOR_EACH_BIT_WIDTH diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs index 06a85369679..ae119df8518 100644 --- a/tests/mir-opt/const_prop/return_place.rs +++ b/tests/mir-opt/const_prop/return_place.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -C overflow-checks=on // EMIT_MIR return_place.add.ConstProp.diff diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff index 1151caaabbc..a091b4ace20 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff @@ -15,7 +15,7 @@ - _2 = consume(_1) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 + _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12 + // + span: $DIR/scalar_literal_propagation.rs:5:5: 5:12 // + literal: Const { ty: fn(u32) {consume}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs index 8724e4d5711..e13e352f8a1 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // EMIT_MIR scalar_literal_propagation.main.ConstProp.diff fn main() { let x = 1; diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index b99b83b0cba..8bd2b48d6d6 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -20,7 +20,7 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:7:6: 7:19 + // + span: $DIR/slice_len.rs:8:6: 8:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index b99b83b0cba..8bd2b48d6d6 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -20,7 +20,7 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:7:6: 7:19 + // + span: $DIR/slice_len.rs:8:6: 8:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 8183def0c63..4499c54f264 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: ConstProp // compile-flags: -Zmir-enable-passes=+InstCombine // EMIT_MIR_FOR_EACH_BIT_WIDTH diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff index ddc1a4493db..85704c48a2c 100644 --- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff @@ -15,14 +15,14 @@ bb1: { _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 // mir::Constant - // + span: $DIR/switch_int.rs:9:14: 9:17 + // + span: $DIR/switch_int.rs:10:14: 10:17 // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) } } bb2: { _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 // mir::Constant - // + span: $DIR/switch_int.rs:8:14: 8:17 + // + span: $DIR/switch_int.rs:9:14: 9:17 // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff index 09c47ee6e83..0864db22523 100644 --- a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff +++ b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff @@ -15,14 +15,14 @@ bb1: { _0 = foo(const -1_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+3:14: +3:21 // mir::Constant - // + span: $DIR/switch_int.rs:9:14: 9:17 + // + span: $DIR/switch_int.rs:10:14: 10:17 // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) } } bb2: { _0 = foo(const 0_i32) -> bb3; // scope 0 at $DIR/switch_int.rs:+2:14: +2:20 // mir::Constant - // + span: $DIR/switch_int.rs:8:14: 8:17 + // + span: $DIR/switch_int.rs:9:14: 9:17 // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs index d7319eca18e..2a2322e43a9 100644 --- a/tests/mir-opt/const_prop/switch_int.rs +++ b/tests/mir-opt/const_prop/switch_int.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #[inline(never)] fn foo(_: i32) { } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index d370abce45a..12313b6c58d 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -15,7 +15,7 @@ + _1 = const (1_u32, 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19 _2 = consume(_1) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15 // mir::Constant - // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12 + // + span: $DIR/tuple_literal_propagation.rs:6:5: 6:12 // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs index e644baec4a8..edd748d00ab 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // EMIT_MIR tuple_literal_propagation.main.ConstProp.diff fn main() { let x = (1, 2); diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff index b183865a9bc..2a0bff57db9 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff @@ -15,7 +15,7 @@ _4 = &_3; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL _0 = cmp_ref(_2, _4) -> bb1; // scope 0 at $DIR/borrowed_local.rs:+8:13: +8:45 // mir::Constant - // + span: $DIR/borrowed_local.rs:23:29: 23:36 + // + span: $DIR/borrowed_local.rs:24:29: 24:36 // + literal: Const { ty: for<'a, 'b> fn(&'a u8, &'b u8) -> bool {cmp_ref}, val: Value(<ZST>) } } @@ -23,7 +23,7 @@ - _0 = opaque::<u8>(_3) -> bb2; // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38 + _0 = opaque::<u8>(_1) -> bb2; // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38 // mir::Constant - // + span: $DIR/borrowed_local.rs:27:28: 27:34 + // + span: $DIR/borrowed_local.rs:28:28: 28:34 // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index c4b980e2b35..9186da5af48 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: CopyProp #![feature(custom_mir, core_intrinsics)] diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff index 8b116532d9f..b78c19d78d0 100644 --- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff +++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff @@ -18,7 +18,7 @@ StorageLive(_1); // scope 0 at $DIR/branch.rs:+1:9: +1:10 _1 = val() -> bb1; // scope 0 at $DIR/branch.rs:+1:13: +1:18 // mir::Constant - // + span: $DIR/branch.rs:13:13: 13:16 + // + span: $DIR/branch.rs:14:13: 14:16 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } @@ -27,7 +27,7 @@ StorageLive(_3); // scope 1 at $DIR/branch.rs:+3:16: +3:22 _3 = cond() -> bb2; // scope 1 at $DIR/branch.rs:+3:16: +3:22 // mir::Constant - // + span: $DIR/branch.rs:15:16: 15:20 + // + span: $DIR/branch.rs:16:16: 16:20 // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) } } @@ -44,7 +44,7 @@ StorageLive(_4); // scope 1 at $DIR/branch.rs:+6:9: +6:14 _4 = val() -> bb5; // scope 1 at $DIR/branch.rs:+6:9: +6:14 // mir::Constant - // + span: $DIR/branch.rs:18:9: 18:12 + // + span: $DIR/branch.rs:19:9: 19:12 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/branch.rs b/tests/mir-opt/copy-prop/branch.rs index 50b1e00fad4..0a2e1694634 100644 --- a/tests/mir-opt/copy-prop/branch.rs +++ b/tests/mir-opt/copy-prop/branch.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Tests that we bail out when there are multiple assignments to the same local. // unit-test: CopyProp fn val() -> i32 { diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff index ac4e9a2bfa7..24bca32207f 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff @@ -13,7 +13,7 @@ _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10 + // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff index 0a3e985e7c2..87708f34005 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff @@ -13,7 +13,7 @@ _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16 _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14 + // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.rs b/tests/mir-opt/copy-prop/copy_propagation_arg.rs index cc98985f1fd..1b65dcb01ed 100644 --- a/tests/mir-opt/copy-prop/copy_propagation_arg.rs +++ b/tests/mir-opt/copy-prop/copy_propagation_arg.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that CopyProp does not propagate an assignment to a function argument // (doing so can break usages of the original argument value) // unit-test: CopyProp diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff index 6ca73ffdde2..160f47bdd8f 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff @@ -11,7 +11,7 @@ - _0 = opaque::<NotCopy>(move _1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41 + _0 = opaque::<NotCopy>(_1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41 // mir::Constant - // + span: $DIR/custom_move_arg.rs:15:24: 15:30 + // + span: $DIR/custom_move_arg.rs:16:24: 16:30 // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) } } @@ -20,7 +20,7 @@ - _0 = opaque::<NotCopy>(_3) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35 + _0 = opaque::<NotCopy>(_1) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35 // mir::Constant - // + span: $DIR/custom_move_arg.rs:19:24: 19:30 + // + span: $DIR/custom_move_arg.rs:20:24: 20:30 // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index 4a591146e61..29c368df82d 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: CopyProp #![feature(custom_mir, core_intrinsics)] diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff index 3e61869e82f..23d92ed1ac5 100644 --- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff @@ -24,7 +24,7 @@ StorageLive(_1); // scope 0 at $DIR/cycle.rs:+1:9: +1:14 _1 = val() -> bb1; // scope 0 at $DIR/cycle.rs:+1:17: +1:22 // mir::Constant - // + span: $DIR/cycle.rs:9:17: 9:20 + // + span: $DIR/cycle.rs:10:17: 10:20 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } @@ -43,7 +43,7 @@ _6 = _1; // scope 3 at $DIR/cycle.rs:+6:10: +6:11 _5 = std::mem::drop::<i32>(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12 // mir::Constant - // + span: $DIR/cycle.rs:14:5: 14:9 + // + span: $DIR/cycle.rs:15:5: 15:9 // + literal: Const { ty: fn(i32) {std::mem::drop::<i32>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/cycle.rs b/tests/mir-opt/copy-prop/cycle.rs index b74c397269d..da70f6bec2e 100644 --- a/tests/mir-opt/copy-prop/cycle.rs +++ b/tests/mir-opt/copy-prop/cycle.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code. // unit-test: CopyProp fn val() -> i32 { diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir index d48b04e2de2..c56418d8893 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir +++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir @@ -18,7 +18,7 @@ fn f(_1: usize) -> usize { _4 = _1; // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9 _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10 // mir::Constant - // + span: $DIR/dead_stores_79191.rs:12:5: 12:7 + // + span: $DIR/dead_stores_79191.rs:13:5: 13:7 // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.rs b/tests/mir-opt/copy-prop/dead_stores_79191.rs index e3493b8b7a1..84453c55e3e 100644 --- a/tests/mir-opt/copy-prop/dead_stores_79191.rs +++ b/tests/mir-opt/copy-prop/dead_stores_79191.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: CopyProp fn id<T>(x: T) -> T { diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir index 727791f50a4..f355421732e 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir +++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir @@ -18,7 +18,7 @@ fn f(_1: usize) -> usize { _4 = _1; // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9 _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10 // mir::Constant - // + span: $DIR/dead_stores_better.rs:16:5: 16:7 + // + span: $DIR/dead_stores_better.rs:17:5: 17:7 // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/dead_stores_better.rs b/tests/mir-opt/copy-prop/dead_stores_better.rs index 8465b3c9853..87b916fd3ff 100644 --- a/tests/mir-opt/copy-prop/dead_stores_better.rs +++ b/tests/mir-opt/copy-prop/dead_stores_better.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates // that that pass enables this one to do more optimizations. diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff index 97d0a01e00b..e09ccb83119 100644 --- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff +++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff @@ -51,7 +51,7 @@ StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18 _5 = core::slice::<impl [i32]>::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24 // mir::Constant - // + span: $DIR/issue_107511.rs:10:19: 10:22 + // + span: $DIR/issue_107511.rs:11:19: 11:22 // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::<impl [i32]>::len}, val: Value(<ZST>) } } @@ -61,7 +61,7 @@ StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24 _3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24 // mir::Constant - // + span: $DIR/issue_107511.rs:10:14: 10:24 + // + span: $DIR/issue_107511.rs:11:14: 11:24 // + literal: Const { ty: fn(std::ops::Range<usize>) -> <std::ops::Range<usize> as IntoIterator>::IntoIter {<std::ops::Range<usize> as IntoIterator>::into_iter}, val: Value(<ZST>) } } @@ -81,7 +81,7 @@ _12 = &mut (*_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 _11 = <std::ops::Range<usize> as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24 // mir::Constant - // + span: $DIR/issue_107511.rs:10:14: 10:24 + // + span: $DIR/issue_107511.rs:11:14: 11:24 // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<usize>) -> Option<<std::ops::Range<usize> as Iterator>::Item> {<std::ops::Range<usize> as Iterator>::next}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs index d593f2872ea..2b00ff15581 100644 --- a/tests/mir-opt/copy-prop/issue_107511.rs +++ b/tests/mir-opt/copy-prop/issue_107511.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: CopyProp // EMIT_MIR issue_107511.main.CopyProp.diff diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff index d76bf1cfe7e..650bd66a7d7 100644 --- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff @@ -24,7 +24,7 @@ - _3 = g::<T>(move _4, move _5) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12 + _3 = g::<T>(_1, _1) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12 // mir::Constant - // + span: $DIR/move_arg.rs:7:5: 7:6 + // + span: $DIR/move_arg.rs:8:5: 8:6 // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/move_arg.rs b/tests/mir-opt/copy-prop/move_arg.rs index 40ae1d8f466..f88d9a9e74b 100644 --- a/tests/mir-opt/copy-prop/move_arg.rs +++ b/tests/mir-opt/copy-prop/move_arg.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Test that we do not move multiple times from the same local. // unit-test: CopyProp diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff index 02308beb88a..beb85d68a66 100644 --- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff +++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff @@ -13,14 +13,14 @@ + _3 = (_1.0: u8); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + _0 = opaque::<Foo>(_1) -> bb1; // scope 0 at $DIR/move_projection.rs:+6:13: +6:44 // mir::Constant - // + span: $DIR/move_projection.rs:19:28: 19:34 + // + span: $DIR/move_projection.rs:20:28: 20:34 // + literal: Const { ty: fn(Foo) -> bool {opaque::<Foo>}, val: Value(<ZST>) } } bb1: { _0 = opaque::<u8>(move _3) -> bb2; // scope 0 at $DIR/move_projection.rs:+9:13: +9:44 // mir::Constant - // + span: $DIR/move_projection.rs:22:28: 22:34 + // + span: $DIR/move_projection.rs:23:28: 23:34 // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index 2a1bbae99a4..c158c69e0cf 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: CopyProp #![feature(custom_mir, core_intrinsics)] diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff index 6c32b675a5b..b4a24824566 100644 --- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff +++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff @@ -39,7 +39,7 @@ - _6 = opaque::<*mut u8>(move _7) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14 + _6 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14 // mir::Constant - // + span: $DIR/reborrow.rs:38:5: 38:11 + // + span: $DIR/reborrow.rs:39:5: 39:11 // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff index 2f1b522c2ec..a6a6c05b24a 100644 --- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff +++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff @@ -35,7 +35,7 @@ - _5 = opaque::<*mut u8>(move _6) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14 + _5 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14 // mir::Constant - // + span: $DIR/reborrow.rs:30:5: 30:11 + // + span: $DIR/reborrow.rs:31:5: 31:11 // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff index 9b580c1f4e1..f3d26cc6e2b 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff +++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff @@ -33,7 +33,7 @@ - _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14 + _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14 // mir::Constant - // + span: $DIR/reborrow.rs:14:5: 14:11 + // + span: $DIR/reborrow.rs:15:5: 15:11 // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff index cff4a176098..63e42b4dc77 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff +++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff @@ -33,7 +33,7 @@ - _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14 + _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14 // mir::Constant - // + span: $DIR/reborrow.rs:22:5: 22:11 + // + span: $DIR/reborrow.rs:23:5: 23:11 // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs index c2926b8fa51..91b77966ba8 100644 --- a/tests/mir-opt/copy-prop/reborrow.rs +++ b/tests/mir-opt/copy-prop/reborrow.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that CopyProp considers reborrows as not mutating the pointer. // unit-test: CopyProp diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index 0738a4ee53b..0f9f5a97fac 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff index 29781e9ce18..1edcc28e68c 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff @@ -8,7 +8,7 @@ let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 scope 1 { } - scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47 + scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47 debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL let mut _4: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index f4aba60f0c8..90349d5270c 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+Inline diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff index 158f187f157..70ef17afd65 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff @@ -26,7 +26,7 @@ _3 = &(*_4); // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14 _2 = escape::<i32>(move _3) -> bb1; // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15 // mir::Constant - // + span: $DIR/ref_without_sb.rs:12:5: 12:11 + // + span: $DIR/ref_without_sb.rs:13:5: 13:11 // + literal: Const { ty: for<'a> fn(&'a i32) {escape::<i32>}, val: Value(<ZST>) } } @@ -38,7 +38,7 @@ StorageLive(_5); // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20 _5 = some_function() -> bb2; // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20 // mir::Constant - // + span: $DIR/ref_without_sb.rs:14:5: 14:18 + // + span: $DIR/ref_without_sb.rs:15:5: 15:18 // + literal: Const { ty: fn() {some_function}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index 2fd480b0968..f53de3cf2d4 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DataflowConstProp #[inline(never)] diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff index 004643e36f1..6ca569f3d8e 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff @@ -32,7 +32,7 @@ _5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11 _4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18 // mir::Constant - // + span: $DIR/sibling_ptr.rs:15:12: 15:15 + // + span: $DIR/sibling_ptr.rs:16:12: 16:15 // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 6dfb3a4ed30..81fc3c2f49c 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`. // According to Miri, that is UB. However, T-opsem has not finalized that // decision and as such we cannot rely on it in optimizations. Consequently, diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff index 8018400e798..9854beaeb21 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff @@ -25,7 +25,7 @@ - _2 = foo(move _3) -> bb1; // scope 1 at $DIR/terminator.rs:+3:5: +3:15 + _2 = foo(const 2_i32) -> bb1; // scope 1 at $DIR/terminator.rs:+3:5: +3:15 // mir::Constant - // + span: $DIR/terminator.rs:9:5: 9:8 + // + span: $DIR/terminator.rs:10:5: 10:8 // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index d151f666a2d..4f001df35f1 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DataflowConstProp fn foo(n: i32) {} diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff index cd3b792fb75..2776ff51d85 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff @@ -32,7 +32,7 @@ + StorageLive(_4); // scope 0 at $DIR/cycle.rs:+3:11: +3:17 + _4 = cond() -> bb2; // scope 0 at $DIR/cycle.rs:+3:11: +3:17 // mir::Constant - // + span: $DIR/cycle.rs:12:11: 12:15 + // + span: $DIR/cycle.rs:13:11: 13:15 // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index b35ce0bcb5a..570bfe84d10 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DeadStoreElimination #[inline(never)] diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index 3b1f81175cb..c4ebf1ca834 100644 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -19,7 +19,7 @@ _3 = &(*_1); // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23 _2 = core::str::<impl str>::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23 // mir::Constant - // + span: $DIR/deduplicate_blocks.rs:5:13: 5:21 + // + span: $DIR/deduplicate_blocks.rs:6:13: 6:21 // + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs index 2b9eed99ecd..46012e19aa4 100644 --- a/tests/mir-opt/deduplicate_blocks.rs +++ b/tests/mir-opt/deduplicate_blocks.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DeduplicateBlocks // EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff diff --git a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir index 9597a0c835f..97826ed19a2 100644 --- a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir +++ b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir @@ -25,19 +25,19 @@ fn foo(_1: Option<String>) -> i32 { _7 = const false; // scope 0 at $DIR/string.rs:+3:9: +3:10 _6 = move _1; // scope 0 at $DIR/string.rs:+3:9: +3:10 _0 = const 4321_i32; // scope 1 at $DIR/string.rs:+3:14: +3:18 - drop(_6) -> bb6; // scope 0 at $DIR/string.rs:+3:17: +3:18 + drop(_6) -> [return: bb6, unwind unreachable]; // scope 0 at $DIR/string.rs:+3:17: +3:18 } bb2: { _2 = &((_1 as Some).0: std::string::String); // scope 0 at $DIR/string.rs:+2:14: +2:17 - _3 = <String as Deref>::deref(move _2) -> bb3; // scope 0 at $DIR/string.rs:+2:14: +2:17 + _3 = <String as Deref>::deref(move _2) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17 // mir::Constant // + span: $DIR/string.rs:9:14: 9:17 // + literal: Const { ty: for<'a> fn(&'a String) -> &'a <String as Deref>::Target {<String as Deref>::deref}, val: Value(<ZST>) } } bb3: { - _4 = <str as PartialEq>::eq(_3, const "a") -> bb4; // scope 0 at $DIR/string.rs:+2:14: +2:17 + _4 = <str as PartialEq>::eq(_3, const "a") -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17 // mir::Constant // + span: $DIR/string.rs:9:14: 9:17 // + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {<str as PartialEq>::eq}, val: Value(<ZST>) } @@ -65,7 +65,7 @@ fn foo(_1: Option<String>) -> i32 { } bb8: { - drop(_1) -> bb7; // scope 0 at $DIR/string.rs:+5:1: +5:2 + drop(_1) -> [return: bb7, unwind unreachable]; // scope 0 at $DIR/string.rs:+5:1: +5:2 } bb9: { diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.diff index ec9cbb25322..426d4fb213c 100644 --- a/tests/mir-opt/derefer_inline_test.main.Derefer.diff +++ b/tests/mir-opt/derefer_inline_test.main.Derefer.diff @@ -35,7 +35,7 @@ } bb4 (cleanup): { - drop(_2) -> bb5; // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18 + drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18 } bb5 (cleanup): { diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff index 9c729663265..b7416d389ef 100644 --- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff @@ -22,7 +22,7 @@ + nop; // scope 0 at $DIR/branch.rs:+1:9: +1:10 + _0 = val() -> bb1; // scope 0 at $DIR/branch.rs:+1:13: +1:18 // mir::Constant - // + span: $DIR/branch.rs:13:13: 13:16 + // + span: $DIR/branch.rs:14:13: 14:16 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } @@ -32,7 +32,7 @@ StorageLive(_3); // scope 1 at $DIR/branch.rs:+3:16: +3:22 _3 = cond() -> bb2; // scope 1 at $DIR/branch.rs:+3:16: +3:22 // mir::Constant - // + span: $DIR/branch.rs:15:16: 15:20 + // + span: $DIR/branch.rs:16:16: 16:20 // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) } } @@ -50,7 +50,7 @@ StorageLive(_4); // scope 1 at $DIR/branch.rs:+6:9: +6:14 _4 = val() -> bb5; // scope 1 at $DIR/branch.rs:+6:9: +6:14 // mir::Constant - // + span: $DIR/branch.rs:18:9: 18:12 + // + span: $DIR/branch.rs:19:9: 19:12 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/branch.rs b/tests/mir-opt/dest-prop/branch.rs index 898c908b18c..7e4276e6692 100644 --- a/tests/mir-opt/dest-prop/branch.rs +++ b/tests/mir-opt/dest-prop/branch.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Tests that assignment in both branches of an `if` are eliminated. // unit-test: DestinationPropagation fn val() -> i32 { diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff index 298991b5ad1..a61e741f73d 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff @@ -16,7 +16,7 @@ + nop; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12 + _2 = dummy(move _1) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10 + // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff index d37a9f71d3e..c7fbecac5c4 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff @@ -15,7 +15,7 @@ - _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 + _1 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17 // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14 + // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14 // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs index 31be6c93139..57cb328c231 100644 --- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs +++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that DestinationPropagation does not propagate an assignment to a function argument // (doing so can break usages of the original argument value) // unit-test: DestinationPropagation diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff index cfc203c5f89..b06f069a2e4 100644 --- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff @@ -28,7 +28,7 @@ + nop; // scope 0 at $DIR/cycle.rs:+1:9: +1:14 + _6 = val() -> bb1; // scope 0 at $DIR/cycle.rs:+1:17: +1:22 // mir::Constant - // + span: $DIR/cycle.rs:9:17: 9:20 + // + span: $DIR/cycle.rs:10:17: 10:20 // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) } } @@ -56,7 +56,7 @@ + nop; // scope 3 at $DIR/cycle.rs:+6:10: +6:11 _5 = std::mem::drop::<i32>(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12 // mir::Constant - // + span: $DIR/cycle.rs:14:5: 14:9 + // + span: $DIR/cycle.rs:15:5: 15:9 // + literal: Const { ty: fn(i32) {std::mem::drop::<i32>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/cycle.rs b/tests/mir-opt/dest-prop/cycle.rs index 6182878f341..3aea19d80dc 100644 --- a/tests/mir-opt/dest-prop/cycle.rs +++ b/tests/mir-opt/dest-prop/cycle.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code. // unit-test: DestinationPropagation fn val() -> i32 { diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir index 63cac133b73..b9d4b59d2f7 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir +++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir @@ -22,7 +22,7 @@ fn f(_1: usize) -> usize { nop; // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9 _0 = id::<usize>(move _1) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10 // mir::Constant - // + span: $DIR/dead_stores_79191.rs:12:5: 12:7 + // + span: $DIR/dead_stores_79191.rs:13:5: 13:7 // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs index 43e0bf66418..9d4814838d4 100644 --- a/tests/mir-opt/dest-prop/dead_stores_79191.rs +++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: DestinationPropagation fn id<T>(x: T) -> T { diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir index 26068931aaf..9eb0e09bf1b 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir +++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir @@ -21,7 +21,7 @@ fn f(_1: usize) -> usize { nop; // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9 _0 = id::<usize>(move _1) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10 // mir::Constant - // + span: $DIR/dead_stores_better.rs:16:5: 16:7 + // + span: $DIR/dead_stores_better.rs:17:5: 17:7 // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs index 003ad57d83e..72d406bfd40 100644 --- a/tests/mir-opt/dest-prop/dead_stores_better.rs +++ b/tests/mir-opt/dest-prop/dead_stores_better.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates // that that pass enables this one to do more optimizations. diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs index d4c27228fe4..3a4aec34e8c 100644 --- a/tests/mir-opt/dest-prop/simple.rs +++ b/tests/mir-opt/dest-prop/simple.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too. // unit-test: DestinationPropagation // EMIT_MIR simple.nrvo.DestinationPropagation.diff diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff index fbed3178801..457fc830874 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff @@ -10,7 +10,7 @@ debug un => _1; // in scope 1 at $DIR/union.rs:+5:9: +5:11 scope 2 { } - scope 3 (inlined std::mem::drop::<u32>) { // at $DIR/union.rs:15:5: 15:27 + scope 3 (inlined std::mem::drop::<u32>) { // at $DIR/union.rs:16:5: 16:27 debug _x => _3; // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL } } @@ -20,7 +20,7 @@ StorageLive(_2); // scope 0 at $DIR/union.rs:+5:23: +5:28 _2 = val() -> bb1; // scope 0 at $DIR/union.rs:+5:23: +5:28 // mir::Constant - // + span: $DIR/union.rs:13:23: 13:26 + // + span: $DIR/union.rs:14:23: 14:26 // + literal: Const { ty: fn() -> u32 {val}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/union.rs b/tests/mir-opt/dest-prop/union.rs index eb6cb09fc45..062d02d0673 100644 --- a/tests/mir-opt/dest-prop/union.rs +++ b/tests/mir-opt/dest-prop/union.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default //! Tests that we can propagate into places that are projections into unions // compile-flags: -Zunsound-mir-opts fn val() -> u32 { diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff index 9ea756c2712..ae63d724d0a 100644 --- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff +++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff @@ -36,7 +36,7 @@ - _6 = _2; // scope 1 at $DIR/unreachable.rs:+3:14: +3:15 - _4 = g::<T>(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16 - // mir::Constant -- // + span: $DIR/unreachable.rs:11:9: 11:10 +- // + span: $DIR/unreachable.rs:12:9: 12:10 - // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) } - } - @@ -60,7 +60,7 @@ + _9 = _1; // scope 1 at $DIR/unreachable.rs:+5:14: +5:15 + _7 = g::<T>(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16 // mir::Constant - // + span: $DIR/unreachable.rs:13:9: 13:10 + // + span: $DIR/unreachable.rs:14:9: 14:10 // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs index 32b5def984a..c73d11ae3ba 100644 --- a/tests/mir-opt/dest-prop/unreachable.rs +++ b/tests/mir-opt/dest-prop/unreachable.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that unreachable code is removed after the destination propagation. // Regression test for issue #105428. // diff --git a/tests/mir-opt/div_overflow.rs b/tests/mir-opt/div_overflow.rs index 10ce5bc0f4f..fe34a865b93 100644 --- a/tests/mir-opt/div_overflow.rs +++ b/tests/mir-opt/div_overflow.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -Copt-level=0 -Coverflow-checks=yes // Tests that division with a const does not emit a panicking branch for overflow diff --git a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff index c1a42a47ed2..c0fc1fb1df3 100644 --- a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff +++ b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff @@ -7,7 +7,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 - _1 = assert_mem_uninitialized_valid::<&T>() -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 + _1 = assert_mem_uninitialized_valid::<&T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 // mir::Constant // + span: $DIR/dont_yeet_assert.rs:10:5: 10:59 // + user_ty: UserType(0) diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff index ec063294856..8a4a1682519 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -40,7 +40,7 @@ _5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37 // mir::Constant - // + span: $DIR/funky_arms.rs:15:26: 15:35 + // + span: $DIR/funky_arms.rs:16:26: 16:35 // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value(<ZST>) } } @@ -74,7 +74,7 @@ _8 = &(*_1); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45 // mir::Constant - // + span: $DIR/funky_arms.rs:24:34: 24:43 + // + span: $DIR/funky_arms.rs:25:34: 25:43 // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option<usize> {Formatter::<'_>::precision}, val: Value(<ZST>) } } @@ -95,7 +95,7 @@ StorageDead(_15); // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79 _0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87 // mir::Constant - // + span: $DIR/funky_arms.rs:26:9: 26:42 + // + span: $DIR/funky_arms.rs:27:9: 27:42 // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) } } @@ -110,7 +110,7 @@ _20 = _6; // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60 _0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68 // mir::Constant - // + span: $DIR/funky_arms.rs:28:9: 28:45 + // + span: $DIR/funky_arms.rs:29:9: 29:45 // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs index 3e70d85e0d4..c4f75b5df6d 100644 --- a/tests/mir-opt/funky_arms.rs +++ b/tests/mir-opt/funky_arms.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: --crate-type lib -Cdebug-assertions=no #![feature(flt2dec)] diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir index cfbe0aaf252..32b472ebeeb 100644 --- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir +++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir @@ -110,7 +110,7 @@ yields () bb13 (cleanup): { StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 - drop(_1) -> bb14; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } bb14 (cleanup): { @@ -119,6 +119,6 @@ yields () bb15 (cleanup): { StorageDead(_3); // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 - drop(_1) -> bb14; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 + drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6 } } diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir index 7efda05d2b8..dc9bb533f13 100644 --- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir @@ -63,7 +63,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24 StorageDead(_7); // scope 1 at $DIR/generator_tiny.rs:+3:17: +3:18 StorageDead(_6); // scope 1 at $DIR/generator_tiny.rs:+3:18: +3:19 StorageLive(_8); // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21 - _8 = callee() -> bb4; // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21 + _8 = callee() -> [return: bb4, unwind unreachable]; // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21 // mir::Constant // + span: $DIR/generator_tiny.rs:23:13: 23:19 // + literal: Const { ty: fn() {callee}, val: Value(<ZST>) } diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.diff index ed290063a93..ba1bfec05d2 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.diff @@ -35,7 +35,7 @@ + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 ++ drop(_2) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 + } + + bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff index 501390c3bf1..8da59757743 100644 --- a/tests/mir-opt/inline/cycle.f.Inline.diff +++ b/tests/mir-opt/inline/cycle.f.Inline.diff @@ -33,7 +33,7 @@ } bb3 (cleanup): { - drop(_1) -> bb4; // scope 0 at $DIR/cycle.rs:+2:1: +2:2 + drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/cycle.rs:+2:1: +2:2 } bb4 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.g.Inline.diff b/tests/mir-opt/inline/cycle.g.Inline.diff index 20d313aecf5..1e6e30f9e9b 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.diff @@ -42,7 +42,7 @@ + } + + bb2 (cleanup): { -+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { diff --git a/tests/mir-opt/inline/cycle.main.Inline.diff b/tests/mir-opt/inline/cycle.main.Inline.diff index dacc5f4be9d..315634945e4 100644 --- a/tests/mir-opt/inline/cycle.main.Inline.diff +++ b/tests/mir-opt/inline/cycle.main.Inline.diff @@ -42,7 +42,7 @@ + } + + bb2 (cleanup): { -+ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff index 64c3e47ff46..75d9bd54d5b 100644 --- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff @@ -9,11 +9,11 @@ let mut _4: &<Q as Query>::C; // in scope 0 at $DIR/dyn_trait.rs:+2:23: +2:24 scope 1 { debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:+1:9: +1:10 -+ scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:34:5: 34:25 -+ debug c => _4; // in scope 2 at $DIR/dyn_trait.rs:26:36: 26:37 -+ let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 -+ scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 -+ debug c => _5; // in scope 3 at $DIR/dyn_trait.rs:20:27: 20:28 ++ scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:35:5: 35:25 ++ debug c => _4; // in scope 2 at $DIR/dyn_trait.rs:27:36: 27:37 ++ let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:28:14: 28:15 ++ scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16 ++ debug c => _5; // in scope 3 at $DIR/dyn_trait.rs:21:27: 21:28 + } + } } @@ -24,7 +24,7 @@ _3 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 _2 = <Q as Query>::cache::<T>(move _3) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:13: +1:24 // mir::Constant - // + span: $DIR/dyn_trait.rs:33:13: 33:21 + // + span: $DIR/dyn_trait.rs:34:13: 34:21 // + user_ty: UserType(0) // + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) } } @@ -34,18 +34,18 @@ StorageLive(_4); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 _4 = &(*_2); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 - _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25 -+ StorageLive(_5); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 -+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 -+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 ++ StorageLive(_5); // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15 ++ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15 ++ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:22:5: 22:22 // mir::Constant -- // + span: $DIR/dyn_trait.rs:34:5: 34:22 +- // + span: $DIR/dyn_trait.rs:35:5: 35:22 - // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) } -+ // + span: $DIR/dyn_trait.rs:21:7: 21:20 ++ // + span: $DIR/dyn_trait.rs:22:7: 22:20 + // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) } } bb2: { -+ StorageDead(_5); // scope 2 at $DIR/dyn_trait.rs:27:15: 27:16 ++ StorageDead(_5); // scope 2 at $DIR/dyn_trait.rs:28:15: 28:16 StorageDead(_4); // scope 1 at $DIR/dyn_trait.rs:+2:24: +2:25 StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+3:1: +3:2 return; // scope 0 at $DIR/dyn_trait.rs:+3:2: +3:2 diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff index 7653a5ded44..925c95988b7 100644 --- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff +++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff @@ -11,7 +11,7 @@ _2 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 _0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 // mir::Constant - // + span: $DIR/dyn_trait.rs:21:7: 21:20 + // + span: $DIR/dyn_trait.rs:22:7: 22:20 // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs index 6a46e1e07b1..2af81f82570 100644 --- a/tests/mir-opt/inline/dyn_trait.rs +++ b/tests/mir-opt/inline/dyn_trait.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #![crate_type = "lib"] use std::fmt::Debug; diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff index 3fa9c3e88f6..f4e5272abfc 100644 --- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff @@ -6,8 +6,8 @@ let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:43: +0:43 let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 let mut _3: &C; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 -+ scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 -+ debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:20:27: 20:28 ++ scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16 ++ debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:21:27: 21:28 + } bb0: { @@ -17,11 +17,11 @@ _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 - _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16 -+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 ++ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:22:5: 22:22 // mir::Constant -- // + span: $DIR/dyn_trait.rs:27:5: 27:13 +- // + span: $DIR/dyn_trait.rs:28:5: 28:13 - // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) } -+ // + span: $DIR/dyn_trait.rs:21:7: 21:20 ++ // + span: $DIR/dyn_trait.rs:22:7: 22:20 + // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff index dd1f253cb47..30af8661dec 100644 --- a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff +++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff @@ -4,14 +4,14 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11 let _1: (); // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 -+ scope 1 (inlined <() as G>::call) { // at $DIR/exponential_runtime.rs:86:5: 86:22 -+ let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 -+ let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 -+ scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25 -+ let _5: (); // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 -+ let _6: (); // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 -+ let _7: (); // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ scope 1 (inlined <() as G>::call) { // at $DIR/exponential_runtime.rs:87:5: 87:22 ++ let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25 ++ scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:74:9: 74:25 ++ let _5: (); // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ let _6: (); // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ let _7: (); // in scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25 + } + } @@ -21,14 +21,14 @@ + StorageLive(_2); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 + StorageLive(_3); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 + StorageLive(_4); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 -+ StorageLive(_5); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ StorageLive(_6); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ StorageLive(_7); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ _5 = <() as E>::call() -> bb4; // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ StorageLive(_5); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ StorageLive(_6); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ StorageLive(_7); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _5 = <() as E>::call() -> bb4; // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 // mir::Constant -- // + span: $DIR/exponential_runtime.rs:86:5: 86:20 +- // + span: $DIR/exponential_runtime.rs:87:5: 87:20 - // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) } -+ // + span: $DIR/exponential_runtime.rs:61:9: 61:23 ++ // + span: $DIR/exponential_runtime.rs:62:9: 62:23 + // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } } @@ -42,33 +42,33 @@ + } + + bb2: { -+ StorageDead(_7); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ StorageDead(_6); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ StorageDead(_5); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ _3 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ StorageDead(_7); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ StorageDead(_6); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ StorageDead(_5); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _3 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 + // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 ++ // + span: $DIR/exponential_runtime.rs:75:9: 75:23 + // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } + } + + bb3: { -+ _4 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ _4 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25 + // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:75:9: 75:23 ++ // + span: $DIR/exponential_runtime.rs:76:9: 76:23 + // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } + } + + bb4: { -+ _6 = <() as E>::call() -> bb5; // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ _6 = <() as E>::call() -> bb5; // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 + // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:62:9: 62:23 ++ // + span: $DIR/exponential_runtime.rs:63:9: 63:23 + // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } + } + + bb5: { -+ _7 = <() as E>::call() -> bb2; // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ _7 = <() as E>::call() -> bb2; // scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25 + // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:63:9: 63:23 ++ // + span: $DIR/exponential_runtime.rs:64:9: 64:23 + // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } } } diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs index d9219d76a98..39985528f46 100644 --- a/tests/mir-opt/inline/exponential_runtime.rs +++ b/tests/mir-opt/inline/exponential_runtime.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Checks that code with exponential runtime does not have exponential behavior in inlining. trait A { diff --git a/tests/mir-opt/inline/inline_cycle.one.Inline.diff b/tests/mir-opt/inline/inline_cycle.one.Inline.diff index 5510cd7bc8c..f6ba69a1d29 100644 --- a/tests/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/tests/mir-opt/inline/inline_cycle.one.Inline.diff @@ -4,9 +4,9 @@ fn one() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 -+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 -+ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 -+ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:15:5: 15:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:44:9: 44:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:29:9: 29:31 + } + } + } @@ -14,10 +14,10 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 -+ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:37:9: 37:28 // mir::Constant -- // + span: $DIR/inline_cycle.rs:14:5: 14:22 -+ // + span: $DIR/inline_cycle.rs:36:9: 36:26 +- // + span: $DIR/inline_cycle.rs:15:5: 15:22 ++ // + span: $DIR/inline_cycle.rs:37:9: 37:26 // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs index 63ad57de1d4..2f81696cf03 100644 --- a/tests/mir-opt/inline/inline_cycle.rs +++ b/tests/mir-opt/inline/inline_cycle.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that inliner handles various forms of recursion and doesn't fall into // an infinite inlining cycle. The particular outcome of inlining is not // crucial otherwise. diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.diff index 0215b3d93f9..c8f58111da7 100644 --- a/tests/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/tests/mir-opt/inline/inline_cycle.two.Inline.diff @@ -5,11 +5,11 @@ let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + let mut _2: fn() {f}; // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 -+ let mut _4: (); // in scope 0 at $DIR/inline_cycle.rs:54:5: 54:8 -+ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:49:5: 49:12 -+ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 -+ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 ++ let mut _4: (); // in scope 0 at $DIR/inline_cycle.rs:55:5: 55:8 ++ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:50:5: 50:12 ++ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:54:22: 54:23 ++ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:55:5: 55:8 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:55:5: 55:8 + } + } @@ -19,19 +19,19 @@ + StorageLive(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + _2 = f; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 // mir::Constant -- // + span: $DIR/inline_cycle.rs:49:5: 49:9 +- // + span: $DIR/inline_cycle.rs:50:5: 50:9 - // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) } - // mir::Constant - // + span: $DIR/inline_cycle.rs:49:10: 49:11 + // + span: $DIR/inline_cycle.rs:50:10: 50:11 // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } + StorageLive(_3); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 -+ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ _4 = const (); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8 ++ _4 = const (); // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8 + _3 = move _2() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { -+ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8 + StorageDead(_3); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13 diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 04de3e61e5f..9429ca59364 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -4,19 +4,19 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +0:11 let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 -+ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:10:5: 10:24 ++ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:39:9: 39:31 + } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:32:9: 32:28 // mir::Constant -- // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 +- // + span: $DIR/inline_cycle_generic.rs:10:5: 10:22 - // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } -+ // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 ++ // + span: $DIR/inline_cycle_generic.rs:32:9: 32:26 + // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs index 24b4f37939a..84e6e4005a6 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.rs +++ b/tests/mir-opt/inline/inline_cycle_generic.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Check that inliner handles various forms of recursion and doesn't fall into // an infinite inlining cycle. The particular outcome of inlining is not // crucial otherwise. diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff index 31208e0052c..d501b6ca8d2 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff @@ -58,11 +58,11 @@ + } + + bb3 (cleanup): { -+ drop(_3) -> bb4; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_3) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + + bb4 (cleanup): { -+ drop(_2) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> [return: bb5, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + + bb5 (cleanup): { diff --git a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff index f1988ea4bd6..a1d2423ae27 100644 --- a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff +++ b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 - _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 // mir::Constant // + span: $DIR/inline_instruction_set.rs:57:5: 57:24 // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } @@ -25,7 +25,7 @@ bb1: { StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 - _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 // mir::Constant // + span: $DIR/inline_instruction_set.rs:58:5: 58:24 // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } @@ -34,7 +34,7 @@ bb2: { StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 -- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 - // mir::Constant - // + span: $DIR/inline_instruction_set.rs:59:5: 59:28 - // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } @@ -43,11 +43,11 @@ - bb3: { StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31 StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 -- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 +- _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 - // mir::Constant - // + span: $DIR/inline_instruction_set.rs:60:5: 60:39 - // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) } -+ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38 ++ asm!("/* do nothing */", options((empty))) -> [return: bb3, unwind unreachable]; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38 } - bb4: { diff --git a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff index e777b2cc29e..36aec4f47b0 100644 --- a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff +++ b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff @@ -14,7 +14,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 - _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 // mir::Constant // + span: $DIR/inline_instruction_set.rs:49:5: 49:24 // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } @@ -23,7 +23,7 @@ bb1: { StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 -- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 +- _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 - // mir::Constant - // + span: $DIR/inline_instruction_set.rs:50:5: 50:24 - // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } @@ -32,7 +32,7 @@ - bb2: { StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 -- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 - // mir::Constant - // + span: $DIR/inline_instruction_set.rs:51:5: 51:28 - // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } @@ -41,8 +41,8 @@ - bb3: { StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31 StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 -- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 -+ _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 +- _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 ++ _4 = inline_always_and_using_inline_asm() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 // mir::Constant // + span: $DIR/inline_instruction_set.rs:52:5: 52:39 // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) } diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff index a4f0ad465e2..a5129e0e8c8 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff @@ -75,7 +75,7 @@ bb4 (cleanup): { - resume; // scope 0 at $DIR/inline_into_box_place.rs:+0:1: +2:2 -+ drop(_2) -> bb2; // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL ++ drop(_2) -> [return: bb2, unwind terminate]; // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL } } diff --git a/tests/mir-opt/inline/inline_options.main.Inline.after.mir b/tests/mir-opt/inline/inline_options.main.Inline.after.mir index abe26bd8ce3..a2938ead0dc 100644 --- a/tests/mir-opt/inline/inline_options.main.Inline.after.mir +++ b/tests/mir-opt/inline/inline_options.main.Inline.after.mir @@ -4,17 +4,17 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/inline_options.rs:+0:11: +0:11 let _1: (); // in scope 0 at $DIR/inline_options.rs:+1:5: +1:18 let _2: (); // in scope 0 at $DIR/inline_options.rs:+2:5: +2:21 - scope 1 (inlined inlined::<u32>) { // at $DIR/inline_options.rs:10:5: 10:21 - let _3: (); // in scope 1 at $DIR/inline_options.rs:16:23: 16:26 - let _4: (); // in scope 1 at $DIR/inline_options.rs:16:28: 16:31 - let _5: (); // in scope 1 at $DIR/inline_options.rs:16:33: 16:36 + scope 1 (inlined inlined::<u32>) { // at $DIR/inline_options.rs:11:5: 11:21 + let _3: (); // in scope 1 at $DIR/inline_options.rs:17:23: 17:26 + let _4: (); // in scope 1 at $DIR/inline_options.rs:17:28: 17:31 + let _5: (); // in scope 1 at $DIR/inline_options.rs:17:33: 17:36 } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 _1 = not_inlined() -> bb1; // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 // mir::Constant - // + span: $DIR/inline_options.rs:9:5: 9:16 + // + span: $DIR/inline_options.rs:10:5: 10:16 // + literal: Const { ty: fn() {not_inlined}, val: Value(<ZST>) } } @@ -24,9 +24,9 @@ fn main() -> () { StorageLive(_3); // scope 0 at $DIR/inline_options.rs:+2:5: +2:21 StorageLive(_4); // scope 0 at $DIR/inline_options.rs:+2:5: +2:21 StorageLive(_5); // scope 0 at $DIR/inline_options.rs:+2:5: +2:21 - _3 = g() -> bb3; // scope 1 at $DIR/inline_options.rs:16:23: 16:26 + _3 = g() -> bb3; // scope 1 at $DIR/inline_options.rs:17:23: 17:26 // mir::Constant - // + span: $DIR/inline_options.rs:16:23: 16:24 + // + span: $DIR/inline_options.rs:17:23: 17:24 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } @@ -40,16 +40,16 @@ fn main() -> () { } bb3: { - _4 = g() -> bb4; // scope 1 at $DIR/inline_options.rs:16:28: 16:31 + _4 = g() -> bb4; // scope 1 at $DIR/inline_options.rs:17:28: 17:31 // mir::Constant - // + span: $DIR/inline_options.rs:16:28: 16:29 + // + span: $DIR/inline_options.rs:17:28: 17:29 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } bb4: { - _5 = g() -> bb2; // scope 1 at $DIR/inline_options.rs:16:33: 16:36 + _5 = g() -> bb2; // scope 1 at $DIR/inline_options.rs:17:33: 17:36 // mir::Constant - // + span: $DIR/inline_options.rs:16:33: 16:34 + // + span: $DIR/inline_options.rs:17:33: 17:34 // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } } } diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs index 477f050b69e..f0a89883239 100644 --- a/tests/mir-opt/inline/inline_options.rs +++ b/tests/mir-opt/inline/inline_options.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Checks that inlining threshold can be controlled with // inline-mir-threshold and inline-hint-threshold options. // diff --git a/tests/mir-opt/inline/inline_specialization.main.Inline.diff b/tests/mir-opt/inline/inline_specialization.main.Inline.diff index af08296edea..9dde9994d1d 100644 --- a/tests/mir-opt/inline/inline_specialization.main.Inline.diff +++ b/tests/mir-opt/inline/inline_specialization.main.Inline.diff @@ -7,19 +7,19 @@ scope 1 { debug x => _1; // in scope 1 at $DIR/inline_specialization.rs:+1:9: +1:10 } -+ scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:5:13: 5:38 ++ scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:6:13: 6:38 + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10 - _1 = <Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline_specialization.rs:+1:13: +1:38 - // mir::Constant -- // + span: $DIR/inline_specialization.rs:5:13: 5:36 +- // + span: $DIR/inline_specialization.rs:6:13: 6:36 - // + literal: Const { ty: fn() -> u32 {<Vec<()> as Foo>::bar}, val: Value(<ZST>) } - } - - bb1: { -+ _1 = const 123_u32; // scope 2 at $DIR/inline_specialization.rs:14:31: 14:34 ++ _1 = const 123_u32; // scope 2 at $DIR/inline_specialization.rs:15:31: 15:34 _0 = const (); // scope 0 at $DIR/inline_specialization.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/inline_specialization.rs:+2:1: +2:2 return; // scope 0 at $DIR/inline_specialization.rs:+2:2: +2:2 diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs index 87275b4e514..c24795e05c6 100644 --- a/tests/mir-opt/inline/inline_specialization.rs +++ b/tests/mir-opt/inline/inline_specialization.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #![feature(specialization)] // EMIT_MIR inline_specialization.main.Inline.diff diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs index 74be53f5512..6aa957eb534 100644 --- a/tests/mir-opt/inline/inline_trait_method.rs +++ b/tests/mir-opt/inline/inline_trait_method.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -Z span_free_formats fn main() { diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir index 637bf282a65..a9020a5bbb7 100644 --- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir +++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir @@ -10,7 +10,7 @@ fn test(_1: &dyn X) -> u32 { _2 = &(*_1); // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 // mir::Constant - // + span: $DIR/inline_trait_method.rs:9:7: 9:8 + // + span: $DIR/inline_trait_method.rs:10:7: 10:8 // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs index 378e71a2567..07a60190801 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.rs +++ b/tests/mir-opt/inline/inline_trait_method_2.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -Z span_free_formats -Z mir-opt-level=4 // EMIT_MIR inline_trait_method_2.test2.Inline.after.mir diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir index b7c5bbecb68..a4bbecf3b87 100644 --- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir @@ -5,8 +5,8 @@ fn test2(_1: &dyn X) -> bool { let mut _0: bool; // return place in scope 0 at $DIR/inline_trait_method_2.rs:+0:24: +0:28 let mut _2: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 let mut _3: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 - scope 1 (inlined test) { // at $DIR/inline_trait_method_2.rs:5:5: 5:12 - debug x => _2; // in scope 1 at $DIR/inline_trait_method_2.rs:9:9: 9:10 + scope 1 (inlined test) { // at $DIR/inline_trait_method_2.rs:6:5: 6:12 + debug x => _2; // in scope 1 at $DIR/inline_trait_method_2.rs:10:9: 10:10 } bb0: { @@ -15,9 +15,9 @@ fn test2(_1: &dyn X) -> bool { _3 = &(*_1); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 StorageDead(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 - _0 = <dyn X as X>::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 + _0 = <dyn X as X>::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:11:5: 11:10 // mir::Constant - // + span: $DIR/inline_trait_method_2.rs:10:7: 10:8 + // + span: $DIR/inline_trait_method_2.rs:11:7: 11:8 // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff index 97361fa5f4c..18df6f9af5f 100644 --- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff @@ -3,14 +3,14 @@ fn outer() -> usize { let mut _0: usize; // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24 -+ scope 1 (inlined inner) { // at $DIR/issue_106141.rs:2:5: 2:12 -+ let mut _1: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21 -+ let mut _2: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21 -+ let mut _3: &[bool; 1]; // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25 ++ scope 1 (inlined inner) { // at $DIR/issue_106141.rs:3:5: 3:12 ++ let mut _1: bool; // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21 ++ let mut _2: bool; // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21 ++ let mut _3: &[bool; 1]; // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25 + scope 2 { -+ debug buffer => _3; // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15 ++ debug buffer => _3; // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15 + scope 3 { -+ debug index => _0; // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14 ++ debug index => _0; // in scope 3 at $DIR/issue_106141.rs:13:9: 13:14 + } + } + } @@ -18,36 +18,36 @@ bb0: { - _0 = inner() -> bb1; // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 + StorageLive(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 -+ _3 = const _; // scope 1 at $DIR/issue_106141.rs:11:18: 11:25 ++ _3 = const _; // scope 1 at $DIR/issue_106141.rs:12:18: 12:25 // mir::Constant -- // + span: $DIR/issue_106141.rs:2:5: 2:10 +- // + span: $DIR/issue_106141.rs:3:5: 3:10 - // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) } -+ // + span: $DIR/issue_106141.rs:11:18: 11:25 ++ // + span: $DIR/issue_106141.rs:12:18: 12:25 + // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) } -+ _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:12:17: 12:24 ++ _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:13:17: 13:24 + // mir::Constant -+ // + span: $DIR/issue_106141.rs:12:17: 12:22 ++ // + span: $DIR/issue_106141.rs:13:17: 13:22 + // + literal: Const { ty: fn() -> usize {index}, val: Value(<ZST>) } } bb1: { -+ StorageLive(_1); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 -+ _2 = Lt(_0, const 1_usize); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 -+ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ StorageLive(_1); // scope 3 at $DIR/issue_106141.rs:14:8: 14:21 ++ _2 = Lt(_0, const 1_usize); // scope 3 at $DIR/issue_106141.rs:14:8: 14:21 ++ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21 + } + + bb2: { -+ _1 = (*_3)[_0]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 -+ switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ _1 = (*_3)[_0]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21 ++ switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21 + } + + bb3: { -+ _0 = const 0_usize; // scope 3 at $DIR/issue_106141.rs:16:9: 16:10 -+ goto -> bb4; // scope 3 at $DIR/issue_106141.rs:13:5: 17:6 ++ _0 = const 0_usize; // scope 3 at $DIR/issue_106141.rs:17:9: 17:10 ++ goto -> bb4; // scope 3 at $DIR/issue_106141.rs:14:5: 18:6 + } + + bb4: { -+ StorageDead(_1); // scope 3 at $DIR/issue_106141.rs:17:5: 17:6 ++ StorageDead(_1); // scope 3 at $DIR/issue_106141.rs:18:5: 18:6 + StorageDead(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 return; // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2 } diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs index c8288b7f341..b6bd806e6fc 100644 --- a/tests/mir-opt/inline/issue_106141.rs +++ b/tests/mir-opt/inline/issue_106141.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default pub fn outer() -> usize { inner() } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff index aa62e4a165e..dc3fe75559e 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff @@ -46,11 +46,11 @@ - bb3: { - return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 + bb3 (cleanup): { -+ drop(_1) -> bb4; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 ++ drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } bb4 (cleanup): { -- drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 +- drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 } diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff index 21055c6bfb5..8f56ef2585c 100644 --- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -47,7 +47,7 @@ } bb4 (cleanup): { - drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 } bb5 (cleanup): { diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs index e55fa745abc..17724530d65 100644 --- a/tests/mir-opt/inline/unchecked_shifts.rs +++ b/tests/mir-opt/inline/unchecked_shifts.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #![crate_type = "lib"] #![feature(unchecked_math)] diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff index 5fd918b3aa5..6184a0acd18 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff @@ -7,43 +7,52 @@ let mut _0: u16; // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68 let mut _3: u16; // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6 let mut _4: u32; // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 -+ scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23 ++ scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23 + debug self => _3; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + debug rhs => _4; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + let mut _5: u16; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + let mut _6: std::option::Option<u16>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + scope 2 { -+ scope 3 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ debug self => _7; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ let mut _8: isize; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ let _9: u16; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ scope 4 { -+ debug x => _9; // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL ++ scope 3 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ debug self => _4; // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL ++ scope 4 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL ++ debug u => _4; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _8: bool; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _9: u32; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _10: u16; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + } -+ scope 5 { -+ scope 6 { -+ debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ scope 5 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ debug self => _7; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ let mut _11: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ let _12: u16; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ scope 6 { ++ debug x => _12; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ scope 7 { ++ scope 8 { ++ debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + } + } + } -+ scope 7 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ debug self => _6; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ let mut _10: &std::option::Option<u16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ scope 8 { -+ debug val => _5; // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 10 { ++ debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL + } -+ scope 9 { -+ scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL -+ scope 12 { -+ scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ scope 11 { ++ scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 14 { ++ scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + } + } -+ scope 10 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL -+ debug self => _10; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL ++ debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL + } + } + } @@ -55,58 +64,78 @@ StorageLive(_4); // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 _4 = _2; // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 - _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23 +- // mir::Constant +- // + span: $DIR/unchecked_shifts.rs:11:7: 11:20 +- // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) } + StorageLive(_5); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageLive(_6); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageLive(_7); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ _7 = <u32 as TryInto<u16>>::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - // mir::Constant -- // + span: $DIR/unchecked_shifts.rs:10:7: 10:20 -- // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) } -+ // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ // + literal: Const { ty: fn(u32) -> Result<u16, <u32 as TryInto<u16>>::Error> {<u32 as TryInto<u16>>::try_into}, val: Value(<ZST>) } ++ StorageLive(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageLive(_9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _9 = const 65535_u32; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _8 = Gt(_4, move _9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageDead(_9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb1: { -+ StorageLive(_9); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ _8 = discriminant(_7); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ } -+ -+ bb2: { -+ StorageDead(_9); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ StorageDead(_12); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageDead(_7); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ StorageLive(_10); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ _11 = discriminant(_6); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL ++ StorageLive(_13); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ _14 = discriminant(_6); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + } + -+ bb3: { ++ bb2: { + StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageDead(_4); // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23 StorageDead(_3); // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23 return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 + } + ++ bb3: { ++ _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ // mir::Constant ++ // + span: no-location ++ // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) } ++ goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ } ++ + bb4: { -+ _6 = Option::<u16>::None; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL -+ goto -> bb2; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ StorageLive(_10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _10 = _4 as u16 (IntToInt); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageDead(_10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + } + + bb5: { -+ unreachable; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL ++ StorageDead(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageLive(_12); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ _11 = discriminant(_7); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb6: { -+ _9 = move ((_7 as Ok).0: u16); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ _6 = Option::<u16>::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL -+ goto -> bb2; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL ++ _6 = Option::<u16>::None; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL ++ goto -> bb1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb7: { -+ _5 = move ((_6 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ StorageDead(_10); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ ++ bb8: { ++ _12 = move ((_7 as Ok).0: u16); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ _6 = Option::<u16>::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ ++ bb9: { ++ _5 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ StorageDead(_13); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageDead(_6); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL -+ _0 = unchecked_shl::<u16>(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL ++ _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir index c5501cef743..726b6bbf93b 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir @@ -4,43 +4,52 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; // in scope 0 at $DIR/unchecked_shifts.rs:+0:46: +0:47 debug b => _2; // in scope 0 at $DIR/unchecked_shifts.rs:+0:54: +0:55 let mut _0: u16; // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68 - scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23 + scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23 debug self => _1; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL debug rhs => _2; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _3: u16; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _4: std::option::Option<u16>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _5: std::result::Result<u16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL scope 2 { - scope 3 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - debug self => _5; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _6: isize; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - let _7: u16; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - scope 4 { - debug x => _7; // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL + scope 3 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + debug self => _2; // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + scope 4 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL + debug u => _2; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _6: bool; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _7: u32; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _8: u16; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } - scope 5 { - scope 6 { - debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + } + scope 5 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + debug self => _5; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + let mut _9: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + let _10: u16; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + scope 6 { + debug x => _10; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + } + scope 7 { + scope 8 { + debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL } } } - scope 7 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - debug self => _4; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - let mut _8: &std::option::Option<u16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - scope 8 { - debug val => _3; // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL + scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + debug self => _4; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + let mut _11: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + scope 10 { + debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL } - scope 9 { - scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL - scope 12 { - scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL + scope 11 { + scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL + scope 14 { + scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL } } } } - scope 10 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL - debug self => _8; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL + scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL + debug self => _11; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL } } } @@ -50,51 +59,70 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { StorageLive(_3); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageLive(_4); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageLive(_5); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - _5 = <u32 as TryInto<u16>>::try_into(_2) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - // + literal: Const { ty: fn(u32) -> Result<u16, <u32 as TryInto<u16>>::Error> {<u32 as TryInto<u16>>::try_into}, val: Value(<ZST>) } + StorageLive(_6); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageLive(_7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _7 = const 65535_u32; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _6 = Gt(_2, move _7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageDead(_7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb1: { - StorageLive(_7); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - _6 = discriminant(_5); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_10); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + StorageLive(_11); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + _12 = discriminant(_4); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL } bb2: { - StorageDead(_7); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - StorageLive(_8); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - _9 = discriminant(_4); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL + StorageDead(_3); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 } bb3: { - StorageDead(_3); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 + _5 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + // mir::Constant + // + span: no-location + // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) } + goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb4: { - _4 = Option::<u16>::None; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - goto -> bb2; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + StorageLive(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _8 = _2 as u16 (IntToInt); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _5 = Result::<u16, TryFromIntError>::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageDead(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb5: { - unreachable; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_6); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageLive(_10); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + _9 = discriminant(_5); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } bb6: { - _7 = move ((_5 as Ok).0: u16); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - _4 = Option::<u16>::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL - goto -> bb2; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + _4 = Option::<u16>::None; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + goto -> bb1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL } bb7: { - _3 = move ((_4 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - StorageDead(_8); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb8: { + _10 = move ((_5 as Ok).0: u16); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + _4 = Option::<u16>::Some(move _10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb9: { + _3 = move ((_4 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + StorageDead(_11); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL StorageDead(_4); // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL - _0 = unchecked_shl::<u16>(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff index 68d3b21fc2a..35d5b6e72f2 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff @@ -7,43 +7,52 @@ let mut _0: i16; // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66 let mut _3: i16; // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6 let mut _4: u32; // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 -+ scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23 ++ scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23 + debug self => _3; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + debug rhs => _4; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + let mut _5: i16; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + let mut _6: std::option::Option<i16>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + scope 2 { -+ scope 3 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ debug self => _7; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ let mut _8: isize; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ let _9: i16; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ scope 4 { -+ debug x => _9; // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL ++ scope 3 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ debug self => _4; // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL ++ scope 4 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL ++ debug u => _4; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _8: bool; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _9: u32; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ let mut _10: i16; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + } -+ scope 5 { -+ scope 6 { -+ debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ scope 5 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ debug self => _7; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ let mut _11: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ let _12: i16; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ scope 6 { ++ debug x => _12; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ scope 7 { ++ scope 8 { ++ debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + } + } + } -+ scope 7 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ debug self => _6; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ let mut _10: &std::option::Option<i16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ scope 8 { -+ debug val => _5; // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 10 { ++ debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL + } -+ scope 9 { -+ scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL -+ scope 12 { -+ scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL ++ scope 11 { ++ scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 14 { ++ scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL + } + } + } + } -+ scope 10 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL -+ debug self => _10; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL ++ scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL ++ debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL + } + } + } @@ -55,58 +64,78 @@ StorageLive(_4); // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 _4 = _2; // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22 - _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23 +- // mir::Constant +- // + span: $DIR/unchecked_shifts.rs:17:7: 17:20 +- // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) } + StorageLive(_5); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageLive(_6); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageLive(_7); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ _7 = <u32 as TryInto<i16>>::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - // mir::Constant -- // + span: $DIR/unchecked_shifts.rs:16:7: 16:20 -- // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) } -+ // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ // + literal: Const { ty: fn(u32) -> Result<i16, <u32 as TryInto<i16>>::Error> {<u32 as TryInto<i16>>::try_into}, val: Value(<ZST>) } ++ StorageLive(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageLive(_9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _9 = const 32767_u32; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _8 = Gt(_4, move _9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageDead(_9); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb1: { -+ StorageLive(_9); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ _8 = discriminant(_7); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ } -+ -+ bb2: { -+ StorageDead(_9); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ StorageDead(_12); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageDead(_7); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ StorageLive(_10); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ _11 = discriminant(_6); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL ++ StorageLive(_13); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ _14 = discriminant(_6); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + } + -+ bb3: { ++ bb2: { + StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL StorageDead(_4); // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23 StorageDead(_3); // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23 return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 + } + ++ bb3: { ++ _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ // mir::Constant ++ // + span: no-location ++ // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) } ++ goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ } ++ + bb4: { -+ _6 = Option::<i16>::None; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL -+ goto -> bb2; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ StorageLive(_10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _10 = _4 as i16 (IntToInt); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageDead(_10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + } + + bb5: { -+ unreachable; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL ++ StorageDead(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL ++ StorageLive(_12); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ _11 = discriminant(_7); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb6: { -+ _9 = move ((_7 as Ok).0: i16); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL -+ _6 = Option::<i16>::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL -+ goto -> bb2; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL ++ _6 = Option::<i16>::None; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL ++ goto -> bb1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb7: { -+ _5 = move ((_6 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL -+ StorageDead(_10); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ ++ bb8: { ++ _12 = move ((_7 as Ok).0: i16); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ _6 = Option::<i16>::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL ++ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL ++ } ++ ++ bb9: { ++ _5 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL ++ StorageDead(_13); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageDead(_6); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL -+ _0 = unchecked_shr::<i16>(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL ++ _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + // mir::Constant + // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir index ed3a89ceace..b006085b54c 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir @@ -4,43 +4,52 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; // in scope 0 at $DIR/unchecked_shifts.rs:+0:44: +0:45 debug b => _2; // in scope 0 at $DIR/unchecked_shifts.rs:+0:52: +0:53 let mut _0: i16; // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66 - scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23 + scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23 debug self => _1; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL debug rhs => _2; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL let mut _3: i16; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL let mut _4: std::option::Option<i16>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL let mut _5: std::result::Result<i16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL scope 2 { - scope 3 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - debug self => _5; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - let mut _6: isize; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - let _7: i16; // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - scope 4 { - debug x => _7; // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL + scope 3 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + debug self => _2; // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + scope 4 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL + debug u => _2; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _6: bool; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _7: u32; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + let mut _8: i16; // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } - scope 5 { - scope 6 { - debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + } + scope 5 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + debug self => _5; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + let mut _9: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + let _10: i16; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + scope 6 { + debug x => _10; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + } + scope 7 { + scope 8 { + debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL } } } - scope 7 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - debug self => _4; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - let mut _8: &std::option::Option<i16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - scope 8 { - debug val => _3; // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL + scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + debug self => _4; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + let mut _11: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + scope 10 { + debug val => _3; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL } - scope 9 { - scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL - scope 12 { - scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL + scope 11 { + scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL + scope 14 { + scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL } } } } - scope 10 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL - debug self => _8; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL + scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL + debug self => _11; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL } } } @@ -50,51 +59,70 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { StorageLive(_3); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL StorageLive(_4); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL StorageLive(_5); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - _5 = <u32 as TryInto<i16>>::try_into(_2) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL - // + literal: Const { ty: fn(u32) -> Result<i16, <u32 as TryInto<i16>>::Error> {<u32 as TryInto<i16>>::try_into}, val: Value(<ZST>) } + StorageLive(_6); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageLive(_7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _7 = const 32767_u32; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _6 = Gt(_2, move _7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageDead(_7); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb1: { - StorageLive(_7); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - _6 = discriminant(_5); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_10); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + StorageLive(_11); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + _12 = discriminant(_4); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL } bb2: { - StorageDead(_7); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - StorageDead(_5); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - StorageLive(_8); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - _9 = discriminant(_4); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL + StorageDead(_3); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 } bb3: { - StorageDead(_3); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - return; // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2 + _5 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + // mir::Constant + // + span: no-location + // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) } + goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb4: { - _4 = Option::<i16>::None; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL - goto -> bb2; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + StorageLive(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _8 = _2 as i16 (IntToInt); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + _5 = Result::<i16, TryFromIntError>::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageDead(_8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + goto -> bb5; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL } bb5: { - unreachable; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_6); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL + StorageLive(_10); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + _9 = discriminant(_5); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL } bb6: { - _7 = move ((_5 as Ok).0: i16); // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL - _4 = Option::<i16>::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL - goto -> bb2; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL + _4 = Option::<i16>::None; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + goto -> bb1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL } bb7: { - _3 = move ((_4 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL - StorageDead(_8); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb8: { + _10 = move ((_5 as Ok).0: i16); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + _4 = Option::<i16>::Some(move _10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL + goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL + } + + bb9: { + _3 = move ((_4 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL + StorageDead(_11); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL StorageDead(_4); // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL - _0 = unchecked_shr::<i16>(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL + _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff index 2f6f5f87efc..49006e012dd 100644 --- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff @@ -14,7 +14,7 @@ bb1: { + Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:12:5 - 13:17; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6 - falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6 + falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6 } bb2: { diff --git a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff index 7031c3f3e69..09fc145e734 100644 --- a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff +++ b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff @@ -9,7 +9,7 @@ bb0: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46 - _1 = assert_inhabited::<T>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46 + _1 = assert_inhabited::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:25:5: 25:44 // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<T>}, val: Value(<ZST>) } @@ -18,7 +18,7 @@ bb1: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:46: +1:47 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47 - _2 = assert_zero_valid::<T>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47 + _2 = assert_zero_valid::<T>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:26:5: 26:45 // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<T>}, val: Value(<ZST>) } @@ -27,7 +27,7 @@ bb2: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:47: +2:48 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60 - _3 = assert_mem_uninitialized_valid::<T>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60 + _3 = assert_mem_uninitialized_valid::<T>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:27:5: 27:58 // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<T>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff index 4caa9971fef..c52174ef5ea 100644 --- a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff +++ b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff @@ -9,8 +9,8 @@ bb0: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50 -- _1 = assert_inhabited::<Never>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50 -+ _1 = assert_inhabited::<Never>(); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50 +- _1 = assert_inhabited::<Never>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50 ++ _1 = assert_inhabited::<Never>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:17:5: 17:48 // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<Never>}, val: Value(<ZST>) } @@ -19,8 +19,8 @@ bb1: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:50: +1:51 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49 -- _2 = assert_zero_valid::<&u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49 -+ _2 = assert_zero_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49 +- _2 = assert_zero_valid::<&u8>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49 ++ _2 = assert_zero_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:18:5: 18:47 // + user_ty: UserType(0) @@ -30,8 +30,8 @@ bb2: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:49: +2:50 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62 -- _3 = assert_mem_uninitialized_valid::<&u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62 -+ _3 = assert_mem_uninitialized_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62 +- _3 = assert_mem_uninitialized_valid::<&u8>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62 ++ _3 = assert_mem_uninitialized_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62 // mir::Constant // + span: $DIR/intrinsic_asserts.rs:19:5: 19:60 // + user_ty: UserType(1) diff --git a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff index b0bec957369..d059d47ee58 100644 --- a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff +++ b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff @@ -9,7 +9,7 @@ bb0: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47 -- _1 = assert_inhabited::<()>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47 +- _1 = assert_inhabited::<()>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47 - // mir::Constant - // + span: $DIR/intrinsic_asserts.rs:7:5: 7:45 - // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<()>}, val: Value(<ZST>) } @@ -19,7 +19,7 @@ bb1: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+1:47: +1:48 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48 -- _2 = assert_zero_valid::<u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48 +- _2 = assert_zero_valid::<u8>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48 - // mir::Constant - // + span: $DIR/intrinsic_asserts.rs:8:5: 8:46 - // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<u8>}, val: Value(<ZST>) } @@ -29,7 +29,7 @@ bb2: { nop; // scope 0 at $DIR/intrinsic_asserts.rs:+2:48: +2:49 nop; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61 -- _3 = assert_mem_uninitialized_valid::<u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61 +- _3 = assert_mem_uninitialized_valid::<u8>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61 - // mir::Constant - // + span: $DIR/intrinsic_asserts.rs:9:5: 9:59 - // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<u8>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff index b377a65b964..d048b9e6513 100644 --- a/tests/mir-opt/issue_101973.inner.ConstProp.diff +++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff @@ -16,15 +16,15 @@ let mut _11: bool; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 let mut _12: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 let mut _13: bool; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 - scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17 - debug x => _1; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14 - let mut _14: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:27 - let mut _15: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20 + scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:15:5: 15:17 + debug x => _1; // in scope 1 at $DIR/issue_101973.rs:6:13: 6:14 + let mut _14: u32; // in scope 1 at $DIR/issue_101973.rs:8:12: 8:27 + let mut _15: u32; // in scope 1 at $DIR/issue_101973.rs:8:12: 8:20 scope 2 { - debug out => _4; // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16 + debug out => _4; // in scope 2 at $DIR/issue_101973.rs:7:9: 7:16 } } - scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58 + scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:15:18: 15:58 debug self => _4; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL debug n => _6; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL } @@ -33,13 +33,13 @@ StorageLive(_2); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65 StorageLive(_3); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58 StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17 - StorageLive(_14); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 - StorageLive(_15); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 - _15 = Shr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20 - _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27 - StorageDead(_15); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 - _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27 - StorageDead(_14); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27 + StorageLive(_14); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27 + StorageLive(_15); // scope 2 at $DIR/issue_101973.rs:8:12: 8:20 + _15 = Shr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:20 + _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27 + StorageDead(_15); // scope 2 at $DIR/issue_101973.rs:8:26: 8:27 + _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:8:5: 8:27 + StorageDead(_14); // scope 2 at $DIR/issue_101973.rs:8:26: 8:27 StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52 StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45 @@ -66,7 +66,7 @@ bb2: { _6 = Shl(move _7, const 1_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57 StorageDead(_7); // scope 0 at $DIR/issue_101973.rs:+1:56: +1:57 - _3 = rotate_right::<u32>(_4, _6) -> bb3; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL + _3 = rotate_right::<u32>(_4, _6) -> [return: bb3, unwind unreachable]; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL // + literal: Const { ty: extern "rust-intrinsic" fn(u32, u32) -> u32 {rotate_right::<u32>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/issue_101973.rs b/tests/mir-opt/issue_101973.rs index 216659a235e..da388f14918 100644 --- a/tests/mir-opt/issue_101973.rs +++ b/tests/mir-opt/issue_101973.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -O -C debug-assertions=on // This needs inlining followed by ConstProp to reproduce, so we cannot use "unit-test". diff --git a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir index b0d5b291b6c..ccaa508c13b 100644 --- a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir @@ -19,7 +19,7 @@ fn main() -> () { } bb1: { - falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6 + falseUnwind -> [real: bb2, unwind: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6 } bb2: { diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff index 7ac75b51a37..ac252024928 100644 --- a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff +++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff @@ -46,17 +46,17 @@ } bb3 (cleanup): { -- drop(_3) -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 +- drop(_3) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } bb4 (cleanup): { -- drop(_4) -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27 +- drop(_4) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27 + goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27 } bb5 (cleanup): { -- drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 +- drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + goto -> bb8; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 } @@ -65,7 +65,7 @@ + } + + bb7 (cleanup): { -+ drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 ++ drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28 + } + + bb8 (cleanup): { diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff index 3dd1a9bbab5..a4a07ad1243 100644 --- a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff +++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff @@ -50,7 +50,7 @@ bb3 (cleanup): { _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6 - drop(_5) -> bb8; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 + drop(_5) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10 } bb4: { @@ -72,18 +72,18 @@ } bb7 (cleanup): { -- drop(_4) -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12 +- drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12 + goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12 } bb8 (cleanup): { -- drop(_2) -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 +- drop(_2) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 + goto -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2 } bb9 (cleanup): { -- drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 -+ goto -> bb12; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 +- drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 ++ goto -> bb13; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } bb10 (cleanup): { @@ -91,11 +91,15 @@ + } + + bb11 (cleanup): { -+ drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 ++ unreachable; // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2 + } + + bb12 (cleanup): { -+ switchInt(_6) -> [0: bb10, otherwise: bb11]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 ++ drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 ++ } ++ ++ bb13 (cleanup): { ++ switchInt(_6) -> [0: bb10, otherwise: bb12]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2 } } diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff index 4e38659a90b..d98f75e7502 100644 --- a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff +++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff @@ -58,7 +58,7 @@ bb4 (cleanup): { _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10 - drop(_3) -> bb11; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 + drop(_3) -> [return: bb11, unwind terminate]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20 } bb5: { @@ -89,7 +89,7 @@ bb9: { StorageDead(_2); // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6 - drop(_1) -> bb10; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 -+ goto -> bb18; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ goto -> bb19; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } bb10: { @@ -101,7 +101,7 @@ } bb11 (cleanup): { -- drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 +- drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } @@ -109,39 +109,43 @@ resume; // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2 + } + -+ bb13: { ++ bb13 (cleanup): { ++ unreachable; // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2 ++ } ++ ++ bb14: { + _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + goto -> bb10; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb14 (cleanup): { ++ bb15 (cleanup): { + goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb15: { -+ drop(_1) -> [return: bb13, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ bb16: { ++ drop(_1) -> [return: bb14, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb16 (cleanup): { -+ drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ bb17 (cleanup): { ++ drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb17: { ++ bb18: { + _10 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 -+ switchInt(move _10) -> [0: bb13, otherwise: bb15]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ switchInt(move _10) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb18: { -+ switchInt(_7) -> [0: bb13, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ bb19: { ++ switchInt(_7) -> [0: bb14, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb19 (cleanup): { ++ bb20 (cleanup): { + _11 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 -+ switchInt(move _11) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ switchInt(move _11) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 + } + -+ bb20 (cleanup): { -+ switchInt(_7) -> [0: bb12, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 ++ bb21 (cleanup): { ++ switchInt(_7) -> [0: bb12, otherwise: bb20]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2 } } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 22b34975d66..8ed9101500e 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -109,11 +109,11 @@ fn test() -> Option<Box<u32>> { } bb11 (cleanup): { - drop(_1) -> bb13; // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6 + drop(_1) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6 } bb12 (cleanup): { - drop(_5) -> bb13; // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24 + drop(_5) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24 } bb13 (cleanup): { diff --git a/tests/mir-opt/issue_76432.rs b/tests/mir-opt/issue_76432.rs index fbbfd4ceb11..76bb11aae3d 100644 --- a/tests/mir-opt/issue_76432.rs +++ b/tests/mir-opt/issue_76432.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -Zmir-enable-passes=-NormalizeArrayLen // Check that we do not insert StorageDead at each target if StorageDead was never seen diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir index 760e5a8f90a..88a383015b0 100644 --- a/tests/mir-opt/issue_91633.bar.built.after.mir +++ b/tests/mir-opt/issue_91633.bar.built.after.mir @@ -31,7 +31,7 @@ fn bar(_1: Box<[T]>) -> () { } bb3 (cleanup): { - drop(_1) -> bb4; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3 + drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3 } 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 4e3dd365e92..569135803ea 100644 --- a/tests/mir-opt/issue_91633.foo.built.after.mir +++ b/tests/mir-opt/issue_91633.foo.built.after.mir @@ -48,7 +48,7 @@ fn foo(_1: Box<[T]>) -> T { } bb5 (cleanup): { - drop(_1) -> bb6; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 + drop(_1) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3 } bb6 (cleanup): { diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index 6e28fb61b6b..42b60532690 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -5,7 +5,7 @@ fn num_to_digit(_1: char) -> u32 { let mut _0: u32; // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38 let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 - scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23 + scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:15:12: 15:23 debug self => _1; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL debug radix => _3; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -15,7 +15,7 @@ fn num_to_digit(_1: char) -> u32 { let mut _6: isize; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL } } - scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50 + scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:15:42: 15:50 debug self => _2; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _7: isize; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _8: !; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL @@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 { StorageLive(_2); // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 // mir::Constant - // + span: $DIR/issue_59352.rs:14:30: 14:38 + // + span: $DIR/issue_59352.rs:15:30: 15:38 // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/issues/issue_59352.rs b/tests/mir-opt/issues/issue_59352.rs index 1e0045555ab..92011bd6588 100644 --- a/tests/mir-opt/issues/issue_59352.rs +++ b/tests/mir-opt/issues/issue_59352.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // This test is a mirror of codegen/issue-59352.rs. // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case // as effectively `if x.is_some() { x.unwrap() } else { 0 }`. diff --git a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir index 4ee2dae49b3..43d00b29e74 100644 --- a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir +++ b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir @@ -35,7 +35,7 @@ fn main() -> () { } bb3: { - falseUnwind -> [real: bb4, cleanup: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6 + falseUnwind -> [real: bb4, unwind: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6 } bb4: { diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs index 972d46cb8e2..e1bb51f2d1d 100644 --- a/tests/mir-opt/lower_array_len.rs +++ b/tests/mir-opt/lower_array_len.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: NormalizeArrayLen // compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls diff --git a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff index 3389db733b9..dd742d87a29 100644 --- a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff @@ -5,7 +5,7 @@ let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:30 bb0: { -- _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42 +- _0 = std::intrinsics::min_align_of::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:21:5: 21:40 - // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff index 5c5a9e90a9d..935eccfc6f4 100644 --- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 -- _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 +- _1 = std::intrinsics::assume(const true) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:105:9: 105:32 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 87960521bb4..1f03b7b0baf 100644 --- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -29,7 +29,7 @@ StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44 _4 = &_1; // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44 _3 = &(*_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44 -- _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 +- _2 = discriminant_value::<T>(move _3) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:82:5: 82:41 - // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) } @@ -50,7 +50,7 @@ // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) } _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44 -- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 +- _5 = discriminant_value::<i32>(move _6) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:83:5: 83:41 - // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) } @@ -71,7 +71,7 @@ // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) } _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45 -- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 +- _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:84:5: 84:41 - // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) } @@ -92,7 +92,7 @@ // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) } _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47 -- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 +- _13 = discriminant_value::<E>(move _14) -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:85:5: 85:41 - // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff index 15cce7f4a2c..b0c32e4b21a 100644 --- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff @@ -47,7 +47,7 @@ _9 = _10; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79 _8 = move _9 as *mut i32 (PtrToPtr); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91 StorageDead(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91 -- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 +- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:98:9: 98:28 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff index 4cbbc02c943..bfb000ccdb5 100644 --- a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff @@ -9,7 +9,7 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31 _2 = move _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31 -- _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32 +- _0 = std::intrinsics::forget::<T>(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:26:5: 26:29 - // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff index d8cd5f59a35..64d82907c7e 100644 --- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff @@ -17,7 +17,7 @@ // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) } StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14 _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14 -- _0 = move _2() -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16 +- _0 = move _2() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16 + _0 = SizeOf(T); // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16 + goto -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16 } diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff index c563703b250..93863fca344 100644 --- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff @@ -22,7 +22,7 @@ StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:+2:13: +2:15 StorageLive(_4); // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56 _4 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56 -- _3 = option_payload_ptr::<usize>(move _4) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57 +- _3 = option_payload_ptr::<usize>(move _4) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:132:18: 132:54 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<usize>) -> *const usize {option_payload_ptr::<usize>}, val: Value(<ZST>) } @@ -35,7 +35,7 @@ StorageLive(_5); // scope 2 at $DIR/lower_intrinsics.rs:+3:13: +3:15 StorageLive(_6); // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56 _6 = &raw const (*_2); // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56 -- _5 = option_payload_ptr::<String>(move _6) -> bb2; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57 +- _5 = option_payload_ptr::<String>(move _6) -> [return: bb2, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:133:18: 133:54 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<String>) -> *const String {option_payload_ptr::<String>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff index f2f676843b2..f816678b4b3 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47 _2 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47 -- _0 = read_via_copy::<i32>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48 +- _0 = read_via_copy::<i32>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:118:14: 118:45 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::<i32>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff index 3ad21283fa4..f3416418922 100644 --- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47 _2 = &raw const (*_1); // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47 -- _0 = read_via_copy::<Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48 +- _0 = read_via_copy::<Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:123:14: 123:45 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::<Never>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff index cf0ab73a5d4..27e8accea8b 100644 --- a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff @@ -5,7 +5,7 @@ let mut _0: usize; // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:24: +0:29 bb0: { -- _0 = std::intrinsics::size_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37 +- _0 = std::intrinsics::size_of::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:16:5: 16:35 - // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff index 814368ec021..1b3b7685185 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35 _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35 -- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36 +- _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:43:14: 43:33 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(std::cmp::Ordering) -> i8 {transmute::<std::cmp::Ordering, i8>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff index 5440c7a4c8e..c6a7d2287e7 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35 _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35 -- _0 = transmute::<&T, *const T>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36 +- _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:53:14: 53:33 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&T) -> *const T {transmute::<&T, *const T>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff index 43ddccc1ef7..8735a750060 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2 StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10 -- _2 = transmute::<usize, Box<Never>>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52 +- _2 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:70:25: 70:44 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff index bf529a9ca67..a772132770c 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2 StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10 -- _2 = transmute::<usize, &mut Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52 +- _2 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:64:25: 64:44 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff index 4940a99021f..c4d53d4e8c7 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff @@ -13,7 +13,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2 StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10 -- _2 = transmute::<usize, &Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48 +- _2 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:58:21: 58:40 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff index f3a12b9ba5f..f0b76127dd5 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff @@ -11,7 +11,7 @@ bb0: { StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48 _2 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48 -- _0 = transmute::<(), Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49 +- _0 = transmute::<(), Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:48:14: 48:46 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Never {transmute::<(), Never>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff index 6f17d44516d..c0cc698c481 100644 --- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_2); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47 StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45 -- _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45 +- _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:31:14: 31:43 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff index 3b9a41249a4..fb12d3dfa6e 100644 --- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff @@ -30,7 +30,7 @@ _4 = _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51 StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54 _5 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54 -- _3 = add_with_overflow::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55 +- _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:111:14: 111:49 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::<i32>}, val: Value(<ZST>) } @@ -46,7 +46,7 @@ _7 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+2:50: +2:51 StorageLive(_8); // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54 _8 = _2; // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54 -- _6 = sub_with_overflow::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55 +- _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:112:14: 112:49 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::<i32>}, val: Value(<ZST>) } @@ -62,7 +62,7 @@ _10 = _1; // scope 2 at $DIR/lower_intrinsics.rs:+3:50: +3:51 StorageLive(_11); // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54 _11 = _2; // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54 -- _9 = mul_with_overflow::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55 +- _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:113:14: 113:49 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::<i32>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff index 22ef75fd804..0bfb34acac2 100644 --- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff +++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff @@ -30,7 +30,7 @@ _4 = _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:45: +1:46 StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49 _5 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49 -- _3 = wrapping_add::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50 +- _3 = wrapping_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:9:14: 9:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::<i32>}, val: Value(<ZST>) } @@ -46,7 +46,7 @@ _7 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+2:45: +2:46 StorageLive(_8); // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49 _8 = _2; // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49 -- _6 = wrapping_sub::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50 +- _6 = wrapping_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:10:14: 10:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::<i32>}, val: Value(<ZST>) } @@ -62,7 +62,7 @@ _10 = _1; // scope 2 at $DIR/lower_intrinsics.rs:+3:45: +3:46 StorageLive(_11); // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49 _11 = _2; // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49 -- _9 = wrapping_mul::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50 +- _9 = wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:11:14: 11:44 - // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::<i32>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir index adfc6b2731c..4f5df133181 100644 --- a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir +++ b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir @@ -12,7 +12,7 @@ fn f_u64() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21 - _2 = f_non_zst::<u64>(const 0_u64) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 + _2 = f_non_zst::<u64>(const 0_u64) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21 // mir::Constant // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18 // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir index 302ca09aac4..8654e80cd7c 100644 --- a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir +++ b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir @@ -10,7 +10,7 @@ fn f_unit() -> () { } bb0: { - _1 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17 + _1 = f_zst::<()>(const ()) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17 // mir::Constant // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14 // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) } diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff index 2b0370cf358..67918e62b9c 100644 --- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff +++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff @@ -22,7 +22,7 @@ _6 = &(*_2); // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 - _5 = core::slice::<impl [u8]>::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 - // mir::Constant -- // + span: $DIR/lower_slice_len.rs:5:22: 5:25 +- // + span: $DIR/lower_slice_len.rs:6:22: 6:25 - // + literal: Const { ty: for<'a> fn(&'a [u8]) -> usize {core::slice::<impl [u8]>::len}, val: Value(<ZST>) } + _5 = Len((*_6)); // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 + goto -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27 diff --git a/tests/mir-opt/lower_slice_len.rs b/tests/mir-opt/lower_slice_len.rs index 12955aed1fb..9c39c29fc4e 100644 --- a/tests/mir-opt/lower_slice_len.rs +++ b/tests/mir-opt/lower_slice_len.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: LowerSliceLenCalls // EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 84e4d35f908..3081e78f26d 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -243,7 +243,7 @@ } - bb25 (cleanup): { -- drop(_2) -> bb26; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 +- drop(_2) -> [return: bb26, unwind terminate]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 + bb22 (cleanup): { + goto -> bb27; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2 } diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 0cb34a2f274..950f8758e31 100644 --- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -40,7 +40,7 @@ fn main() -> () { } bb3 (cleanup): { - drop(_2) -> bb4; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35 + drop(_2) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35 } bb4 (cleanup): { diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/nrvo_simple.rs index 5786ae62127..525dfe4262a 100644 --- a/tests/mir-opt/nrvo_simple.rs +++ b/tests/mir-opt/nrvo_simple.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: RenameReturnPlace // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir index 56cb9166c37..81b96e3b631 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir @@ -33,7 +33,7 @@ fn main() -> () { bb1 (cleanup): { (_1.0: Aligned) = move _4; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8 - drop(_1) -> bb3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2 + drop(_1) -> [return: bb3, unwind terminate]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2 } bb2: { diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index a8dd91efc37..0e8309532c2 100644 --- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -34,7 +34,7 @@ _3 = std::ops::Range::<i32> { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 _2 = <std::ops::Range<i32> as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19 // mir::Constant - // + span: $DIR/remove_storage_markers.rs:10:14: 10:19 + // + span: $DIR/remove_storage_markers.rs:11:14: 11:19 // + literal: Const { ty: fn(std::ops::Range<i32>) -> <std::ops::Range<i32> as IntoIterator>::IntoIter {<std::ops::Range<i32> as IntoIterator>::into_iter}, val: Value(<ZST>) } } @@ -54,7 +54,7 @@ _8 = &mut (*_9); // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19 _7 = <std::ops::Range<i32> as Iterator>::next(move _8) -> bb3; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19 // mir::Constant - // + span: $DIR/remove_storage_markers.rs:10:14: 10:19 + // + span: $DIR/remove_storage_markers.rs:11:14: 11:19 // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<i32>) -> Option<<std::ops::Range<i32> as Iterator>::Item> {<std::ops::Range<i32> as Iterator>::next}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs index f00b826911c..480db8ac155 100644 --- a/tests/mir-opt/remove_storage_markers.rs +++ b/tests/mir-opt/remove_storage_markers.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: RemoveStorageMarkers // Checks that storage markers are removed at opt-level=0. diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 2eb2a0980ce..4eef028e1cc 100644 --- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -186,11 +186,11 @@ fn main() -> () { } bb7 (cleanup): { - drop(_21) -> bb9; // scope 7 at $DIR/retag.rs:+18:24: +18:25 + drop(_21) -> [return: bb9, unwind terminate]; // scope 7 at $DIR/retag.rs:+18:24: +18:25 } bb8 (cleanup): { - drop(_5) -> bb9; // scope 1 at $DIR/retag.rs:+3:36: +3:37 + drop(_5) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/retag.rs:+3:36: +3:37 } bb9 (cleanup): { diff --git a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff index 1e66b1f703e..c61107d25e0 100644 --- a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff +++ b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff @@ -12,8 +12,8 @@ } bb1: { -- falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6 -+ falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6 +- falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6 ++ falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6 } bb2: { diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff index ac79e727013..b473d0fdecd 100644 --- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff +++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff @@ -16,7 +16,7 @@ bb1: { _2 = noop() -> bb2; // scope 0 at $DIR/simplify_if.rs:+2:9: +2:15 // mir::Constant - // + span: $DIR/simplify_if.rs:7:9: 7:13 + // + span: $DIR/simplify_if.rs:8:9: 8:13 // + literal: Const { ty: fn() {noop}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs index 2d093d9266b..b86f80a8038 100644 --- a/tests/mir-opt/simplify_if.rs +++ b/tests/mir-opt/simplify_if.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #[inline(never)] fn noop() {} diff --git a/tests/mir-opt/simplify_locals_fixedpoint.rs b/tests/mir-opt/simplify_locals_fixedpoint.rs index 1fdba6e99e3..7c41e8b7c20 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.rs +++ b/tests/mir-opt/simplify_locals_fixedpoint.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // compile-flags: -Zmir-opt-level=1 fn foo<T>() { diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff index 0f8866f9c2f..ae2c774f29d 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff @@ -56,7 +56,7 @@ + StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21 + _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22 // mir::Constant - // + span: $DIR/simplify_locals_removes_unused_consts.rs:15:5: 15:12 + // + span: $DIR/simplify_locals_removes_unused_consts.rs:16:5: 16:12 // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(<ZST>) } } @@ -84,7 +84,7 @@ + StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34 + _5 = use_u8(move _6) -> bb2; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35 // mir::Constant - // + span: $DIR/simplify_locals_removes_unused_consts.rs:17:5: 17:11 + // + span: $DIR/simplify_locals_removes_unused_consts.rs:18:5: 18:11 // + literal: Const { ty: fn(u8) {use_u8}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.rs b/tests/mir-opt/simplify_locals_removes_unused_consts.rs index 7a03a2837ae..983d8004e2e 100644 --- a/tests/mir-opt/simplify_locals_removes_unused_consts.rs +++ b/tests/mir-opt/simplify_locals_removes_unused_consts.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // unit-test: SimplifyLocals-before-const-prop // compile-flags: -C overflow-checks=no diff --git a/tests/mir-opt/simplify_match.main.ConstProp.diff b/tests/mir-opt/simplify_match.main.ConstProp.diff index b700adfb105..d2b9ac3cc0b 100644 --- a/tests/mir-opt/simplify_match.main.ConstProp.diff +++ b/tests/mir-opt/simplify_match.main.ConstProp.diff @@ -22,7 +22,7 @@ bb2: { _0 = noop() -> bb3; // scope 0 at $DIR/simplify_match.rs:+2:17: +2:23 // mir::Constant - // + span: $DIR/simplify_match.rs:7:17: 7:21 + // + span: $DIR/simplify_match.rs:8:17: 8:21 // + literal: Const { ty: fn() {noop}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs index 216203f9ff0..6a2a6f21719 100644 --- a/tests/mir-opt/simplify_match.rs +++ b/tests/mir-opt/simplify_match.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default #[inline(never)] fn noop() {} 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 3884d29db41..11115c96e23 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]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 _3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_4)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + drop((*_4)) -> [return: bb4, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 } bb4 (cleanup): { diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index f6f2344e82f..579587a430b 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -58,7 +58,7 @@ StorageLive(_2); // scope 0 at $DIR/lifetimes.rs:+2:12: +2:31 StorageLive(_3); // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 StorageLive(_4); // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 - _4 = Box::<u32>::new(const 5_u32) -> bb1; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 + _4 = Box::<u32>::new(const 5_u32) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30 // mir::Constant // + span: $DIR/lifetimes.rs:19:15: 19:23 // + user_ty: UserType(1) @@ -113,7 +113,7 @@ StorageLive(_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 _22 = &_8; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 _21 = &(*_22); // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 - _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 + _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23 // mir::Constant // + span: $DIR/lifetimes.rs:27:20: 27:23 // + user_ty: UserType(4) @@ -127,7 +127,7 @@ StorageLive(_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 _25 = &_6; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 _24 = &(*_25); // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 - _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 + _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27 // mir::Constant // + span: $DIR/lifetimes.rs:27:24: 27:27 // + user_ty: UserType(5) @@ -143,7 +143,7 @@ _17 = &(*_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL _16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _11 = Arguments::<'_>::new_v1(move _12, move _16) -> bb5; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/std/src/macros.rs:LL:COL // + user_ty: UserType(3) @@ -153,7 +153,7 @@ bb5: { StorageDead(_16); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _10 = _eprint(move _11) -> bb6; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _10 = _eprint(move _11) -> [return: bb6, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL // mir::Constant // + span: $SRC_DIR/std/src/macros.rs:LL:COL // + literal: Const { ty: for<'a> fn(Arguments<'a>) {_eprint}, val: Value(<ZST>) } @@ -170,7 +170,7 @@ _9 = const (); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_9); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL _0 = const (); // scope 4 at $DIR/lifetimes.rs:+9:22: +11:6 - drop(_8) -> bb8; // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6 + drop(_8) -> [return: bb8, unwind unreachable]; // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6 } bb7: { @@ -204,11 +204,11 @@ } bb12: { - drop(((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>)) -> bb10; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + drop(((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>)) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 } bb13: { - drop(_5) -> bb10; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 + drop(_5) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2 } } diff --git a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff index b6439c00a00..d378c260a00 100644 --- a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff @@ -23,11 +23,11 @@ StorageDead(_4); // scope 0 at $DIR/structs.rs:+1:29: +1:30 StorageDead(_3); // scope 0 at $DIR/structs.rs:+1:29: +1:30 _1 = move (_2.1: Tag); // scope 0 at $DIR/structs.rs:+1:5: +1:32 - drop(_1) -> bb1; // scope 0 at $DIR/structs.rs:+1:32: +1:33 + drop(_1) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33 } bb1: { - drop((_2.0: Tag)) -> bb3; // scope 0 at $DIR/structs.rs:+1:32: +1:33 + drop((_2.0: Tag)) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33 } bb2: { @@ -38,7 +38,7 @@ } bb3: { - drop((_2.2: Tag)) -> bb2; // scope 0 at $DIR/structs.rs:+1:32: +1:33 + drop((_2.2: Tag)) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33 } } diff --git a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff index d45823d4bac..3074fcbdf53 100644 --- a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff @@ -15,7 +15,7 @@ StorageLive(_3); // scope 0 at $DIR/structs.rs:+1:7: +1:41 StorageLive(_4); // scope 0 at $DIR/structs.rs:+1:8: +1:39 StorageLive(_5); // scope 0 at $DIR/structs.rs:+1:34: +1:37 - _5 = g() -> bb1; // scope 0 at $DIR/structs.rs:+1:34: +1:37 + _5 = g() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:34: +1:37 // mir::Constant // + span: $DIR/structs.rs:78:34: 78:35 // + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) } @@ -26,7 +26,7 @@ StorageDead(_5); // scope 0 at $DIR/structs.rs:+1:38: +1:39 _3 = &(_4.0: u32); // scope 0 at $DIR/structs.rs:+1:7: +1:41 _2 = &raw const (*_3); // scope 0 at $DIR/structs.rs:+1:7: +1:41 - _1 = f(move _2) -> bb2; // scope 0 at $DIR/structs.rs:+1:5: +1:42 + _1 = f(move _2) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:5: +1:42 // mir::Constant // + span: $DIR/structs.rs:78:5: 78:6 // + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) } diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff index 848bff1d492..323b61346c0 100644 --- a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff +++ b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff @@ -21,7 +21,7 @@ StorageLive(_1); // scope 1 at $DIR/unreachable.rs:+1:23: +1:30 _1 = empty() -> bb1; // scope 1 at $DIR/unreachable.rs:+1:23: +1:30 // mir::Constant - // + span: $DIR/unreachable.rs:9:23: 9:28 + // + span: $DIR/unreachable.rs:10:23: 10:28 // + literal: Const { ty: fn() -> Option<Empty> {empty}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index 6098b525b55..97093729dd1 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default enum Empty {} fn empty() -> Option<Empty> { diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff index fb778470e53..94bc633613b 100644 --- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff +++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff @@ -23,7 +23,7 @@ StorageLive(_2); // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32 _2 = empty() -> bb1; // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32 // mir::Constant - // + span: $DIR/unreachable_diverging.rs:14:25: 14:30 + // + span: $DIR/unreachable_diverging.rs:15:25: 15:30 // + literal: Const { ty: fn() -> Option<Empty> {empty}, val: Value(<ZST>) } } @@ -44,7 +44,7 @@ bb3: { _5 = loop_forever() -> bb5; // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27 // mir::Constant - // + span: $DIR/unreachable_diverging.rs:16:13: 16:25 + // + span: $DIR/unreachable_diverging.rs:17:13: 17:25 // + literal: Const { ty: fn() {loop_forever}, val: Value(<ZST>) } } diff --git a/tests/mir-opt/unreachable_diverging.rs b/tests/mir-opt/unreachable_diverging.rs index bbf28efc7dd..24e776148c1 100644 --- a/tests/mir-opt/unreachable_diverging.rs +++ b/tests/mir-opt/unreachable_diverging.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default pub enum Empty {} fn empty() -> Option<Empty> { 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 ed9f3bdbdf4..c27a93e91f8 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>)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 } bb5: { diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs index afd083acb34..d10048dd908 100644 --- a/tests/mir-opt/while_storage.rs +++ b/tests/mir-opt/while_storage.rs @@ -1,3 +1,4 @@ +// ignore-wasm32 compiled with panic=abort by default // Test that we correctly generate StorageDead statements for while loop // conditions on all branches diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir index 318119bd477..811789a60c3 100644 --- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -14,7 +14,7 @@ fn while_loop(_1: bool) -> () { StorageLive(_2); // scope 0 at $DIR/while_storage.rs:+1:11: +1:22 _2 = get_bool(_1) -> bb2; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22 // mir::Constant - // + span: $DIR/while_storage.rs:10:11: 10:19 + // + span: $DIR/while_storage.rs:11:11: 11:19 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) } } @@ -26,7 +26,7 @@ fn while_loop(_1: bool) -> () { StorageLive(_3); // scope 0 at $DIR/while_storage.rs:+2:12: +2:23 _3 = get_bool(_1) -> bb4; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23 // mir::Constant - // + span: $DIR/while_storage.rs:11:12: 11:20 + // + span: $DIR/while_storage.rs:12:12: 12:20 // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) } } diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt index 00f46f42a07..a71c58d618d 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt +++ b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt @@ -32,7 +32,7 @@ 30| |// Notes: 31| |// 1. Compare this program and its coverage results to those of the similar tests 32| |// `panic_unwind.rs` and `try_error_result.rs`. - 33| |// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`. + 33| |// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`. 34| |// 3. The test does not invoke the abort. By executing to a successful completion, the coverage 35| |// results show where the program did and did not execute. 36| |// 4. If the program actually aborted, the coverage counters would not be saved (which "works as diff --git a/tests/run-make/coverage/abort.rs b/tests/run-make/coverage/abort.rs index 3dac43df8f3..98264bdc1af 100644 --- a/tests/run-make/coverage/abort.rs +++ b/tests/run-make/coverage/abort.rs @@ -30,7 +30,7 @@ fn main() -> Result<(), u8> { // Notes: // 1. Compare this program and its coverage results to those of the similar tests // `panic_unwind.rs` and `try_error_result.rs`. -// 2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`. +// 2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`. // 3. The test does not invoke the abort. By executing to a successful completion, the coverage // results show where the program did and did not execute. // 4. If the program actually aborted, the coverage counters would not be saved (which "works as diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml index 279048e37c1..ec423125236 100644 --- a/tests/rustdoc-gui/go-to-collapsed-elem.goml +++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml @@ -9,13 +9,32 @@ property: ("#implementations-list .implementors-toggle", {"open": "false"}) click: "//*[@class='sidebar']//a[@href='#method.must_use']" assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) -// Now we do the same through search result. -// First we reload the page without the anchor in the URL. +define-function: ("collapsed-from-search", (), block { + // Now we do the same through search result. + // First we reload the page without the anchor in the URL. + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" + // Then we collapse the section again... + property: ("#implementations-list .implementors-toggle", {"open": "false"}) + // Then we run the search. + write: (".search-input", "foo::must_use") + wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" + click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" + assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) +}) + +call-function: ("collapsed-from-search", {}) + +// Now running the same check but with mobile. +size: (600, 600) goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" -// Then we collapse the section again... +// We check that the implementors block is expanded. +assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) +// We now collapse the implementors block. property: ("#implementations-list .implementors-toggle", {"open": "false"}) -// Then we run the search. -write: (".search-input", "foo::must_use") -wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" -click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']" +// First we expand the mobile menu. +click: ".sidebar-menu-toggle" +// Then we click on the link to the method to ensure it'll expand the implementors block. +click: "//*[@class='sidebar shown']//a[@href='#method.must_use']" assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}) + +call-function: ("collapsed-from-search", {}) diff --git a/tests/rustdoc-gui/theme-defaults.goml b/tests/rustdoc-gui/theme-defaults.goml new file mode 100644 index 00000000000..d5ed536b1a9 --- /dev/null +++ b/tests/rustdoc-gui/theme-defaults.goml @@ -0,0 +1,24 @@ +// Ensure that the theme picker always starts with the actual defaults. +goto: "file://" + |DOC_PATH| + "/test_docs/index.html" +click: "#settings-menu" +wait-for: "#theme-system-preference" +assert: "#theme-system-preference:checked" +assert: "#preferred-light-theme-light:checked" +assert: "#preferred-dark-theme-dark:checked" +assert-false: "#preferred-dark-theme-ayu:checked" + +// Test legacy migration from old theme setup without system-preference matching. +// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732 +local-storage: { + "rustdoc-preferred-light-theme": null, + "rustdoc-preferred-dark-theme": null, + "rustdoc-use-system-theme": null, + "rustdoc-theme": "ayu" +} +goto: "file://" + |DOC_PATH| + "/test_docs/index.html" +click: "#settings-menu" +wait-for: "#theme-system-preference" +assert: "#theme-system-preference:checked" +assert: "#preferred-light-theme-light:checked" +assert-false: "#preferred-dark-theme-dark:checked" +assert: "#preferred-dark-theme-ayu:checked" diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 3151c712566..61724c11745 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -50,7 +50,7 @@ enum DiagnosticOnEnum { #[derive(Diagnostic)] #[diag(no_crate_example, code = "E0123")] #[diag = "E0123"] -//~^ ERROR `#[diag = ...]` is not a valid attribute +//~^ ERROR expected parentheses: #[diag(...)] struct WrongStructAttrStyle {} #[derive(Diagnostic)] @@ -62,8 +62,7 @@ struct InvalidStructAttr {} #[derive(Diagnostic)] #[diag("E0123")] -//~^ ERROR `#[diag("...")]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug not specified struct InvalidLitNestedAttr {} #[derive(Diagnostic)] @@ -73,27 +72,25 @@ struct InvalidNestedStructAttr {} #[derive(Diagnostic)] #[diag(nonsense("foo"), code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug must be the first argument +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument //~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument //~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] #[diag(no_crate_example, code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument struct InvalidNestedStructAttr4 {} #[derive(Diagnostic)] @@ -118,7 +115,7 @@ struct CodeSpecifiedTwice {} #[derive(Diagnostic)] #[diag(no_crate_example, no_crate::example, code = "E0456")] -//~^ ERROR `#[diag(no_crate::example)]` is not a valid attribute +//~^ ERROR diagnostic slug must be the first argument struct SlugSpecifiedTwice {} #[derive(Diagnostic)] @@ -232,7 +229,7 @@ struct SuggestWithoutCode { #[diag(no_crate_example, code = "E0123")] struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] - //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -241,7 +238,7 @@ struct SuggestWithBadKey { #[diag(no_crate_example, code = "E0123")] struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] - //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -530,7 +527,7 @@ struct BoolField { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingPath { #[label(no_crate_label, foo)] - //~^ ERROR `#[label(foo)]` is not a valid attribute + //~^ ERROR a diagnostic slug must be the first argument to the attribute span: Span, } @@ -538,7 +535,7 @@ struct LabelWithTrailingPath { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingNameValue { #[label(no_crate_label, foo = "...")] - //~^ ERROR `#[label(foo = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute span: Span, } @@ -546,7 +543,7 @@ struct LabelWithTrailingNameValue { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingList { #[label(no_crate_label, foo("..."))] - //~^ ERROR `#[label(foo(...))]` is not a valid attribute + //~^ ERROR invalid nested attribute span: Span, } @@ -643,8 +640,8 @@ struct MissingCodeInSuggestion { //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute //~| ERROR cannot find attribute `multipart_suggestion` in this scope #[multipart_suggestion()] -//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute -//~| ERROR cannot find attribute `multipart_suggestion` in this scope +//~^ ERROR cannot find attribute `multipart_suggestion` in this scope +//~| ERROR unexpected end of input, unexpected token in nested attribute, expected ident struct MultipartSuggestion { #[multipart_suggestion(no_crate_suggestion)] //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute @@ -698,7 +695,7 @@ struct RawIdentDiagnosticArg { #[diag(no_crate_example)] struct SubdiagnosticBad { #[subdiagnostic(bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -714,7 +711,7 @@ struct SubdiagnosticBadStr { #[diag(no_crate_example)] struct SubdiagnosticBadTwice { #[subdiagnostic(bad, bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -722,7 +719,7 @@ struct SubdiagnosticBadTwice { #[diag(no_crate_example)] struct SubdiagnosticBadLitStr { #[subdiagnostic("bad")] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -797,14 +794,15 @@ struct SuggestionsNoItem { struct SuggestionsInvalidItem { #[suggestion(code(foo))] //~^ ERROR `code(...)` must contain only string literals + //~| ERROR unexpected token sub: Span, } -#[derive(Diagnostic)] +#[derive(Diagnostic)] //~ ERROR cannot find value `__code_34` in this scope #[diag(no_crate_example)] struct SuggestionsInvalidLiteral { #[suggestion(code = 3)] - //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + //~^ ERROR expected string literal sub: Span, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 513b675e5dd..cd14c7496b3 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -20,11 +20,11 @@ LL | Bar, | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:52:1 +error: expected parentheses: #[diag(...)] + --> $DIR/diagnostic-derive.rs:52:8 | LL | #[diag = "E0123"] - | ^^^^^^^^^^^^^^^^^ + | ^ error: `#[nonsense(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:57:1 @@ -44,35 +44,24 @@ LL | | struct InvalidStructAttr {} | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag("...")]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:64:8 - | -LL | #[diag("E0123")] - | ^^^^^^^ - | - = help: a diagnostic slug is required as the first argument - error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:64:1 | LL | / #[diag("E0123")] LL | | -LL | | LL | | struct InvalidLitNestedAttr {} | |______________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:75:8 +error: diagnostic slug must be the first argument + --> $DIR/diagnostic-derive.rs:74:16 | LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^ - | - = help: a diagnostic slug is required as the first argument + | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:75:1 + --> $DIR/diagnostic-derive.rs:74:1 | LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")] LL | | @@ -82,120 +71,102 @@ LL | | struct InvalidNestedStructAttr1 {} | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:81:8 - | -LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^ - | - = help: only `code` is a valid nested attributes following the slug - -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:81:42 +error: unknown argument + --> $DIR/diagnostic-derive.rs:80:8 | LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ + | ^^^^^^^^ | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:81:1 + --> $DIR/diagnostic-derive.rs:80:1 | LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | LL | | -LL | | LL | | struct InvalidNestedStructAttr2 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:88:8 - | -LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ - -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:88:38 +error: unknown argument + --> $DIR/diagnostic-derive.rs:86:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ + | ^^^^^^^^ | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:88:1 + --> $DIR/diagnostic-derive.rs:86:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | LL | | -LL | | LL | | struct InvalidNestedStructAttr3 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:95:42 +error: unknown argument + --> $DIR/diagnostic-derive.rs:92:42 | LL | #[diag(no_crate_example, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ + | ^^^^ | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:102:5 + --> $DIR/diagnostic-derive.rs:99:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:8 + --> $DIR/diagnostic-derive.rs:106:8 | LL | #[diag(no_crate_example, code = "E0456")] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:8 + --> $DIR/diagnostic-derive.rs:105:8 | LL | #[diag(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:33 + --> $DIR/diagnostic-derive.rs:106:26 | LL | #[diag(no_crate_example, code = "E0456")] - | ^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:33 + --> $DIR/diagnostic-derive.rs:105:26 | LL | #[diag(no_crate_example, code = "E0123")] - | ^^^^^^^ + | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:115:49 + --> $DIR/diagnostic-derive.rs:112:42 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] - | ^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:115:33 + --> $DIR/diagnostic-derive.rs:112:26 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] - | ^^^^^^^ + | ^^^^ -error: `#[diag(no_crate::example)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:120:26 +error: diagnostic slug must be the first argument + --> $DIR/diagnostic-derive.rs:117:43 | LL | #[diag(no_crate_example, no_crate::example, code = "E0456")] - | ^^^^^^^^^^^^^^^^^ - | - = help: diagnostic slug must be the first argument + | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:125:1 + --> $DIR/diagnostic-derive.rs:122:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +174,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:128:1 + --> $DIR/diagnostic-derive.rs:125:1 | LL | / #[diag(code = "E0456")] LL | | @@ -213,31 +184,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:139:5 + --> $DIR/diagnostic-derive.rs:136:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:147:5 + --> $DIR/diagnostic-derive.rs:144:5 | LL | #[nonsense] | ^^^^^^^^^^^ error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:164:5 + --> $DIR/diagnostic-derive.rs:161:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:172:46 + --> $DIR/diagnostic-derive.rs:169:46 | LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:177:10 + --> $DIR/diagnostic-derive.rs:174:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `'}'` in format string @@ -246,7 +217,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:187:10 + --> $DIR/diagnostic-derive.rs:184:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -255,47 +226,47 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:207:5 + --> $DIR/diagnostic-derive.rs:204:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:226:5 + --> $DIR/diagnostic-derive.rs:223:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:234:18 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:231:18 | LL | #[suggestion(nonsense = "bar")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:234:5 + --> $DIR/diagnostic-derive.rs:231:5 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:243:18 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:240:18 | LL | #[suggestion(msg = "bar")] - | ^^^^^^^^^^^ + | ^^^ | = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:243:5 + --> $DIR/diagnostic-derive.rs:240:5 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:266:5 + --> $DIR/diagnostic-derive.rs:263:5 | LL | / #[suggestion(no_crate_suggestion, code = "This is suggested code")] LL | | @@ -305,81 +276,79 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:282:24 + --> $DIR/diagnostic-derive.rs:279:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:282:18 + --> $DIR/diagnostic-derive.rs:279:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:290:33 + --> $DIR/diagnostic-derive.rs:287:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:290:18 + --> $DIR/diagnostic-derive.rs:287:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:297:5 + --> $DIR/diagnostic-derive.rs:294:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:448:53 + --> $DIR/diagnostic-derive.rs:445:5 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:450:24 + --> $DIR/diagnostic-derive.rs:447:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:456:53 + --> $DIR/diagnostic-derive.rs:453:69 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:523:5 + --> $DIR/diagnostic-derive.rs:520:5 | LL | #[help(no_crate_help)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: `#[label(foo)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:532:29 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/diagnostic-derive.rs:529:32 | LL | #[label(no_crate_label, foo)] - | ^^^ - | - = help: a diagnostic slug must be the first argument to the attribute + | ^ -error: `#[label(foo = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:540:29 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:537:29 | LL | #[label(no_crate_label, foo = "...")] - | ^^^^^^^^^^^ + | ^^^ -error: `#[label(foo(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:548:29 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:545:29 | LL | #[label(no_crate_label, foo("..."))] - | ^^^^^^^^^^ + | ^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:560:5 + --> $DIR/diagnostic-derive.rs:557:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -387,13 +356,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | / #[error(no_crate_example, code = "E0123")] LL | | @@ -405,13 +374,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | / #[warn_(no_crate_example, code = "E0123")] LL | | @@ -423,13 +392,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:591:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:591:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -441,19 +410,19 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -466,19 +435,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:611:53 + --> $DIR/diagnostic-derive.rs:608:53 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:611:39 + --> $DIR/diagnostic-derive.rs:608:39 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:620:24 + --> $DIR/diagnostic-derive.rs:617:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -486,7 +455,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:628:17 + --> $DIR/diagnostic-derive.rs:625:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -494,13 +463,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:635:5 + --> $DIR/diagnostic-derive.rs:632:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:642:1 + --> $DIR/diagnostic-derive.rs:639:1 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -508,23 +477,21 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:645:1 - | -LL | #[multipart_suggestion()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider creating a `Subdiagnostic` instead - -error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:649:5 + --> $DIR/diagnostic-derive.rs:646:5 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider creating a `Subdiagnostic` instead +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/diagnostic-derive.rs:642:24 + | +LL | #[multipart_suggestion()] + | ^ + error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:657:1 + --> $DIR/diagnostic-derive.rs:654:1 | LL | #[suggestion(no_crate_suggestion, code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -532,45 +499,39 @@ LL | #[suggestion(no_crate_suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:666:1 + --> $DIR/diagnostic-derive.rs:663:1 | LL | #[label] | ^^^^^^^^ | = help: `#[label]` and `#[suggestion]` can only be applied to fields -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:700:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:697:7 | LL | #[subdiagnostic(bad)] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:708:5 + --> $DIR/diagnostic-derive.rs:705:5 | LL | #[subdiagnostic = "bad"] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:716:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:713:7 | LL | #[subdiagnostic(bad, bad)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:724:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:721:7 | LL | #[subdiagnostic("bad")] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:732:5 + --> $DIR/diagnostic-derive.rs:729:5 | LL | #[subdiagnostic(eager)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -578,25 +539,31 @@ LL | #[subdiagnostic(eager)] = help: eager subdiagnostics are not supported on lints error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:790:18 + --> $DIR/diagnostic-derive.rs:787:23 | LL | #[suggestion(code())] - | ^^^^^^ + | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:798:23 + --> $DIR/diagnostic-derive.rs:795:23 | LL | #[suggestion(code(foo))] | ^^^ -error: `code = "..."`/`code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:806:18 +error: unexpected token + --> $DIR/diagnostic-derive.rs:795:23 + | +LL | #[suggestion(code(foo))] + | ^^^ + +error: expected string literal + --> $DIR/diagnostic-derive.rs:804:25 | LL | #[suggestion(code = 3)] - | ^^^^^^^^ + | ^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:821:5 + --> $DIR/diagnostic-derive.rs:819:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -612,61 +579,69 @@ LL | #[nonsense(no_crate_example, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:147:7 + --> $DIR/diagnostic-derive.rs:144:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:580:3 + --> $DIR/diagnostic-derive.rs:577:3 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:587:3 + --> $DIR/diagnostic-derive.rs:584:3 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:594:3 + --> $DIR/diagnostic-derive.rs:591:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:601:3 + --> $DIR/diagnostic-derive.rs:598:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:642:3 + --> $DIR/diagnostic-derive.rs:639:3 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:645:3 + --> $DIR/diagnostic-derive.rs:642:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:649:7 + --> $DIR/diagnostic-derive.rs:646:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` - --> $DIR/diagnostic-derive.rs:70:8 + --> $DIR/diagnostic-derive.rs:69:8 | LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `crate::fluent_generated` +error[E0425]: cannot find value `__code_34` in this scope + --> $DIR/diagnostic-derive.rs:801:10 + | +LL | #[derive(Diagnostic)] + | ^^^^^^^^^^ not found in this scope + | + = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:341:10 + --> $DIR/diagnostic-derive.rs:338:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -676,7 +651,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 85 previous errors +error: aborting due to 84 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index c882f7792d5..1d928ca93f9 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -82,7 +82,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] -//~^ ERROR `#[label(bug = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct G { #[primary_span] @@ -92,8 +92,7 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] -//~^ ERROR `#[label("...")]` is not a valid attribute -//~| ERROR diagnostic slug must be first argument +//~^ ERROR unexpected literal in nested attribute, expected ident struct H { #[primary_span] span: Span, @@ -102,7 +101,7 @@ struct H { #[derive(Subdiagnostic)] #[label(slug = 4)] -//~^ ERROR `#[label(slug = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct J { #[primary_span] @@ -112,7 +111,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] -//~^ ERROR `#[label(slug(...))]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct K { #[primary_span] @@ -132,7 +131,7 @@ struct L { #[derive(Subdiagnostic)] #[label()] -//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute +//~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident struct M { #[primary_span] span: Span, @@ -141,7 +140,7 @@ struct M { #[derive(Subdiagnostic)] #[label(no_crate_example, code = "...")] -//~^ ERROR `#[label(code = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute struct N { #[primary_span] span: Span, @@ -150,7 +149,7 @@ struct N { #[derive(Subdiagnostic)] #[label(no_crate_example, applicability = "machine-applicable")] -//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute struct O { #[primary_span] span: Span, @@ -222,7 +221,7 @@ enum T { enum U { #[label(code = "...")] //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute - //~| ERROR `#[label(code = ...)]` is not a valid attribute + //~| ERROR invalid nested attribute A { #[primary_span] span: Span, @@ -323,7 +322,7 @@ struct AD { #[derive(Subdiagnostic)] #[label(no_crate_example, no_crate::example)] -//~^ ERROR `#[label(no_crate::example)]` is not a valid attribute +//~^ ERROR a diagnostic slug must be the first argument to the attribute struct AE { #[primary_span] span: Span, @@ -537,7 +536,7 @@ struct BA { #[derive(Subdiagnostic)] #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute +//~| ERROR invalid nested attribute struct BBa { var: String, } @@ -554,7 +553,7 @@ struct BBb { #[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] struct BBc { #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident span1: Span, } @@ -574,10 +573,11 @@ struct BD { //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` span1: Span, #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident span2: Span, #[suggestion_part(foo = "bar")] - //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute + //~^ ERROR `code` is the only valid nested attribute + //~| ERROR expected `,` span4: Span, #[suggestion_part(code = "...")] //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` @@ -669,6 +669,7 @@ enum BL { struct BM { #[suggestion_part(code("foo"))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -678,6 +679,7 @@ struct BM { struct BN { #[suggestion_part(code("foo", "bar"))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -687,6 +689,7 @@ struct BN { struct BO { #[suggestion_part(code(3))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -701,10 +704,13 @@ struct BP { } #[derive(Subdiagnostic)] +//~^ ERROR cannot find value `__code_29` in this scope +//~| NOTE in this expansion +//~| NOTE not found in this scope #[multipart_suggestion(no_crate_example)] struct BQ { #[suggestion_part(code = 3)] - //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + //~^ ERROR expected string literal span: Span, r#type: String, } @@ -779,7 +785,7 @@ struct SuggestionStyleInvalid1 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style = 42)] -//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute +//~^ ERROR expected `= "xxx"` struct SuggestionStyleInvalid2 { #[primary_span] sub: Span, @@ -787,7 +793,7 @@ struct SuggestionStyleInvalid2 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style)] -//~^ ERROR `#[suggestion(style)]` is not a valid attribute +//~^ ERROR a diagnostic slug must be the first argument to the attribute struct SuggestionStyleInvalid3 { #[primary_span] sub: Span, @@ -795,7 +801,8 @@ struct SuggestionStyleInvalid3 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style("foo"))] -//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute +//~^ ERROR expected `= "xxx"` +//~| ERROr expected `,` struct SuggestionStyleInvalid4 { #[primary_span] sub: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 343134af6bc..4211b91f04a 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -26,11 +26,11 @@ error: `#[label = ...]` is not a valid attribute LL | #[label = "..."] | ^^^^^^^^^^^^^^^^ -error: `#[label(bug = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:84:9 | LL | #[label(bug = "...")] - | ^^^^^^^^^^^ + | ^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:84:1 @@ -38,110 +38,104 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute LL | #[label(bug = "...")] | ^^^^^^^^^^^^^^^^^^^^^ -error: `#[label("...")]` is not a valid attribute +error: unexpected literal in nested attribute, expected ident --> $DIR/subdiagnostic-derive.rs:94:9 | LL | #[label("...")] | ^^^^^ -error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:94:1 - | -LL | #[label("...")] - | ^^^^^^^^^^^^^^^ - -error: `#[label(slug = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:104:9 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:103:9 | LL | #[label(slug = 4)] - | ^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:104:1 + --> $DIR/subdiagnostic-derive.rs:103:1 | LL | #[label(slug = 4)] | ^^^^^^^^^^^^^^^^^^ -error: `#[label(slug(...))]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:114:9 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:113:9 | LL | #[label(slug("..."))] - | ^^^^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:114:1 + --> $DIR/subdiagnostic-derive.rs:113:1 | LL | #[label(slug("..."))] | ^^^^^^^^^^^^^^^^^^^^^ -error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:134:1 +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:133:9 | LL | #[label()] - | ^^^^^^^^^^ + | ^ -error: `#[label(code = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:143:27 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:142:27 | LL | #[label(no_crate_example, code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ -error: `#[label(applicability = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:152:27 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:151:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:161:1 + --> $DIR/subdiagnostic-derive.rs:160:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:175:5 + --> $DIR/subdiagnostic-derive.rs:174:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:187:5 + --> $DIR/subdiagnostic-derive.rs:186:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:199:5 + --> $DIR/subdiagnostic-derive.rs:198:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:211:5 + --> $DIR/subdiagnostic-derive.rs:210:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ -error: `#[label(code = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:223:13 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:222:13 | LL | #[label(code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:223:5 + --> $DIR/subdiagnostic-derive.rs:222:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:252:5 + --> $DIR/subdiagnostic-derive.rs:251:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:249:1 + --> $DIR/subdiagnostic-derive.rs:248:1 | LL | / #[label(no_crate_example)] LL | | @@ -153,13 +147,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:262:5 + --> $DIR/subdiagnostic-derive.rs:261:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:272:5 + --> $DIR/subdiagnostic-derive.rs:271:5 | LL | #[bar] | ^^^^^^ @@ -167,13 +161,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:283:5 + --> $DIR/subdiagnostic-derive.rs:282:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:294:5 + --> $DIR/subdiagnostic-derive.rs:293:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -181,7 +175,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:310:1 + --> $DIR/subdiagnostic-derive.rs:309:1 | LL | / union AC { LL | | @@ -190,76 +184,74 @@ LL | | b: u64, LL | | } | |_^ -error: `#[label(no_crate::example)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:325:27 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive.rs:324:44 | LL | #[label(no_crate_example, no_crate::example)] - | ^^^^^^^^^^^^^^^^^ - | - = help: a diagnostic slug must be the first argument to the attribute + | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:338:5 + --> $DIR/subdiagnostic-derive.rs:337:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:335:5 + --> $DIR/subdiagnostic-derive.rs:334:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:344:8 + --> $DIR/subdiagnostic-derive.rs:343:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:381:46 + --> $DIR/subdiagnostic-derive.rs:380:46 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:381:32 + --> $DIR/subdiagnostic-derive.rs:380:32 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:399:5 + --> $DIR/subdiagnostic-derive.rs:398:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:396:5 + --> $DIR/subdiagnostic-derive.rs:395:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:409:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:422:1 + --> $DIR/subdiagnostic-derive.rs:421:1 | LL | #[suggestion(no_crate_example)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:432:46 + --> $DIR/subdiagnostic-derive.rs:431:62 | LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:450:1 + --> $DIR/subdiagnostic-derive.rs:449:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -269,25 +261,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:464:1 + --> $DIR/subdiagnostic-derive.rs:463:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:484:39 + --> $DIR/subdiagnostic-derive.rs:483:39 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:503:43 + --> $DIR/subdiagnostic-derive.rs:502:43 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:526:5 + --> $DIR/subdiagnostic-derive.rs:525:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -295,7 +287,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:529:5 + --> $DIR/subdiagnostic-derive.rs:528:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -303,7 +295,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:523:1 + --> $DIR/subdiagnostic-derive.rs:522:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -314,16 +306,16 @@ LL | | var: String, LL | | } | |_^ -error: `#[multipart_suggestion(code = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:538:42 +error: invalid nested attribute + --> $DIR/subdiagnostic-derive.rs:537:42 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] - | ^^^^^^^^^^^^ + | ^^^^ | = help: only `style` and `applicability` are valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:538:1 + --> $DIR/subdiagnostic-derive.rs:537:1 | LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] LL | | @@ -334,19 +326,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:548:5 + --> $DIR/subdiagnostic-derive.rs:547:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ -error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:556:5 +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:555:23 | LL | #[suggestion_part()] - | ^^^^^^^^^^^^^^^^^^^^ + | ^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:565:5 + --> $DIR/subdiagnostic-derive.rs:564:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -354,7 +346,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:562:1 + --> $DIR/subdiagnostic-derive.rs:561:1 | LL | / #[multipart_suggestion(no_crate_example)] LL | | @@ -366,24 +358,16 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:573:5 + --> $DIR/subdiagnostic-derive.rs:572:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ -error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:576:5 - | -LL | #[suggestion_part()] - | ^^^^^^^^^^^^^^^^^^^^ - -error: `#[suggestion_part(foo = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:579:23 +error: `code` is the only valid nested attribute + --> $DIR/subdiagnostic-derive.rs:578:23 | LL | #[suggestion_part(foo = "bar")] - | ^^^^^^^^^^^ - | - = help: `code` is the only valid nested attribute + | ^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` --> $DIR/subdiagnostic-derive.rs:582:5 @@ -397,17 +381,29 @@ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:575:23 + | +LL | #[suggestion_part()] + | ^ + +error: expected `,` + --> $DIR/subdiagnostic-derive.rs:578:27 + | +LL | #[suggestion_part(foo = "bar")] + | ^ + error: specified multiple times --> $DIR/subdiagnostic-derive.rs:593:37 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^ | note: previously specified here --> $DIR/subdiagnostic-derive.rs:593:23 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` --> $DIR/subdiagnostic-derive.rs:622:5 @@ -416,49 +412,67 @@ LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:670:23 + --> $DIR/subdiagnostic-derive.rs:670:34 | LL | #[suggestion_part(code("foo"))] - | ^^^^^^^^^^^ + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:670:28 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:679:23 + --> $DIR/subdiagnostic-derive.rs:680:41 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:680:28 | LL | #[suggestion_part(code("foo", "bar"))] - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:688:23 + --> $DIR/subdiagnostic-derive.rs:690:30 | LL | #[suggestion_part(code(3))] - | ^^^^^^^ + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:690:28 + | +LL | #[suggestion_part(code(3))] + | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:697:23 + --> $DIR/subdiagnostic-derive.rs:700:29 | LL | #[suggestion_part(code())] - | ^^^^^^ + | ^ -error: `code = "..."`/`code(...)` must contain only string literals - --> $DIR/subdiagnostic-derive.rs:706:23 +error: expected string literal + --> $DIR/subdiagnostic-derive.rs:712:30 | LL | #[suggestion_part(code = 3)] - | ^^^^^^^^ + | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:748:61 + --> $DIR/subdiagnostic-derive.rs:754:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:748:43 + --> $DIR/subdiagnostic-derive.rs:754:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:757:1 + --> $DIR/subdiagnostic-derive.rs:763:1 | LL | #[suggestion_hidden(no_crate_example, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -466,7 +480,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:765:1 + --> $DIR/subdiagnostic-derive.rs:771:1 | LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -474,35 +488,39 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: invalid suggestion style - --> $DIR/subdiagnostic-derive.rs:773:51 + --> $DIR/subdiagnostic-derive.rs:779:51 | LL | #[suggestion(no_crate_example, code = "", style = "foo")] | ^^^^^ | = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` -error: `#[suggestion(style = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:781:43 +error: expected `= "xxx"` + --> $DIR/subdiagnostic-derive.rs:787:49 | LL | #[suggestion(no_crate_example, code = "", style = 42)] - | ^^^^^^^^^^ + | ^ -error: `#[suggestion(style)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:789:43 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive.rs:795:48 | LL | #[suggestion(no_crate_example, code = "", style)] - | ^^^^^ + | ^ + +error: expected `= "xxx"` + --> $DIR/subdiagnostic-derive.rs:803:48 | - = help: a diagnostic slug must be the first argument to the attribute +LL | #[suggestion(no_crate_example, code = "", style("foo"))] + | ^ -error: `#[suggestion(style(...))]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:797:43 +error: expected `,` + --> $DIR/subdiagnostic-derive.rs:803:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] - | ^^^^^^^^^^^^ + | ^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:808:5 + --> $DIR/subdiagnostic-derive.rs:815:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -511,7 +529,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:805:1 + --> $DIR/subdiagnostic-derive.rs:812:1 | LL | / #[suggestion(no_crate_example, code = "")] LL | | @@ -529,59 +547,67 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:161:3 + --> $DIR/subdiagnostic-derive.rs:160:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:175:7 + --> $DIR/subdiagnostic-derive.rs:174:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:187:7 + --> $DIR/subdiagnostic-derive.rs:186:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:199:7 + --> $DIR/subdiagnostic-derive.rs:198:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:211:7 + --> $DIR/subdiagnostic-derive.rs:210:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:272:7 + --> $DIR/subdiagnostic-derive.rs:271:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:283:7 + --> $DIR/subdiagnostic-derive.rs:282:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:294:7 + --> $DIR/subdiagnostic-derive.rs:293:7 | LL | #[bar("...")] | ^^^ error[E0425]: cannot find value `slug` in module `crate::fluent_generated` - --> $DIR/subdiagnostic-derive.rs:124:9 + --> $DIR/subdiagnostic-derive.rs:123:9 | LL | #[label(slug)] | ^^^^ not found in `crate::fluent_generated` -error: aborting due to 81 previous errors +error[E0425]: cannot find value `__code_29` in this scope + --> $DIR/subdiagnostic-derive.rs:706:10 + | +LL | #[derive(Subdiagnostic)] + | ^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 86 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr index 227b2f40223..a61411d6eb6 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.stderr +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<N>` LL | let foo = Foo::foo(); | ^^^ | -help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified +help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified | LL | let foo: Foo<N> = Foo::foo(); | ++++++++ diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs new file mode 100644 index 00000000000..d7bf1b47fb5 --- /dev/null +++ b/tests/ui/const-generics/transmute-fail.rs @@ -0,0 +1,35 @@ +#![feature(transmute_generic_consts)] +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + //~^ ERROR mismatched types + //~| ERROR mismatched types + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute between types + } +} + +fn baz<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 8888888] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn main() {} diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr new file mode 100644 index 00000000000..41b098135e8 --- /dev/null +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -0,0 +1,52 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:7:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H+1]; W]` (generic size [const expr]) + = note: target type: `[[u32; W+1]; H]` (generic size [const expr]) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:16:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) + = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:53 + | +LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:67 + | +LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:23:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (generic size [const expr]) + = note: target type: `[u32; W * H * H]` (generic size [const expr]) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:30:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture) + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0512. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs new file mode 100644 index 00000000000..30560a95b5e --- /dev/null +++ b/tests/ui/const-generics/transmute.rs @@ -0,0 +1,83 @@ +// run-pass +#![feature(generic_const_exprs)] +#![feature(transmute_generic_consts)] +#![allow(incomplete_features)] + +fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + } +} + +fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten_3d<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [u32; D * W * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten_somewhat<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [[u32; D * W]; H] { + unsafe { + std::mem::transmute(v) + } +} + +fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] { + unsafe { + std::mem::transmute(v) + } +} + +fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] { + unsafe { + std::mem::transmute(v) + } +} + +fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] { + unsafe { + std::mem::transmute(v) + } +} + +fn transpose_with_const<const W: usize, const H: usize>( + v: [[u32; 2 * H]; W + W] +) -> [[u32; W + W]; 2 * H] { + unsafe { + std::mem::transmute(v) + } +} + +fn main() { + let _ = transpose([[0; 8]; 16]); + let _ = transpose_with_const::<8,4>([[0; 8]; 16]); + let _ = ident([[0; 8]; 16]); + let _ = flatten([[0; 13]; 5]); + let _: [[_; 5]; 13] = coagulate([0; 65]); + let _ = flatten_3d([[[0; 3]; 13]; 5]); + let _ = flatten_somewhat([[[0; 3]; 13]; 5]); + let _ = known_size([16; 13]); + let _: [u16; 5] = condense_bytes([16u8; 10]); + let _ = singleton_each([16; 10]); +} diff --git a/tests/ui/const-generics/transmute_no_gate.rs b/tests/ui/const-generics/transmute_no_gate.rs new file mode 100644 index 00000000000..e1ac44390a5 --- /dev/null +++ b/tests/ui/const-generics/transmute_no_gate.rs @@ -0,0 +1,91 @@ +// gate-test-transmute_generic_consts +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { + unsafe { + std::mem::transmute(v) + } +} + +fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn flatten_3d<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [u32; D * W * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn flatten_somewhat<const W: usize, const H: usize, const D: usize>( + v: [[[u32; D]; H]; W] +) -> [[u32; D * W]; H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn transpose_with_const<const W: usize, const H: usize>( + v: [[u32; 2 * H]; W + W] +) -> [[u32; W + W]; 2 * H] { + unsafe { + std::mem::transmute(v) + //~^ ERROR cannot transmute + } +} + +fn main() { + let _ = transpose([[0; 8]; 16]); + let _ = transpose_with_const::<8,4>([[0; 8]; 16]); + let _ = ident([[0; 8]; 16]); + let _ = flatten([[0; 13]; 5]); + let _: [[_; 5]; 13] = coagulate([0; 65]); + let _ = flatten_3d([[[0; 3]; 13]; 5]); + let _ = flatten_somewhat([[[0; 3]; 13]; 5]); + let _ = known_size([16; 13]); + let _: [u16; 5] = condense_bytes([16u8; 10]); + let _ = singleton_each([16; 10]); +} diff --git a/tests/ui/const-generics/transmute_no_gate.stderr b/tests/ui/const-generics/transmute_no_gate.stderr new file mode 100644 index 00000000000..9c271b34849 --- /dev/null +++ b/tests/ui/const-generics/transmute_no_gate.stderr @@ -0,0 +1,84 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:7:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) + = note: target type: `[[u32; W]; H]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:20:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) + = note: target type: `[u32; W * H]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:27:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u32; H*W]` (this type does not have a fixed size) + = note: target type: `[[u32; W]; H]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:36:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size) + = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:45:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size) + = note: target type: `[[u32; D * W]; H]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:52:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u16; L]` (this type does not have a fixed size) + = note: target type: `[u8; L * 2]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:59:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; L * 2]` (this type does not have a fixed size) + = note: target type: `[u16; L]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:66:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; L]` (this type does not have a fixed size) + = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute_no_gate.rs:75:5 + | +LL | std::mem::transmute(v) + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[u32; 2 * H]; W + W]` (this type does not have a fixed size) + = note: target type: `[[u32; W + W]; 2 * H]` (this type does not have a fixed size) + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr index d56e1273f24..835f7f76560 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr @@ -6,7 +6,7 @@ LL | fn a() -> impl Fn(&u8) -> impl Debug { LL | |x| x | --- ^ | | - | hidden type `&u8` captures the anonymous lifetime #1 defined here + | hidden type `&u8` captures the anonymous lifetime as defined here error: aborting due to previous error diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr index f2ee8692e38..97ed53fb3ce 100644 --- a/tests/ui/inference/issue-83606.stderr +++ b/tests/ui/inference/issue-83606.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; N]` LL | let _ = foo("foo"); | ^ | -help: consider giving this pattern a type, where the the value of const parameter `N` is specified +help: consider giving this pattern a type, where the value of const parameter `N` is specified | LL | let _: [usize; N] = foo("foo"); | ++++++++++++ diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs index 72e0e74f323..fc79e6201bd 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.rs +++ b/tests/ui/inference/need_type_info/concrete-impl.rs @@ -7,10 +7,13 @@ struct Two; struct Struct; impl Ambiguous<One> for Struct {} +//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found impl Ambiguous<Two> for Struct {} fn main() { <Struct as Ambiguous<_>>::method(); //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `A` //~| ERROR type annotations needed + //~| NOTE infer type of the type parameter `A` } diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr index aa32969950d..74c3f6cd5cf 100644 --- a/tests/ui/inference/need_type_info/concrete-impl.stderr +++ b/tests/ui/inference/need_type_info/concrete-impl.stderr @@ -1,20 +1,21 @@ error[E0282]: type annotations needed - --> $DIR/concrete-impl.rs:13:5 + --> $DIR/concrete-impl.rs:14:5 | LL | <Struct as Ambiguous<_>>::method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous` error[E0283]: type annotations needed - --> $DIR/concrete-impl.rs:13:5 + --> $DIR/concrete-impl.rs:14:5 | LL | <Struct as Ambiguous<_>>::method(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous` | note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found --> $DIR/concrete-impl.rs:9:1 | LL | impl Ambiguous<One> for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | LL | impl Ambiguous<Two> for Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/inference/need_type_info/issue-109905.rs b/tests/ui/inference/need_type_info/issue-109905.rs new file mode 100644 index 00000000000..99d10a5eae0 --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-109905.rs @@ -0,0 +1,25 @@ +// Test that we show the correct type parameter that couldn't be inferred and that we don't +// end up stating nonsense like "type parameter `'a`" which we used to do. + +trait Trait<'a, T> { + fn m(self); +} + +impl<'a, A> Trait<'a, A> for () { + fn m(self) {} +} + +fn qualified() { + <() as Trait<'static, _>>::m(()); + //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `T` + +} + +fn unqualified() { + Trait::<'static, _>::m(()); + //~^ ERROR type annotations needed + //~| NOTE cannot infer type of the type parameter `T` +} + +fn main() {} diff --git a/tests/ui/inference/need_type_info/issue-109905.stderr b/tests/ui/inference/need_type_info/issue-109905.stderr new file mode 100644 index 00000000000..fcdd50f1422 --- /dev/null +++ b/tests/ui/inference/need_type_info/issue-109905.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/issue-109905.rs:13:5 + | +LL | <() as Trait<'static, _>>::m(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait` + +error[E0282]: type annotations needed + --> $DIR/issue-109905.rs:20:5 + | +LL | Trait::<'static, _>::m(()); + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr index fd905392a21..4fd9f3030fc 100644 --- a/tests/ui/issues/issue-98299.stderr +++ b/tests/ui/issues/issue-98299.stderr @@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `SmallCString<N>` LL | SmallCString::try_from(p).map(|cstr| cstr); | ^^^^ | -help: consider giving this closure parameter an explicit type, where the the value of const parameter `N` is specified +help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified | LL | SmallCString::try_from(p).map(|cstr: SmallCString<N>| cstr); | +++++++++++++++++ diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index 363ddfaffe0..c0d95ddaa07 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) i32)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr index 5a8462d4dc5..61e2a1ea6f0 100644 --- a/tests/ui/nll/closure-requirements/escape-argument.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument.stderr @@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | = note: defining type: test::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)), (), ] diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 7da6ce58bf7..5a7b12732df 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#4r diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 993687605c4..db2ecc779ef 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 721cd45ded9..1d9dafbe55f 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure substs [ i32, - for<Region(BrAnon(0, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)), + for<Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), (), ] @@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure substs [ i32, - for<Region(BrAnon(0, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)), + for<Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), (), ] = note: number of external vids: 2 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 43dfc3bb9f8..85f7fe35c0a 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 96c734226ef..7194843e203 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 03dbd686e49..71f8a1c67c6 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index d716d3de2a1..e1cb97b1c7d 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index b924873fca6..b66e8391c01 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#2r diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 9b25efd0b66..49641fd06fd 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)), + for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] = note: late-bound region is '_#3r diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr index 6db72b88632..4e34ba51659 100644 --- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a` | = note: defining type: test::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, (), ] diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index a442cf12d82..2c4a0597554 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::<T>::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), (), ] = note: number of external vids: 2 @@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::<T>::{closure#0} with closure substs [ i16, - for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)), + for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), (), ] = note: late-bound region is '_#2r diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs index d2b02cc2af5..6341e053277 100644 --- a/tests/ui/parser/dyn-trait-compatibility.rs +++ b/tests/ui/parser/dyn-trait-compatibility.rs @@ -9,6 +9,6 @@ type A2 = dyn<dyn, dyn>; type A3 = dyn<<dyn as dyn>::dyn>; //~^ ERROR cannot find type `dyn` in this scope //~| ERROR cannot find type `dyn` in this scope -//~| ERROR use of undeclared crate or module `dyn` +//~| ERROR cannot find trait `dyn` in this scope fn main() {} diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr index 0cae01bd1e3..653be5b3b71 100644 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ b/tests/ui/parser/dyn-trait-compatibility.stderr @@ -4,12 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `dyn` LL | type A1 = dyn::dyn; | ^^^ use of undeclared crate or module `dyn` -error[E0433]: failed to resolve: use of undeclared crate or module `dyn` - --> $DIR/dyn-trait-compatibility.rs:9:23 - | -LL | type A3 = dyn<<dyn as dyn>::dyn>; - | ^^^ use of undeclared crate or module `dyn` - error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:1:11 | @@ -40,6 +34,12 @@ error[E0412]: cannot find type `dyn` in this scope LL | type A3 = dyn<<dyn as dyn>::dyn>; | ^^^ not found in this scope +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-trait-compatibility.rs:9:23 + | +LL | type A3 = dyn<<dyn as dyn>::dyn>; + | ^^^ not found in this scope + error[E0412]: cannot find type `dyn` in this scope --> $DIR/dyn-trait-compatibility.rs:9:16 | @@ -48,5 +48,5 @@ LL | type A3 = dyn<<dyn as dyn>::dyn>; error: aborting due to 8 previous errors -Some errors have detailed explanations: E0412, E0433. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0405, E0412, E0433. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/issues/issue-110014.rs b/tests/ui/parser/issues/issue-110014.rs new file mode 100644 index 00000000000..69d8f402bb6 --- /dev/null +++ b/tests/ui/parser/issues/issue-110014.rs @@ -0,0 +1,3 @@ +fn`2222222222222222222222222222222222222222() {} +//~^ ERROR unknown start of token: ` +//~^^ ERROR expected identifier, found `2222222222222222222222222222222222222222` diff --git a/tests/ui/parser/issues/issue-110014.stderr b/tests/ui/parser/issues/issue-110014.stderr new file mode 100644 index 00000000000..7f1dd592e12 --- /dev/null +++ b/tests/ui/parser/issues/issue-110014.stderr @@ -0,0 +1,19 @@ +error: unknown start of token: ` + --> $DIR/issue-110014.rs:1:3 + | +LL | fn`2222222222222222222222222222222222222222() {} + | ^ + | +help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not + | +LL | fn'2222222222222222222222222222222222222222() {} + | ~ + +error: expected identifier, found `2222222222222222222222222222222222222222` + --> $DIR/issue-110014.rs:1:4 + | +LL | fn`2222222222222222222222222222222222222222() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr index 2cb9ba0d1d1..39b1ef1e078 100644 --- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr @@ -10,14 +10,11 @@ error[E0603]: tuple struct constructor `TupleStruct` is private LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ private tuple struct constructor | - ::: $DIR/auxiliary/structs.rs:12:24 - | -LL | pub struct TupleStruct(pub u16, pub u16); - | ---------------- a constructor is private if any of the fields is private - | note: the tuple struct constructor `TupleStruct` is defined here --> $DIR/auxiliary/structs.rs:12:1 | +LL | #[non_exhaustive] + | ----------------- cannot be constructed because it is `#[non_exhaustive]` LL | pub struct TupleStruct(pub u16, pub u16); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -30,6 +27,8 @@ LL | let us_explicit = structs::UnitStruct; note: the unit struct `UnitStruct` is defined here --> $DIR/auxiliary/structs.rs:9:1 | +LL | #[non_exhaustive] + | ----------------- cannot be constructed because it is `#[non_exhaustive]` LL | pub struct UnitStruct; | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr index 720b7b119ce..4083f57a9cd 100644 --- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr @@ -8,7 +8,9 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^ + | ----------------- ^^^^^ + | | + | cannot be constructed because it is `#[non_exhaustive]` error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -20,7 +22,9 @@ note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 | LL | #[non_exhaustive] Unit, - | ^^^^ + | ----------------- ^^^^ + | | + | cannot be constructed because it is `#[non_exhaustive]` error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:18:32 @@ -32,7 +36,9 @@ note: the unit variant `Unit` is defined here --> $DIR/auxiliary/variants.rs:4:23 | LL | #[non_exhaustive] Unit, - | ^^^^ + | ----------------- ^^^^ + | | + | cannot be constructed because it is `#[non_exhaustive]` error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:20:32 @@ -44,7 +50,9 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^ + | ----------------- ^^^^^ + | | + | cannot be constructed because it is `#[non_exhaustive]` error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 @@ -56,7 +64,9 @@ note: the tuple variant `Tuple` is defined here --> $DIR/auxiliary/variants.rs:5:23 | LL | #[non_exhaustive] Tuple(u32), - | ^^^^^ + | ----------------- ^^^^^ + | | + | cannot be constructed because it is `#[non_exhaustive]` error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed index 85d106bc11f..ede0c2e8eaf 100644 --- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed @@ -18,9 +18,11 @@ mod foo { fn main() { let _: <foo::Baz as crate::foo::Foo>::Bar = (); //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition + //~| ERROR absolute paths must start with + //~| WARN this is accepted in the current edition let _: <crate::foo::Baz as foo::Foo>::Bar = (); //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition } diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs index 9ff3c2e5fcf..48b091ddb45 100644 --- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs @@ -18,9 +18,11 @@ mod foo { fn main() { let _: <foo::Baz as ::foo::Foo>::Bar = (); //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition + //~| ERROR absolute paths must start with + //~| WARN this is accepted in the current edition let _: <::foo::Baz as foo::Foo>::Bar = (); //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition } diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr index e1709db0990..497ee440dfd 100644 --- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr +++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr @@ -13,7 +13,16 @@ LL | #![deny(absolute_paths_not_starting_with_crate)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - --> $DIR/edition-lint-fully-qualified-paths.rs:23:13 + --> $DIR/edition-lint-fully-qualified-paths.rs:19:25 + | +LL | let _: <foo::Baz as ::foo::Foo>::Bar = (); + | ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130> + +error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition + --> $DIR/edition-lint-fully-qualified-paths.rs:25:13 | LL | let _: <::foo::Baz as foo::Foo>::Bar = (); | ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz` @@ -21,5 +30,5 @@ LL | let _: <::foo::Baz as foo::Foo>::Bar = (); = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130> -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs index 471a6b836b5..8e43b7249f7 100644 --- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs @@ -18,6 +18,6 @@ fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expec fn issue_95327() where <u8 as Unresolved>::Assoc: String {} //~^ ERROR expected trait, found struct -//~| ERROR use of undeclared type `Unresolved` +//~| ERROR cannot find trait `Unresolved` in this scope fn main() {} diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr index 5be33498641..0020f9e416d 100644 --- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr +++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr @@ -1,9 +1,3 @@ -error[E0433]: failed to resolve: use of undeclared type `Unresolved` - --> $DIR/assoc_type_bound_with_struct.rs:19:31 - | -LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} - | ^^^^^^^^^^ use of undeclared type `Unresolved` - error[E0404]: expected trait, found struct `String` --> $DIR/assoc_type_bound_with_struct.rs:5:46 | @@ -76,6 +70,12 @@ help: a trait with a similar name exists LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString { | ~~~~~~~~ +error[E0405]: cannot find trait `Unresolved` in this scope + --> $DIR/assoc_type_bound_with_struct.rs:19:31 + | +LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} + | ^^^^^^^^^^ not found in this scope + error[E0404]: expected trait, found struct `String` --> $DIR/assoc_type_bound_with_struct.rs:19:51 | @@ -87,5 +87,5 @@ LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {} error: aborting due to 6 previous errors -Some errors have detailed explanations: E0404, E0433. +Some errors have detailed explanations: E0404, E0405. For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/ufcs/ufcs-partially-resolved.rs b/tests/ui/ufcs/ufcs-partially-resolved.rs index e6470aa6d64..712668728c9 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.rs +++ b/tests/ui/ufcs/ufcs-partially-resolved.rs @@ -17,37 +17,37 @@ type A = u32; fn main() { let _: <u8 as Tr>::N; //~ ERROR cannot find associated type `N` in trait `Tr` - let _: <u8 as E>::N; //~ ERROR cannot find associated type `N` in enum `E` - let _: <u8 as A>::N; //~ ERROR cannot find associated type `N` in `A` + let _: <u8 as E>::N; //~ ERROR expected trait, found enum `E` + let _: <u8 as A>::N; //~ ERROR expected trait, found type alias `A` <u8 as Tr>::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr` - <u8 as E>::N; //~ ERROR cannot find method or associated constant `N` in enum `E` - <u8 as A>::N; //~ ERROR cannot find method or associated constant `N` in `A` + <u8 as E>::N; //~ ERROR expected trait, found enum `E` + <u8 as A>::N; //~ ERROR expected trait, found type alias `A` let _: <u8 as Tr>::Y; // OK - let _: <u8 as E>::Y; //~ ERROR expected associated type, found variant `E::Y` + let _: <u8 as E>::Y; //~ ERROR expected trait, found enum `E` <u8 as Tr>::Y; // OK - <u8 as E>::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y` + <u8 as E>::Y; //~ ERROR expected trait, found enum `E` let _: <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr` - let _: <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E` - let _: <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A` + let _: <u8 as E>::N::NN; //~ ERROR expected trait, found enum `E` + let _: <u8 as A>::N::NN; //~ ERROR expected trait, found type alias `A` <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr` - <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E` - <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A` + <u8 as E>::N::NN; //~ ERROR expected trait, found enum `E` + <u8 as A>::N::NN; //~ ERROR expected trait, found type alias `A` let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type - let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y` + let _: <u8 as E>::Y::NN; //~ ERROR expected trait, found enum `E` <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `u16` - <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y` + <u8 as E>::Y::NN; //~ ERROR expected trait, found enum `E` - let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N` - let _: <u8 as E::N>::NN; //~ ERROR cannot find associated type `NN` in `E::N` - let _: <u8 as A::N>::NN; //~ ERROR cannot find associated type `NN` in `A::N` - <u8 as Tr::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::N` - <u8 as E::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N` - <u8 as A::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N` - let _: <u8 as Tr::Y>::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y` - let _: <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module - <u8 as Tr::Y>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y` - <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module + let _: <u8 as Tr::N>::NN; //~ ERROR cannot find trait `N` in trait `Tr` + let _: <u8 as E::N>::NN; //~ ERROR cannot find trait `N` in enum `E` + let _: <u8 as A::N>::NN; //~ ERROR cannot find trait `N` in `A` + <u8 as Tr::N>::NN; //~ ERROR cannot find trait `N` in trait `Tr` + <u8 as E::N>::NN; //~ ERROR cannot find trait `N` in enum `E` + <u8 as A::N>::NN; //~ ERROR cannot find trait `N` in `A` + let _: <u8 as Tr::Y>::NN; //~ ERROR expected trait, found associated type `Tr::Y + let _: <u8 as E::Y>::NN; //~ ERROR expected trait, found variant `E::Y` + <u8 as Tr::Y>::NN; //~ ERROR expected trait, found associated type `Tr::Y` + <u8 as E::Y>::NN; //~ ERROR expected trait, found variant `E::Y` let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found associated function `Dr::Z` <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X` diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr index 72fccea8ae3..eef55c8dc68 100644 --- a/tests/ui/ufcs/ufcs-partially-resolved.stderr +++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr @@ -1,15 +1,3 @@ -error[E0433]: failed to resolve: `Y` is a variant, not a module - --> $DIR/ufcs-partially-resolved.rs:48:22 - | -LL | let _: <u8 as E::Y>::NN; - | ^ `Y` is a variant, not a module - -error[E0433]: failed to resolve: `Y` is a variant, not a module - --> $DIR/ufcs-partially-resolved.rs:50:15 - | -LL | <u8 as E::Y>::NN; - | ^ `Y` is a variant, not a module - error[E0576]: cannot find associated type `N` in trait `Tr` --> $DIR/ufcs-partially-resolved.rs:19:24 | @@ -19,17 +7,25 @@ LL | type Y = u16; LL | let _: <u8 as Tr>::N; | ^ help: an associated type with a similar name exists: `Y` -error[E0576]: cannot find associated type `N` in enum `E` - --> $DIR/ufcs-partially-resolved.rs:20:23 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:20:19 | LL | let _: <u8 as E>::N; - | ^ not found in `E` + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0576]: cannot find associated type `N` in `A` - --> $DIR/ufcs-partially-resolved.rs:21:23 +error[E0404]: expected trait, found type alias `A` + --> $DIR/ufcs-partially-resolved.rs:21:19 | LL | let _: <u8 as A>::N; - | ^ not found in `A` + | ^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait A = u32; + | error[E0576]: cannot find method or associated constant `N` in trait `Tr` --> $DIR/ufcs-partially-resolved.rs:22:17 @@ -40,29 +36,43 @@ LL | fn Y() {} LL | <u8 as Tr>::N; | ^ help: an associated function with a similar name exists: `Y` -error[E0576]: cannot find method or associated constant `N` in enum `E` - --> $DIR/ufcs-partially-resolved.rs:23:16 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:23:12 | LL | <u8 as E>::N; - | ^ not found in `E` + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0576]: cannot find method or associated constant `N` in `A` - --> $DIR/ufcs-partially-resolved.rs:24:16 +error[E0404]: expected trait, found type alias `A` + --> $DIR/ufcs-partially-resolved.rs:24:12 | LL | <u8 as A>::N; - | ^ not found in `A` + | ^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait A = u32; + | -error[E0575]: expected associated type, found variant `E::Y` - --> $DIR/ufcs-partially-resolved.rs:26:12 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:26:19 | LL | let _: <u8 as E>::Y; - | ^^^^^^^^^^^^ not a associated type + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0575]: expected method or associated constant, found unit variant `E::Y` - --> $DIR/ufcs-partially-resolved.rs:28:5 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:28:12 | LL | <u8 as E>::Y; - | ^^^^^^^^^^^^ not a method or associated constant + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here error[E0576]: cannot find associated type `N` in trait `Tr` --> $DIR/ufcs-partially-resolved.rs:30:24 @@ -73,17 +83,25 @@ LL | type Y = u16; LL | let _: <u8 as Tr>::N::NN; | ^ help: an associated type with a similar name exists: `Y` -error[E0576]: cannot find associated type `N` in enum `E` - --> $DIR/ufcs-partially-resolved.rs:31:23 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:31:19 | LL | let _: <u8 as E>::N::NN; - | ^ not found in `E` + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0576]: cannot find associated type `N` in `A` - --> $DIR/ufcs-partially-resolved.rs:32:23 +error[E0404]: expected trait, found type alias `A` + --> $DIR/ufcs-partially-resolved.rs:32:19 | LL | let _: <u8 as A>::N::NN; - | ^ not found in `A` + | ^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait A = u32; + | error[E0576]: cannot find associated type `N` in trait `Tr` --> $DIR/ufcs-partially-resolved.rs:33:17 @@ -94,77 +112,103 @@ LL | type Y = u16; LL | <u8 as Tr>::N::NN; | ^ help: an associated type with a similar name exists: `Y` -error[E0576]: cannot find associated type `N` in enum `E` - --> $DIR/ufcs-partially-resolved.rs:34:16 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:34:12 | LL | <u8 as E>::N::NN; - | ^ not found in `E` + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0576]: cannot find associated type `N` in `A` - --> $DIR/ufcs-partially-resolved.rs:35:16 +error[E0404]: expected trait, found type alias `A` + --> $DIR/ufcs-partially-resolved.rs:35:12 | LL | <u8 as A>::N::NN; - | ^ not found in `A` + | ^ type aliases cannot be used as traits + | +help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias + | +LL | trait A = u32; + | -error[E0575]: expected associated type, found variant `E::Y` - --> $DIR/ufcs-partially-resolved.rs:37:12 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:37:19 | LL | let _: <u8 as E>::Y::NN; - | ^^^^^^^^^^^^^^^^ not a associated type + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0575]: expected associated type, found variant `E::Y` - --> $DIR/ufcs-partially-resolved.rs:39:5 +error[E0404]: expected trait, found enum `E` + --> $DIR/ufcs-partially-resolved.rs:39:12 | LL | <u8 as E>::Y::NN; - | ^^^^^^^^^^^^^^^^ not a associated type + | ^ help: a trait with a similar name exists: `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: similarly named trait `Eq` defined here -error[E0576]: cannot find associated type `NN` in `Tr::N` - --> $DIR/ufcs-partially-resolved.rs:41:27 +error[E0405]: cannot find trait `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:41:23 | LL | let _: <u8 as Tr::N>::NN; - | ^^ not found in `Tr::N` + | ^ not found in `Tr` -error[E0576]: cannot find associated type `NN` in `E::N` - --> $DIR/ufcs-partially-resolved.rs:42:26 +error[E0405]: cannot find trait `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:42:22 | LL | let _: <u8 as E::N>::NN; - | ^^ not found in `E::N` + | ^ not found in `E` -error[E0576]: cannot find associated type `NN` in `A::N` - --> $DIR/ufcs-partially-resolved.rs:43:26 +error[E0405]: cannot find trait `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:43:22 | LL | let _: <u8 as A::N>::NN; - | ^^ not found in `A::N` + | ^ not found in `A` -error[E0576]: cannot find method or associated constant `NN` in `Tr::N` - --> $DIR/ufcs-partially-resolved.rs:44:20 +error[E0405]: cannot find trait `N` in trait `Tr` + --> $DIR/ufcs-partially-resolved.rs:44:16 | LL | <u8 as Tr::N>::NN; - | ^^ not found in `Tr::N` + | ^ not found in `Tr` -error[E0576]: cannot find method or associated constant `NN` in `E::N` - --> $DIR/ufcs-partially-resolved.rs:45:19 +error[E0405]: cannot find trait `N` in enum `E` + --> $DIR/ufcs-partially-resolved.rs:45:15 | LL | <u8 as E::N>::NN; - | ^^ not found in `E::N` + | ^ not found in `E` -error[E0576]: cannot find method or associated constant `NN` in `A::N` - --> $DIR/ufcs-partially-resolved.rs:46:19 +error[E0405]: cannot find trait `N` in `A` + --> $DIR/ufcs-partially-resolved.rs:46:15 | LL | <u8 as A::N>::NN; - | ^^ not found in `A::N` + | ^ not found in `A` -error[E0576]: cannot find associated type `NN` in `Tr::Y` - --> $DIR/ufcs-partially-resolved.rs:47:27 +error[E0404]: expected trait, found associated type `Tr::Y` + --> $DIR/ufcs-partially-resolved.rs:47:19 | LL | let _: <u8 as Tr::Y>::NN; - | ^^ not found in `Tr::Y` + | ^^^^^ not a trait + +error[E0404]: expected trait, found variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:48:19 + | +LL | let _: <u8 as E::Y>::NN; + | ^^^^ not a trait -error[E0576]: cannot find method or associated constant `NN` in `Tr::Y` - --> $DIR/ufcs-partially-resolved.rs:49:20 +error[E0404]: expected trait, found associated type `Tr::Y` + --> $DIR/ufcs-partially-resolved.rs:49:12 | LL | <u8 as Tr::Y>::NN; - | ^^ not found in `Tr::Y` + | ^^^^^ not a trait + +error[E0404]: expected trait, found variant `E::Y` + --> $DIR/ufcs-partially-resolved.rs:50:12 + | +LL | <u8 as E::Y>::NN; + | ^^^^ not a trait error[E0575]: expected associated type, found associated function `Dr::Z` --> $DIR/ufcs-partially-resolved.rs:52:12 @@ -226,5 +270,5 @@ LL | <u8 as Dr>::X::N; error: aborting due to 32 previous errors -Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599. +Some errors have detailed explanations: E0223, E0404, E0405, E0575, E0576, E0599. For more information about an error, try `rustc --explain E0223`. diff --git a/triagebot.toml b/triagebot.toml index 2d7be7d1273..5f4de0562f8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -470,8 +470,8 @@ cc = ["@rust-lang/style"] [mentions."Cargo.lock"] message = """ -These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs. -This was probably unintentional and should be reverted before this PR is merged. +These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs. +This was probably unintentional and should be reverted before this PR is merged. If this was intentional then you can ignore this comment. """ @@ -499,7 +499,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@compiler-errors", - "@eholk", "@jackh726", "@TaKO8Ki", "@WaffleLapkin", |
