diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 7dee8fbd3b9f0..9de25c4cec405 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -261,6 +261,7 @@ impl StableOrd for ExternAbi { rustc_error_messages::into_diag_arg_using_display!(ExternAbi); #[cfg(feature = "nightly")] +#[derive(Debug)] pub enum CVariadicStatus { NotSupported, Stable, diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 46d7beae8fe58..e8df8ce6e6dc3 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::msg; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{Span, sym}; use rustc_target::asm; diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 4e1b46d568099..86eb721ad284c 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1693,7 +1693,7 @@ impl<'hir> LoweringContext<'_, 'hir> { && !self.tcx.features().coroutines() && !self.tcx.features().gen_blocks() { - rustc_session::parse::feature_err( + rustc_session::errors::feature_err( &self.tcx.sess, sym::yield_expr, span, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6ca6bf3e1f6dc..49790c2da6de4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -62,7 +62,7 @@ use rustc_macros::extension; use rustc_middle::hir::{self as mid_hir}; use rustc_middle::span_bug; use rustc_middle::ty::{DelegationInfo, ResolverAstLowering, TyCtxt}; -use rustc_session::parse::add_feature_diagnostics; +use rustc_session::errors::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use smallvec::SmallVec; diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 49c5f060e2a1e..ef60dc6fc4f1c 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, PartialRes, PerNS, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg}; use rustc_middle::{span_bug, ty}; -use rustc_session::parse::add_feature_diagnostics; +use rustc_session::errors::add_feature_diagnostics; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; use smallvec::smallvec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index d185cc9163eb6..326576bb14881 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_abi::ExternAbi; use rustc_feature::Features; use rustc_session::Session; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 770189d8c7999..e9e8e42e16b31 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -30,11 +30,11 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{DiagCtxtHandle, Diagnostic, LintBuffer}; use rustc_feature::Features; use rustc_session::Session; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN, PATTERNS_IN_FNS_WITHOUT_BODY, UNUSED_VISIBILITIES, }; -use rustc_session::parse::feature_err; use rustc_span::{Ident, Span, kw, sym}; use rustc_target::spec::{AbiMap, AbiMapping}; use thin_vec::thin_vec; @@ -762,12 +762,23 @@ impl<'a> AstValidator<'a> { match fn_ctxt { FnCtxt::Foreign => return, FnCtxt::Free | FnCtxt::Assoc(_) => { - if !self.sess.target.supports_c_variadic_definitions() { - self.dcx().emit_err(errors::CVariadicNotSupported { - variadic_span: variadic_param.span, - target: &*self.sess.target.llvm_target, - }); - return; + match self.sess.target.supports_c_variadic_definitions() { + CVariadicStatus::NotSupported => { + self.dcx().emit_err(errors::CVariadicNotSupported { + variadic_span: variadic_param.span, + target: &*self.sess.target.llvm_target, + }); + return; + } + CVariadicStatus::Unstable { feature } if !self.features.enabled(feature) => { + let msg = + format!("C-variadic function definitions on this target are unstable"); + feature_err(&self.sess, feature, variadic_param.span, msg).emit(); + return; + } + CVariadicStatus::Unstable { .. } | CVariadicStatus::Stable => { + /* fall through */ + } } match sig.header.ext { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 5831636a81b2c..2b08906a77434 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -6,7 +6,7 @@ use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Feat use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_session::Session; -use rustc_session::parse::{feature_err, feature_warn}; +use rustc_session::errors::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, Symbol, sym}; use thin_vec::ThinVec; @@ -510,6 +510,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental"); gate_all!(unsafe_binders, "unsafe binder types are experimental"); gate_all!(unsafe_fields, "`unsafe` fields are experimental"); + gate_all!(view_types, "view types are experimental"); gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); gate_all!(yeet_expr, "`do yeet` expression is experimental"); // tidy-alphabetical-end diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 80a1d9aa5defd..4cc07ceaf231f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -13,8 +13,9 @@ use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::{exp, parse_in}; use rustc_session::Session; use rustc_session::config::ExpectedValues; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::UNEXPECTED_CFGS; -use rustc_session::parse::{ParseSess, feature_err}; +use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use thin_vec::ThinVec; diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index a20813406b024..a6cf25330b557 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,5 +1,5 @@ use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::edition::Edition::Edition2024; use super::prelude::*; diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index c0b90c2c6d97f..ecb136edad5fc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -5,7 +5,7 @@ use rustc_hir::Target; use rustc_hir::attrs::{ AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow, }; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{Span, Symbol, edition, sym}; use thin_vec::ThinVec; diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 0ca059bf4030b..039977c74c1bb 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -3,8 +3,8 @@ use rustc_feature::Features; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_hir::attrs::*; use rustc_session::Session; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; -use rustc_session::parse::feature_err; use rustc_span::edition::Edition::Edition2024; use rustc_span::kw; use rustc_target::spec::{Arch, BinaryFormat}; diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index be4bde5145d8c..33f0f6fc2f809 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1659,6 +1659,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { unimplemented!(); } + fn get_funclet_cleanuppad(&self, _funclet: &Funclet) -> RValue<'gcc> { + unimplemented!(); + } + // Atomic Operations fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index d50968bad2501..4be25b3fb0934 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -430,8 +430,8 @@ impl WriteBackendMethods for GccCodegenBackend { } fn optimize_and_codegen_fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, _tm_factory: TargetMachineFactoryFn, // FIXME(bjorn3): Limit LTO exports to these symbols @@ -439,7 +439,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index a61ec362e800d..7e5f71209fbab 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1289,6 +1289,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ret } + fn get_funclet_cleanuppad(&self, funclet: &Funclet<'ll>) -> &'ll Value { + funclet.cleanuppad() + } + // Atomic Operations fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 65c70c754918d..575e37d0b171d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -133,8 +133,8 @@ impl WriteBackendMethods for LlvmCodegenBackend { back::write::target_machine_factory(sess, optlvl, target_features) } fn optimize_and_codegen_fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], @@ -143,7 +143,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { ) -> CompiledModule { let mut module = back::lto::run_fat( cgcx, - prof, + &sess.prof, shared_emitter, tm_factory, exported_symbols_for_lto, @@ -153,9 +153,9 @@ impl WriteBackendMethods for LlvmCodegenBackend { let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); - back::lto::run_pass_manager(cgcx, prof, dcx, &mut module, false); + back::lto::run_pass_manager(cgcx, &sess.prof, dcx, &mut module, false); - back::write::codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config) + back::write::codegen(cgcx, &sess.prof, shared_emitter, module, &cgcx.module_config) } fn run_thin_lto( cgcx: &CodegenContext, diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index cfdd47b3a8c8c..09d3a5a3f040f 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1,4 +1,4 @@ -use rustc_abi::{Align, BackendRepr, Endian, HasDataLayout, Primitive, Size}; +use rustc_abi::{Align, BackendRepr, CVariadicStatus, Endian, HasDataLayout, Primitive, Size}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::mir::operand::OperandRef; @@ -1038,6 +1038,8 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( assert!(!bx.layout_of(target_ty).is_zst()); let target = &bx.cx.tcx.sess.target; + let stability = target.supports_c_variadic_definitions(); + match target.arch { Arch::X86 => emit_ptr_va_arg( bx, @@ -1094,6 +1096,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( ForceRightAdjust::Yes, ), Arch::RiscV32 if target.llvm_abiname == LlvmAbi::Ilp32e => { + std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); // FIXME: clang manually adjusts the alignment for this ABI. It notes: // // > To be compatible with GCC's behaviors, we force arguments with @@ -1215,10 +1218,15 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::SpirV => bug!("spirv does not support c-variadic functions"), Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => { + std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); + // Clang uses the LLVM implementation for these architectures. bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) } + Arch::Other(ref arch) => { + std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); + // Just to be safe we error out explicitly here, instead of crossing our fingers that // the default LLVM implementation has the correct behavior for this target. bug!("c-variadic functions are not currently implemented for custom target {arch}") diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ff91a08de4de6..c48e8a58b6964 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -961,15 +961,15 @@ fn execute_copy_from_cache_work_item( } fn do_fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: SharedEmitter, tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], needs_fat_lto: Vec>, ) -> CompiledModule { - let _timer = prof.verbose_generic_activity("LLVM_fatlto"); + let _timer = sess.prof.verbose_generic_activity("LLVM_fatlto"); let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); @@ -977,8 +977,8 @@ fn do_fat_lto( check_lto_allowed(&cgcx, dcx); B::optimize_and_codegen_fat_lto( + sess, cgcx, - prof, &shared_emitter, tm_factory, exported_symbols_for_lto, @@ -2177,8 +2177,8 @@ impl OngoingCodegen { CompiledModules { modules: vec![do_fat_lto( + sess, &cgcx, - &sess.prof, shared_emitter, tm_factory, &exported_symbols_for_lto, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 820436bb6a265..3e19f7f95470f 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -12,8 +12,8 @@ use rustc_middle::middle::codegen_fn_attrs::{ use rustc_middle::mono::Visibility; use rustc_middle::query::Providers; use rustc_middle::ty::{self as ty, TyCtxt}; +use rustc_session::errors::feature_err; use rustc_session::lint; -use rustc_session::parse::feature_err; use rustc_span::{Span, sym}; use rustc_target::spec::Os; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 06c81662d6018..2967db9df787c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -214,19 +214,18 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, mir::UnwindAction::Terminate(reason) => { - if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) { + if fx.mir[self.bb].is_cleanup && base::wants_wasm_eh(fx.cx.tcx().sess) { + // For wasm, we need to generate a nested `cleanuppad within %outer_pad` + // to catch exceptions during cleanup and call `panic_in_cleanup`. + Some(fx.terminate_block(reason, Some(self.bb))) + } else if fx.mir[self.bb].is_cleanup + && base::wants_new_eh_instructions(fx.cx.tcx().sess) + { // MSVC SEH will abort automatically if an exception tries to // propagate out from cleanup. - - // FIXME(@mirkootter): For wasm, we currently do not support terminate during - // cleanup, because this requires a few more changes: The current code - // caches the `terminate_block` for each function; funclet based code - however - - // requires a different terminate_block for each funclet - // Until this is implemented, we just do not unwind inside cleanup blocks - None } else { - Some(fx.terminate_block(reason)) + Some(fx.terminate_block(reason, None)) } } }; @@ -238,7 +237,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if let Some(unwind_block) = unwind_block { let ret_llbb = if let Some((_, target)) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -309,7 +308,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { ) -> MergingSucc { let unwind_target = match unwind { mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)), - mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason)), + mir::UnwindAction::Terminate(reason) => Some(fx.terminate_block(reason, None)), mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, }; @@ -317,7 +316,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) { assert!(unwind_target.is_none()); let ret_llbb = if let Some(target) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -334,7 +333,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { MergingSucc::False } else if let Some(cleanup) = unwind_target { let ret_llbb = if let Some(target) = destination { - fx.llbb(target) + self.llbb_with_cleanup(fx, target) } else { fx.unreachable_block() }; @@ -1906,8 +1905,39 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } - fn terminate_block(&mut self, reason: UnwindTerminateReason) -> Bx::BasicBlock { - if let Some((cached_bb, cached_reason)) = self.terminate_block + fn terminate_block( + &mut self, + reason: UnwindTerminateReason, + outer_catchpad_bb: Option, + ) -> Bx::BasicBlock { + // mb_funclet_bb should be present if and only if the target is wasm and + // we're terminating because of an unwind in a cleanup block. In that + // case we have nested funclets and the inner catch_switch needs to know + // what outer catch_pad it is contained in. + debug_assert!( + outer_catchpad_bb.is_some() + == (base::wants_wasm_eh(self.cx.tcx().sess) + && reason == UnwindTerminateReason::InCleanup) + ); + + // When we aren't in a wasm InCleanup block, there's only one terminate + // block needed so we cache at START_BLOCK index. + let mut cache_bb = mir::START_BLOCK; + // In wasm eh InCleanup, use the outer funclet's cleanup BB as the cache + // key. + if let Some(outer_bb) = outer_catchpad_bb { + let cleanup_kinds = + self.cleanup_kinds.as_ref().expect("cleanup_kinds required for funclets"); + cache_bb = cleanup_kinds[outer_bb] + .funclet_bb(outer_bb) + .expect("funclet_bb should be in a funclet"); + + // Ensure the outer funclet is created first + if self.funclets[cache_bb].is_none() { + self.landing_pad_for(cache_bb); + } + } + if let Some((cached_bb, cached_reason)) = self.terminate_blocks[cache_bb] && reason == cached_reason { return cached_bb; @@ -1945,12 +1975,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // cp_terminate: // %cp = catchpad within %cs [null, i32 64, null] // ... + // + // By contrast, on WebAssembly targets, we specifically _do_ want to + // catch foreign exceptions. The situation with MSVC is a + // regrettable hack which we don't want to extend to other targets + // unless necessary. For WebAssembly, to generate catch(...) and + // catch only C++ exception instead of generating a catch_all, we + // need to call the intrinsics @llvm.wasm.get.exception and + // @llvm.wasm.get.ehselector in the catch pad. Since we don't do + // this, we generate a catch_all. We originally got this behavior + // by accident but it luckily matches our intention. llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); - let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); let mut cs_bx = Bx::build(self.cx, llbb); - let cs = cs_bx.catch_switch(None, None, &[cp_llbb]); + + // For wasm InCleanup blocks, our catch_switch is nested within the + // outer catchpad, so we need to provide it as the parent value to + // catch_switch. + let mut outer_cleanuppad = None; + if outer_catchpad_bb.is_some() { + // Get the outer funclet's catchpad + let outer_funclet = self.funclets[cache_bb] + .as_ref() + .expect("landing_pad_for didn't create funclet"); + outer_cleanuppad = Some(cs_bx.get_funclet_cleanuppad(outer_funclet)); + } + let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); + let cs = cs_bx.catch_switch(outer_cleanuppad, None, &[cp_llbb]); + drop(cs_bx); bx = Bx::build(self.cx, cp_llbb); let null = @@ -1971,13 +2024,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { // Specifying more arguments than necessary usually doesn't // hurt, but the `WasmEHPrepare` LLVM pass does not recognize - // anything other than a single `null` as a `catch (...)` block, + // anything other than a single `null` as a `catch_all` block, // leading to problems down the line during instruction // selection. &[null] as &[_] }; funclet = Some(bx.catch_pad(cs, args)); + // On wasm, if we wanted to generate a catch(...) and only catch C++ + // exceptions, we'd call @llvm.wasm.get.exception and + // @llvm.wasm.get.ehselector selectors here. We want a catch_all so + // we leave them out. This is intentionally diverging from the MSVC + // behavior. } else { llbb = Bx::append_block(self.cx, self.llfn, "terminate"); bx = Bx::build(self.cx, llbb); @@ -2003,7 +2061,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.unreachable(); - self.terminate_block = Some((llbb, reason)); + self.terminate_blocks[cache_bb] = Some((llbb, reason)); llbb } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 93da12107bab0..5c14d6f2c0930 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -90,8 +90,11 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option, - /// Cached terminate upon unwinding block and its reason - terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>, + /// Cached terminate upon unwinding block and its reason. For non-wasm + /// targets, there is at most one such block per function, stored at index + /// `START_BLOCK`. For wasm targets, each funclet needs its own terminate + /// block, indexed by the cleanup block that is the funclet's head. + terminate_blocks: IndexVec>, /// A bool flag for each basic block indicating whether it is a cold block. /// A cold block is a block that is unlikely to be executed at runtime. @@ -227,7 +230,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, - terminate_block: None, + terminate_blocks: IndexVec::from_elem(None, &mir.basic_blocks), cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 4b1b0866f2eb9..b7d09d69aaecd 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -7,8 +7,8 @@ use rustc_middle::middle::codegen_fn_attrs::{TargetFeature, TargetFeatureKind}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON; -use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, edit_distance, sym}; use rustc_target::spec::{Arch, SanitizerSet}; use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index c222aef4574bf..5092f28a33f7b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -552,12 +552,12 @@ pub trait BuilderMethods<'a, 'tcx>: fn set_personality_fn(&mut self, personality: Self::Function); - // These are used by everyone except msvc + // These are used by everyone except msvc and wasm EH fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value); fn filter_landing_pad(&mut self, pers_fn: Self::Function); fn resume(&mut self, exn0: Self::Value, exn1: Self::Value); - // These are used only by msvc + // These are used by msvc and wasm EH fn cleanup_pad(&mut self, parent: Option, args: &[Self::Value]) -> Self::Funclet; fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option); fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet; @@ -567,6 +567,7 @@ pub trait BuilderMethods<'a, 'tcx>: unwind: Option, handlers: &[Self::BasicBlock], ) -> Self::Value; + fn get_funclet_cleanuppad(&self, funclet: &Self::Funclet) -> Self::Value; fn atomic_cmpxchg( &mut self, diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index cca6db78e381e..9b8bf138e7a14 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -30,8 +30,8 @@ pub trait WriteBackendMethods: Clone + 'static { /// Performs fat LTO by merging all modules into a single one, running autodiff /// if necessary and running any further optimizations fn optimize_and_codegen_fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, tm_factory: TargetMachineFactoryFn, exported_symbols_for_lto: &[String], diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index d64cf8e032935..c776fa69ba5c1 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{ self, AssocContainer, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef, Ty, suggest_constraining_type_param, }; -use rustc_session::parse::add_feature_diagnostics; +use rustc_session::errors::add_feature_diagnostics; use rustc_span::{BytePos, Pos, Span, Symbol, sym}; use rustc_trait_selection::error_reporting::traits::call_kind::{ CallDesugaringKind, CallKind, call_kind, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 6c9cd2e608ae1..7b2983620d420 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -216,14 +216,11 @@ impl std::fmt::Display for ImmTy<'_, Prov> { ty::tls::with(|tcx| { match self.imm { Immediate::Scalar(s) => { - if let Some(ty) = tcx.lift(self.layout.ty) { - let s = FmtPrinter::print_string(tcx, Namespace::ValueNS, |p| { - print_scalar(p, s, ty) - })?; - f.write_str(&s)?; - return Ok(()); - } - write!(f, "{:x}: {}", s, self.layout.ty) + let ty = tcx.lift(self.layout.ty); + let s = FmtPrinter::print_string(tcx, Namespace::ValueNS, |p| { + print_scalar(p, s, ty) + })?; + f.write_str(&s) } Immediate::ScalarPair(a, b) => { // FIXME(oli-obk): at least print tuples and slices nicely diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b8325f7ba3987..e50c232df2d86 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -423,6 +423,10 @@ pub trait MacResult { None } + fn make_method_receiver_expr(self: Box) -> Option> { + self.make_expr() + } + /// Creates zero or more items. fn make_items(self: Box) -> Option; 1]>> { None diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index b5f85536d9cac..2b914a2664fe5 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -27,7 +27,7 @@ use rustc_hir::{ }; use rustc_parse::parser::Recovery; use rustc_session::Session; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::instrument; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index fe363e7d4a511..1f67496575297 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -30,8 +30,8 @@ use rustc_parse::parser::{ RecoverColon, RecoverComma, Recovery, token_descr, }; use rustc_session::Session; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; -use rustc_session::parse::feature_err; use rustc_span::hygiene::SyntaxContext; use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym}; use smallvec::SmallVec; @@ -55,14 +55,11 @@ macro_rules! ast_fragments { $($Kind:ident($AstTy:ty) { $kind_name:expr; $(one - fn $mut_visit_ast:ident; fn $visit_ast:ident; - fn $ast_to_string:path; )? $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident($($args:tt)*); - fn $ast_to_string_elt:path; )? fn $make_ast:ident; })* @@ -71,7 +68,6 @@ macro_rules! ast_fragments { /// Can also serve as an input and intermediate result for macro expansion operations. pub enum AstFragment { OptExpr(Option>), - MethodReceiverExpr(Box), $($Kind($AstTy),)* } @@ -79,7 +75,6 @@ macro_rules! ast_fragments { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AstFragmentKind { OptExpr, - MethodReceiverExpr, $($Kind,)* } @@ -87,7 +82,6 @@ macro_rules! ast_fragments { pub fn name(self) -> &'static str { match self { AstFragmentKind::OptExpr => "expression", - AstFragmentKind::MethodReceiverExpr => "expression", $(AstFragmentKind::$Kind => $kind_name,)* } } @@ -96,8 +90,6 @@ macro_rules! ast_fragments { match self { AstFragmentKind::OptExpr => result.make_expr().map(Some).map(AstFragment::OptExpr), - AstFragmentKind::MethodReceiverExpr => - result.make_expr().map(AstFragment::MethodReceiverExpr), $(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)* } } @@ -120,21 +112,14 @@ macro_rules! ast_fragments { pub(crate) fn make_opt_expr(self) -> Option> { match self { AstFragment::OptExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), - } - } - - pub(crate) fn make_method_receiver_expr(self) -> Box { - match self { - AstFragment::MethodReceiverExpr(expr) => expr, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + _ => panic!("AstFragment::make_opt_expr called on the wrong kind of fragment"), } } $(pub fn $make_ast(self) -> $AstTy { match self { AstFragment::$Kind(ast) => ast, - _ => panic!("AstFragment::make_* called on the wrong kind of fragment"), + _ => panic!("AstFragment::{} called on the wrong kind of fragment", stringify!($make_ast)), } })* @@ -149,8 +134,7 @@ macro_rules! ast_fragments { *opt_expr = vis.filter_map_expr(expr) } } - AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr), - $($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)* + $($(AstFragment::$Kind(ast) => vis.$visit_ast(ast),)?)* $($(AstFragment::$Kind(ast) => ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast, $($args)*)),)?)* } @@ -160,27 +144,11 @@ macro_rules! ast_fragments { match self { AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)), AstFragment::OptExpr(None) => {} - AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)), $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)* $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)* } V::Result::output() } - - pub(crate) fn to_string(&self) -> String { - match self { - AstFragment::OptExpr(Some(expr)) => pprust::expr_to_string(expr), - AstFragment::OptExpr(None) => unreachable!(), - AstFragment::MethodReceiverExpr(expr) => pprust::expr_to_string(expr), - $($(AstFragment::$Kind(ast) => $ast_to_string(ast),)?)* - $($( - AstFragment::$Kind(ast) => { - // The closure unwraps a `P` if present, or does nothing otherwise. - elems_to_string(&*ast, |ast| $ast_to_string_elt(&*ast)) - } - )?)* - } - } } impl<'a, 'b> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a, 'b> { @@ -195,94 +163,97 @@ macro_rules! ast_fragments { ast_fragments! { Expr(Box) { "expression"; - one fn visit_expr; fn visit_expr; fn pprust::expr_to_string; + one fn visit_expr; fn make_expr; } + MethodReceiverExpr(Box) { + "expression"; + one fn visit_method_receiver_expr; + fn make_method_receiver_expr; + } Pat(Box) { "pattern"; - one fn visit_pat; fn visit_pat; fn pprust::pat_to_string; + one fn visit_pat; fn make_pat; } Ty(Box) { "type"; - one fn visit_ty; fn visit_ty; fn pprust::ty_to_string; + one fn visit_ty; fn make_ty; } Stmts(SmallVec<[ast::Stmt; 1]>) { "statement"; - many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string; + many fn flat_map_stmt; fn visit_stmt(); fn make_stmts; } Items(SmallVec<[Box; 1]>) { "item"; - many fn flat_map_item; fn visit_item(); fn pprust::item_to_string; + many fn flat_map_item; fn visit_item(); fn make_items; } TraitItems(SmallVec<[Box; 1]>) { "trait item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait); - fn pprust::assoc_item_to_string; fn make_trait_items; } ImplItems(SmallVec<[Box; 1]>) { "impl item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false }); - fn pprust::assoc_item_to_string; fn make_impl_items; } TraitImplItems(SmallVec<[Box; 1]>) { "impl item"; many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true }); - fn pprust::assoc_item_to_string; fn make_trait_impl_items; } ForeignItems(SmallVec<[Box; 1]>) { "foreign item"; - many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string; + many fn flat_map_foreign_item; fn visit_foreign_item(); fn make_foreign_items; } Arms(SmallVec<[ast::Arm; 1]>) { "match arm"; - many fn flat_map_arm; fn visit_arm(); fn unreachable_to_string; + many fn flat_map_arm; fn visit_arm(); fn make_arms; } ExprFields(SmallVec<[ast::ExprField; 1]>) { "field expression"; - many fn flat_map_expr_field; fn visit_expr_field(); fn unreachable_to_string; + many fn flat_map_expr_field; fn visit_expr_field(); fn make_expr_fields; } PatFields(SmallVec<[ast::PatField; 1]>) { "field pattern"; - many fn flat_map_pat_field; fn visit_pat_field(); fn unreachable_to_string; + many fn flat_map_pat_field; fn visit_pat_field(); fn make_pat_fields; } GenericParams(SmallVec<[ast::GenericParam; 1]>) { "generic parameter"; - many fn flat_map_generic_param; fn visit_generic_param(); fn unreachable_to_string; + many fn flat_map_generic_param; fn visit_generic_param(); fn make_generic_params; } Params(SmallVec<[ast::Param; 1]>) { "function parameter"; - many fn flat_map_param; fn visit_param(); fn unreachable_to_string; + many fn flat_map_param; fn visit_param(); fn make_params; } FieldDefs(SmallVec<[ast::FieldDef; 1]>) { "field"; - many fn flat_map_field_def; fn visit_field_def(); fn unreachable_to_string; + many fn flat_map_field_def; fn visit_field_def(); fn make_field_defs; } Variants(SmallVec<[ast::Variant; 1]>) { - "variant"; many fn flat_map_variant; fn visit_variant(); fn unreachable_to_string; + "variant"; + many fn flat_map_variant; fn visit_variant(); fn make_variants; } WherePredicates(SmallVec<[ast::WherePredicate; 1]>) { "where predicate"; - many fn flat_map_where_predicate; fn visit_where_predicate(); fn unreachable_to_string; + many fn flat_map_where_predicate; fn visit_where_predicate(); fn make_where_predicates; } Crate(ast::Crate) { "crate"; - one fn visit_crate; fn visit_crate; fn unreachable_to_string; + one fn visit_crate; fn make_crate; } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index eed13a13fa911..cb22ad136645b 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -23,7 +23,8 @@ use rustc_lint_defs::builtin::{ use rustc_parse::exp; use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; -use rustc_session::parse::{ParseSess, feature_err}; +use rustc_session::errors::feature_err; +use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol, kw, sym}; diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 92d19820848b4..443a17287d734 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::Applicability; use rustc_feature::Features; use rustc_session::Session; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, kw, sym}; diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs index 0d60141f274ec..d7bd5329da8b3 100644 --- a/compiler/rustc_expand/src/stats.rs +++ b/compiler/rustc_expand/src/stats.rs @@ -32,8 +32,34 @@ pub(crate) fn elems_to_string(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> Str s } -pub(crate) fn unreachable_to_string(_: &T) -> String { - unreachable!() +fn fragment_to_string(fragment: &AstFragment) -> String { + match fragment { + AstFragment::OptExpr(Some(expr)) + | AstFragment::MethodReceiverExpr(expr) + | AstFragment::Expr(expr) => pprust::expr_to_string(expr), + AstFragment::Pat(ast) => pprust::pat_to_string(ast), + AstFragment::Ty(ast) => pprust::ty_to_string(ast), + AstFragment::Stmts(ast) => elems_to_string(ast, pprust::stmt_to_string), + AstFragment::Items(ast) => elems_to_string(ast, |ast| pprust::item_to_string(ast)), + AstFragment::TraitItems(ast) + | AstFragment::ImplItems(ast) + | AstFragment::TraitImplItems(ast) => { + elems_to_string(ast, |ast| pprust::assoc_item_to_string(ast)) + } + AstFragment::ForeignItems(ast) => { + elems_to_string(ast, |ast| pprust::foreign_item_to_string(ast)) + } + AstFragment::OptExpr(None) + | AstFragment::Crate(_) + | AstFragment::Arms(_) + | AstFragment::ExprFields(_) + | AstFragment::PatFields(_) + | AstFragment::GenericParams(_) + | AstFragment::Params(_) + | AstFragment::FieldDefs(_) + | AstFragment::Variants(_) + | AstFragment::WherePredicates(_) => unreachable!(), + } } pub(crate) fn update_bang_macro_stats( @@ -98,7 +124,7 @@ pub(crate) fn update_attr_macro_stats( let input = format!( "{}\n{}", pprust::attribute_to_string(attr), - fragment_kind.expect_from_annotatables(iter::once(item)).to_string(), + fragment_to_string(&fragment_kind.expect_from_annotatables(iter::once(item))), ); update_macro_stats(ecx, MacroKind::Attr, fragment_kind, span, path, &input, fragment); } @@ -129,7 +155,7 @@ pub(crate) fn update_macro_stats( // Measure the size of the output by pretty-printing it and counting // the lines and bytes. let name = Symbol::intern(&pprust::path_to_string(path)); - let output = fragment.to_string(); + let output = fragment_to_string(fragment); let num_lines = output.trim_end().split('\n').count(); let num_bytes = output.len(); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e1f562ca3a59b..d77031564db5d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -420,6 +420,9 @@ declare_features! ( (unstable, bpf_target_feature, "1.54.0", Some(150247)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), + /// Allows defining c-variadic functions on targets where this feature has not yet + /// undergone sufficient testing for stabilization. + (unstable, c_variadic_experimental_arch, "CURRENT_RUSTC_VERSION", Some(155973)), /// Allows defining c-variadic naked functions with any extern ABI that is allowed /// on c-variadic foreign functions. (unstable, c_variadic_naked_functions, "1.93.0", Some(148767)), @@ -750,6 +753,8 @@ declare_features! ( (internal, unsized_fn_params, "1.49.0", Some(48055)), /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. (unstable, used_with_arg, "1.60.0", Some(93798)), + /// Allows view types. + (unstable, view_types, "CURRENT_RUSTC_VERSION", Some(155938)), /// Target features on wasm. (unstable, wasm_target_feature, "1.30.0", Some(150260)), /// Allows use of attributes in `where` clauses. diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index fcdbb11b297c1..3225e00b24b26 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -92,7 +92,7 @@ use rustc_middle::ty::{ Unnormalized, }; use rustc_middle::{bug, span_bug}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -312,7 +312,7 @@ fn default_body_is_unstable( }); let inject_span = item_did.is_local().then(|| tcx.crate_level_attribute_injection_span()); - rustc_session::parse::add_feature_diagnostics_for_issue( + rustc_session::errors::add_feature_diagnostics_for_issue( &mut err, &tcx.sess, feature, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 05d16d2ddb49c..d0277d2e24264 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -27,7 +27,7 @@ use rustc_middle::ty::{ Unnormalized, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::regions::{InferCtxtRegionExt, OutlivesEnvironmentBuildExt}; diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 07ad5db47b6d8..05a9f68131819 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -11,7 +11,7 @@ use rustc_hir::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, elaborate}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{ErrorGuaranteed, sym}; use tracing::debug; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3a2f3948f0abc..d8cf13db265fd 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1272,7 +1272,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async() && !self.tcx.features().anonymous_lifetime_in_impl_trait() { - let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err( + let mut diag: rustc_errors::Diag<'_> = rustc_session::errors::feature_err( &self.tcx.sess, sym::anonymous_lifetime_in_impl_trait, lifetime_ref.ident.span, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 41b1ec91e0e75..3ac603fc715f3 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -505,7 +505,7 @@ fn infer_placeholder_type<'tcx>( fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { if !tcx.features().inherent_associated_types() { - use rustc_session::parse::feature_err; + use rustc_session::errors::feature_err; use rustc_span::sym; feature_err( &tcx.sess, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 0aa478f99200b..5e11819805e15 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{ self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_param, }; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5096e5ef76f0d..75ea42a38ff4c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -43,8 +43,8 @@ use rustc_middle::ty::{ const_lit_matches_ty, fold_regions, }; use rustc_middle::{bug, span_bug}; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc_session::parse::feature_err; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::wf::object_region_bounds; diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0721bfcab519a..9cadaef8f886b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -89,7 +89,7 @@ use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; use rustc_middle::{middle, ty}; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 71c02dc32f6b5..664c3c457876c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -30,8 +30,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TypeVisitableExt, Unnormalized}; use rustc_middle::{bug, span_bug}; -use rustc_session::errors::ExprParenthesesNeeded; -use rustc_session::parse::feature_err; +use rustc_session::errors::{ExprParenthesesNeeded, feature_err}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; use rustc_span::{Ident, Span, Spanned, Symbol, kw, sym}; @@ -3767,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block); if !self.tcx.features().offset_of_enum() { - rustc_session::parse::feature_err( + rustc_session::errors::feature_err( &self.tcx.sess, sym::offset_of_enum, ident.span, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 5a4cd6d24a8b6..d7f15222376c8 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -21,8 +21,8 @@ use rustc_infer::infer::RegionVariableOrigin; use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt, Unnormalized}; use rustc_middle::{bug, span_bug}; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; -use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym}; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 38d899853cd5b..feb32cbc81807 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -39,8 +39,8 @@ use rustc_resolve::{Resolver, ResolverOutputs}; use rustc_session::Session; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; +use rustc_session::errors::feature_err; use rustc_session::output::{filename_for_input, invalid_output_for_target}; -use rustc_session::parse::feature_err; use rustc_session::search_paths::PathKind; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym, @@ -1016,9 +1016,24 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); - let res = f(tcx); - // FIXME maybe run finish even when a fatal error occurred? or at least - // tcx.alloc_self_profile_query_strings()? + // There are two paths out of `f`. + // - Normal exit. + // - Panic, e.g. triggered by `abort_if_errors` or a fatal error. + // + // If a panic occurs, we still need to wind down the self-profiler to correctly record + // the query events that are still in flight. Otherwise, they will be invalid and will + // show up as "" in the profiling data. + let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(tcx))); + let res = match res { + Ok(res) => res, + Err(err) => { + tcx.alloc_self_profile_query_strings(); + + // Resume unwinding if a panic happened. + std::panic::resume_unwind(err); + } + }; + tcx.finish(); res }, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 2b859b65c9f8f..0c308e18b1533 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -966,7 +966,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let mut lint = Diag::new(dcx, level, msg!("unknown lint: `{$name}`")) .with_arg("name", lint_id.lint.name_lower()) .with_note(msg!("the `{$name}` lint is unstable")); - rustc_session::parse::add_feature_diagnostics_for_issue( + rustc_session::errors::add_feature_diagnostics_for_issue( &mut lint, sess, feature, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1e3ce972a3667..6d9f486f627f6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -306,7 +306,7 @@ impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op") .with_span_label(self.label, "this function will not propagate the caller location"); - rustc_session::parse::add_feature_diagnostics( + rustc_session::errors::add_feature_diagnostics( &mut diag, self.session, sym::async_fn_track_caller, diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs index 03ea396a42c75..9affbf5f1583b 100644 --- a/compiler/rustc_macros/src/lift.rs +++ b/compiler/rustc_macros/src/lift.rs @@ -34,16 +34,19 @@ pub(super) fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To let bindings = &vi.bindings(); vi.construct(|_, index| { let bi = &bindings[index]; - quote! { __tcx.lift(#bi)? } + quote! { __tcx.lift(#bi) } }) }); s.add_impl_generic(newtcx); - s.bound_impl(quote!(::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>), quote! { - type Lifted = #lifted; + s.bound_impl( + quote!(::rustc_middle::ty::Lift<::rustc_middle::ty::TyCtxt<'__lifted>>), + quote! { + type Lifted = #lifted; - fn lift_to_interner(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> Option<#lifted> { - Some(match self { #body }) - } - }) + fn lift_to_interner(self, __tcx: ::rustc_middle::ty::TyCtxt<'__lifted>) -> #lifted { + match self { #body } + } + }, + ) } diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 0ae774ebee795..3d0971ed1ffd9 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -46,8 +46,8 @@ macro_rules! TrivialLiftImpls { $( impl<'tcx> $crate::ty::Lift<$crate::ty::TyCtxt<'tcx>> for $ty { type Lifted = Self; - fn lift_to_interner(self, _: $crate::ty::TyCtxt<'tcx>) -> Option { - Some(self) + fn lift_to_interner(self, _: $crate::ty::TyCtxt<'tcx>) -> Self { + self } } )+ diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index f9821c92df369..2c59517847370 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -11,9 +11,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, ConstStability, DefaultBodyStability, HirId, Stability}; use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; use rustc_session::Session; +use rustc_session::errors::feature_err_issue; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE}; use rustc_session::lint::{DeprecatedSinceKind, Level, Lint}; -use rustc_session::parse::feature_err_issue; use rustc_span::{Span, Symbol, sym}; use tracing::debug; diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index de3ef6deca1fc..c3dd68fdd9187 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -493,7 +493,7 @@ impl<'tcx> Display for Const<'tcx> { // FIXME(valtrees): Correctly print mir constants. Const::Unevaluated(c, _ty) => { ty::tls::with(move |tcx| { - let c = tcx.lift(c).unwrap(); + let c = tcx.lift(c); // Matches `GlobalId` printing. let instance = with_no_trimmed_paths!(tcx.def_path_str_with_args(c.def, c.args)); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index d160aada80a83..c59e6b6fa2151 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1165,7 +1165,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Adt(adt_did, variant, args, _user_ty, _) => { ty::tls::with(|tcx| { let variant_def = &tcx.adt_def(adt_did).variant(variant); - let args = tcx.lift(args).expect("could not lift for printing"); + let args = tcx.lift(args); let name = FmtPrinter::print_string(tcx, Namespace::ValueNS, |p| { p.print_def_path(variant_def.def_id, args) })?; @@ -1187,7 +1187,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Closure(def_id, args) | AggregateKind::CoroutineClosure(def_id, args) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { - let args = tcx.lift(args).unwrap(); + let args = tcx.lift(args); format!("{{closure@{}}}", tcx.def_path_str_with_args(def_id, args),) } else { let span = tcx.def_span(def_id); @@ -1911,8 +1911,6 @@ fn pretty_print_const_value_tcx<'tcx>( // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` // to be able to destructure the tuple into `(0u8, *mut T)` (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { - let ct = tcx.lift(ct).unwrap(); - let ty = tcx.lift(ty).unwrap(); if let Some(contents) = tcx.try_destructure_mir_constant_for_user_output(ct, ty) { let fields: Vec<(ConstValue, Ty<'_>)> = contents.fields.to_vec(); match *ty.kind() { @@ -1937,7 +1935,6 @@ fn pretty_print_const_value_tcx<'tcx>( .variant .expect("destructed mir constant of adt without variant idx"); let variant_def = &def.variant(variant_idx); - let args = tcx.lift(args).unwrap(); let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); p.print_alloc_ids = true; p.pretty_print_value_path(variant_def.def_id, args)?; @@ -1974,7 +1971,6 @@ fn pretty_print_const_value_tcx<'tcx>( (ConstValue::Scalar(scalar), _) => { let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); p.print_alloc_ids = true; - let ty = tcx.lift(ty).unwrap(); p.pretty_print_const_scalar(scalar, ty)?; fmt.write_str(&p.into_buffer())?; return Ok(()); @@ -2000,8 +1996,7 @@ pub(crate) fn pretty_print_const_value<'tcx>( fmt: &mut Formatter<'_>, ) -> fmt::Result { ty::tls::with(|tcx| { - let ct = tcx.lift(ct).unwrap(); - let ty = tcx.lift(ty).unwrap(); + let ty = tcx.lift(ty); pretty_print_const_value_tcx(tcx, ct, ty, fmt) }) } diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 50242613b3e7f..8866860661c41 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -238,9 +238,8 @@ impl<'tcx> rustc_type_ir::inherent::ValueConst> for Value<'tcx> { impl<'tcx> fmt::Display for Value<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(move |tcx| { - let cv = tcx.lift(*self).unwrap(); let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); - p.pretty_print_const_valtree(cv, /*print_ty*/ true)?; + p.pretty_print_const_valtree(tcx.lift(*self), /*print_ty*/ true)?; f.write_str(&p.into_buffer()) }) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2e9708483a85b..b1927e190f033 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -958,7 +958,7 @@ impl<'tcx> TyCtxt<'tcx> { (start, end) } - pub fn lift>>(self, value: T) -> Option { + pub fn lift>>(self, value: T) -> T::Lifted { value.lift_to_interner(self) } @@ -1689,7 +1689,8 @@ macro_rules! nop_lift { ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift> for $ty { type Lifted = $lifted; - fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option { + #[track_caller] + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { // Assert that the set has the right type. // Given an argument that has an interned type, the return type has the type of // the corresponding interner set. This won't actually return anything, we're @@ -1709,12 +1710,10 @@ macro_rules! nop_lift { _type_eq(&interner, &tcx.interners.$set); } - tcx.interners - .$set - .contains_pointer_to(&InternedInSet(&*self.0.0)) - // SAFETY: `self` is interned and therefore valid - // for the entire lifetime of the `TyCtxt`. - .then(|| unsafe { mem::transmute(self) }) + assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0))); + // SAFETY: we just checked that `self` is interned and therefore is valid for the + // entire lifetime of the `TyCtxt`. + unsafe { mem::transmute(self) } } } }; @@ -1724,19 +1723,19 @@ macro_rules! nop_list_lift { ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift> for &'a List<$ty> { type Lifted = &'tcx List<$lifted>; - fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option { + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { // Assert that the set has the right type. if false { let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set; } if self.is_empty() { - return Some(List::empty()); + return List::empty(); } - tcx.interners - .$set - .contains_pointer_to(&InternedInSet(self)) - .then(|| unsafe { mem::transmute(self) }) + assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(self))); + // SAFETY: we just checked that `self` is interned and therefore is valid for the + // entire lifetime of the `TyCtxt`. + unsafe { mem::transmute(self) } } } }; diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index a4c30f1f88434..082e5de16cf98 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -223,10 +223,8 @@ impl<'tcx> TyCtxt<'tcx> { T: Copy + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { let mut type_limit = 50; - let regular = FmtPrinter::print_string(self, ns, |p| { - self.lift(t).expect("could not lift for printing").print(p) - }) - .expect("could not write to `String`"); + let regular = FmtPrinter::print_string(self, ns, |p| self.lift(t).print(p)) + .expect("could not write to `String`"); if regular.len() <= length_limit { return regular; } @@ -235,10 +233,7 @@ impl<'tcx> TyCtxt<'tcx> { // Look for the longest properly trimmed path that still fits in length_limit. short = with_forced_trimmed_paths!({ let mut p = FmtPrinter::new_with_limit(self, ns, Limit(type_limit)); - self.lift(t) - .expect("could not lift for printing") - .print(&mut p) - .expect("could not print type"); + self.lift(t).print(&mut p).expect("could not print type"); p.into_buffer() }); if short.len() <= length_limit || type_limit == 0 { @@ -273,10 +268,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: Copy + Hash + for<'a, 'b> Lift, Lifted: Print<'b, FmtPrinter<'a, 'b>>>, { - let regular = FmtPrinter::print_string(self, namespace, |p| { - self.lift(t).expect("could not lift for printing").print(p) - }) - .expect("could not write to `String`"); + let regular = FmtPrinter::print_string(self, namespace, |p| self.lift(t).print(p)) + .expect("could not write to `String`"); if !self.sess.opts.unstable_opts.write_long_types_to_disk || self.sess.opts.verbose { return regular; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index daeabf24d749f..c57c0851d8a49 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -320,11 +320,11 @@ impl<'tcx> GenericArg<'tcx> { impl<'a, 'tcx> Lift> for GenericArg<'a> { type Lifted = GenericArg<'tcx>; - fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option { + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { match self.kind() { - GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()), - GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()), - GenericArgKind::Const(ct) => tcx.lift(ct).map(|ct| ct.into()), + GenericArgKind::Lifetime(lt) => tcx.lift(lt).into(), + GenericArgKind::Type(ty) => tcx.lift(ty).into(), + GenericArgKind::Const(ct) => tcx.lift(ct).into(), } } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 408edf19dbf23..8166053f9bd5f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -381,8 +381,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); - let instance = tcx.lift(*self).expect("could not lift for printing"); - instance.print(&mut p)?; + tcx.lift(*self).print(&mut p)?; let s = p.into_buffer(); f.write_str(&s) }) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index d2ae226c4d8dc..d5d1c3634c7d1 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -418,7 +418,7 @@ where fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { ty::tls::with(|tcx| { let mut p = FmtPrinter::new(tcx, Namespace::TypeNS); - tcx.lift(*t).expect("could not lift for printing").print(&mut p)?; + tcx.lift(*t).print(&mut p)?; fmt.write_str(&p.into_buffer())?; Ok(()) }) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f997e49868ba8..04d76e4304fe9 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2082,10 +2082,9 @@ pub(crate) fn pretty_print_const<'tcx>( print_types: bool, ) -> fmt::Result { ty::tls::with(|tcx| { - let literal = tcx.lift(c).unwrap(); let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); p.print_alloc_ids = true; - p.pretty_print_const(literal, print_types)?; + p.pretty_print_const(tcx.lift(c), print_types)?; fmt.write_str(&p.into_buffer())?; Ok(()) }) @@ -3098,7 +3097,6 @@ macro_rules! forward_display_to_print { ty::tls::with(|tcx| { let mut p = FmtPrinter::new(tcx, Namespace::TypeNS); tcx.lift(*self) - .expect("could not lift for printing") .print(&mut p)?; f.write_str(&p.into_buffer())?; Ok(()) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 29b784e837954..bc53fc18b41b6 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -271,20 +271,17 @@ TrivialTypeTraversalAndLiftImpls! { impl<'tcx, T: Lift>> Lift> for Option { type Lifted = Option; - fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option { - Some(match self { - Some(x) => Some(tcx.lift(x)?), - None => None, - }) + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { + self.map(|x| tcx.lift(x)) } } impl<'a, 'tcx> Lift> for Term<'a> { type Lifted = ty::Term<'tcx>; - fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option { + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { match self.kind() { - TermKind::Ty(ty) => tcx.lift(ty).map(Into::into), - TermKind::Const(c) => tcx.lift(c).map(Into::into), + TermKind::Ty(ty) => tcx.lift(ty).into(), + TermKind::Const(c) => tcx.lift(c).into(), } } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 072975f445bf4..b5151cf20ab02 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -19,7 +19,7 @@ use crate::errors::{ NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow, }; use crate::parser::item::FrontMatterParsingMode; -use crate::parser::{FnContext, FnParseMode}; +use crate::parser::{ExpTokenPair, FnContext, FnParseMode}; use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; /// Signals whether parsing a type should allow `+`. @@ -768,6 +768,25 @@ impl<'a> Parser<'a> { self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; + if self.token == TokenKind::Dot && self.look_ahead(1, |t| t.kind == TokenKind::OpenBrace) { + // & [mut] . { } + // ^ + // we are here + let view_start_span = self.token.span; + self.bump(); + let fields = self + .parse_delim_comma_seq( + ExpTokenPair { tok: TokenKind::OpenBrace, token_type: TokenType::OpenBrace }, + ExpTokenPair { tok: TokenKind::CloseBrace, token_type: TokenType::CloseBrace }, + |p| p.parse_ident(), + )? + .0; + // FIXME(scrabsha): actually propagate field view in the AST. + let _ = fields; + let view_end_span = self.prev_token.span; + let span = view_start_span.to(view_end_span); + self.psess.gated_spans.gate(sym::view_types, span); + } Ok(match pinned { Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }), Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }), diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 831199a59a432..2817cf3020ff9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -36,12 +36,12 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized}; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; +use rustc_session::errors::feature_err; use rustc_session::lint; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; -use rustc_session::parse::feature_err; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index dc41bb1f687fe..165ad737fccb8 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -49,9 +49,9 @@ impl RustcInternal for DefId { fn internal<'tcx>( &self, tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, + _tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.def_ids[*self]).unwrap() + tables.def_ids[*self] } } @@ -78,7 +78,7 @@ impl RustcInternal for GenericArgKind { GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(), GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(), }; - tcx.lift(arg).unwrap() + arg } } @@ -101,7 +101,7 @@ impl RustcInternal for Ty { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.types[*self]).unwrap() + tcx.lift(tables.types[*self]) } } @@ -112,7 +112,7 @@ impl RustcInternal for TyConst { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.ty_consts[self.id]).unwrap() + tcx.lift(tables.ty_consts[self.id]) } } @@ -316,11 +316,10 @@ impl RustcInternal for FnSig { .set_abi(self.abi.internal(tables, tcx)) .set_safety(self.safety.internal(tables, tcx)) .set_c_variadic(self.c_variadic); - tcx.lift(rustc_ty::FnSig { + rustc_ty::FnSig { inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)), fn_sig_kind, - }) - .unwrap() + } } } @@ -358,16 +357,13 @@ impl RustcInternal for MirConst { let constant = tables.mir_consts[self.id]; match constant { rustc_middle::mir::Const::Ty(ty, ct) => { - rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap()) + rustc_middle::mir::Const::Ty(tcx.lift(ty), tcx.lift(ct)) } rustc_middle::mir::Const::Unevaluated(uneval, ty) => { - rustc_middle::mir::Const::Unevaluated( - tcx.lift(uneval).unwrap(), - tcx.lift(ty).unwrap(), - ) + rustc_middle::mir::Const::Unevaluated(tcx.lift(uneval), tcx.lift(ty)) } rustc_middle::mir::Const::Val(const_val, ty) => { - rustc_middle::mir::Const::Val(tcx.lift(const_val).unwrap(), tcx.lift(ty).unwrap()) + rustc_middle::mir::Const::Val(tcx.lift(const_val), tcx.lift(ty)) } } } @@ -400,7 +396,7 @@ impl RustcInternal for Instance { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.instances[self.def]).unwrap() + tcx.lift(tables.instances[self.def]) } } @@ -553,9 +549,9 @@ impl RustcInternal for AllocId { fn internal<'tcx>( &self, tables: &mut Tables<'_, BridgeTys>, - tcx: impl InternalCx<'tcx>, + _tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.alloc_ids[*self]).unwrap() + tables.alloc_ids[*self] } } @@ -691,7 +687,7 @@ impl RustcInternal for Layout { tables: &mut Tables<'_, BridgeTys>, tcx: impl InternalCx<'tcx>, ) -> Self::T<'tcx> { - tcx.lift(tables.layouts[*self]).unwrap() + tcx.lift(tables.layouts[*self]) } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index d8c4cee7abbe4..56fbd8108786a 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -58,7 +58,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - tables.layout_id(cx.lift(*self).unwrap()) + tables.layout_id(cx.lift(*self)) } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index 0d04053aab76b..2bc23e2837048 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -864,7 +864,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - let id = tables.intern_mir_const(cx.lift(*self).unwrap()); + let id = tables.intern_mir_const(cx.lift(*self)); match *self { mir::Const::Ty(ty, c) => MirConst::new( crate::ty::ConstantKind::Ty(c.stable(tables, cx)), @@ -885,8 +885,8 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { MirConst::new(ConstantKind::ZeroSized, ty, id) } mir::Const::Val(val, ty) => { - let ty = cx.lift(ty).unwrap(); - let val = cx.lift(val).unwrap(); + let ty = cx.lift(ty); + let val = cx.lift(val); let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx)); let ty = ty.stable(tables, cx); MirConst::new(kind, ty, id) diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 4c4a51f7444bb..80453d838b880 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -408,7 +408,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - tables.intern_ty(cx.lift(*self).unwrap()) + tables.intern_ty(cx.lift(*self)) } } @@ -526,7 +526,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - let ct = cx.lift(*self).unwrap(); + let ct = cx.lift(*self); let kind = match ct.kind() { ty::ConstKind::Value(cv) => { let const_val = cx.valtree_to_const_val(cv); @@ -967,7 +967,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { - let def = tables.instance_def(cx.lift(*self).unwrap()); + let def = tables.instance_def(cx.lift(*self)); let kind = match self.def { ty::InstanceKind::Item(..) => crate::mir::mono::InstanceKind::Item, ty::InstanceKind::Intrinsic(..) => crate::mir::mono::InstanceKind::Intrinsic, diff --git a/compiler/rustc_public/src/unstable/internal_cx/mod.rs b/compiler/rustc_public/src/unstable/internal_cx/mod.rs index 161f2754bed87..f178ced7224c1 100644 --- a/compiler/rustc_public/src/unstable/internal_cx/mod.rs +++ b/compiler/rustc_public/src/unstable/internal_cx/mod.rs @@ -44,7 +44,7 @@ impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { self } - fn lift>>(self, value: T) -> Option { + fn lift>>(self, value: T) -> T::Lifted { TyCtxt::lift(self, value) } diff --git a/compiler/rustc_public/src/unstable/mod.rs b/compiler/rustc_public/src/unstable/mod.rs index ec979eef40cd1..8c20a54018553 100644 --- a/compiler/rustc_public/src/unstable/mod.rs +++ b/compiler/rustc_public/src/unstable/mod.rs @@ -26,7 +26,7 @@ mod internal_cx; pub trait InternalCx<'tcx>: Copy + Clone { fn tcx(self) -> TyCtxt<'tcx>; - fn lift>>(self, value: T) -> Option; + fn lift>>(self, value: T) -> T::Lifted; fn mk_args_from_iter(self, iter: I) -> T::Output where diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index bb504bd0017a0..260b9cd2198cf 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -53,7 +53,7 @@ impl<'tcx, B: Bridge> AllocRangeHelpers<'tcx> for CompilerCtxt<'tcx, B> { } impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> { - pub fn lift>>(&self, value: T) -> Option { + pub fn lift>>(&self, value: T) -> T::Lifted { self.tcx.lift(value) } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 723890a2f1ca2..b60bfc3be4ebc 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -605,12 +605,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span, label: None, refer_to_type_directly: None, + use_let: None, sugg: None, static_or_const, is_self, - item: inner_item.as_ref().map(|(span, kind)| { + item: inner_item.as_ref().map(|(label_span, _, kind)| { errs::GenericParamsFromOuterItemInnerItem { - span: *span, + span: *label_span, descr: kind.descr().to_string(), is_self, } @@ -618,10 +619,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let sm = self.tcx.sess.source_map(); + // Note: do not early return for missing def_id here, + // we still want to provide suggestions for `Res::SelfTyParam` and `Res::SelfTyAlias`. let def_id = match outer_res { Res::SelfTyParam { .. } => { err.label = Some(Label::SelfTyParam(span)); - return self.dcx().create_err(err); + None } Res::SelfTyAlias { alias_to: def_id, .. } => { err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword( @@ -630,15 +633,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ))); err.refer_to_type_directly = current_self_ty.map(|snippet| errs::UseTypeDirectly { span, snippet }); - return self.dcx().create_err(err); + None } Res::Def(DefKind::TyParam, def_id) => { err.label = Some(Label::TyParam(self.def_span(def_id))); - def_id + Some(def_id) } Res::Def(DefKind::ConstParam, def_id) => { err.label = Some(Label::ConstParam(self.def_span(def_id))); - def_id + Some(def_id) } _ => { bug!( @@ -649,8 +652,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; - if let HasGenericParams::Yes(span) = has_generic_params - && !matches!(inner_item, Some((_, ItemKind::Delegation(..)))) + if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() { + err.use_let = Some(errs::GenericParamsFromOuterItemUseLet { + span: sm.span_until_whitespace(*item_span), + }); + } + + if let Some(def_id) = def_id + && let HasGenericParams::Yes(span) = has_generic_params + && !matches!(inner_item, Some((_, _, ItemKind::Delegation(..)))) { let name = self.tcx.item_name(def_id); let (span, snippet) = if span.is_empty() { @@ -2152,6 +2162,111 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()` } + /// Returns the path segments (as symbols) of a module, including `kw::Crate` at the start. + /// For example, for `crate::foo::bar`, returns `[Crate, foo, bar]`. + /// Returns `None` for block modules that don't have a `DefId`. + fn module_path_names(&self, module: Module<'ra>) -> Option> { + let mut path = Vec::new(); + let mut def_id = module.opt_def_id()?; + while let Some(parent) = self.tcx.opt_parent(def_id) { + if let Some(name) = self.tcx.opt_item_name(def_id) { + path.push(name); + } + if parent.is_top_level_module() { + break; + } + def_id = parent; + } + path.reverse(); + path.insert(0, kw::Crate); + Some(path) + } + + /// Shortens a candidate import path to use `super::` (up to 1 level) or `self::` (same module) + /// relative to the current scope, if possible. Only applies to crate-local items and + /// only when the resulting path is actually shorter than the original. + fn shorten_candidate_path( + &self, + suggestion: &mut ImportSuggestion, + current_module: Module<'ra>, + ) { + const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1; + + // Only shorten local items. + if suggestion.did.is_none_or(|did| !did.is_local()) { + return; + } + + // Build current module path: [Crate, foo, bar, ...]. + let Some(current_mod_path) = self.module_path_names(current_module) else { + return; + }; + + // Normalise candidate path: filter out `PathRoot` (`::`), and if the path + // doesn't start with `Crate`, prepend it (edition 2015 paths are relative + // to the crate root without an explicit `crate::` prefix). + let candidate_names = { + let filtered_segments: Vec<_> = suggestion + .path + .segments + .iter() + .filter(|segment| segment.ident.name != kw::PathRoot) + .collect(); + + let mut candidate_names: Vec = + filtered_segments.iter().map(|segment| segment.ident.name).collect(); + if candidate_names.first() != Some(&kw::Crate) { + candidate_names.insert(0, kw::Crate); + } + if candidate_names.len() < 2 { + return; + } + candidate_names + }; + + // The candidate's module path is everything except the last segment (the item name). + let candidate_mod_names = &candidate_names[..candidate_names.len() - 1]; + + // Find the longest common prefix between the current module and candidate module paths. + let common_prefix_length = current_mod_path + .iter() + .zip(candidate_mod_names.iter()) + .take_while(|(current, candidate)| current == candidate) + .count(); + + // Non-crate-local item; keep the full absolute path. + if common_prefix_length == 0 { + return; + } + + let super_count = current_mod_path.len() - common_prefix_length; + + // At the crate root, `use` paths resolve from the crate root anyway, so we can + // drop the `crate::` prefix entirely instead of replacing it with `self::`. + let at_crate_root = current_mod_path.len() == 1; + + let mut new_segments = if super_count == 0 && at_crate_root { + ThinVec::new() + } else { + let prefix_keyword = match super_count { + 0 => kw::SelfLower, + 1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super, + _ => return, // Too many `super` levels; keep the full absolute path. + }; + thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword),)] + }; + for &name in &candidate_names[common_prefix_length..] { + new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name))); + } + + // Only apply if the result is strictly shorter than the original path. + if new_segments.len() >= suggestion.path.segments.len() { + return; + } + + suggestion.path = Path { span: suggestion.path.span, segments: new_segments, tokens: None }; + } + fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) { let PrivacyError { ident, @@ -2180,12 +2295,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut not_publicly_reexported = false; if let Some((this_res, outer_ident)) = outermost_res { - let import_suggestions = self.lookup_import_candidates( + let mut import_suggestions = self.lookup_import_candidates( outer_ident, this_res.ns().unwrap_or(Namespace::TypeNS), &parent_scope, &|res: Res| res == this_res, ); + // Shorten candidate paths using `super::` or `self::` when possible. + for suggestion in &mut import_suggestions { + self.shorten_candidate_path(suggestion, parent_scope.module); + } let point_to_def = !show_candidates( self.tcx, &mut err, diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 9f26fc076e57f..342484a8c0d51 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -32,6 +32,8 @@ pub(crate) struct GenericParamsFromOuterItem { #[subdiagnostic] pub(crate) refer_to_type_directly: Option, #[subdiagnostic] + pub(crate) use_let: Option, + #[subdiagnostic] pub(crate) sugg: Option, #[subdiagnostic] pub(crate) static_or_const: Option, @@ -86,6 +88,19 @@ pub(crate) struct GenericParamsFromOuterItemSugg { pub(crate) span: Span, pub(crate) snippet: String, } + +#[derive(Subdiagnostic)] +#[suggestion( + "try using a local `let` binding instead", + code = "let", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct GenericParamsFromOuterItemUseLet { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Subdiagnostic)] #[suggestion( "refer to the type directly here instead", diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5fae50041a02d..658e36083b0ad 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -6,8 +6,8 @@ use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; use rustc_middle::{bug, span_bug}; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; -use rustc_session::parse::feature_err; use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; use rustc_span::{Ident, Span, kw, sym}; @@ -1589,12 +1589,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let item = if let Some(diag_metadata) = diag_metadata && let Some(current_item) = diag_metadata.current_item { - let span = current_item + let label_span = current_item .kind .ident() .map(|i| i.span) .unwrap_or(current_item.span); - Some((span, current_item.kind.clone())) + Some((label_span, current_item.span, current_item.kind.clone())) } else { None }; @@ -1683,12 +1683,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let item = if let Some(diag_metadata) = diag_metadata && let Some(current_item) = diag_metadata.current_item { - let span = current_item + let label_span = current_item .kind .ident() .map(|i| i.span) .unwrap_or(current_item.span); - Some((span, current_item.kind.clone())) + Some((label_span, current_item.span, current_item.kind.clone())) } else { None }; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 2695655278fb4..360c14afa8ba6 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -18,11 +18,11 @@ use rustc_hir::def_id::{DefId, LocalDefIdMap}; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::span_bug; use rustc_middle::ty::{TyCtxt, Visibility}; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; -use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; use rustc_span::{Ident, Span, Symbol, kw, sym}; @@ -1292,6 +1292,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for error in &mut self.privacy_errors[privacy_errors_len..] { error.outermost_res = res; } + } else { + // The final item is not a module (e.g., a struct, function, or macro). + // Resolve it directly in the parent module to get its Res, so + // `report_privacy_error()` can search for public re-export paths. + for ns in [TypeNS, ValueNS, MacroNS] { + if let Ok(binding) = self.cm().resolve_ident_in_module( + module, + ident, + ns, + &import.parent_scope, + None, + ignore_decl, + None, + ) { + let res = binding.res(); + for error in &mut self.privacy_errors[privacy_errors_len..] { + error.outermost_res = Some((res, ident)); + } + break; + } + } } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6eb5fe17bc169..014a472c2c1bb 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -32,8 +32,8 @@ use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; +use rustc_session::errors::feature_err; use rustc_session::lint; -use rustc_session::parse::feature_err; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Spanned, Symbol, kw, respan, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4d86da95e3fa8..c733299154ab7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -248,7 +248,8 @@ enum ResolutionError<'ra> { outer_res: Res, has_generic_params: HasGenericParams, def_kind: DefKind, - inner_item: Option<(Span, ast::ItemKind)>, + /// 1. label span, 2. item span, 3. item kind + inner_item: Option<(Span, Span, ast::ItemKind)>, current_self_ty: Option, }, /// Error E0403: the name is already used for a type or const parameter in this generic diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dc20d4fcf36b7..998cf27a85de1 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -23,11 +23,11 @@ use rustc_hir::{Attribute, StabilityLevel}; use rustc_middle::middle::stability; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::{ LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACRO_RULES, UNUSED_MACROS, }; -use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 54f88aa22bdc4..bc4c5e98282a5 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -5,14 +5,179 @@ use rustc_ast::util::literal::LitError; use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level, - MultiSpan, + MultiSpan, StashKey, }; +use rustc_feature::{GateIssue, find_feature_issue}; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::{Span, Symbol}; +use rustc_span::{Span, Symbol, sym}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple}; +use crate::Session; +use crate::lint::builtin::UNSTABLE_SYNTAX_PRE_EXPANSION; use crate::parse::ParseSess; +/// Construct a diagnostic for a language feature error due to the given `span`. +/// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbol`. +#[track_caller] +pub fn feature_err( + sess: &Session, + feature: Symbol, + span: impl Into, + explain: impl Into, +) -> Diag<'_> { + feature_err_issue(sess, feature, span, GateIssue::Language, explain) +} + +/// Construct a diagnostic for a feature gate error. +/// +/// This variant allows you to control whether it is a library or language feature. +/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`. +#[track_caller] +pub fn feature_err_issue( + sess: &Session, + feature: Symbol, + span: impl Into, + issue: GateIssue, + explain: impl Into, +) -> Diag<'_> { + let span = span.into(); + + // Cancel an earlier warning for this same error, if it exists. + if let Some(span) = span.primary_span() + && let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) + { + err.cancel() + } + + let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() }); + add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None); + err +} + +/// Construct a future incompatibility diagnostic for a feature gate. +/// +/// This diagnostic is only a warning and *does not cause compilation to fail*. +#[track_caller] +pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) { + feature_warn_issue(sess, feature, span, GateIssue::Language, explain); +} + +/// Construct a future incompatibility diagnostic for a feature gate. +/// +/// This diagnostic is only a warning and *does not cause compilation to fail*. +/// +/// This variant allows you to control whether it is a library or language feature. +/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`. +#[track_caller] +pub fn feature_warn_issue( + sess: &Session, + feature: Symbol, + span: Span, + issue: GateIssue, + explain: &'static str, +) { + let mut err = sess.dcx().struct_span_warn(span, explain); + add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None); + + // Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level + let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; + let future_incompatible = lint.future_incompatible.as_ref().unwrap(); + err.is_lint(lint.name_lower(), /* has_future_breakage */ false); + err.warn(lint.desc); + err.note(format!("for more information, see {}", future_incompatible.reason.reference())); + + // A later feature_err call can steal and cancel this warning. + err.stash(span, StashKey::EarlySyntaxWarning); +} + +/// Adds the diagnostics for a feature to an existing error. +/// Must be a language feature! +pub fn add_feature_diagnostics( + err: &mut Diag<'_, G>, + sess: &Session, + feature: Symbol, +) { + add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None); +} + +/// Adds the diagnostics for a feature to an existing error. +/// +/// This variant allows you to control whether it is a library or language feature. +/// Almost always, you want to use this for a language feature. If so, prefer +/// `add_feature_diagnostics`. +pub fn add_feature_diagnostics_for_issue( + err: &mut Diag<'_, G>, + sess: &Session, + feature: Symbol, + issue: GateIssue, + feature_from_cli: bool, + inject_span: Option, +) { + if let Some(n) = find_feature_issue(feature, issue) { + err.subdiagnostic(FeatureDiagnosticForIssue { n }); + } + + // #23973: do not suggest `#![feature(...)]` if we are in beta/stable + if sess.unstable_features.is_nightly_build() { + if feature_from_cli { + err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); + } else if let Some(span) = inject_span { + err.subdiagnostic(FeatureDiagnosticSuggestion { feature, span }); + } else { + err.subdiagnostic(FeatureDiagnosticHelp { feature }); + } + if feature == sym::rustc_attrs { + // We're unlikely to stabilize something out of `rustc_attrs` + // without at least renaming it, so pointing out how old + // the compiler is will do little good. + } else if sess.opts.unstable_opts.ui_testing { + err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { + err.subdiagnostic(suggestion); + } + } +} + +/// This is only used by unstable_feature_bound as it does not have issue number information for now. +/// This is basically the same as `feature_err_issue` +/// but without the feature issue note. If we can do a lookup for issue number from feature name, +/// then we should directly use `feature_err_issue` for ambiguity error of +/// `#[unstable_feature_bound]`. +#[track_caller] +pub fn feature_err_unstable_feature_bound( + sess: &Session, + feature: Symbol, + span: impl Into, + explain: impl Into, +) -> Diag<'_> { + let span = span.into(); + + // Cancel an earlier warning for this same error, if it exists. + if let Some(span) = span.primary_span() { + if let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) { + err.cancel() + } + } + + let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() }); + + // #23973: do not suggest `#![feature(...)]` if we are in beta/stable + if sess.unstable_features.is_nightly_build() { + err.subdiagnostic(FeatureDiagnosticHelp { feature }); + + if feature == sym::rustc_attrs { + // We're unlikely to stabilize something out of `rustc_attrs` + // without at least renaming it, so pointing out how old + // the compiler is will do little good. + } else if sess.opts.unstable_opts.ui_testing { + err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { + err.subdiagnostic(suggestion); + } + } + err +} + #[derive(Diagnostic)] pub(crate) enum AppleDeploymentTarget { #[diag("failed to parse deployment target specified in {$env_var}: {$error}")] diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index c09e3eed37125..54058e9f5f046 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -1,7 +1,6 @@ //! Contains `ParseSess` which holds state living beyond what one `Parser` might. //! It also serves as an input to the parser itself. -use std::str; use std::sync::Arc; use rustc_ast::attr::AttrIdGenerator; @@ -11,21 +10,15 @@ use rustc_data_structures::sync::{AppendOnlyVec, DynSend, DynSync, Lock}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{EmitterWithNote, stderr_destination}; use rustc_errors::{ - BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle, - DiagMessage, EmissionGuarantee, Level, MultiSpan, StashKey, + BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle, Level, + MultiSpan, }; -use rustc_feature::{GateIssue, find_feature_issue}; use rustc_span::edition::Edition; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{FilePathMapping, SourceMap}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol}; use crate::Session; -use crate::errors::{ - CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, - FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler, -}; -use crate::lint::builtin::UNSTABLE_SYNTAX_PRE_EXPANSION; use crate::lint::{Lint, LintId}; /// Collected spans during parsing for places where a certain feature was @@ -78,169 +71,6 @@ impl SymbolGallery { } } -// FIXME: this function now accepts `Session` instead of `ParseSess` and should be relocated -/// Construct a diagnostic for a language feature error due to the given `span`. -/// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbol`. -#[track_caller] -pub fn feature_err( - sess: &Session, - feature: Symbol, - span: impl Into, - explain: impl Into, -) -> Diag<'_> { - feature_err_issue(sess, feature, span, GateIssue::Language, explain) -} - -/// Construct a diagnostic for a feature gate error. -/// -/// This variant allows you to control whether it is a library or language feature. -/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`. -#[track_caller] -pub fn feature_err_issue( - sess: &Session, - feature: Symbol, - span: impl Into, - issue: GateIssue, - explain: impl Into, -) -> Diag<'_> { - let span = span.into(); - - // Cancel an earlier warning for this same error, if it exists. - if let Some(span) = span.primary_span() - && let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) - { - err.cancel() - } - - let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() }); - add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None); - err -} - -/// Construct a future incompatibility diagnostic for a feature gate. -/// -/// This diagnostic is only a warning and *does not cause compilation to fail*. -#[track_caller] -pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) { - feature_warn_issue(sess, feature, span, GateIssue::Language, explain); -} - -/// Construct a future incompatibility diagnostic for a feature gate. -/// -/// This diagnostic is only a warning and *does not cause compilation to fail*. -/// -/// This variant allows you to control whether it is a library or language feature. -/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`. -#[track_caller] -pub fn feature_warn_issue( - sess: &Session, - feature: Symbol, - span: Span, - issue: GateIssue, - explain: &'static str, -) { - let mut err = sess.dcx().struct_span_warn(span, explain); - add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None); - - // Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level - let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; - let future_incompatible = lint.future_incompatible.as_ref().unwrap(); - err.is_lint(lint.name_lower(), /* has_future_breakage */ false); - err.warn(lint.desc); - err.note(format!("for more information, see {}", future_incompatible.reason.reference())); - - // A later feature_err call can steal and cancel this warning. - err.stash(span, StashKey::EarlySyntaxWarning); -} - -/// Adds the diagnostics for a feature to an existing error. -/// Must be a language feature! -pub fn add_feature_diagnostics( - err: &mut Diag<'_, G>, - sess: &Session, - feature: Symbol, -) { - add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None); -} - -/// Adds the diagnostics for a feature to an existing error. -/// -/// This variant allows you to control whether it is a library or language feature. -/// Almost always, you want to use this for a language feature. If so, prefer -/// `add_feature_diagnostics`. -pub fn add_feature_diagnostics_for_issue( - err: &mut Diag<'_, G>, - sess: &Session, - feature: Symbol, - issue: GateIssue, - feature_from_cli: bool, - inject_span: Option, -) { - if let Some(n) = find_feature_issue(feature, issue) { - err.subdiagnostic(FeatureDiagnosticForIssue { n }); - } - - // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { - if feature_from_cli { - err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); - } else if let Some(span) = inject_span { - err.subdiagnostic(FeatureDiagnosticSuggestion { feature, span }); - } else { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); - } - if feature == sym::rustc_attrs { - // We're unlikely to stabilize something out of `rustc_attrs` - // without at least renaming it, so pointing out how old - // the compiler is will do little good. - } else if sess.opts.unstable_opts.ui_testing { - err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); - } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { - err.subdiagnostic(suggestion); - } - } -} - -/// This is only used by unstable_feature_bound as it does not have issue number information for now. -/// This is basically the same as `feature_err_issue` -/// but without the feature issue note. If we can do a lookup for issue number from feature name, -/// then we should directly use `feature_err_issue` for ambiguity error of -/// `#[unstable_feature_bound]`. -#[track_caller] -pub fn feature_err_unstable_feature_bound( - sess: &Session, - feature: Symbol, - span: impl Into, - explain: impl Into, -) -> Diag<'_> { - let span = span.into(); - - // Cancel an earlier warning for this same error, if it exists. - if let Some(span) = span.primary_span() { - if let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) { - err.cancel() - } - } - - let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() }); - - // #23973: do not suggest `#![feature(...)]` if we are in beta/stable - if sess.unstable_features.is_nightly_build() { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); - - if feature == sym::rustc_attrs { - // We're unlikely to stabilize something out of `rustc_attrs` - // without at least renaming it, so pointing out how old - // the compiler is will do little good. - } else if sess.opts.unstable_opts.ui_testing { - err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); - } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { - err.subdiagnostic(suggestion); - } - } - err -} - /// Info about a parsing session. pub struct ParseSess { dcx: DiagCtxt, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6c04a39063e34..5491e89f57f79 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -45,7 +45,7 @@ use crate::config::{ }; use crate::filesearch::FileSearch; use crate::lint::LintId; -use crate::parse::{ParseSess, add_feature_diagnostics}; +use crate::parse::ParseSess; use crate::search_paths::SearchPath; use crate::{errors, filesearch, lint}; @@ -282,7 +282,7 @@ impl Session { if err.code.is_none() { err.code(E0658); } - add_feature_diagnostics(&mut err, self, feature); + errors::add_feature_diagnostics(&mut err, self, feature); err } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index caeb923c18f78..702c3c54101c3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -548,6 +548,7 @@ symbols! { c_str_literals, c_unwind, c_variadic, + c_variadic_experimental_arch, c_variadic_naked_functions, c_void, call, @@ -2232,6 +2233,7 @@ symbols! { verbatim, version, vfp2, + view_types, vis, visible_private_types, volatile, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 209cece71f873..b910779537f38 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -47,7 +47,8 @@ use std::str::FromStr; use std::{fmt, io}; use rustc_abi::{ - Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutError, + Align, CVariadicStatus, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, + TargetDataLayoutError, }; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_error_messages::{DiagArgValue, IntoDiagArg, into_diag_arg_using_display}; @@ -2208,10 +2209,13 @@ impl Target { Ok(dl) } - pub fn supports_c_variadic_definitions(&self) -> bool { + pub fn supports_c_variadic_definitions(&self) -> CVariadicStatus { use Arch::*; match self.arch { + // These targets just inherently do not support c-variadic definitions. + Bpf | SpirV => CVariadicStatus::NotSupported, + // The c-variadic ABI for this target may change in the future, per this comment in // clang: // @@ -2219,19 +2223,40 @@ impl Target { // > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`, // > `unsigned long long` and `double` to have 4-byte alignment. This // > behavior may be changed when RV32E/ILP32E is ratified. - RiscV32 if self.llvm_abiname == LlvmAbi::Ilp32e => false, - - // These targets just do not support c-variadic definitions. - Bpf | SpirV => false, + RiscV32 if self.llvm_abiname == LlvmAbi::Ilp32e => { + CVariadicStatus::Unstable { feature: sym::c_variadic_experimental_arch } + } // We don't know how c-variadics work for this target. Using the default LLVM - // fallback implementation may work, but just to be safe we disallow this. - Other(_) => false, + // fallback implementation probably works, but we can't guarantee it. + Other(_) => CVariadicStatus::Unstable { feature: sym::c_variadic_experimental_arch }, - AArch64 | AmdGpu | Arm | Arm64EC | Avr | CSky | Hexagon | LoongArch32 | LoongArch64 - | M68k | Mips | Mips32r6 | Mips64 | Mips64r6 | Msp430 | Nvptx64 | PowerPC - | PowerPC64 | RiscV32 | RiscV64 | S390x | Sparc | Sparc64 | Wasm32 | Wasm64 | X86 - | X86_64 | Xtensa => true, + // These targets require more testing before we commit to c-variadic definitions + // being stable. + // + // To stabilize c-variadic functions for one of these targets, the following + // requirements must be met: + // + // - Check that `core::ffi::VaArgSafe` is (un)implemented for all the correct types. + // - Add an assembly test to `tests/assembly-llvm/c-variadic` that tests the assembly + // for all implementers of `VaArgSafe`. The generated assembly should either match + // `clang`, or we should understand and document why it deviates. + // - Ensure that `va_arg` is implemented in rustc. For stable targets we don't rely on + // the LLVM implementation, it has historically caused miscompilations. + // - The `tests/ui/c-variadic/roundtrip.rs` test must pass for the target. It may + // need slight modifications for embedded targets, that's fine. + // - Check that calling c-variadic functions defined in Rust can be called from C. + // For most targets `tests/run-make/c-link-to-rust-va-list-fn` can be used here. + // For no_std targets a manual setup may be needed. + Sparc | Avr | M68k | Msp430 => { + CVariadicStatus::Unstable { feature: sym::c_variadic_experimental_arch } + } + + AArch64 | AmdGpu | Arm | Arm64EC | CSky | Hexagon | LoongArch32 | LoongArch64 + | Mips | Mips32r6 | Mips64 | Mips64r6 | Nvptx64 | PowerPC | PowerPC64 | RiscV32 + | RiscV64 | S390x | Sparc64 | Wasm32 | Wasm64 | X86 | X86_64 | Xtensa => { + CVariadicStatus::Stable + } } } } diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index c11edf7c618c2..b936a2ba2570d 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { llvm_abiname: LlvmAbi::Ilp32d, max_atomic_width: Some(32), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "\u{1}_mcount".into(), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs index f9a7d307c74a3..74a8a88dff674 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { llvm_abiname: LlvmAbi::Lp64d, max_atomic_width: Some(64), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "\u{1}_mcount".into(), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index 76c9ad65700c2..f362e694db4d2 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { llvm_abiname: LlvmAbi::Lp64d, max_atomic_width: Some(64), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "\u{1}_mcount".into(), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 1a308ee334d3b..108262d507ef7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -13,7 +13,7 @@ use rustc_infer::traits::{ }; use rustc_middle::ty::print::PrintPolyTraitPredicateExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _, Unnormalized}; -use rustc_session::parse::feature_err_unstable_feature_bound; +use rustc_session::errors::feature_err_unstable_feature_bound; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 66a2fcaa562d1..57b14e93e277c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{ self, GenericArgsRef, Term, TermKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_session::parse::feature_err; +use rustc_session::errors::feature_err; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{Span, sym}; use tracing::{debug, instrument, trace}; diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 79dff2ffbbce9..b45832744f82f 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -45,11 +45,11 @@ where { type Lifted = Binder; - fn lift_to_interner(self, cx: U) -> Option { - Some(Binder { - value: self.value.lift_to_interner(cx)?, - bound_vars: self.bound_vars.lift_to_interner(cx)?, - }) + fn lift_to_interner(self, cx: U) -> Self::Lifted { + Binder { + value: self.value.lift_to_interner(cx), + bound_vars: self.bound_vars.lift_to_interner(cx), + } } } @@ -991,12 +991,12 @@ where { type Lifted = Placeholder; - fn lift_to_interner(self, cx: U) -> Option { - Some(Placeholder { + fn lift_to_interner(self, cx: U) -> Self::Lifted { + Placeholder { universe: self.universe, - bound: self.bound.lift_to_interner(cx)?, + bound: self.bound.lift_to_interner(cx), _tcx: PhantomData, - }) + } } } @@ -1186,8 +1186,8 @@ where { type Lifted = BoundTy; - fn lift_to_interner(self, cx: U) -> Option { - Some(BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx)? }) + fn lift_to_interner(self, cx: U) -> Self::Lifted { + BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx) } } } diff --git a/compiler/rustc_type_ir/src/lift.rs b/compiler/rustc_type_ir/src/lift.rs index e5a099d1f5042..739d3a8512329 100644 --- a/compiler/rustc_type_ir/src/lift.rs +++ b/compiler/rustc_type_ir/src/lift.rs @@ -9,13 +9,13 @@ /// It would be more efficient if `TypedArena` provided a way to /// determine whether the address is in the allocated range. /// -/// `None` is returned if the value or one of the components is not part +/// Panics if the value or one of the components is not part /// of the provided context. -/// For `Ty`, `None` can be returned if either the type interner doesn't +/// For `Ty`, this can happen if either the type interner doesn't /// contain the `TyKind` key or if the address of the interned /// pointer differs. The latter case is possible if a primitive type, /// e.g., `()` or `u8`, was interned in a different context. pub trait Lift: std::fmt::Debug { type Lifted: std::fmt::Debug; - fn lift_to_interner(self, cx: I) -> Option; + fn lift_to_interner(self, cx: I) -> Self::Lifted; } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index fa03cec596549..b419a871f37d2 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -35,8 +35,8 @@ where { type Lifted = OutlivesPredicate; - fn lift_to_interner(self, cx: U) -> Option { - Some(OutlivesPredicate(self.0.lift_to_interner(cx)?, self.1.lift_to_interner(cx)?)) + fn lift_to_interner(self, cx: U) -> Self::Lifted { + OutlivesPredicate(self.0.lift_to_interner(cx), self.1.lift_to_interner(cx)) } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index dd893a9288703..c5078115870c4 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -782,8 +782,8 @@ pub struct FnSigKind { impl crate::lift::Lift for FnSigKind { type Lifted = FnSigKind; - fn lift_to_interner(self, _cx: J) -> Option { - Some(FnSigKind { flags: self.flags, _marker: PhantomData }) + fn lift_to_interner(self, _cx: J) -> Self::Lifted { + FnSigKind { flags: self.flags, _marker: PhantomData } } } diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index 8df10b6a9eccd..7ea8bd384e3cf 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -168,7 +168,7 @@ fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift }); let bind = &bindings[index]; quote! { - #bind.lift_to_interner(interner)? + #bind.lift_to_interner(interner) } }) }); @@ -189,8 +189,8 @@ fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { fn lift_to_interner( self, interner: J, - ) -> Option { - Some(match self { #body_fold }) + ) -> Self::Lifted { + match self { #body_fold } } }, ) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 45061a02e7525..eb1dee2e16d7b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1492,7 +1492,7 @@ impl LinkCollector<'_, '_> { Some((sp, _)) => sp, None => item.attr_span(self.cx.tcx), }; - rustc_session::parse::feature_err( + rustc_session::errors::feature_err( self.cx.tcx.sess, sym::intra_doc_pointers, span, diff --git a/tests/codegen-llvm/double_panic_wasm.rs b/tests/codegen-llvm/double_panic_wasm.rs new file mode 100644 index 0000000000000..1eafe60503809 --- /dev/null +++ b/tests/codegen-llvm/double_panic_wasm.rs @@ -0,0 +1,34 @@ +//@ compile-flags: -C panic=unwind -Copt-level=0 +//@ needs-unwind +//@ only-wasm32 + +#![crate_type = "lib"] + +// Test that `panic_in_cleanup` is called on webassembly targets when a panic +// occurs in a destructor during unwinding. + +extern "Rust" { + fn may_panic(); +} + +struct PanicOnDrop; + +impl Drop for PanicOnDrop { + fn drop(&mut self) { + unsafe { may_panic() } + } +} + +// CHECK-LABEL: @double_panic +// CHECK: invoke void @may_panic() +// CHECK: invoke void @{{.+}}drop_in_place{{.+}} +// CHECK: unwind label %[[TERMINATE:.*]] +// +// CHECK: [[TERMINATE]]: +// CHECK: call void @{{.*panic_in_cleanup}} +// CHECK: unreachable +#[no_mangle] +pub fn double_panic() { + let _guard = PanicOnDrop; + unsafe { may_panic() } +} diff --git a/tests/codegen-llvm/terminating-catchpad.rs b/tests/codegen-llvm/terminating-catchpad.rs index a2ec19871d1fc..7c98ea94fdc13 100644 --- a/tests/codegen-llvm/terminating-catchpad.rs +++ b/tests/codegen-llvm/terminating-catchpad.rs @@ -9,6 +9,10 @@ // Ensure a catch-all generates: // - `catchpad ... [ptr null]` on Wasm (otherwise LLVM gets confused) // - `catchpad ... [ptr null, i32 64, ptr null]` on Windows (otherwise we catch SEH exceptions) +// +// Unlike on windows, on Wasm, we specifically do want to catch foreign +// exceptions. To catch only C++ exceptions we'd need to call +// @llvm.wasm.get.exception and @llvm.wasm.get.ehselector in the catchpad. #![feature(no_core, lang_items, rustc_attrs)] #![crate_type = "lib"] @@ -36,8 +40,14 @@ fn panic_cannot_unwind() -> ! { #[no_mangle] #[rustc_nounwind] pub fn doesnt_unwind() { + // CHECK: catchswitch within none [label %{{.*}}] unwind to caller // emscripten: %catchpad = catchpad within %catchswitch [ptr null] // wasi: %catchpad = catchpad within %catchswitch [ptr null] // seh: %catchpad = catchpad within %catchswitch [ptr null, i32 64, ptr null] + // + // We don't call these intrinsics on wasm targets so we generate a catch_all + // instruction which also picks up foreign exceptions + // NOT: @llvm.wasm.get.exception + // NOT: @llvm.wasm.get.ehselector unwinds(); } diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs index a5df237b7fddc..b516bb1508ec4 100644 --- a/tests/run-make/print-cfg/rmake.rs +++ b/tests/run-make/print-cfg/rmake.rs @@ -48,6 +48,12 @@ fn main() { includes: &["unix", "target_abi=\"eabihf\""], disallow: &["windows"], }); + // Regression test for #90834: Android must not have `target_env="gnu"`. + check(PrintCfg { + target: "i686-linux-android", + includes: &["unix", "target_os=\"android\""], + disallow: &["windows", "target_env=\"gnu\""], + }); } fn check(PrintCfg { target, includes, disallow }: PrintCfg) { diff --git a/tests/ui/issues/issue-31769.rs b/tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.rs similarity index 70% rename from tests/ui/issues/issue-31769.rs rename to tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.rs index 354c1be9ed554..f295ecf302598 100644 --- a/tests/ui/issues/issue-31769.rs +++ b/tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.rs @@ -1,3 +1,4 @@ +//! Regression test for fn main() { #[inline] struct Foo; //~ ERROR attribute cannot be used on #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to a struct, enum, or union diff --git a/tests/ui/issues/issue-31769.stderr b/tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.stderr similarity index 77% rename from tests/ui/issues/issue-31769.stderr rename to tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.stderr index 0f75e84f2a704..fc8e22f171c20 100644 --- a/tests/ui/issues/issue-31769.stderr +++ b/tests/ui/attributes/dont-allow-inline-and-repr-at-invalid-positions.stderr @@ -1,5 +1,5 @@ error: `#[inline]` attribute cannot be used on structs - --> $DIR/issue-31769.rs:2:5 + --> $DIR/dont-allow-inline-and-repr-at-invalid-positions.rs:3:5 | LL | #[inline] struct Foo; | ^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[inline] struct Foo; = help: `#[inline]` can only be applied to functions error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-31769.rs:3:12 + --> $DIR/dont-allow-inline-and-repr-at-invalid-positions.rs:4:12 | LL | #[repr(C)] fn foo() {} | ^ ----------- not a struct, enum, or union diff --git a/tests/ui/issues/issue-33202.rs b/tests/ui/attributes/repr-on-single-variant-Enum.rs similarity index 67% rename from tests/ui/issues/issue-33202.rs rename to tests/ui/attributes/repr-on-single-variant-Enum.rs index 3fef98606afab..ab45c76ef5aae 100644 --- a/tests/ui/issues/issue-33202.rs +++ b/tests/ui/attributes/repr-on-single-variant-Enum.rs @@ -1,3 +1,4 @@ +//! Regression test for //@ run-pass #[repr(C)] pub enum CPOption { diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr new file mode 100644 index 0000000000000..df7697845814e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr @@ -0,0 +1,23 @@ +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.custom.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.custom.stderr new file mode 100644 index 0000000000000..fd9d7777a3886 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.custom.stderr @@ -0,0 +1,14 @@ +error: requires `va_list` lang_item + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:26:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + +error: requires `va_list` lang_item + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:30:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr new file mode 100644 index 0000000000000..df7697845814e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr @@ -0,0 +1,23 @@ +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr new file mode 100644 index 0000000000000..df7697845814e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr @@ -0,0 +1,23 @@ +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr new file mode 100644 index 0000000000000..df7697845814e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr @@ -0,0 +1,23 @@ +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs new file mode 100644 index 0000000000000..98b5f063d5844 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs @@ -0,0 +1,45 @@ +//@ add-minicore +//@ ignore-backends: gcc +// +//@ revisions: riscv32e sparc avr m68k msp430 +// +//@[riscv32e] compile-flags: --target riscv32e-unknown-none-elf +//@[riscv32e] needs-llvm-components: riscv +// +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +// +//@[avr] compile-flags: --target avr-none -Ctarget-cpu=atmega328p +//@[avr] needs-llvm-components: avr +// +//@[m68k] compile-flags: --target m68k-unknown-none-elf -Ctarget-cpu=M68020 +//@[m68k] needs-llvm-components: m68k +// +//@[msp430] compile-flags: --target msp430-none-elf -Ctarget-cpu=msp430 +//@[msp430] needs-llvm-components: msp430 +#![feature(no_core, lang_items, rustc_attrs, c_variadic)] +#![crate_type = "rlib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[repr(transparent)] +struct VaListInner { + ptr: *const c_void, +} + +#[repr(transparent)] +#[lang = "va_list"] +pub struct VaList<'a> { + inner: VaListInner, + _marker: PhantomData<&'a mut ()>, +} + +pub unsafe extern "C" fn test(_: i32, ap: ...) {} +//~^ ERROR C-variadic function definitions on this target are unstable + +trait Trait { + unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + //~^ ERROR C-variadic function definitions on this target are unstable +} diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr new file mode 100644 index 0000000000000..df7697845814e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr @@ -0,0 +1,23 @@ +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + | +LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: C-variadic function definitions on this target are unstable + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} + | ^^^^^^^ + | + = note: see issue #155973 for more information + = help: add `#![feature(c_variadic_experimental_arch)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-view-types.rs b/tests/ui/feature-gates/feature-gate-view-types.rs new file mode 100644 index 0000000000000..eb0c26d61db4a --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-view-types.rs @@ -0,0 +1,17 @@ +struct Foo { + a: usize, + b: usize, +} + +fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) { + //~^ ERROR view types are experimental + //~| ERROR view types are experimental + a.a += 1; + b.b += 1; +} + +fn main() { + let mut foo = Foo { a: 0, b: 0 }; + bar(&mut foo, &mut foo); + //~^ ERROR cannot borrow `foo` as mutable more than once at a time +} diff --git a/tests/ui/feature-gates/feature-gate-view-types.stderr b/tests/ui/feature-gates/feature-gate-view-types.stderr new file mode 100644 index 0000000000000..661783ec59202 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-view-types.stderr @@ -0,0 +1,33 @@ +error[E0658]: view types are experimental + --> $DIR/feature-gate-view-types.rs:6:19 + | +LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) { + | ^^^^^^ + | + = note: see issue #155938 for more information + = help: add `#![feature(view_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: view types are experimental + --> $DIR/feature-gate-view-types.rs:6:38 + | +LL | fn bar(a: &mut Foo.{ a }, b: &mut Foo.{ b }) { + | ^^^^^^ + | + = note: see issue #155938 for more information + = help: add `#![feature(view_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/feature-gate-view-types.rs:15:19 + | +LL | bar(&mut foo, &mut foo); + | --- -------- ^^^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0658. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/issues/issue-38763.rs b/tests/ui/foreign/foreign-fn-with-more-than-8-byte-arg-size.rs similarity index 72% rename from tests/ui/issues/issue-38763.rs rename to tests/ui/foreign/foreign-fn-with-more-than-8-byte-arg-size.rs index 87c758db1723c..4bd78a423cd2c 100644 --- a/tests/ui/issues/issue-38763.rs +++ b/tests/ui/foreign/foreign-fn-with-more-than-8-byte-arg-size.rs @@ -1,3 +1,4 @@ +//! Regression test for //@ run-pass //@ needs-threads diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index 0ebcf8e58d627..cb3836305c1ab 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -14,7 +14,9 @@ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:36:22 | LL | use crate::b::a::foo::S; - | ^^^ private module import + | ^^^ - struct `S` is not publicly re-exported + | | + | private module import | note: the module import `foo` is defined here... --> $DIR/reexports.rs:24:17 @@ -31,7 +33,9 @@ error[E0603]: module import `foo` is private --> $DIR/reexports.rs:37:22 | LL | use crate::b::b::foo::S as T; - | ^^^ private module import + | ^^^ - struct `S` is not publicly re-exported + | | + | private module import | note: the module import `foo` is defined here... --> $DIR/reexports.rs:29:17 diff --git a/tests/ui/imports/suggest-public-reexport-for-use.edition2015.stderr b/tests/ui/imports/suggest-public-reexport-for-use.edition2015.stderr new file mode 100644 index 0000000000000..815f91a0b6c8a --- /dev/null +++ b/tests/ui/imports/suggest-public-reexport-for-use.edition2015.stderr @@ -0,0 +1,119 @@ +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:27:12 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:28:12 + | +LL | use outer::inner::my_function; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL - use outer::inner::my_function; +LL + use outer::my_function; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:29:12 + | +LL | use outer::inner::MyTrait; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this trait through its public re-export instead + | +LL - use outer::inner::MyTrait; +LL + use outer::MyTrait; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:30:12 + | +LL | use outer::inner::MyEnum; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this enum through its public re-export instead + | +LL - use outer::inner::MyEnum; +LL + use outer::MyEnum; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:36:16 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:46:20 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `hidden` is private + --> $DIR/suggest-public-reexport-for-use.rs:60:18 + | +LL | use no_reexport::hidden::Secret; + | ^^^^^^ ------ struct `Secret` is not publicly re-exported + | | + | private module + | +note: the module `hidden` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:55:5 + | +LL | mod hidden { + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/suggest-public-reexport-for-use.edition2018.stderr b/tests/ui/imports/suggest-public-reexport-for-use.edition2018.stderr new file mode 100644 index 0000000000000..0295cb29ca3e2 --- /dev/null +++ b/tests/ui/imports/suggest-public-reexport-for-use.edition2018.stderr @@ -0,0 +1,119 @@ +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:27:12 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:28:12 + | +LL | use outer::inner::my_function; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL - use outer::inner::my_function; +LL + use outer::my_function; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:29:12 + | +LL | use outer::inner::MyTrait; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this trait through its public re-export instead + | +LL - use outer::inner::MyTrait; +LL + use outer::MyTrait; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:30:12 + | +LL | use outer::inner::MyEnum; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this enum through its public re-export instead + | +LL - use outer::inner::MyEnum; +LL + use outer::MyEnum; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:39:23 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:49:27 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `hidden` is private + --> $DIR/suggest-public-reexport-for-use.rs:60:18 + | +LL | use no_reexport::hidden::Secret; + | ^^^^^^ ------ struct `Secret` is not publicly re-exported + | | + | private module + | +note: the module `hidden` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:55:5 + | +LL | mod hidden { + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/suggest-public-reexport-for-use.edition2021.stderr b/tests/ui/imports/suggest-public-reexport-for-use.edition2021.stderr new file mode 100644 index 0000000000000..0295cb29ca3e2 --- /dev/null +++ b/tests/ui/imports/suggest-public-reexport-for-use.edition2021.stderr @@ -0,0 +1,119 @@ +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:27:12 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:28:12 + | +LL | use outer::inner::my_function; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL - use outer::inner::my_function; +LL + use outer::my_function; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:29:12 + | +LL | use outer::inner::MyTrait; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this trait through its public re-export instead + | +LL - use outer::inner::MyTrait; +LL + use outer::MyTrait; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:30:12 + | +LL | use outer::inner::MyEnum; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this enum through its public re-export instead + | +LL - use outer::inner::MyEnum; +LL + use outer::MyEnum; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:39:23 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:49:27 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `hidden` is private + --> $DIR/suggest-public-reexport-for-use.rs:60:18 + | +LL | use no_reexport::hidden::Secret; + | ^^^^^^ ------ struct `Secret` is not publicly re-exported + | | + | private module + | +note: the module `hidden` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:55:5 + | +LL | mod hidden { + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/suggest-public-reexport-for-use.edition2024.stderr b/tests/ui/imports/suggest-public-reexport-for-use.edition2024.stderr new file mode 100644 index 0000000000000..0295cb29ca3e2 --- /dev/null +++ b/tests/ui/imports/suggest-public-reexport-for-use.edition2024.stderr @@ -0,0 +1,119 @@ +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:27:12 + | +LL | use outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use outer::inner::MyStruct; +LL + use outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:28:12 + | +LL | use outer::inner::my_function; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL - use outer::inner::my_function; +LL + use outer::my_function; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:29:12 + | +LL | use outer::inner::MyTrait; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this trait through its public re-export instead + | +LL - use outer::inner::MyTrait; +LL + use outer::MyTrait; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:30:12 + | +LL | use outer::inner::MyEnum; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this enum through its public re-export instead + | +LL - use outer::inner::MyEnum; +LL + use outer::MyEnum; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:39:23 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `inner` is private + --> $DIR/suggest-public-reexport-for-use.rs:49:27 + | +LL | use crate::outer::inner::MyStruct; + | ^^^^^ private module + | +note: the module `inner` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:16:5 + | +LL | mod inner { + | ^^^^^^^^^ +help: consider importing this struct through its public re-export instead + | +LL - use crate::outer::inner::MyStruct; +LL + use crate::outer::MyStruct; + | + +error[E0603]: module `hidden` is private + --> $DIR/suggest-public-reexport-for-use.rs:60:18 + | +LL | use no_reexport::hidden::Secret; + | ^^^^^^ ------ struct `Secret` is not publicly re-exported + | | + | private module + | +note: the module `hidden` is defined here + --> $DIR/suggest-public-reexport-for-use.rs:55:5 + | +LL | mod hidden { + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/suggest-public-reexport-for-use.rs b/tests/ui/imports/suggest-public-reexport-for-use.rs new file mode 100644 index 0000000000000..1658735e36cf9 --- /dev/null +++ b/tests/ui/imports/suggest-public-reexport-for-use.rs @@ -0,0 +1,62 @@ +//@ revisions: edition2015 edition2018 edition2021 edition2024 +//@ [edition2015] edition:2015 +//@ [edition2018] edition:2018 +//@ [edition2021] edition:2021 +//@ [edition2024] edition:2024 + +// When a `use` statement accesses an item through a private module, +// the compiler should suggest a public re-export if one exists. + +mod outer { + pub use self::inner::MyStruct; + pub use self::inner::my_function; + pub use self::inner::MyTrait; + pub use self::inner::MyEnum; + + mod inner { + pub struct MyStruct; + pub fn my_function() {} + pub trait MyTrait {} + pub enum MyEnum { + Variant, + } + } +} + +// Accessing items through a private module should suggest the public re-export. +use outer::inner::MyStruct; //~ ERROR module `inner` is private +use outer::inner::my_function; //~ ERROR module `inner` is private +use outer::inner::MyTrait; //~ ERROR module `inner` is private +use outer::inner::MyEnum; //~ ERROR module `inner` is private + +// From a sibling module, the suggestion should keep the full path +// (shortening to `super::` would not reduce the segment count here). +mod sibling { + #[cfg(edition2015)] + use outer::inner::MyStruct; //[edition2015]~ ERROR module `inner` is private + + #[cfg(not(edition2015))] + use crate::outer::inner::MyStruct; //[edition2018,edition2021,edition2024]~ ERROR module `inner` is private +} + +// From a deeply nested module, the suggestion should keep the full path. +mod deep { + mod nested { + #[cfg(edition2015)] + use outer::inner::MyStruct; //[edition2015]~ ERROR module `inner` is private + + #[cfg(not(edition2015))] + use crate::outer::inner::MyStruct; //[edition2018,edition2021,edition2024]~ ERROR module `inner` is private + } +} + +// Items with no public re-export should say "not publicly re-exported". +mod no_reexport { + mod hidden { + pub struct Secret; + } +} + +use no_reexport::hidden::Secret; //~ ERROR module `hidden` is private + +fn main() {} diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index f62ef3ae2e4cc..5d1e003c703b4 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -4,6 +4,12 @@ error[E0603]: module `baz` is private LL | use bar::baz::{foo, bar}; | ^^^ private module | +help: consider importing this function through its public re-export instead: + bar::foo + --> $DIR/privacy1.rs:139:24 + | +LL | use bar::baz::{foo, bar}; + | ^^^ note: the module `baz` is defined here --> $DIR/privacy1.rs:57:5 | @@ -16,12 +22,17 @@ error[E0603]: module `baz` is private LL | use bar::baz::{foo, bar}; | ^^^ private module | +help: consider importing this function through its public re-export instead: + bar::bar + --> $DIR/privacy1.rs:139:29 + | +LL | use bar::baz::{foo, bar}; + | ^^^ note: the module `baz` is defined here --> $DIR/privacy1.rs:57:5 | LL | mod baz { | ^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0603]: module `baz` is private --> $DIR/privacy1.rs:148:18 @@ -39,7 +50,9 @@ error[E0603]: module `i` is private --> $DIR/privacy1.rs:172:20 | LL | use self::foo::i::A; - | ^ private module + | ^ - struct `A` is not publicly re-exported + | | + | private module | note: the module `i` is defined here --> $DIR/privacy1.rs:177:9 diff --git a/tests/ui/issues/issue-19001.rs b/tests/ui/recursion/recursive-struct-with-raw-pointer-field.rs similarity index 73% rename from tests/ui/issues/issue-19001.rs rename to tests/ui/recursion/recursive-struct-with-raw-pointer-field.rs index 51aebf88c95fb..97fa08fab1d93 100644 --- a/tests/ui/issues/issue-19001.rs +++ b/tests/ui/recursion/recursive-struct-with-raw-pointer-field.rs @@ -1,3 +1,4 @@ +//! Regression test for //@ run-pass #![allow(dead_code)] // check that we handle recursive arrays correctly in `type_of` diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index 8827d1bbb49d3..21f80198f1978 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -10,9 +10,14 @@ LL | const K: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const K: u32 = T::C; +LL + let K: u32 = T::C; + | error[E0401]: can't use generic parameters from outer item - --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 + --> $DIR/generic-params-from-outer-item-in-const-item.rs:20:24 | LL | impl Tr for T { // outer impl block | - type parameter from outer item @@ -24,9 +29,14 @@ LL | const I: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const I: u32 = T::C; +LL + let I: u32 = T::C; + | error[E0401]: can't use generic parameters from outer item - --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 + --> $DIR/generic-params-from-outer-item-in-const-item.rs:29:20 | LL | struct S(U32<{ // outer struct | - type parameter from outer item @@ -37,6 +47,11 @@ LL | const _: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const _: u32 = T::C; +LL + let _: u32 = T::C; + | error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 8ff9771b9ade6..54a53a097bcbe 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -10,13 +10,18 @@ LL | const K: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const K: u32 = T::C; +LL + let K: u32 = T::C; + | help: try introducing a local generic parameter here | LL | const K: u32 = T::C; | +++ error[E0401]: can't use generic parameters from outer item - --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 + --> $DIR/generic-params-from-outer-item-in-const-item.rs:20:24 | LL | impl Tr for T { // outer impl block | - type parameter from outer item @@ -28,13 +33,18 @@ LL | const I: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const I: u32 = T::C; +LL + let I: u32 = T::C; + | help: try introducing a local generic parameter here | LL | const I: u32 = T::C; | +++ error[E0401]: can't use generic parameters from outer item - --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 + --> $DIR/generic-params-from-outer-item-in-const-item.rs:29:20 | LL | struct S(U32<{ // outer struct | - type parameter from outer item @@ -45,6 +55,11 @@ LL | const _: u32 = T::C; | = note: nested items are independent from their parent item for everything except for privacy and name resolution = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const _: u32 = T::C; +LL + let _: u32 = T::C; + | help: try introducing a local generic parameter here | LL | const _: u32 = T::C; diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs index c9a64de7f6bba..9616144ec3103 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.rs @@ -11,6 +11,7 @@ fn outer() { // outer function const K: u32 = T::C; //~^ ERROR can't use generic parameters from outer item + //~| HELP try using a local `let` binding instead //[generic_const_items]~| HELP try introducing a local generic parameter here } @@ -18,6 +19,7 @@ impl Tr for T { // outer impl block const C: u32 = { const I: u32 = T::C; //~^ ERROR can't use generic parameters from outer item + //~| HELP try using a local `let` binding instead //[generic_const_items]~| HELP try introducing a local generic parameter here I }; @@ -26,6 +28,7 @@ impl Tr for T { // outer impl block struct S(U32<{ // outer struct const _: u32 = T::C; //~^ ERROR can't use generic parameters from outer item + //~| HELP try using a local `let` binding instead //[generic_const_items]~| HELP try introducing a local generic parameter here 0 }>); diff --git a/tests/ui/resolve/generic-params-from-outer-item-suggestion.fixed b/tests/ui/resolve/generic-params-from-outer-item-suggestion.fixed new file mode 100644 index 0000000000000..fea9f7a6f8516 --- /dev/null +++ b/tests/ui/resolve/generic-params-from-outer-item-suggestion.fixed @@ -0,0 +1,39 @@ +// Regression test for . +// Ensure we provide a suggestion to change from `const` to `let` +// on the generic params from outer item errors. + +//@ run-rustfix + +#![allow(unused, non_snake_case)] + +const fn size_plus_one() -> usize { + //~^ NOTE type parameter from outer item + let size: usize = core::mem::size_of::(); + //~^ ERROR can't use generic parameters from outer item + //~| NOTE nested items are independent + //~| NOTE a `const` is a separate item + //~| NOTE use of generic parameter from outer item + //~| NOTE generic parameter used in this inner constant item + //~| HELP try using a local `let` binding instead + size + 1 +} + +struct A; + +impl A { + //~^ NOTE `Self` type implicitly declared here, by this `impl` + const VALUE: u32 = 1; + + fn f() { + let K: u32 = A::VALUE; + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item + //~| NOTE `Self` used in this inner constant item + //~| NOTE nested items are independent + //~| NOTE a `const` is a separate item + //~| HELP refer to the type directly here instead + //~| HELP try using a local `let` binding instead + } +} + +fn main() {} diff --git a/tests/ui/resolve/generic-params-from-outer-item-suggestion.rs b/tests/ui/resolve/generic-params-from-outer-item-suggestion.rs new file mode 100644 index 0000000000000..3f87f3e2a2ae8 --- /dev/null +++ b/tests/ui/resolve/generic-params-from-outer-item-suggestion.rs @@ -0,0 +1,39 @@ +// Regression test for . +// Ensure we provide a suggestion to change from `const` to `let` +// on the generic params from outer item errors. + +//@ run-rustfix + +#![allow(unused, non_snake_case)] + +const fn size_plus_one() -> usize { + //~^ NOTE type parameter from outer item + const size: usize = core::mem::size_of::(); + //~^ ERROR can't use generic parameters from outer item + //~| NOTE nested items are independent + //~| NOTE a `const` is a separate item + //~| NOTE use of generic parameter from outer item + //~| NOTE generic parameter used in this inner constant item + //~| HELP try using a local `let` binding instead + size + 1 +} + +struct A; + +impl A { + //~^ NOTE `Self` type implicitly declared here, by this `impl` + const VALUE: u32 = 1; + + fn f() { + const K: u32 = Self::VALUE; + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item + //~| NOTE `Self` used in this inner constant item + //~| NOTE nested items are independent + //~| NOTE a `const` is a separate item + //~| HELP refer to the type directly here instead + //~| HELP try using a local `let` binding instead + } +} + +fn main() {} diff --git a/tests/ui/resolve/generic-params-from-outer-item-suggestion.stderr b/tests/ui/resolve/generic-params-from-outer-item-suggestion.stderr new file mode 100644 index 0000000000000..3d3280cfbbb4b --- /dev/null +++ b/tests/ui/resolve/generic-params-from-outer-item-suggestion.stderr @@ -0,0 +1,46 @@ +error[E0401]: can't use generic parameters from outer item + --> $DIR/generic-params-from-outer-item-suggestion.rs:11:46 + | +LL | const fn size_plus_one() -> usize { + | - type parameter from outer item +LL | +LL | const size: usize = core::mem::size_of::(); + | ---- ^ use of generic parameter from outer item + | | + | generic parameter used in this inner constant item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution + = note: a `const` is a separate item from the item that contains it +help: try using a local `let` binding instead + | +LL - const size: usize = core::mem::size_of::(); +LL + let size: usize = core::mem::size_of::(); + | + +error[E0401]: can't use `Self` from outer item + --> $DIR/generic-params-from-outer-item-suggestion.rs:28:24 + | +LL | impl A { + | ---- `Self` type implicitly declared here, by this `impl` +... +LL | const K: u32 = Self::VALUE; + | - ^^^^ use of `Self` from outer item + | | + | `Self` used in this inner constant item + | + = note: nested items are independent from their parent item for everything except for privacy and name resolution + = note: a `const` is a separate item from the item that contains it +help: refer to the type directly here instead + | +LL - const K: u32 = Self::VALUE; +LL + const K: u32 = A::VALUE; + | +help: try using a local `let` binding instead + | +LL - const K: u32 = Self::VALUE; +LL + let K: u32 = Self::VALUE; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/shadowed/shadowed-use-visibility.stderr b/tests/ui/shadowed/shadowed-use-visibility.stderr index b062341dc8be8..bbec8380fd032 100644 --- a/tests/ui/shadowed/shadowed-use-visibility.stderr +++ b/tests/ui/shadowed/shadowed-use-visibility.stderr @@ -14,6 +14,11 @@ note: ...and refers to the module `foo` which is defined here | LL | mod foo { | ^^^^^^^ +help: consider importing this function instead + | +LL - use crate::foo::bar::f as g; +LL + use foo::f as g; + | error[E0603]: module import `f` is private --> $DIR/shadowed-use-visibility.rs:15:10 @@ -31,6 +36,11 @@ note: ...and refers to the module `foo` which is defined here | LL | mod foo { | ^^^^^^^ +help: consider importing this function through its public re-export instead + | +LL - use bar::f::f; +LL + use bar::f; + | error: aborting due to 2 previous errors diff --git a/tests/ui/use/use-mod/use-mod-3.stderr b/tests/ui/use/use-mod/use-mod-3.stderr index 049b50e5b3b0f..17e5b4219de23 100644 --- a/tests/ui/use/use-mod/use-mod-3.stderr +++ b/tests/ui/use/use-mod/use-mod-3.stderr @@ -17,6 +17,8 @@ error[E0603]: module `bar` is private | LL | use foo::bar::{ | ^^^ private module +LL | Bar + | --- type alias `Bar` is not publicly re-exported | note: the module `bar` is defined here --> $DIR/use-mod-3.rs:9:5