diff --git a/Cargo.lock b/Cargo.lock index 96d9449db57c0..f51712e8e2cc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3595,6 +3595,7 @@ dependencies = [ "rustc_index", "rustc_infer", "rustc_lexer", + "rustc_macros", "rustc_middle", "rustc_mir_dataflow", "rustc_serialize", diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 0b531623ba6f5..8a35921d745cf 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -19,6 +19,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lexer = { path = "../rustc_lexer" } +rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 07f182102f346..1ef2b0ae98843 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -19,6 +19,9 @@ use std::fmt; use std::rc::Rc; use crate::region_infer::values::RegionElement; +use crate::session_diagnostics::HigherRankedErrorCause; +use crate::session_diagnostics::HigherRankedLifetimeError; +use crate::session_diagnostics::HigherRankedSubtypeError; use crate::MirBorrowckCtxt; #[derive(Clone)] @@ -69,7 +72,7 @@ impl<'tcx> UniverseInfo<'tcx> { // up in the existing UI tests. Consider investigating this // some more. mbcx.buffer_error( - mbcx.infcx.tcx.sess.struct_span_err(cause.span, "higher-ranked subtype error"), + mbcx.infcx.tcx.sess.create_err(HigherRankedSubtypeError { span: cause.span }), ); } } @@ -216,9 +219,12 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { tcx: TyCtxt<'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); - err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); - err + tcx.sess.create_err(HigherRankedLifetimeError { + cause: Some(HigherRankedErrorCause::CouldNotProve { + predicate: self.canonical_query.value.value.predicate.to_string(), + }), + span, + }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -263,9 +269,12 @@ where tcx: TyCtxt<'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); - err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value)); - err + tcx.sess.create_err(HigherRankedLifetimeError { + cause: Some(HigherRankedErrorCause::CouldNotNormalize { + value: self.canonical_query.value.value.value.to_string(), + }), + span, + }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -326,7 +335,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. - tcx.sess.struct_span_err(span, "higher-ranked lifetime error") + tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) } fn base_universe(&self) -> ty::UniverseIndex { @@ -366,7 +375,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. - tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!") + tcx.sess.create_err(HigherRankedLifetimeError { cause: None, span }) } fn base_universe(&self) -> ty::UniverseIndex { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e0f8da1c872d3..5d3997289bb33 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -24,6 +24,7 @@ use rustc_span::symbol::Ident; use rustc_span::Span; use crate::borrowck_errors; +use crate::session_diagnostics::GenericDoesNotLiveLongEnough; use super::{OutlivesSuggestionBuilder, RegionName}; use crate::region_infer::BlameConstraint; @@ -196,9 +197,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // to report it; we could probably handle it by // iterating over the universal regions and reporting // an error that multiple bounds are required. - self.buffer_error(self.infcx.tcx.sess.struct_span_err( - type_test_span, - &format!("`{}` does not live long enough", type_test.generic_kind), + self.buffer_error(self.infcx.tcx.sess.create_err( + GenericDoesNotLiveLongEnough { + kind: type_test.generic_kind.to_string(), + span: type_test_span, + }, )); } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a2df072aa3119..7d6f37340c2bb 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -76,6 +76,7 @@ mod places_conflict; mod prefixes; mod region_infer; mod renumber; +mod session_diagnostics; mod type_check; mod universal_regions; mod used_muts; diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs new file mode 100644 index 0000000000000..895723d44ff1b --- /dev/null +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -0,0 +1,44 @@ +use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; +use rustc_middle::ty::Ty; +use rustc_span::Span; + +#[derive(SessionDiagnostic)] +#[error(borrowck::move_unsized, code = "E0161")] +pub(crate) struct MoveUnsized<'tcx> { + pub ty: Ty<'tcx>, + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::higher_ranked_lifetime_error)] +pub(crate) struct HigherRankedLifetimeError { + #[subdiagnostic] + pub cause: Option<HigherRankedErrorCause>, + #[primary_span] + pub span: Span, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum HigherRankedErrorCause { + #[note(borrowck::could_not_prove)] + CouldNotProve { predicate: String }, + #[note(borrowck::could_not_normalize)] + CouldNotNormalize { value: String }, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::higher_ranked_subtype_error)] +pub(crate) struct HigherRankedSubtypeError { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(borrowck::generic_does_not_live_long_enough)] +pub(crate) struct GenericDoesNotLiveLongEnough { + pub kind: String, + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 542fc6b0f485d..5ee1f5a8e8e37 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -9,7 +9,6 @@ use hir::OpaqueTyOrigin; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::vec_map::VecMap; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -48,6 +47,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::ResultsCursor; +use crate::session_diagnostics::MoveUnsized; use crate::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, @@ -1780,19 +1780,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // slot or local, so to find all unsized rvalues it is enough // to check all temps, return slots and locals. if self.reported_errors.replace((ty, span)).is_none() { - let mut diag = struct_span_err!( - self.tcx().sess, - span, - E0161, - "cannot move a value of type {0}: the size of {0} \ - cannot be statically determined", - ty - ); - // While this is located in `nll::typeck` this error is not // an NLL error, it's a required check to prevent creation // of unsized rvalues in a call expression. - diag.emit(); + self.tcx().sess.emit_err(MoveUnsized { ty, span }); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 71699b5cf3830..551733e7abe93 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -103,14 +103,14 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { // for macOS to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. // Android has the same issue (#22398) - if let Some(version) = sess.target.dwarf_version { - llvm::LLVMRustAddModuleFlag( - self.llmod, - llvm::LLVMModFlagBehavior::Warning, - "Dwarf Version\0".as_ptr().cast(), - version, - ) - } + let dwarf_version = + sess.opts.debugging_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); + llvm::LLVMRustAddModuleFlag( + self.llmod, + llvm::LLVMModFlagBehavior::Warning, + "Dwarf Version\0".as_ptr().cast(), + dwarf_version, + ); // Indicate that we want CodeView debug information on MSVC if sess.target.is_like_msvc { diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index fb484fba9fd06..076415b2d1b2f 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -366,22 +366,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); - if def_a.is_box() || def_b.is_box() { - if !def_a.is_box() || !def_b.is_box() { - span_bug!( - self.cur_span(), - "invalid unsizing between {:?} -> {:?}", - src.layout.ty, - cast_ty.ty - ); - } - return self.unsize_into_ptr( - src, - dest, - src.layout.ty.boxed_ty(), - cast_ty.ty.boxed_ty(), - ); - } // unsizing of generic struct with pointer fields // Example: `Arc<T>` -> `Arc<Trait>` diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 630281bb09254..905ab6cb578fc 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -594,7 +594,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::Adt(def, ..) if def.is_box() => { - self.check_safe_pointer(value, "box")?; + let unique = self.ecx.operand_field(value, 0)?; + let nonnull = self.ecx.operand_field(&unique, 0)?; + let ptr = self.ecx.operand_field(&nonnull, 0)?; + self.check_safe_pointer(&ptr, "box")?; + + // Check other fields of Box + self.walk_value(value)?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl new file mode 100644 index 0000000000000..645673ef47aeb --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -0,0 +1,18 @@ +borrowck-move-unsized = + cannot move a value of type `{$ty}` + .label = the size of `{$ty}` cannot be statically determined + +borrowck-higher-ranked-lifetime-error = + higher-ranked lifetime error + +borrowck-could-not-prove = + could not prove `{$predicate}` + +borrowck-could-not-normalize = + could not normalize `{$value}` + +borrowck-higher-ranked-subtype-error = + higher-ranked subtype error + +generic-does-not-live-long-enough = + `{$kind}` does not live long enough \ No newline at end of file diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 90eb5ef54462d..d52b94b78dfac 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -35,6 +35,7 @@ fluent_messages! { privacy => "../locales/en-US/privacy.ftl", typeck => "../locales/en-US/typeck.ftl", builtin_macros => "../locales/en-US/builtin_macros.ftl", + borrowck => "../locales/en-US/borrowck.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 8b2a995f1c58e..6d74e9a9f2b9e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -281,9 +281,19 @@ pub trait Emitter { let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle"); let value = match attr { Some(attr) => { - message.get_attribute(attr).expect("missing attribute in fluent message").value() + if let Some(attr) = message.get_attribute(attr) { + attr.value() + } else { + panic!("missing attribute `{attr}` in fluent message `{identifier}`") + } + } + None => { + if let Some(value) = message.value() { + value + } else { + panic!("missing value in fluent message `{identifier}`") + } } - None => message.value().expect("missing value in fluent message"), }; let mut err = vec![]; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 502afa493fe66..5b263aded9cdf 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -972,6 +972,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { if !tcx.sess.opts.debugging_opts.thir_unsafeck { rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } + tcx.ensure().has_ffi_unwind_calls(def_id); if tcx.hir().body_const_context(def_id).is_some() { tcx.ensure() diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 30a29ed6ed38f..b3dbbfe7fc7ad 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -733,6 +733,7 @@ fn test_debugging_options_tracking_hash() { tracked!(dep_info_omit_d_target, true); tracked!(drop_tracking, true); tracked!(dual_proc_macros, true); + tracked!(dwarf_version, Some(5)); tracked!(fewer_names, Some(true)); tracked!(force_unstable_if_unmarked, true); tracked!(fuel, Some(("abc".to_string(), 99))); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d52455e2576c9..40601bb5aad47 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3231,6 +3231,7 @@ declare_lint_pass! { UNEXPECTED_CFGS, DEPRECATED_WHERE_CLAUSE_LOCATION, TEST_UNSTABLE_LINT, + FFI_UNWIND_CALLS, ] } @@ -3896,3 +3897,42 @@ declare_lint! { "this unstable lint is only for testing", @feature_gate = sym::test_unstable_lint; } + +declare_lint! { + /// The `ffi_unwind_calls` lint detects calls to foreign functions or function pointers with + /// `C-unwind` or other FFI-unwind ABIs. + /// + /// ### Example + /// + /// ```rust,ignore (need FFI) + /// #![feature(ffi_unwind_calls)] + /// #![feature(c_unwind)] + /// + /// # mod impl { + /// # #[no_mangle] + /// # pub fn "C-unwind" fn foo() {} + /// # } + /// + /// extern "C-unwind" { + /// fn foo(); + /// } + /// + /// fn bar() { + /// unsafe { foo(); } + /// let ptr: unsafe extern "C-unwind" fn() = foo; + /// unsafe { ptr(); } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// For crates containing such calls, if they are compiled with `-C panic=unwind` then the + /// produced library cannot be linked with crates compiled with `-C panic=abort`. For crates + /// that desire this ability it is therefore necessary to avoid such calls. + pub FFI_UNWIND_CALLS, + Allow, + "call to foreign functions or function pointers with FFI-unwind ABI", + @feature_gate = sym::c_unwind; +} diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 555db5846edd0..cb50c0fb7385f 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -748,7 +748,7 @@ impl<'a> CrateLoader<'a> { if !data.is_panic_runtime() { self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); } - if data.panic_strategy() != desired_strategy { + if data.required_panic_strategy() != Some(desired_strategy) { self.sess.err(&format!( "the crate `{}` does not have the panic \ strategy `{}`", diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 245b2076ebca9..770d164894a73 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -60,7 +60,6 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; -use rustc_target::spec::PanicStrategy; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.sess @@ -367,14 +366,19 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { prev_name, cur_name )); } - panic_runtime = Some((cnum, tcx.panic_strategy(cnum))); + panic_runtime = Some(( + cnum, + tcx.required_panic_strategy(cnum).unwrap_or_else(|| { + bug!("cannot determine panic strategy of a panic runtime"); + }), + )); } } // If we found a panic runtime, then we know by this point that it's the // only one, but we perform validation here that all the panic strategy // compilation modes for the whole DAG are valid. - if let Some((cnum, found_strategy)) = panic_runtime { + if let Some((runtime_cnum, found_strategy)) = panic_runtime { let desired_strategy = sess.panic_strategy(); // First up, validate that our selected panic runtime is indeed exactly @@ -384,7 +388,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { "the linked panic runtime `{}` is \ not compiled with this crate's \ panic strategy `{}`", - tcx.crate_name(cnum), + tcx.crate_name(runtime_cnum), desired_strategy.desc() )); } @@ -397,18 +401,14 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { if let Linkage::NotLinked = *linkage { continue; } - if desired_strategy == PanicStrategy::Abort { - continue; - } let cnum = CrateNum::new(i + 1); - if tcx.is_compiler_builtins(cnum) { + if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) { continue; } - let found_strategy = tcx.panic_strategy(cnum); - if desired_strategy != found_strategy { + if let Some(found_strategy) = tcx.required_panic_strategy(cnum) && desired_strategy != found_strategy { sess.err(&format!( - "the crate `{}` is compiled with the \ + "the crate `{}` requires \ panic strategy `{}` which is \ incompatible with this crate's \ strategy of `{}`", diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3280fd5c3108b..f0ccf02c9fa5f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1758,8 +1758,8 @@ impl CrateMetadata { self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) } - pub(crate) fn panic_strategy(&self) -> PanicStrategy { - self.root.panic_strategy + pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> { + self.root.required_panic_strategy } pub(crate) fn needs_panic_runtime(&self) -> bool { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0bea2a10da896..565eec18ea9b8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -246,7 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_global_allocator => { cdata.root.has_global_allocator } has_panic_handler => { cdata.root.has_panic_handler } is_profiler_runtime => { cdata.root.profiler_runtime } - panic_strategy => { cdata.root.panic_strategy } + required_panic_strategy => { cdata.root.required_panic_strategy } panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy } extern_crate => { let r = *cdata.extern_crate.lock(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 75286b8906871..bb4b502bded45 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -665,7 +665,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), - panic_strategy: tcx.sess.panic_strategy(), + required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop, edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a58c0e68ee38c..a50eb2a71cf4a 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -217,7 +217,7 @@ pub(crate) struct CrateRoot { extra_filename: String, hash: Svh, stable_crate_id: StableCrateId, - panic_strategy: PanicStrategy, + required_panic_strategy: Option<PanicStrategy>, panic_in_drop_strategy: PanicStrategy, edition: Edition, has_global_allocator: bool, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2e68fc8a7c050..095e8cbdd10a0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1358,9 +1358,13 @@ rustc_queries! { desc { "query a crate is `#![profiler_runtime]`" } separate_provide_extern } - query panic_strategy(_: CrateNum) -> PanicStrategy { + query has_ffi_unwind_calls(key: LocalDefId) -> bool { + desc { |tcx| "check if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) } + cache_on_disk_if { true } + } + query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> { fatal_cycle - desc { "query a crate's configured panic strategy" } + desc { "query a crate's required panic strategy" } separate_provide_extern } query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 11980382ffdb2..2c8389e532dd7 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -1,6 +1,5 @@ use crate::MirPass; use rustc_ast::InlineAsmOptions; -use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::ty::layout; use rustc_middle::ty::{self, TyCtxt}; @@ -31,11 +30,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { // We don't simplify the MIR of constants at this time because that // namely results in a cyclic query when we call `tcx.type_of` below. - let is_function = match kind { - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, - _ => tcx.is_closure(def_id), - }; - if !is_function { + if !kind.is_fn_like() { return; } diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs new file mode 100644 index 0000000000000..7728fdaffb0dc --- /dev/null +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -0,0 +1,170 @@ +use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE}; +use rustc_middle::mir::*; +use rustc_middle::ty::layout; +use rustc_middle::ty::query::Providers; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_session::lint::builtin::FFI_UNWIND_CALLS; +use rustc_target::spec::abi::Abi; +use rustc_target::spec::PanicStrategy; + +fn abi_can_unwind(abi: Abi) -> bool { + use Abi::*; + match abi { + C { unwind } + | System { unwind } + | Cdecl { unwind } + | Stdcall { unwind } + | Fastcall { unwind } + | Vectorcall { unwind } + | Thiscall { unwind } + | Aapcs { unwind } + | Win64 { unwind } + | SysV64 { unwind } => unwind, + PtxKernel + | Msp430Interrupt + | X86Interrupt + | AmdGpuKernel + | EfiApi + | AvrInterrupt + | AvrNonBlockingInterrupt + | CCmseNonSecureCall + | Wasm + | RustIntrinsic + | PlatformIntrinsic + | Unadjusted => false, + Rust | RustCall | RustCold => true, + } +} + +// Check if the body of this def_id can possibly leak a foreign unwind into Rust code. +fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { + debug!("has_ffi_unwind_calls({local_def_id:?})"); + + // Only perform check on functions because constants cannot call FFI functions. + let def_id = local_def_id.to_def_id(); + let kind = tcx.def_kind(def_id); + if !kind.is_fn_like() { + return false; + } + + let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow(); + + let body_ty = tcx.type_of(def_id); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Generator(..) => Abi::Rust, + _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), + }; + let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); + + // Foreign unwinds cannot leak past functions that themselves cannot unwind. + if !body_can_unwind { + return false; + } + + let mut tainted = false; + + for block in body.basic_blocks() { + if block.is_cleanup { + continue; + } + let Some(terminator) = &block.terminator else { continue }; + let TerminatorKind::Call { func, .. } = &terminator.kind else { continue }; + + let ty = func.ty(body, tcx); + let sig = ty.fn_sig(tcx); + + // Rust calls cannot themselves create foreign unwinds. + if let Abi::Rust | Abi::RustCall | Abi::RustCold = sig.abi() { + continue; + }; + + let fn_def_id = match ty.kind() { + ty::FnPtr(_) => None, + &ty::FnDef(def_id, _) => { + // Rust calls cannot themselves create foreign unwinds. + if !tcx.is_foreign_item(def_id) { + continue; + } + Some(def_id) + } + _ => bug!("invalid callee of type {:?}", ty), + }; + + if layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) && abi_can_unwind(sig.abi()) { + // We have detected a call that can possibly leak foreign unwind. + // + // Because the function body itself can unwind, we are not aborting this function call + // upon unwind, so this call can possibly leak foreign unwind into Rust code if the + // panic runtime linked is panic-abort. + + let lint_root = body.source_scopes[terminator.source_info.scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; + let span = terminator.source_info.span; + + tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, |lint| { + let msg = match fn_def_id { + Some(_) => "call to foreign function with FFI-unwind ABI", + None => "call to function pointer with FFI-unwind ABI", + }; + let mut db = lint.build(msg); + db.span_label(span, msg); + db.emit(); + }); + + tainted = true; + } + } + + tainted +} + +fn required_panic_strategy(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<PanicStrategy> { + assert_eq!(cnum, LOCAL_CRATE); + + if tcx.is_panic_runtime(LOCAL_CRATE) { + return Some(tcx.sess.panic_strategy()); + } + + if tcx.sess.panic_strategy() == PanicStrategy::Abort { + return Some(PanicStrategy::Abort); + } + + for def_id in tcx.hir().body_owners() { + if tcx.has_ffi_unwind_calls(def_id) { + // Given that this crate is compiled in `-C panic=unwind`, the `AbortUnwindingCalls` + // MIR pass will not be run on FFI-unwind call sites, therefore a foreign exception + // can enter Rust through these sites. + // + // On the other hand, crates compiled with `-C panic=abort` expects that all Rust + // functions cannot unwind (whether it's caused by Rust panic or foreign exception), + // and this expectation mismatch can cause unsoundness (#96926). + // + // To address this issue, we enforce that if FFI-unwind calls are used in a crate + // compiled with `panic=unwind`, then the final panic strategy must be `panic=unwind`. + // This will ensure that no crates will have wrong unwindability assumption. + // + // It should be noted that it is okay to link `panic=unwind` into a `panic=abort` + // program if it contains no FFI-unwind calls. In such case foreign exception can only + // enter Rust in a `panic=abort` crate, which will lead to an abort. There will also + // be no exceptions generated from Rust, so the assumption which `panic=abort` crates + // make, that no Rust function can unwind, indeed holds for crates compiled with + // `panic=unwind` as well. In such case this function returns `None`, indicating that + // the crate does not require a particular final panic strategy, and can be freely + // linked to crates with either strategy (we need such ability for libstd and its + // dependencies). + return Some(PanicStrategy::Unwind); + } + } + + // This crate can be linked with either runtime. + None +} + +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { has_ffi_unwind_calls, required_panic_strategy, ..*providers }; +} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b7caa61ef07a7..12fcb299ce3f4 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -59,6 +59,7 @@ pub mod dump_mir; mod early_otherwise_branch; mod elaborate_box_derefs; mod elaborate_drops; +mod ffi_unwind_calls; mod function_item_references; mod generator; mod inline; @@ -98,6 +99,7 @@ pub fn provide(providers: &mut Providers) { check_unsafety::provide(providers); check_packed_ref::provide(providers); coverage::query::provide(providers); + ffi_unwind_calls::provide(providers); shim::provide(providers); *providers = Providers { mir_keys, @@ -223,6 +225,9 @@ fn mir_const<'tcx>( } } + // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + tcx.ensure().has_ffi_unwind_calls(def.did); + let mut body = tcx.mir_built(def).steal(); rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 441e1f9f6a2b8..372402c80096a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1269,6 +1269,8 @@ options! { computed `block` spans (one span encompassing a block's terminator and \ all statements). If `-Z instrument-coverage` is also enabled, create \ an additional `.html` file showing the computed coverage spans."), + dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED], + "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b5058fd699aca..d3beb123ad1a6 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1489,6 +1489,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { )) } } + + if let Some(dwarf_version) = sess.opts.debugging_opts.dwarf_version { + if dwarf_version > 5 { + sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version)); + } + } } /// Holds data on the current incremental compilation session, if there is one. diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index c2b9d696776f5..dc06597db6fd4 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -3,7 +3,7 @@ use crate::spec::TargetOptions; pub fn opts() -> TargetOptions { let mut base = super::linux_base::opts(); base.os = "android".into(); - base.dwarf_version = Some(2); + base.default_dwarf_version = 2; base.position_independent_executables = true; base.has_thread_local = false; // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867 diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index e8460a509e2ba..713dc9a1f0ea7 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -28,7 +28,7 @@ pub fn opts(os: &'static str) -> TargetOptions { executables: true, families: cvs!["unix"], is_like_osx: true, - dwarf_version: Some(2), + default_dwarf_version: 2, frame_pointer: FramePointer::Always, has_rpath: true, dll_suffix: ".dylib".into(), diff --git a/compiler/rustc_target/src/spec/dragonfly_base.rs b/compiler/rustc_target/src/spec/dragonfly_base.rs index b59322d07f57a..c1e469746cb4c 100644 --- a/compiler/rustc_target/src/spec/dragonfly_base.rs +++ b/compiler/rustc_target/src/spec/dragonfly_base.rs @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, position_independent_executables: true, relro_level: RelroLevel::Full, - dwarf_version: Some(2), + default_dwarf_version: 2, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/freebsd_base.rs b/compiler/rustc_target/src/spec/freebsd_base.rs index a7e0f9f704127..36312d26e3700 100644 --- a/compiler/rustc_target/src/spec/freebsd_base.rs +++ b/compiler/rustc_target/src/spec/freebsd_base.rs @@ -10,7 +10,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, relro_level: RelroLevel::Full, abi_return_struct_as_int: true, - dwarf_version: Some(2), + default_dwarf_version: 2, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index a08603da04095..48ccb10f21426 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1275,9 +1275,9 @@ pub struct TargetOptions { pub is_like_msvc: bool, /// Whether a target toolchain is like WASM. pub is_like_wasm: bool, - /// Version of DWARF to use if not using the default. + /// Default supported version of DWARF on this platform. /// Useful because some platforms (osx, bsd) only want up to DWARF2. - pub dwarf_version: Option<u32>, + pub default_dwarf_version: u32, /// Whether the linker support GNU-like arguments such as -O. Defaults to true. pub linker_is_gnu: bool, /// The MinGW toolchain has a known issue that prevents it from correctly @@ -1539,7 +1539,7 @@ impl Default for TargetOptions { is_like_windows: false, is_like_msvc: false, is_like_wasm: false, - dwarf_version: None, + default_dwarf_version: 4, linker_is_gnu: true, allows_weak_linkage: true, has_rpath: false, @@ -1778,13 +1778,13 @@ impl Target { base.$key_name = s; } } ); - ($key_name:ident, Option<u32>) => ( { + ($key_name:ident, u32) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { if s < 1 || s > 5 { return Err("Not a valid DWARF version number".into()); } - base.$key_name = Some(s as u32); + base.$key_name = s as u32; } } ); ($key_name:ident, Option<u64>) => ( { @@ -2143,7 +2143,7 @@ impl Target { key!(is_like_windows, bool); key!(is_like_msvc, bool); key!(is_like_wasm, bool); - key!(dwarf_version, Option<u32>); + key!(default_dwarf_version, u32); key!(linker_is_gnu, bool); key!(allows_weak_linkage, bool); key!(has_rpath, bool); @@ -2387,7 +2387,7 @@ impl ToJson for Target { target_option_val!(is_like_windows); target_option_val!(is_like_msvc); target_option_val!(is_like_wasm); - target_option_val!(dwarf_version); + target_option_val!(default_dwarf_version); target_option_val!(linker_is_gnu); target_option_val!(allows_weak_linkage); target_option_val!(has_rpath); diff --git a/compiler/rustc_target/src/spec/netbsd_base.rs b/compiler/rustc_target/src/spec/netbsd_base.rs index 69016d77cf97b..40ef04ba04382 100644 --- a/compiler/rustc_target/src/spec/netbsd_base.rs +++ b/compiler/rustc_target/src/spec/netbsd_base.rs @@ -11,7 +11,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, relro_level: RelroLevel::Full, use_ctors_section: true, - dwarf_version: Some(2), + default_dwarf_version: 2, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/openbsd_base.rs b/compiler/rustc_target/src/spec/openbsd_base.rs index bbd322bb6ce2b..51cecdd47eab2 100644 --- a/compiler/rustc_target/src/spec/openbsd_base.rs +++ b/compiler/rustc_target/src/spec/openbsd_base.rs @@ -11,7 +11,7 @@ pub fn opts() -> TargetOptions { position_independent_executables: true, frame_pointer: FramePointer::Always, // FIXME 43575: should be MayOmit... relro_level: RelroLevel::Full, - dwarf_version: Some(2), + default_dwarf_version: 2, ..Default::default() } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 5d08ea99ac64a..424eff2f6212a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -236,7 +236,7 @@ impl<'tcx> AbstractConst<'tcx> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); - Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs })) + Ok(inner.map(|inner| AbstractConst { inner, substs: tcx.erase_regions(uv.substs) })) } pub fn from_const( @@ -416,6 +416,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // `AbstractConst`s should not contain any promoteds as they require references which // are not allowed. assert_eq!(ct.promoted, None); + assert_eq!(ct, self.tcx.erase_regions(ct)); } } } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 93cdf121fbe0f..43e4b7f08e22d 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -231,7 +231,8 @@ impl fmt::Debug for c_void { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[repr(transparent)] #[unstable( @@ -254,7 +255,8 @@ pub struct VaListImpl<'f> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[unstable( feature = "c_variadic", @@ -276,7 +278,8 @@ impl<'f> fmt::Debug for VaListImpl<'f> { #[cfg(all( target_arch = "aarch64", not(any(target_os = "macos", target_os = "ios")), - not(windows) + not(target_os = "uefi"), + not(windows), ))] #[repr(C)] #[derive(Debug)] @@ -297,7 +300,7 @@ pub struct VaListImpl<'f> { } /// PowerPC ABI implementation of a `va_list`. -#[cfg(all(target_arch = "powerpc", not(windows)))] +#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))] #[repr(C)] #[derive(Debug)] #[unstable( @@ -317,7 +320,7 @@ pub struct VaListImpl<'f> { } /// x86_64 ABI implementation of a `va_list`. -#[cfg(all(target_arch = "x86_64", not(windows)))] +#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))] #[repr(C)] #[derive(Debug)] #[unstable( @@ -354,7 +357,8 @@ pub struct VaList<'a, 'f: 'a> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] inner: VaListImpl<'f>, @@ -363,7 +367,8 @@ pub struct VaList<'a, 'f: 'a> { any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_family = "wasm"), not(target_arch = "asmjs"), - not(windows) + not(target_os = "uefi"), + not(windows), ))] inner: &'a mut VaListImpl<'f>, @@ -375,7 +380,8 @@ pub struct VaList<'a, 'f: 'a> { all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_family = "wasm", target_arch = "asmjs", - windows + target_os = "uefi", + windows, ))] #[unstable( feature = "c_variadic", @@ -396,7 +402,8 @@ impl<'f> VaListImpl<'f> { any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_family = "wasm"), not(target_arch = "asmjs"), - not(windows) + not(target_os = "uefi"), + not(windows), ))] #[unstable( feature = "c_variadic", diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65b8df4299663..8e9189629db0d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -210,6 +210,8 @@ #![allow(unused_lifetimes)] // Tell the compiler to link to either panic_abort or panic_unwind #![needs_panic_runtime] +// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind` +#![cfg_attr(not(bootstrap), deny(ffi_unwind_calls))] // std may use features in a platform-specific way #![allow(unused_features)] #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 0a6a7cfe976cc..c70ac8c9806d6 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -159,6 +159,7 @@ use crate::cell::UnsafeCell; use crate::ffi::{CStr, CString}; use crate::fmt; use crate::io; +use crate::marker::PhantomData; use crate::mem; use crate::num::NonZeroU64; use crate::num::NonZeroUsize; @@ -462,7 +463,7 @@ impl Builder { unsafe fn spawn_unchecked_<'a, 'scope, F, T>( self, f: F, - scope_data: Option<&'scope scoped::ScopeData>, + scope_data: Option<Arc<scoped::ScopeData>>, ) -> io::Result<JoinInner<'scope, T>> where F: FnOnce() -> T, @@ -479,8 +480,11 @@ impl Builder { })); let their_thread = my_thread.clone(); - let my_packet: Arc<Packet<'scope, T>> = - Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) }); + let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet { + scope: scope_data, + result: UnsafeCell::new(None), + _marker: PhantomData, + }); let their_packet = my_packet.clone(); let output_capture = crate::io::set_output_capture(None); @@ -507,7 +511,7 @@ impl Builder { unsafe { *their_packet.result.get() = Some(try_result) }; }; - if let Some(scope_data) = scope_data { + if let Some(scope_data) = &my_packet.scope { scope_data.increment_num_running_threads(); } @@ -1298,8 +1302,9 @@ pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>; // An Arc to the packet is stored into a `JoinInner` which in turns is placed // in `JoinHandle`. struct Packet<'scope, T> { - scope: Option<&'scope scoped::ScopeData>, + scope: Option<Arc<scoped::ScopeData>>, result: UnsafeCell<Option<Result<T>>>, + _marker: PhantomData<Option<&'scope scoped::ScopeData>>, } // Due to the usage of `UnsafeCell` we need to manually implement Sync. @@ -1330,7 +1335,7 @@ impl<'scope, T> Drop for Packet<'scope, T> { rtabort!("thread result panicked on drop"); } // Book-keeping so the scope knows when it's done. - if let Some(scope) = self.scope { + if let Some(scope) = &self.scope { // Now that there will be no more user code running on this thread // that can use 'scope, mark the thread as 'finished'. // It's important we only do this after the `result` has been dropped, diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index a387a09dc8b15..e6dbf35bd0286 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -11,7 +11,7 @@ use crate::sync::Arc; /// See [`scope`] for details. #[stable(feature = "scoped_threads", since = "1.63.0")] pub struct Scope<'scope, 'env: 'scope> { - data: ScopeData, + data: Arc<ScopeData>, /// Invariance over 'scope, to make sure 'scope cannot shrink, /// which is necessary for soundness. /// @@ -130,12 +130,14 @@ pub fn scope<'env, F, T>(f: F) -> T where F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T, { + // We put the `ScopeData` into an `Arc` so that other threads can finish their + // `decrement_num_running_threads` even after this function returns. let scope = Scope { - data: ScopeData { + data: Arc::new(ScopeData { num_running_threads: AtomicUsize::new(0), main_thread: current(), a_thread_panicked: AtomicBool::new(false), - }, + }), env: PhantomData, scope: PhantomData, }; @@ -250,7 +252,7 @@ impl Builder { F: FnOnce() -> T + Send + 'scope, T: Send + 'scope, { - Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(&scope.data)) }?)) + Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(scope.data.clone())) }?)) } } diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index dca782c29c252..759a99c330c27 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -61,6 +61,30 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> { } } +fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { + let mut cfg = cc::Build::new(); + cfg.cargo_metadata(false) + .opt_level(2) + .warnings(false) + .debug(false) + .target(&target.triple) + .host(&build.build.triple); + match build.crt_static(target) { + Some(a) => { + cfg.static_crt(a); + } + None => { + if target.contains("msvc") { + cfg.static_crt(true); + } + if target.contains("musl") { + cfg.static_flag(true); + } + } + } + cfg +} + pub fn find(build: &mut Build) { // For all targets we're going to need a C compiler for building some shims // and such as well as for being a linker for Rust code. @@ -72,27 +96,7 @@ pub fn find(build: &mut Build) { .chain(iter::once(build.build)) .collect::<HashSet<_>>(); for target in targets.into_iter() { - let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false) - .opt_level(2) - .warnings(false) - .debug(false) - .target(&target.triple) - .host(&build.build.triple); - match build.crt_static(target) { - Some(a) => { - cfg.static_crt(a); - } - None => { - if target.contains("msvc") { - cfg.static_crt(true); - } - if target.contains("musl") { - cfg.static_flag(true); - } - } - } - + let mut cfg = new_cc_build(build, target); let config = build.config.target_config.get(&target); if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { cfg.compiler(cc); @@ -112,15 +116,8 @@ pub fn find(build: &mut Build) { // If we use llvm-libunwind, we will need a C++ compiler as well for all targets // We'll need one anyways if the target triple is also a host triple - let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false) - .opt_level(2) - .warnings(false) - .debug(false) - .cpp(true) - .target(&target.triple) - .host(&build.build.triple); - + let mut cfg = new_cc_build(build, target); + cfg.cpp(true); let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); true diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 859d35b7d7ba1..40ff0381c8bc1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -107,15 +107,11 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; use std::fs::{self, File}; +use std::io; use std::path::{Path, PathBuf}; use std::process::{self, Command}; use std::str; -#[cfg(unix)] -use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] -use std::os::windows::fs::symlink_file; - use filetime::FileTime; use once_cell::sync::OnceCell; @@ -1460,7 +1456,7 @@ impl Build { src = t!(fs::canonicalize(src)); } else { let link = t!(fs::read_link(src)); - t!(symlink_file(link, dst)); + t!(self.symlink_file(link, dst)); return; } } @@ -1585,6 +1581,14 @@ impl Build { iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter() } + fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(&self, src: P, link: Q) -> io::Result<()> { + #[cfg(unix)] + use std::os::unix::fs::symlink as symlink_file; + #[cfg(windows)] + use std::os::windows::fs::symlink_file; + if !self.config.dry_run { symlink_file(src.as_ref(), link.as_ref()) } else { Ok(()) } + } + fn remove(&self, f: &Path) { if self.config.dry_run { return; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 9cd8b6d1455dd..b196b55c5e758 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -251,9 +251,7 @@ impl Step for Llvm { }; builder.update_submodule(&Path::new("src").join("llvm-project")); - if builder.llvm_link_shared() - && (target.contains("windows") || target.contains("apple-darwin")) - { + if builder.llvm_link_shared() && target.contains("windows") { panic!("shared linking to LLVM is not currently supported on {}", target.triple); } @@ -359,7 +357,9 @@ impl Step for Llvm { // // If we're not linking rustc to a dynamic LLVM, though, then don't link // tools to it. - if builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared() { + let llvm_link_shared = + builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared(); + if llvm_link_shared { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } @@ -429,27 +429,35 @@ impl Step for Llvm { // should use llvm-tblgen from there, also should verify that it // actually exists most of the time in normal installs of LLVM. let host_bin = builder.llvm_out(builder.config.build).join("bin"); - cfg.define("CMAKE_CROSSCOMPILING", "True"); cfg.define("LLVM_TABLEGEN", host_bin.join("llvm-tblgen").with_extension(EXE_EXTENSION)); + // LLVM_NM is required for cross compiling using MSVC cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION)); cfg.define( "LLVM_CONFIG_PATH", host_bin.join("llvm-config").with_extension(EXE_EXTENSION), ); + if builder.config.llvm_clang { + let build_bin = builder.llvm_out(builder.config.build).join("build").join("bin"); + let clang_tblgen = build_bin.join("clang-tblgen").with_extension(EXE_EXTENSION); + if !clang_tblgen.exists() { + panic!("unable to find {}", clang_tblgen.display()); + } + cfg.define("CLANG_TABLEGEN", clang_tblgen); + } } - if let Some(ref suffix) = builder.config.llvm_version_suffix { + let llvm_version_suffix = if let Some(ref suffix) = builder.config.llvm_version_suffix { // Allow version-suffix="" to not define a version suffix at all. - if !suffix.is_empty() { - cfg.define("LLVM_VERSION_SUFFIX", suffix); - } + if !suffix.is_empty() { Some(suffix.to_string()) } else { None } } else if builder.config.channel == "dev" { // Changes to a version suffix require a complete rebuild of the LLVM. // To avoid rebuilds during a time of version bump, don't include rustc // release number on the dev channel. - cfg.define("LLVM_VERSION_SUFFIX", "-rust-dev"); + Some("-rust-dev".to_string()) } else { - let suffix = format!("-rust-{}-{}", builder.version, builder.config.channel); + Some(format!("-rust-{}-{}", builder.version, builder.config.channel)) + }; + if let Some(ref suffix) = llvm_version_suffix { cfg.define("LLVM_VERSION_SUFFIX", suffix); } @@ -478,6 +486,27 @@ impl Step for Llvm { cfg.build(); + // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned + // libLLVM.dylib will be built. However, llvm-config will still look + // for a versioned path like libLLVM-14.dylib. Manually create a symbolic + // link to make llvm-config happy. + if llvm_link_shared && target.contains("apple-darwin") { + let mut cmd = Command::new(&build_llvm_config); + let version = output(cmd.arg("--version")); + let major = version.split('.').next().unwrap(); + let lib_name = match llvm_version_suffix { + Some(s) => format!("lib/libLLVM-{}{}.dylib", major, s), + None => format!("lib/libLLVM-{}.dylib", major), + }; + + // The reason why we build the library path from llvm-config is because + // the output of llvm-config depends on its location in the file system. + // Make sure we create the symlink exactly where it's needed. + let llvm_base = build_llvm_config.parent().unwrap().parent().unwrap(); + let lib_llvm = llvm_base.join(lib_name); + t!(builder.symlink_file("libLLVM.dylib", &lib_llvm)); + } + t!(stamp.write()); build_llvm_config @@ -526,6 +555,8 @@ fn configure_cmake( cfg.target(&target.triple).host(&builder.config.build.triple); if target != builder.config.build { + cfg.define("CMAKE_CROSSCOMPILING", "True"); + if target.contains("netbsd") { cfg.define("CMAKE_SYSTEM_NAME", "NetBSD"); } else if target.contains("freebsd") { @@ -543,6 +574,17 @@ fn configure_cmake( // Since, the LLVM itself makes rather limited use of version checks in // CMakeFiles (and then only in tests), and so far no issues have been // reported, the system version is currently left unset. + + if target.contains("darwin") { + // Make sure that CMake does not build universal binaries on macOS. + // Explicitly specifiy the one single target architecture. + if target.starts_with("aarch64") { + // macOS uses a different name for building arm64 + cfg.define("CMAKE_OSX_ARCHITECTURES", "arm64"); + } else { + cfg.define("CMAKE_OSX_ARCHITECTURES", target.triple.split('-').next().unwrap()); + } + } } let sanitize_cc = |cc: &Path| { diff --git a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md new file mode 100644 index 0000000000000..c5e86f17df741 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md @@ -0,0 +1,9 @@ +## `dwarf-version` + +This option controls the version of DWARF that the compiler emits, on platforms +that use DWARF to encode debug information. It takes one of the following +values: + +* `2`: DWARF version 2 (the default on certain platforms, like macOS). +* `4`: DWARF version 4 (the default on certain platforms, like Linux). +* `5`: DWARF version 5. diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 70dbfd4442540..c33e272774438 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -412,14 +412,15 @@ function loadCss(cssFileName) { window.hidePopoverMenus(); } - const disableShortcuts = getSettingValue("disable-shortcuts") === "true"; function handleShortcut(ev) { // Don't interfere with browser shortcuts + const disableShortcuts = getSettingValue("disable-shortcuts") === "true"; if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) { return; } - if (document.activeElement.tagName === "INPUT") { + if (document.activeElement.tagName === "INPUT" && + document.activeElement.type !== "checkbox") { switch (getVirtualKey(ev)) { case "Escape": handleEscape(ev); @@ -926,6 +927,7 @@ function loadCss(cssFileName) { function showHelp() { const menu = getHelpMenu(true); if (menu.style.display === "none") { + window.hidePopoverMenus(); menu.style.display = ""; } } @@ -939,6 +941,8 @@ function loadCss(cssFileName) { const shouldShowHelp = menu.style.display === "none"; if (shouldShowHelp) { showHelp(); + } else { + window.hidePopoverMenus(); } }); diff --git a/src/test/assembly/dwarf5.rs b/src/test/assembly/dwarf5.rs new file mode 100644 index 0000000000000..f41e6bd55be7d --- /dev/null +++ b/src/test/assembly/dwarf5.rs @@ -0,0 +1,20 @@ +// Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5. +// assembly-output: emit-asm +// compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 +// needs-llvm-components: x86 + +#![feature(no_core, lang_items)] +#![crate_type = "rlib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +pub fn wibble() {} + +// CHECK: .section .debug_info +// CHECK-NOT: .short 2 +// CHECK-NOT: .short 4 +// CHECK: .short 5 diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml index ba2986e969a35..54f3790a76521 100644 --- a/src/test/rustdoc-gui/pocket-menu.goml +++ b/src/test/rustdoc-gui/pocket-menu.goml @@ -24,6 +24,11 @@ click: "#help-button" assert-css: ("#help-button .popover", {"display": "block"}) assert-css: ("#settings-menu .popover", {"display": "none"}) +// Now verify that clicking the help menu again closes it. +click: "#help-button" +assert-css: ("#help-button .popover", {"display": "none"}) +assert-css: ("#settings-menu .popover", {"display": "none"}) + // We check the borders color now: // Ayu theme diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index 237a4751a8d66..c402c7991c8bb 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -121,6 +121,20 @@ local-storage: {"rustdoc-disable-shortcuts": "false"} click: ".setting-line:last-child .toggle .label" assert-local-storage: {"rustdoc-disable-shortcuts": "true"} +// Make sure that "Disable keyboard shortcuts" actually took effect. +press-key: "Escape" +press-key: "?" +assert-false: "#help-button .popover" +wait-for-css: ("#settings-menu .popover", {"display": "block"}) + +// Now turn keyboard shortcuts back on, and see if they work. +click: ".setting-line:last-child .toggle .label" +assert-local-storage: {"rustdoc-disable-shortcuts": "false"} +press-key: "Escape" +press-key: "?" +wait-for-css: ("#help-button .popover", {"display": "block"}) +assert-css: ("#settings-menu .popover", {"display": "none"}) + // Now we go to the settings page to check that the CSS is loaded as expected. goto: file://|DOC_PATH|/settings.html wait-for: "#settings" diff --git a/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs b/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs new file mode 100644 index 0000000000000..2ae0ae70dd977 --- /dev/null +++ b/src/test/ui/const-generics/try_unify_ignore_lifetimes.rs @@ -0,0 +1,33 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Num<const N: usize>; + +trait NumT { + const VALUE: usize; +} + +impl<const N: usize> NumT for Num<N> { + const VALUE: usize = N; +} + +struct Foo<'a, N: NumT>(&'a [u32; N::VALUE]) where [(); N::VALUE]:; + +trait Bar { + type Size: NumT; + + fn bar<'a>(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +trait Baz<'a> { + type Size: NumT; + + fn baz(foo: &Foo<'a, Self::Size>) where [(); Self::Size::VALUE]: { + todo!(); + } +} + +fn main() {} diff --git a/src/test/ui/dst/dst-index.stderr b/src/test/ui/dst/dst-index.stderr index 6bcd70cbaad45..d38af3f89c21b 100644 --- a/src/test/ui/dst/dst-index.stderr +++ b/src/test/ui/dst/dst-index.stderr @@ -1,14 +1,14 @@ -error[E0161]: cannot move a value of type str: the size of str cannot be statically determined +error[E0161]: cannot move a value of type `str` --> $DIR/dst-index.rs:31:5 | LL | S[0]; - | ^^^^ + | ^^^^ the size of `str` cannot be statically determined -error[E0161]: cannot move a value of type dyn Debug: the size of dyn Debug cannot be statically determined +error[E0161]: cannot move a value of type `dyn Debug` --> $DIR/dst-index.rs:34:5 | LL | T[0]; - | ^^^^ + | ^^^^ the size of `dyn Debug` cannot be statically determined error[E0507]: cannot move out of index of `S` --> $DIR/dst-index.rs:31:5 diff --git a/src/test/ui/error-codes/E0161.base.stderr b/src/test/ui/error-codes/E0161.base.stderr index fb578cda17e9f..15d98b657a262 100644 --- a/src/test/ui/error-codes/E0161.base.stderr +++ b/src/test/ui/error-codes/E0161.base.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined +error[E0161]: cannot move a value of type `dyn Bar` --> $DIR/E0161.rs:16:5 | LL | x.f(); - | ^^^^^ + | ^^^^^ the size of `dyn Bar` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr index 15e83ab5a347d..43e609cc59efb 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: could not prove [closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed + = note: could not prove `[closure@$DIR/issue-59311.rs:17:9: 17:14] well-formed` error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 @@ -12,7 +12,7 @@ error: higher-ranked lifetime error LL | v.t(|| {}); | ^^^^^ | - = note: could not prove for<'a> &'a V: 'static + = note: could not prove `for<'a> &'a V: 'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr index 3a5ab62ab96f6..72bb0782f4b4f 100644 --- a/src/test/ui/lifetimes/re-empty-in-error.stderr +++ b/src/test/ui/lifetimes/re-empty-in-error.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | foo(&10); | ^^^^^^^^ | - = note: could not prove for<'b, 'r> &'b (): 'r + = note: could not prove `for<'b, 'r> &'b (): 'r` error: aborting due to previous error diff --git a/src/test/ui/mir/issue-67947.rs b/src/test/ui/mir/issue-67947.rs index 79e75e655ff1f..f73d38f80426f 100644 --- a/src/test/ui/mir/issue-67947.rs +++ b/src/test/ui/mir/issue-67947.rs @@ -1,6 +1,6 @@ struct Bug { A: [(); { *"" }.len()], - //~^ ERROR: cannot move a value of type str + //~^ ERROR: cannot move a value of type `str` //~| ERROR: cannot move out of a shared reference } diff --git a/src/test/ui/mir/issue-67947.stderr b/src/test/ui/mir/issue-67947.stderr index d526218162076..7697a411eb481 100644 --- a/src/test/ui/mir/issue-67947.stderr +++ b/src/test/ui/mir/issue-67947.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type str: the size of str cannot be statically determined +error[E0161]: cannot move a value of type `str` --> $DIR/issue-67947.rs:2:13 | LL | A: [(); { *"" }.len()], - | ^^^^^^^ + | ^^^^^^^ the size of `str` cannot be statically determined error[E0507]: cannot move out of a shared reference --> $DIR/issue-67947.rs:2:15 diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.rs b/src/test/ui/object-safety/object-safety-by-value-self-use.rs index f903f26c0901d..8e93c538217bb 100644 --- a/src/test/ui/object-safety/object-safety-by-value-self-use.rs +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.rs @@ -12,7 +12,7 @@ trait Baz { } fn use_bar(t: Box<dyn Bar>) { - t.bar() //~ ERROR cannot move a value of type dyn Bar + t.bar() //~ ERROR cannot move a value of type `dyn Bar` } fn main() { } diff --git a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr index 7ccc0cbdd576b..94fdcdf263ae0 100644 --- a/src/test/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/src/test/ui/object-safety/object-safety-by-value-self-use.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type dyn Bar: the size of dyn Bar cannot be statically determined +error[E0161]: cannot move a value of type `dyn Bar` --> $DIR/object-safety-by-value-self-use.rs:15:5 | LL | t.bar() - | ^^^^^^^ + | ^^^^^^^ the size of `dyn Bar` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/panic-runtime/auxiliary/needs-abort.rs b/src/test/ui/panic-runtime/auxiliary/needs-abort.rs new file mode 100644 index 0000000000000..8fad49b5e9d32 --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/needs-abort.rs @@ -0,0 +1,5 @@ +// compile-flags:-C panic=abort +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] diff --git a/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs b/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs new file mode 100644 index 0000000000000..d555b531986b0 --- /dev/null +++ b/src/test/ui/panic-runtime/auxiliary/needs-unwind.rs @@ -0,0 +1,13 @@ +// compile-flags:-C panic=unwind +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] +#![feature(c_unwind)] + +extern "C-unwind" fn foo() {} + +fn bar() { + let ptr: extern "C-unwind" fn() = foo; + ptr(); +} diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.rs b/src/test/ui/panic-runtime/need-abort-got-unwind.rs new file mode 100644 index 0000000000000..c72fb96e357f0 --- /dev/null +++ b/src/test/ui/panic-runtime/need-abort-got-unwind.rs @@ -0,0 +1,9 @@ +// build-fail +// needs-unwind +// error-pattern:is incompatible with this crate's strategy of `unwind` +// aux-build:needs-abort.rs +// ignore-wasm32-bare compiled with panic=abort by default + +extern crate needs_abort; + +fn main() {} diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.stderr b/src/test/ui/panic-runtime/need-abort-got-unwind.stderr new file mode 100644 index 0000000000000..d29c7875fd0ff --- /dev/null +++ b/src/test/ui/panic-runtime/need-abort-got-unwind.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` + +error: aborting due to previous error + diff --git a/src/test/ui/panic-runtime/need-unwind-got-abort.rs b/src/test/ui/panic-runtime/need-unwind-got-abort.rs new file mode 100644 index 0000000000000..6752ecf90d2f7 --- /dev/null +++ b/src/test/ui/panic-runtime/need-unwind-got-abort.rs @@ -0,0 +1,9 @@ +// build-fail +// error-pattern:is incompatible with this crate's strategy of `abort` +// aux-build:needs-unwind.rs +// compile-flags:-C panic=abort +// no-prefer-dynamic + +extern crate needs_unwind; + +fn main() {} diff --git a/src/test/ui/panic-runtime/need-unwind-got-abort.stderr b/src/test/ui/panic-runtime/need-unwind-got-abort.stderr new file mode 100644 index 0000000000000..4c71df3ebc147 --- /dev/null +++ b/src/test/ui/panic-runtime/need-unwind-got-abort.stderr @@ -0,0 +1,4 @@ +error: the crate `needs_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` + +error: aborting due to previous error + diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr index 4af754c81f97c..7f4a8ed290ecf 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.stderr @@ -2,9 +2,7 @@ error: cannot link together two panic runtimes: panic_runtime_unwind and panic_r error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index c48caaf079077..23bfea6af15c1 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,6 +1,6 @@ // build-fail // needs-unwind -// error-pattern:is incompatible with this crate's strategy of `unwind` +// error-pattern:is not compiled with this crate's panic strategy `unwind` // aux-build:panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr index d4fd2cca81fdc..d306ce6c5ea28 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.stderr +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.stderr @@ -1,6 +1,4 @@ error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr index 364a27a24eb70..014437b7f1b66 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.stderr @@ -1,8 +1,6 @@ error: the linked panic runtime `panic_runtime_abort` is not compiled with this crate's panic strategy `unwind` -error: the crate `wants_panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` +error: the crate `wants_panic_runtime_abort` requires panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -error: the crate `panic_runtime_abort` is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.rs b/src/test/ui/unsized/return-unsized-from-trait-method.rs index ebe6edd101014..f053f4b0af89c 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.rs +++ b/src/test/ui/unsized/return-unsized-from-trait-method.rs @@ -7,7 +7,7 @@ trait Foo { fn foo(f: Option<&dyn Foo>) { if let Some(f) = f { let _ = f.foo(); - //~^ ERROR cannot move a value of type [u8]: the size of [u8] cannot be statically determined + //~^ ERROR cannot move a value of type `[u8]` } } diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.stderr b/src/test/ui/unsized/return-unsized-from-trait-method.stderr index 4dd7cf5e02fc2..671d409937cac 100644 --- a/src/test/ui/unsized/return-unsized-from-trait-method.stderr +++ b/src/test/ui/unsized/return-unsized-from-trait-method.stderr @@ -1,8 +1,8 @@ -error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined +error[E0161]: cannot move a value of type `[u8]` --> $DIR/return-unsized-from-trait-method.rs:9:17 | LL | let _ = f.foo(); - | ^^^^^^^ + | ^^^^^^^ the size of `[u8]` cannot be statically determined error: aborting due to previous error diff --git a/src/test/ui/unwind-abis/feature-gate-c-unwind.rs b/src/test/ui/unwind-abis/feature-gate-c-unwind.rs index f02a368d4e097..ba72f74f20ce6 100644 --- a/src/test/ui/unwind-abis/feature-gate-c-unwind.rs +++ b/src/test/ui/unwind-abis/feature-gate-c-unwind.rs @@ -1,6 +1,10 @@ // Test that the "C-unwind" ABI is feature-gated, and cannot be used when the // `c_unwind` feature gate is not used. +#![allow(ffi_unwind_calls)] +//~^ WARNING unknown lint: `ffi_unwind_calls` +//~| WARNING unknown lint: `ffi_unwind_calls` + extern "C-unwind" fn f() {} //~^ ERROR C-unwind ABI is experimental and subject to change [E0658] diff --git a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr index f4c785a235f67..a67f46cd2e3b6 100644 --- a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr +++ b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr @@ -1,5 +1,16 @@ +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unknown_lints)]` on by default + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + error[E0658]: C-unwind ABI is experimental and subject to change - --> $DIR/feature-gate-c-unwind.rs:4:8 + --> $DIR/feature-gate-c-unwind.rs:8:8 | LL | extern "C-unwind" fn f() {} | ^^^^^^^^^^ @@ -7,6 +18,16 @@ LL | extern "C-unwind" fn f() {} = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information = help: add `#![feature(c_unwind)]` to the crate attributes to enable -error: aborting due to previous error +warning: unknown lint: `ffi_unwind_calls` + --> $DIR/feature-gate-c-unwind.rs:4:1 + | +LL | #![allow(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `ffi_unwind_calls` lint is unstable + = note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information + = help: add `#![feature(c_unwind)]` to the crate attributes to enable + +error: aborting due to previous error; 2 warnings emitted For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs new file mode 100644 index 0000000000000..67c20e9eac54e --- /dev/null +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs @@ -0,0 +1,25 @@ +// build-pass + +#![feature(c_unwind)] +#![warn(ffi_unwind_calls)] + +mod foo { + #[no_mangle] + pub extern "C-unwind" fn foo() {} +} + +extern "C-unwind" { + fn foo(); +} + +fn main() { + // Call to Rust function is fine. + foo::foo(); + // Call to foreign function should warn. + unsafe { foo(); } + //~^ WARNING call to foreign function with FFI-unwind ABI + let ptr: extern "C-unwind" fn() = foo::foo; + // Call to function pointer should also warn. + ptr(); + //~^ WARNING call to function pointer with FFI-unwind ABI +} diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr new file mode 100644 index 0000000000000..cf8a7782e35ee --- /dev/null +++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr @@ -0,0 +1,20 @@ +warning: call to foreign function with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:19:14 + | +LL | unsafe { foo(); } + | ^^^^^ call to foreign function with FFI-unwind ABI + | +note: the lint level is defined here + --> $DIR/ffi-unwind-calls-lint.rs:4:9 + | +LL | #![warn(ffi_unwind_calls)] + | ^^^^^^^^^^^^^^^^ + +warning: call to function pointer with FFI-unwind ABI + --> $DIR/ffi-unwind-calls-lint.rs:23:5 + | +LL | ptr(); + | ^^^^^ call to function pointer with FFI-unwind ABI + +warning: 2 warnings emitted + diff --git a/triagebot.toml b/triagebot.toml index 100dfd613f0cb..bebb583e100a4 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -219,7 +219,7 @@ changelog-branch = "master" [mentions."compiler/rustc_apfloat"] message = """ -Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost +Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost \ certainly don't want to change it (see #55993). """ cc = ["@eddyb"] @@ -258,22 +258,22 @@ cc = ["@GuillaumeGomez"] message = """ Hey! It looks like you've submitted a new PR for the library teams! -If this PR contains changes to any `rust-lang/rust` public library APIs then -please comment with `@rustbot label +T-libs-api -T-libs` to tag it -appropriately. If this PR contains changes to any unstable APIs please edit -the PR description to add a link to the relevant [API Change -Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) -or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) -if you haven't already. If you're unsure where your change falls no worries, -just leave it as is and the reviewer will take a look and make a decision to +If this PR contains changes to any `rust-lang/rust` public library APIs then \ +please comment with `@rustbot label +T-libs-api -T-libs` to tag it \ +appropriately. If this PR contains changes to any unstable APIs please edit \ +the PR description to add a link to the relevant [API Change \ +Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) \ +or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) \ +if you haven't already. If you're unsure where your change falls no worries, \ +just leave it as is and the reviewer will take a look and make a decision to \ forward on if necessary. Examples of `T-libs-api` changes: * Stabilizing library features -* Introducing insta-stable changes such as new implementations of existing +* Introducing insta-stable changes such as new implementations of existing \ stable traits on existing stable types -* Introducing new or changing existing unstable library APIs (excluding +* Introducing new or changing existing unstable library APIs (excluding \ permanently unstable features / features without a tracking issue) * Changing public documentation in ways that create new stability guarantees * Changing observable runtime behavior of library APIs @@ -300,8 +300,8 @@ cc = ["@Cldfire"] [mentions."src/rustdoc-json-types"] message = """ -rustdoc-json-types is a **public** (although nightly-only) API. -If possible, consider changing `src/librustdoc/json/conversions.rs`; +rustdoc-json-types is a **public** (although nightly-only) API. \ +If possible, consider changing `src/librustdoc/json/conversions.rs`; \ otherwise, make sure you bump the `FORMAT_VERSION` constant. """ cc = [