| author | bors <bors@rust-lang.org> 2026-03-05 00:14:57 UTC |
| committer | bors <bors@rust-lang.org> 2026-03-05 00:14:57 UTC |
| log | f8704be04fe1150527fc2cf21dd44327f0fe87fb |
| tree | 8b92af487814146f5926991f963dc99b822aa811 |
| parent | b55e20ad905a336395ca80863488d0827712d067 |
| parent | 53ef4d297ed951adf7f95f2ee6617c03436f208d |
Rollup of 12 pull requests
Successful merges:
- rust-lang/rust#153402 (miri subtree update)
- rust-lang/rust#152164 (Lint unused features)
- rust-lang/rust#152801 (Refactor WriteBackendMethods a bit)
- rust-lang/rust#153196 (Update path separators to be available in const context)
- rust-lang/rust#153204 (Add `#[must_use]` attribute to `HashMap` and `HashSet` constructors)
- rust-lang/rust#153317 (Abort after `representability` errors)
- rust-lang/rust#153276 (Remove `cycle_fatal` query modifier)
- rust-lang/rust#153300 (Tweak some of our internal `#[rustc_*]` TEST attributes)
- rust-lang/rust#153396 (use `minicore` in some `run-make` tests)
- rust-lang/rust#153401 (Migrationg of `LintDiagnostic` - part 7)
- rust-lang/rust#153406 (Remove a ping for myself)
- rust-lang/rust#153414 (Rename translation -> formatting)309 files changed, 1947 insertions(+), 1785 deletions(-)
compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs+85-4| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | use rustc_hir::Target; | |
| 2 | 1 | use rustc_hir::attrs::AttributeKind; |
| 2 | use rustc_hir::{MethodKind, Target}; | |
| 3 | 3 | use rustc_span::{Span, Symbol, sym}; |
| 4 | 4 | |
| 5 | 5 | use crate::attributes::prelude::Allow; |
| ... | ... | @@ -25,6 +25,20 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParentsParser { |
| 25 | 25 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub(crate) struct RustcDumpInferredOutlivesParser; | |
| 29 | ||
| 30 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpInferredOutlivesParser { | |
| 31 | const PATH: &[Symbol] = &[sym::rustc_dump_inferred_outlives]; | |
| 32 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 33 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | |
| 34 | Allow(Target::Struct), | |
| 35 | Allow(Target::Enum), | |
| 36 | Allow(Target::Union), | |
| 37 | Allow(Target::TyAlias), | |
| 38 | ]); | |
| 39 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpInferredOutlives; | |
| 40 | } | |
| 41 | ||
| 28 | 42 | pub(crate) struct RustcDumpItemBoundsParser; |
| 29 | 43 | |
| 30 | 44 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser { |
| ... | ... | @@ -34,21 +48,88 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser { |
| 34 | 48 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; |
| 35 | 49 | } |
| 36 | 50 | |
| 51 | pub(crate) struct RustcDumpObjectLifetimeDefaultsParser; | |
| 52 | ||
| 53 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpObjectLifetimeDefaultsParser { | |
| 54 | const PATH: &[Symbol] = &[sym::rustc_dump_object_lifetime_defaults]; | |
| 55 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; | |
| 56 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | |
| 57 | Allow(Target::AssocConst), | |
| 58 | Allow(Target::AssocTy), | |
| 59 | Allow(Target::Const), | |
| 60 | Allow(Target::Enum), | |
| 61 | Allow(Target::Fn), | |
| 62 | Allow(Target::ForeignFn), | |
| 63 | Allow(Target::Impl { of_trait: false }), | |
| 64 | Allow(Target::Impl { of_trait: true }), | |
| 65 | Allow(Target::Method(MethodKind::Inherent)), | |
| 66 | Allow(Target::Method(MethodKind::Trait { body: false })), | |
| 67 | Allow(Target::Method(MethodKind::Trait { body: true })), | |
| 68 | Allow(Target::Method(MethodKind::TraitImpl)), | |
| 69 | Allow(Target::Struct), | |
| 70 | Allow(Target::Trait), | |
| 71 | Allow(Target::TraitAlias), | |
| 72 | Allow(Target::TyAlias), | |
| 73 | Allow(Target::Union), | |
| 74 | ]); | |
| 75 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpObjectLifetimeDefaults; | |
| 76 | } | |
| 77 | ||
| 37 | 78 | pub(crate) struct RustcDumpPredicatesParser; |
| 38 | 79 | |
| 39 | 80 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicatesParser { |
| 40 | 81 | const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; |
| 41 | 82 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; |
| 42 | 83 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 43 | Allow(Target::Struct), | |
| 84 | Allow(Target::AssocConst), | |
| 85 | Allow(Target::AssocTy), | |
| 86 | Allow(Target::Const), | |
| 87 | Allow(Target::Delegation { mac: false }), | |
| 88 | Allow(Target::Delegation { mac: true }), | |
| 44 | 89 | Allow(Target::Enum), |
| 45 | Allow(Target::Union), | |
| 90 | Allow(Target::Fn), | |
| 91 | Allow(Target::Impl { of_trait: false }), | |
| 92 | Allow(Target::Impl { of_trait: true }), | |
| 93 | Allow(Target::Method(MethodKind::Inherent)), | |
| 94 | Allow(Target::Method(MethodKind::Trait { body: false })), | |
| 95 | Allow(Target::Method(MethodKind::Trait { body: true })), | |
| 96 | Allow(Target::Method(MethodKind::TraitImpl)), | |
| 97 | Allow(Target::Struct), | |
| 46 | 98 | Allow(Target::Trait), |
| 47 | Allow(Target::AssocTy), | |
| 99 | Allow(Target::TraitAlias), | |
| 100 | Allow(Target::TyAlias), | |
| 101 | Allow(Target::Union), | |
| 48 | 102 | ]); |
| 49 | 103 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates; |
| 50 | 104 | } |
| 51 | 105 | |
| 106 | pub(crate) struct RustcDumpVariancesParser; | |
| 107 | ||
| 108 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVariancesParser { | |
| 109 | const PATH: &[Symbol] = &[sym::rustc_dump_variances]; | |
| 110 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 111 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | |
| 112 | Allow(Target::Enum), | |
| 113 | Allow(Target::Fn), | |
| 114 | Allow(Target::Method(MethodKind::Inherent)), | |
| 115 | Allow(Target::Method(MethodKind::Trait { body: false })), | |
| 116 | Allow(Target::Method(MethodKind::Trait { body: true })), | |
| 117 | Allow(Target::Method(MethodKind::TraitImpl)), | |
| 118 | Allow(Target::Struct), | |
| 119 | Allow(Target::Union), | |
| 120 | ]); | |
| 121 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariances; | |
| 122 | } | |
| 123 | ||
| 124 | pub(crate) struct RustcDumpVariancesOfOpaquesParser; | |
| 125 | ||
| 126 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVariancesOfOpaquesParser { | |
| 127 | const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; | |
| 128 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 129 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); | |
| 130 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; | |
| 131 | } | |
| 132 | ||
| 52 | 133 | pub(crate) struct RustcDumpVtableParser; |
| 53 | 134 | |
| 54 | 135 | impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpVtableParser { |
compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs-9| ... | ... | @@ -588,15 +588,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationPa |
| 588 | 588 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation; |
| 589 | 589 | } |
| 590 | 590 | |
| 591 | pub(crate) struct RustcObjectLifetimeDefaultParser; | |
| 592 | ||
| 593 | impl<S: Stage> NoArgsAttributeParser<S> for RustcObjectLifetimeDefaultParser { | |
| 594 | const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default]; | |
| 595 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; | |
| 596 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); | |
| 597 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcObjectLifetimeDefault; | |
| 598 | } | |
| 599 | ||
| 600 | 591 | pub(crate) struct RustcSimdMonomorphizeLaneLimitParser; |
| 601 | 592 | |
| 602 | 593 | impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser { |
compiler/rustc_attr_parsing/src/attributes/test_attrs.rs-36| ... | ... | @@ -93,28 +93,6 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser { |
| 93 | 93 | } |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | pub(crate) struct RustcVarianceParser; | |
| 97 | ||
| 98 | impl<S: Stage> NoArgsAttributeParser<S> for RustcVarianceParser { | |
| 99 | const PATH: &[Symbol] = &[sym::rustc_variance]; | |
| 100 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 101 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | |
| 102 | Allow(Target::Struct), | |
| 103 | Allow(Target::Enum), | |
| 104 | Allow(Target::Union), | |
| 105 | ]); | |
| 106 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVariance; | |
| 107 | } | |
| 108 | ||
| 109 | pub(crate) struct RustcVarianceOfOpaquesParser; | |
| 110 | ||
| 111 | impl<S: Stage> NoArgsAttributeParser<S> for RustcVarianceOfOpaquesParser { | |
| 112 | const PATH: &[Symbol] = &[sym::rustc_variance_of_opaques]; | |
| 113 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 114 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); | |
| 115 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVarianceOfOpaques; | |
| 116 | } | |
| 117 | ||
| 118 | 96 | pub(crate) struct ReexportTestHarnessMainParser; |
| 119 | 97 | |
| 120 | 98 | impl<S: Stage> SingleAttributeParser<S> for ReexportTestHarnessMainParser { |
| ... | ... | @@ -215,20 +193,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEvaluateWhereClausesParser { |
| 215 | 193 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses; |
| 216 | 194 | } |
| 217 | 195 | |
| 218 | pub(crate) struct RustcOutlivesParser; | |
| 219 | ||
| 220 | impl<S: Stage> NoArgsAttributeParser<S> for RustcOutlivesParser { | |
| 221 | const PATH: &[Symbol] = &[sym::rustc_outlives]; | |
| 222 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; | |
| 223 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ | |
| 224 | Allow(Target::Struct), | |
| 225 | Allow(Target::Enum), | |
| 226 | Allow(Target::Union), | |
| 227 | Allow(Target::TyAlias), | |
| 228 | ]); | |
| 229 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOutlives; | |
| 230 | } | |
| 231 | ||
| 232 | 196 | pub(crate) struct TestRunnerParser; |
| 233 | 197 | |
| 234 | 198 | impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser { |
compiler/rustc_attr_parsing/src/context.rs+4-4| ... | ... | @@ -281,9 +281,13 @@ attribute_parsers!( |
| 281 | 281 | Single<WithoutArgs<RustcDenyExplicitImplParser>>, |
| 282 | 282 | Single<WithoutArgs<RustcDoNotConstCheckParser>>, |
| 283 | 283 | Single<WithoutArgs<RustcDumpDefParentsParser>>, |
| 284 | Single<WithoutArgs<RustcDumpInferredOutlivesParser>>, | |
| 284 | 285 | Single<WithoutArgs<RustcDumpItemBoundsParser>>, |
| 286 | Single<WithoutArgs<RustcDumpObjectLifetimeDefaultsParser>>, | |
| 285 | 287 | Single<WithoutArgs<RustcDumpPredicatesParser>>, |
| 286 | 288 | Single<WithoutArgs<RustcDumpUserArgsParser>>, |
| 289 | Single<WithoutArgs<RustcDumpVariancesOfOpaquesParser>>, | |
| 290 | Single<WithoutArgs<RustcDumpVariancesParser>>, | |
| 287 | 291 | Single<WithoutArgs<RustcDumpVtableParser>>, |
| 288 | 292 | Single<WithoutArgs<RustcDynIncompatibleTraitParser>>, |
| 289 | 293 | Single<WithoutArgs<RustcEffectiveVisibilityParser>>, |
| ... | ... | @@ -306,9 +310,7 @@ attribute_parsers!( |
| 306 | 310 | Single<WithoutArgs<RustcNonConstTraitMethodParser>>, |
| 307 | 311 | Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>, |
| 308 | 312 | Single<WithoutArgs<RustcNounwindParser>>, |
| 309 | Single<WithoutArgs<RustcObjectLifetimeDefaultParser>>, | |
| 310 | 313 | Single<WithoutArgs<RustcOffloadKernelParser>>, |
| 311 | Single<WithoutArgs<RustcOutlivesParser>>, | |
| 312 | 314 | Single<WithoutArgs<RustcParenSugarParser>>, |
| 313 | 315 | Single<WithoutArgs<RustcPassByValueParser>>, |
| 314 | 316 | Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>, |
| ... | ... | @@ -323,8 +325,6 @@ attribute_parsers!( |
| 323 | 325 | Single<WithoutArgs<RustcStrictCoherenceParser>>, |
| 324 | 326 | Single<WithoutArgs<RustcTrivialFieldReadsParser>>, |
| 325 | 327 | Single<WithoutArgs<RustcUnsafeSpecializationMarkerParser>>, |
| 326 | Single<WithoutArgs<RustcVarianceOfOpaquesParser>>, | |
| 327 | Single<WithoutArgs<RustcVarianceParser>>, | |
| 328 | 328 | Single<WithoutArgs<ThreadLocalParser>>, |
| 329 | 329 | Single<WithoutArgs<TrackCallerParser>>, |
| 330 | 330 | // tidy-alphabetical-end |
compiler/rustc_borrowck/src/diagnostics/mod.rs+1-1| ... | ... | @@ -1310,7 +1310,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { |
| 1310 | 1310 | { |
| 1311 | 1311 | let mut span: MultiSpan = spans.clone().into(); |
| 1312 | 1312 | err.arg("ty", param_ty.to_string()); |
| 1313 | let msg = err.dcx.eagerly_translate_to_string( | |
| 1313 | let msg = err.dcx.eagerly_format_to_string( | |
| 1314 | 1314 | msg!("`{$ty}` is made to be an `FnOnce` closure here"), |
| 1315 | 1315 | err.args.iter(), |
| 1316 | 1316 | ); |
compiler/rustc_builtin_macros/src/errors.rs+3-3| ... | ... | @@ -764,7 +764,7 @@ pub(crate) struct FormatUnusedArg { |
| 764 | 764 | impl Subdiagnostic for FormatUnusedArg { |
| 765 | 765 | fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { |
| 766 | 766 | diag.arg("named", self.named); |
| 767 | let msg = diag.eagerly_translate(msg!( | |
| 767 | let msg = diag.eagerly_format(msg!( | |
| 768 | 768 | "{$named -> |
| 769 | 769 | [true] named argument |
| 770 | 770 | *[false] argument |
| ... | ... | @@ -947,8 +947,8 @@ pub(crate) struct AsmClobberNoReg { |
| 947 | 947 | impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg { |
| 948 | 948 | fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { |
| 949 | 949 | // eager translation as `span_labels` takes `AsRef<str>` |
| 950 | let lbl1 = dcx.eagerly_translate_to_string(msg!("clobber_abi"), [].into_iter()); | |
| 951 | let lbl2 = dcx.eagerly_translate_to_string(msg!("generic outputs"), [].into_iter()); | |
| 950 | let lbl1 = dcx.eagerly_format_to_string(msg!("clobber_abi"), [].into_iter()); | |
| 951 | let lbl2 = dcx.eagerly_format_to_string(msg!("generic outputs"), [].into_iter()); | |
| 952 | 952 | Diag::new( |
| 953 | 953 | dcx, |
| 954 | 954 | level, |
compiler/rustc_codegen_gcc/src/back/lto.rs+6-6| ... | ... | @@ -26,7 +26,7 @@ use object::read::archive::ArchiveFile; |
| 26 | 26 | use rustc_codegen_ssa::back::lto::SerializedModule; |
| 27 | 27 | use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; |
| 28 | 28 | use rustc_codegen_ssa::traits::*; |
| 29 | use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; | |
| 29 | use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file}; | |
| 30 | 30 | use rustc_data_structures::memmap::Mmap; |
| 31 | 31 | use rustc_data_structures::profiling::SelfProfilerRef; |
| 32 | 32 | use rustc_errors::{DiagCtxt, DiagCtxtHandle}; |
| ... | ... | @@ -34,7 +34,7 @@ use rustc_log::tracing::info; |
| 34 | 34 | use rustc_session::config::Lto; |
| 35 | 35 | use tempfile::{TempDir, tempdir}; |
| 36 | 36 | |
| 37 | use crate::back::write::save_temp_bitcode; | |
| 37 | use crate::back::write::{codegen, save_temp_bitcode}; | |
| 38 | 38 | use crate::errors::LtoBitcodeFromRlib; |
| 39 | 39 | use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; |
| 40 | 40 | |
| ... | ... | @@ -112,7 +112,7 @@ pub(crate) fn run_fat( |
| 112 | 112 | shared_emitter: &SharedEmitter, |
| 113 | 113 | each_linked_rlib_for_lto: &[PathBuf], |
| 114 | 114 | modules: Vec<FatLtoInput<GccCodegenBackend>>, |
| 115 | ) -> ModuleCodegen<GccContext> { | |
| 115 | ) -> CompiledModule { | |
| 116 | 116 | let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); |
| 117 | 117 | let dcx = dcx.handle(); |
| 118 | 118 | let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); |
| ... | ... | @@ -132,12 +132,12 @@ pub(crate) fn run_fat( |
| 132 | 132 | fn fat_lto( |
| 133 | 133 | cgcx: &CodegenContext, |
| 134 | 134 | prof: &SelfProfilerRef, |
| 135 | _dcx: DiagCtxtHandle<'_>, | |
| 135 | dcx: DiagCtxtHandle<'_>, | |
| 136 | 136 | modules: Vec<FatLtoInput<GccCodegenBackend>>, |
| 137 | 137 | mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>, |
| 138 | 138 | tmp_path: TempDir, |
| 139 | 139 | //symbols_below_threshold: &[String], |
| 140 | ) -> ModuleCodegen<GccContext> { | |
| 140 | ) -> CompiledModule { | |
| 141 | 141 | let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); |
| 142 | 142 | info!("going for a fat lto"); |
| 143 | 143 | |
| ... | ... | @@ -260,7 +260,7 @@ fn fat_lto( |
| 260 | 260 | // of now. |
| 261 | 261 | module.module_llvm.temp_dir = Some(tmp_path); |
| 262 | 262 | |
| 263 | module | |
| 263 | codegen(cgcx, prof, dcx, module, &cgcx.module_config) | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | pub struct ModuleBuffer(PathBuf); |
compiler/rustc_codegen_gcc/src/back/write.rs+3-8| ... | ... | @@ -2,12 +2,10 @@ use std::{env, fs}; |
| 2 | 2 | |
| 3 | 3 | use gccjit::{Context, OutputKind}; |
| 4 | 4 | use rustc_codegen_ssa::back::link::ensure_removed; |
| 5 | use rustc_codegen_ssa::back::write::{ | |
| 6 | BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter, | |
| 7 | }; | |
| 5 | use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; | |
| 8 | 6 | use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; |
| 9 | 7 | use rustc_data_structures::profiling::SelfProfilerRef; |
| 10 | use rustc_errors::DiagCtxt; | |
| 8 | use rustc_errors::DiagCtxtHandle; | |
| 11 | 9 | use rustc_fs_util::link_or_copy; |
| 12 | 10 | use rustc_log::tracing::debug; |
| 13 | 11 | use rustc_session::config::OutputType; |
| ... | ... | @@ -20,13 +18,10 @@ use crate::{GccContext, LtoMode}; |
| 20 | 18 | pub(crate) fn codegen( |
| 21 | 19 | cgcx: &CodegenContext, |
| 22 | 20 | prof: &SelfProfilerRef, |
| 23 | shared_emitter: &SharedEmitter, | |
| 21 | dcx: DiagCtxtHandle<'_>, | |
| 24 | 22 | module: ModuleCodegen<GccContext>, |
| 25 | 23 | config: &ModuleConfig, |
| 26 | 24 | ) -> CompiledModule { |
| 27 | let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); | |
| 28 | let dcx = dcx.handle(); | |
| 29 | ||
| 30 | 25 | let _timer = prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); |
| 31 | 26 | { |
| 32 | 27 | let context = &module.module_llvm.context; |
compiler/rustc_codegen_gcc/src/lib.rs+18-24| ... | ... | @@ -92,7 +92,7 @@ use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodege |
| 92 | 92 | use rustc_data_structures::fx::FxIndexMap; |
| 93 | 93 | use rustc_data_structures::profiling::SelfProfilerRef; |
| 94 | 94 | use rustc_data_structures::sync::IntoDynSyncSend; |
| 95 | use rustc_errors::DiagCtxtHandle; | |
| 95 | use rustc_errors::{DiagCtxt, DiagCtxtHandle}; | |
| 96 | 96 | use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; |
| 97 | 97 | use rustc_middle::ty::TyCtxt; |
| 98 | 98 | use rustc_middle::util::Providers; |
| ... | ... | @@ -371,16 +371,6 @@ impl ExtraBackendMethods for GccCodegenBackend { |
| 371 | 371 | self.lto_supported.load(Ordering::SeqCst), |
| 372 | 372 | ) |
| 373 | 373 | } |
| 374 | ||
| 375 | fn target_machine_factory( | |
| 376 | &self, | |
| 377 | _sess: &Session, | |
| 378 | _opt_level: OptLevel, | |
| 379 | _features: &[String], | |
| 380 | ) -> TargetMachineFactoryFn<Self> { | |
| 381 | // TODO(antoyo): set opt level. | |
| 382 | Arc::new(|_, _| ()) | |
| 383 | } | |
| 384 | 374 | } |
| 385 | 375 | |
| 386 | 376 | #[derive(Clone, Copy, PartialEq)] |
| ... | ... | @@ -429,7 +419,17 @@ impl WriteBackendMethods for GccCodegenBackend { |
| 429 | 419 | type ModuleBuffer = ModuleBuffer; |
| 430 | 420 | type ThinData = (); |
| 431 | 421 | |
| 432 | fn run_and_optimize_fat_lto( | |
| 422 | fn target_machine_factory( | |
| 423 | &self, | |
| 424 | _sess: &Session, | |
| 425 | _opt_level: OptLevel, | |
| 426 | _features: &[String], | |
| 427 | ) -> TargetMachineFactoryFn<Self> { | |
| 428 | // TODO(antoyo): set opt level. | |
| 429 | Arc::new(|_, _| ()) | |
| 430 | } | |
| 431 | ||
| 432 | fn optimize_and_codegen_fat_lto( | |
| 433 | 433 | cgcx: &CodegenContext, |
| 434 | 434 | prof: &SelfProfilerRef, |
| 435 | 435 | shared_emitter: &SharedEmitter, |
| ... | ... | @@ -438,7 +438,7 @@ impl WriteBackendMethods for GccCodegenBackend { |
| 438 | 438 | _exported_symbols_for_lto: &[String], |
| 439 | 439 | each_linked_rlib_for_lto: &[PathBuf], |
| 440 | 440 | modules: Vec<FatLtoInput<Self>>, |
| 441 | ) -> ModuleCodegen<Self::Module> { | |
| 441 | ) -> CompiledModule { | |
| 442 | 442 | back::lto::run_fat(cgcx, prof, shared_emitter, each_linked_rlib_for_lto, modules) |
| 443 | 443 | } |
| 444 | 444 | |
| ... | ... | @@ -455,14 +455,6 @@ impl WriteBackendMethods for GccCodegenBackend { |
| 455 | 455 | unreachable!() |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | fn print_pass_timings(&self) { | |
| 459 | unimplemented!(); | |
| 460 | } | |
| 461 | ||
| 462 | fn print_statistics(&self) { | |
| 463 | unimplemented!() | |
| 464 | } | |
| 465 | ||
| 466 | 458 | fn optimize( |
| 467 | 459 | _cgcx: &CodegenContext, |
| 468 | 460 | _prof: &SelfProfilerRef, |
| ... | ... | @@ -473,13 +465,13 @@ impl WriteBackendMethods for GccCodegenBackend { |
| 473 | 465 | module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); |
| 474 | 466 | } |
| 475 | 467 | |
| 476 | fn optimize_thin( | |
| 468 | fn optimize_and_codegen_thin( | |
| 477 | 469 | _cgcx: &CodegenContext, |
| 478 | 470 | _prof: &SelfProfilerRef, |
| 479 | 471 | _shared_emitter: &SharedEmitter, |
| 480 | 472 | _tm_factory: TargetMachineFactoryFn<Self>, |
| 481 | 473 | _thin: ThinModule<Self>, |
| 482 | ) -> ModuleCodegen<Self::Module> { | |
| 474 | ) -> CompiledModule { | |
| 483 | 475 | unreachable!() |
| 484 | 476 | } |
| 485 | 477 | |
| ... | ... | @@ -490,7 +482,9 @@ impl WriteBackendMethods for GccCodegenBackend { |
| 490 | 482 | module: ModuleCodegen<Self::Module>, |
| 491 | 483 | config: &ModuleConfig, |
| 492 | 484 | ) -> CompiledModule { |
| 493 | back::write::codegen(cgcx, prof, shared_emitter, module, config) | |
| 485 | let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); | |
| 486 | let dcx = dcx.handle(); | |
| 487 | back::write::codegen(cgcx, prof, dcx, module, config) | |
| 494 | 488 | } |
| 495 | 489 | |
| 496 | 490 | fn serialize_module(_module: Self::Module, _is_thin: bool) -> Self::ModuleBuffer { |
compiler/rustc_codegen_llvm/src/back/lto.rs+6-5| ... | ... | @@ -12,7 +12,7 @@ use rustc_codegen_ssa::back::write::{ |
| 12 | 12 | CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn, |
| 13 | 13 | }; |
| 14 | 14 | use rustc_codegen_ssa::traits::*; |
| 15 | use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; | |
| 15 | use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file}; | |
| 16 | 16 | use rustc_data_structures::fx::FxHashMap; |
| 17 | 17 | use rustc_data_structures::memmap::Mmap; |
| 18 | 18 | use rustc_data_structures::profiling::SelfProfilerRef; |
| ... | ... | @@ -24,7 +24,8 @@ use rustc_session::config::{self, Lto}; |
| 24 | 24 | use tracing::{debug, info}; |
| 25 | 25 | |
| 26 | 26 | use crate::back::write::{ |
| 27 | self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, save_temp_bitcode, | |
| 27 | self, CodegenDiagnosticsStage, DiagnosticHandlers, bitcode_section_name, codegen, | |
| 28 | save_temp_bitcode, | |
| 28 | 29 | }; |
| 29 | 30 | use crate::errors::{LlvmError, LtoBitcodeFromRlib}; |
| 30 | 31 | use crate::llvm::{self, build_string}; |
| ... | ... | @@ -709,13 +710,13 @@ impl ModuleBufferMethods for ModuleBuffer { |
| 709 | 710 | } |
| 710 | 711 | } |
| 711 | 712 | |
| 712 | pub(crate) fn optimize_thin_module( | |
| 713 | pub(crate) fn optimize_and_codegen_thin_module( | |
| 713 | 714 | cgcx: &CodegenContext, |
| 714 | 715 | prof: &SelfProfilerRef, |
| 715 | 716 | shared_emitter: &SharedEmitter, |
| 716 | 717 | tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>, |
| 717 | 718 | thin_module: ThinModule<LlvmCodegenBackend>, |
| 718 | ) -> ModuleCodegen<ModuleLlvm> { | |
| 719 | ) -> CompiledModule { | |
| 719 | 720 | let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); |
| 720 | 721 | let dcx = dcx.handle(); |
| 721 | 722 | |
| ... | ... | @@ -794,7 +795,7 @@ pub(crate) fn optimize_thin_module( |
| 794 | 795 | save_temp_bitcode(cgcx, &module, "thin-lto-after-pm"); |
| 795 | 796 | } |
| 796 | 797 | } |
| 797 | module | |
| 798 | codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config) | |
| 798 | 799 | } |
| 799 | 800 | |
| 800 | 801 | /// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys |
compiler/rustc_codegen_llvm/src/back/write.rs+5-10| ... | ... | @@ -335,13 +335,13 @@ pub(crate) fn save_temp_bitcode( |
| 335 | 335 | &module.name, |
| 336 | 336 | cgcx.invocation_temp.as_deref(), |
| 337 | 337 | ); |
| 338 | write_bitcode_to_file(module, &path) | |
| 338 | write_bitcode_to_file(&module.module_llvm, &path) | |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) { | |
| 341 | fn write_bitcode_to_file(module: &ModuleLlvm, path: &Path) { | |
| 342 | 342 | unsafe { |
| 343 | 343 | let path = path_to_c_string(&path); |
| 344 | let llmod = module.module_llvm.llmod(); | |
| 344 | let llmod = module.llmod(); | |
| 345 | 345 | llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr()); |
| 346 | 346 | } |
| 347 | 347 | } |
| ... | ... | @@ -905,13 +905,8 @@ pub(crate) fn optimize( |
| 905 | 905 | let _handlers = |
| 906 | 906 | DiagnosticHandlers::new(cgcx, shared_emitter, llcx, module, CodegenDiagnosticsStage::Opt); |
| 907 | 907 | |
| 908 | if config.emit_no_opt_bc { | |
| 909 | let out = cgcx.output_filenames.temp_path_ext_for_cgu( | |
| 910 | "no-opt.bc", | |
| 911 | &module.name, | |
| 912 | cgcx.invocation_temp.as_deref(), | |
| 913 | ); | |
| 914 | write_bitcode_to_file(module, &out) | |
| 908 | if module.kind == ModuleKind::Regular { | |
| 909 | save_temp_bitcode(cgcx, module, "no-opt"); | |
| 915 | 910 | } |
| 916 | 911 | |
| 917 | 912 | // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts |
compiler/rustc_codegen_llvm/src/errors.rs+1-1| ... | ... | @@ -24,7 +24,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { |
| 24 | 24 | fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { |
| 25 | 25 | let diag: Diag<'_, G> = self.0.into_diag(dcx, level); |
| 26 | 26 | let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); |
| 27 | let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter()); | |
| 27 | let message = dcx.eagerly_format_to_string(message.clone(), diag.args.iter()); | |
| 28 | 28 | Diag::new( |
| 29 | 29 | dcx, |
| 30 | 30 | level, |
compiler/rustc_codegen_llvm/src/lib.rs+30-47| ... | ... | @@ -79,24 +79,18 @@ pub(crate) use macros::TryFromU32; |
| 79 | 79 | #[derive(Clone)] |
| 80 | 80 | pub struct LlvmCodegenBackend(()); |
| 81 | 81 | |
| 82 | struct TimeTraceProfiler { | |
| 83 | enabled: bool, | |
| 84 | } | |
| 82 | struct TimeTraceProfiler {} | |
| 85 | 83 | |
| 86 | 84 | impl TimeTraceProfiler { |
| 87 | fn new(enabled: bool) -> Self { | |
| 88 | if enabled { | |
| 89 | unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() } | |
| 90 | } | |
| 91 | TimeTraceProfiler { enabled } | |
| 85 | fn new() -> Self { | |
| 86 | unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() } | |
| 87 | TimeTraceProfiler {} | |
| 92 | 88 | } |
| 93 | 89 | } |
| 94 | 90 | |
| 95 | 91 | impl Drop for TimeTraceProfiler { |
| 96 | 92 | fn drop(&mut self) { |
| 97 | if self.enabled { | |
| 98 | unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() } | |
| 99 | } | |
| 93 | unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() } | |
| 100 | 94 | } |
| 101 | 95 | } |
| 102 | 96 | |
| ... | ... | @@ -122,30 +116,6 @@ impl ExtraBackendMethods for LlvmCodegenBackend { |
| 122 | 116 | ) -> (ModuleCodegen<ModuleLlvm>, u64) { |
| 123 | 117 | base::compile_codegen_unit(tcx, cgu_name) |
| 124 | 118 | } |
| 125 | fn target_machine_factory( | |
| 126 | &self, | |
| 127 | sess: &Session, | |
| 128 | optlvl: OptLevel, | |
| 129 | target_features: &[String], | |
| 130 | ) -> TargetMachineFactoryFn<Self> { | |
| 131 | back::write::target_machine_factory(sess, optlvl, target_features) | |
| 132 | } | |
| 133 | ||
| 134 | fn spawn_named_thread<F, T>( | |
| 135 | time_trace: bool, | |
| 136 | name: String, | |
| 137 | f: F, | |
| 138 | ) -> std::io::Result<std::thread::JoinHandle<T>> | |
| 139 | where | |
| 140 | F: FnOnce() -> T, | |
| 141 | F: Send + 'static, | |
| 142 | T: Send + 'static, | |
| 143 | { | |
| 144 | std::thread::Builder::new().name(name).spawn(move || { | |
| 145 | let _profiler = TimeTraceProfiler::new(time_trace); | |
| 146 | f() | |
| 147 | }) | |
| 148 | } | |
| 149 | 119 | } |
| 150 | 120 | |
| 151 | 121 | impl WriteBackendMethods for LlvmCodegenBackend { |
| ... | ... | @@ -153,15 +123,18 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 153 | 123 | type ModuleBuffer = back::lto::ModuleBuffer; |
| 154 | 124 | type TargetMachine = OwnedTargetMachine; |
| 155 | 125 | type ThinData = back::lto::ThinData; |
| 156 | fn print_pass_timings(&self) { | |
| 157 | let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap(); | |
| 158 | print!("{timings}"); | |
| 126 | fn thread_profiler() -> Box<dyn Any> { | |
| 127 | Box::new(TimeTraceProfiler::new()) | |
| 159 | 128 | } |
| 160 | fn print_statistics(&self) { | |
| 161 | let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap(); | |
| 162 | print!("{stats}"); | |
| 129 | fn target_machine_factory( | |
| 130 | &self, | |
| 131 | sess: &Session, | |
| 132 | optlvl: OptLevel, | |
| 133 | target_features: &[String], | |
| 134 | ) -> TargetMachineFactoryFn<Self> { | |
| 135 | back::write::target_machine_factory(sess, optlvl, target_features) | |
| 163 | 136 | } |
| 164 | fn run_and_optimize_fat_lto( | |
| 137 | fn optimize_and_codegen_fat_lto( | |
| 165 | 138 | cgcx: &CodegenContext, |
| 166 | 139 | prof: &SelfProfilerRef, |
| 167 | 140 | shared_emitter: &SharedEmitter, |
| ... | ... | @@ -169,7 +142,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 169 | 142 | exported_symbols_for_lto: &[String], |
| 170 | 143 | each_linked_rlib_for_lto: &[PathBuf], |
| 171 | 144 | modules: Vec<FatLtoInput<Self>>, |
| 172 | ) -> ModuleCodegen<Self::Module> { | |
| 145 | ) -> CompiledModule { | |
| 173 | 146 | let mut module = back::lto::run_fat( |
| 174 | 147 | cgcx, |
| 175 | 148 | prof, |
| ... | ... | @@ -184,7 +157,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 184 | 157 | let dcx = dcx.handle(); |
| 185 | 158 | back::lto::run_pass_manager(cgcx, prof, dcx, &mut module, false); |
| 186 | 159 | |
| 187 | module | |
| 160 | back::write::codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config) | |
| 188 | 161 | } |
| 189 | 162 | fn run_thin_lto( |
| 190 | 163 | cgcx: &CodegenContext, |
| ... | ... | @@ -214,14 +187,14 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 214 | 187 | ) { |
| 215 | 188 | back::write::optimize(cgcx, prof, shared_emitter, module, config) |
| 216 | 189 | } |
| 217 | fn optimize_thin( | |
| 190 | fn optimize_and_codegen_thin( | |
| 218 | 191 | cgcx: &CodegenContext, |
| 219 | 192 | prof: &SelfProfilerRef, |
| 220 | 193 | shared_emitter: &SharedEmitter, |
| 221 | 194 | tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>, |
| 222 | 195 | thin: ThinModule<Self>, |
| 223 | ) -> ModuleCodegen<Self::Module> { | |
| 224 | back::lto::optimize_thin_module(cgcx, prof, shared_emitter, tm_factory, thin) | |
| 196 | ) -> CompiledModule { | |
| 197 | back::lto::optimize_and_codegen_thin_module(cgcx, prof, shared_emitter, tm_factory, thin) | |
| 225 | 198 | } |
| 226 | 199 | fn codegen( |
| 227 | 200 | cgcx: &CodegenContext, |
| ... | ... | @@ -389,6 +362,16 @@ impl CodegenBackend for LlvmCodegenBackend { |
| 389 | 362 | (compiled_modules, work_products) |
| 390 | 363 | } |
| 391 | 364 | |
| 365 | fn print_pass_timings(&self) { | |
| 366 | let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap(); | |
| 367 | print!("{timings}"); | |
| 368 | } | |
| 369 | ||
| 370 | fn print_statistics(&self) { | |
| 371 | let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap(); | |
| 372 | print!("{stats}"); | |
| 373 | } | |
| 374 | ||
| 392 | 375 | fn link( |
| 393 | 376 | &self, |
| 394 | 377 | sess: &Session, |
compiler/rustc_codegen_ssa/src/back/write.rs+38-41| ... | ... | @@ -94,7 +94,6 @@ pub struct ModuleConfig { |
| 94 | 94 | |
| 95 | 95 | // Flags indicating which outputs to produce. |
| 96 | 96 | pub emit_pre_lto_bc: bool, |
| 97 | pub emit_no_opt_bc: bool, | |
| 98 | 97 | pub emit_bc: bool, |
| 99 | 98 | pub emit_ir: bool, |
| 100 | 99 | pub emit_asm: bool, |
| ... | ... | @@ -195,7 +194,6 @@ impl ModuleConfig { |
| 195 | 194 | save_temps || need_pre_lto_bitcode_for_incr_comp(sess), |
| 196 | 195 | false |
| 197 | 196 | ), |
| 198 | emit_no_opt_bc: if_regular!(save_temps, false), | |
| 199 | 197 | emit_bc: if_regular!( |
| 200 | 198 | save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode), |
| 201 | 199 | save_temps |
| ... | ... | @@ -356,7 +354,7 @@ pub struct CodegenContext { |
| 356 | 354 | pub parallel: bool, |
| 357 | 355 | } |
| 358 | 356 | |
| 359 | fn generate_thin_lto_work<B: ExtraBackendMethods>( | |
| 357 | fn generate_thin_lto_work<B: WriteBackendMethods>( | |
| 360 | 358 | cgcx: &CodegenContext, |
| 361 | 359 | prof: &SelfProfilerRef, |
| 362 | 360 | dcx: DiagCtxtHandle<'_>, |
| ... | ... | @@ -824,7 +822,7 @@ pub(crate) fn compute_per_cgu_lto_type( |
| 824 | 822 | } |
| 825 | 823 | } |
| 826 | 824 | |
| 827 | fn execute_optimize_work_item<B: ExtraBackendMethods>( | |
| 825 | fn execute_optimize_work_item<B: WriteBackendMethods>( | |
| 828 | 826 | cgcx: &CodegenContext, |
| 829 | 827 | prof: &SelfProfilerRef, |
| 830 | 828 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -969,7 +967,7 @@ fn execute_copy_from_cache_work_item( |
| 969 | 967 | } |
| 970 | 968 | } |
| 971 | 969 | |
| 972 | fn do_fat_lto<B: ExtraBackendMethods>( | |
| 970 | fn do_fat_lto<B: WriteBackendMethods>( | |
| 973 | 971 | cgcx: &CodegenContext, |
| 974 | 972 | prof: &SelfProfilerRef, |
| 975 | 973 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -990,7 +988,7 @@ fn do_fat_lto<B: ExtraBackendMethods>( |
| 990 | 988 | needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module }) |
| 991 | 989 | } |
| 992 | 990 | |
| 993 | let module = B::run_and_optimize_fat_lto( | |
| 991 | B::optimize_and_codegen_fat_lto( | |
| 994 | 992 | cgcx, |
| 995 | 993 | prof, |
| 996 | 994 | &shared_emitter, |
| ... | ... | @@ -998,11 +996,10 @@ fn do_fat_lto<B: ExtraBackendMethods>( |
| 998 | 996 | exported_symbols_for_lto, |
| 999 | 997 | each_linked_rlib_for_lto, |
| 1000 | 998 | needs_fat_lto, |
| 1001 | ); | |
| 1002 | B::codegen(cgcx, prof, &shared_emitter, module, &cgcx.module_config) | |
| 999 | ) | |
| 1003 | 1000 | } |
| 1004 | 1001 | |
| 1005 | fn do_thin_lto<B: ExtraBackendMethods>( | |
| 1002 | fn do_thin_lto<B: WriteBackendMethods>( | |
| 1006 | 1003 | cgcx: &CodegenContext, |
| 1007 | 1004 | prof: &SelfProfilerRef, |
| 1008 | 1005 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -1155,7 +1152,7 @@ fn do_thin_lto<B: ExtraBackendMethods>( |
| 1155 | 1152 | compiled_modules |
| 1156 | 1153 | } |
| 1157 | 1154 | |
| 1158 | fn execute_thin_lto_work_item<B: ExtraBackendMethods>( | |
| 1155 | fn execute_thin_lto_work_item<B: WriteBackendMethods>( | |
| 1159 | 1156 | cgcx: &CodegenContext, |
| 1160 | 1157 | prof: &SelfProfilerRef, |
| 1161 | 1158 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -1164,8 +1161,7 @@ fn execute_thin_lto_work_item<B: ExtraBackendMethods>( |
| 1164 | 1161 | ) -> CompiledModule { |
| 1165 | 1162 | let _timer = prof.generic_activity_with_arg("codegen_module_perform_lto", module.name()); |
| 1166 | 1163 | |
| 1167 | let module = B::optimize_thin(cgcx, prof, &shared_emitter, tm_factory, module); | |
| 1168 | B::codegen(cgcx, prof, &shared_emitter, module, &cgcx.module_config) | |
| 1164 | B::optimize_and_codegen_thin(cgcx, prof, &shared_emitter, tm_factory, module) | |
| 1169 | 1165 | } |
| 1170 | 1166 | |
| 1171 | 1167 | /// Messages sent to the coordinator. |
| ... | ... | @@ -1472,7 +1468,9 @@ fn start_executing_work<B: ExtraBackendMethods>( |
| 1472 | 1468 | // Each LLVM module is automatically sent back to the coordinator for LTO if |
| 1473 | 1469 | // necessary. There's already optimizations in place to avoid sending work |
| 1474 | 1470 | // back to the coordinator if LTO isn't requested. |
| 1475 | return B::spawn_named_thread(cgcx.time_trace, "coordinator".to_string(), move || { | |
| 1471 | let f = move || { | |
| 1472 | let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) }; | |
| 1473 | ||
| 1476 | 1474 | // This is where we collect codegen units that have gone all the way |
| 1477 | 1475 | // through codegen and LLVM. |
| 1478 | 1476 | let mut compiled_modules = vec![]; |
| ... | ... | @@ -1813,8 +1811,11 @@ fn start_executing_work<B: ExtraBackendMethods>( |
| 1813 | 1811 | B::codegen(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config) |
| 1814 | 1812 | }), |
| 1815 | 1813 | })) |
| 1816 | }) | |
| 1817 | .expect("failed to spawn coordinator thread"); | |
| 1814 | }; | |
| 1815 | return std::thread::Builder::new() | |
| 1816 | .name("coordinator".to_owned()) | |
| 1817 | .spawn(f) | |
| 1818 | .expect("failed to spawn coordinator thread"); | |
| 1818 | 1819 | |
| 1819 | 1820 | // A heuristic that determines if we have enough LLVM WorkItems in the |
| 1820 | 1821 | // queue so that the main thread can do LLVM work instead of codegen |
| ... | ... | @@ -1878,7 +1879,7 @@ fn start_executing_work<B: ExtraBackendMethods>( |
| 1878 | 1879 | #[must_use] |
| 1879 | 1880 | pub(crate) struct WorkerFatalError; |
| 1880 | 1881 | |
| 1881 | fn spawn_work<'a, B: ExtraBackendMethods>( | |
| 1882 | fn spawn_work<'a, B: WriteBackendMethods>( | |
| 1882 | 1883 | cgcx: &CodegenContext, |
| 1883 | 1884 | prof: &'a SelfProfilerRef, |
| 1884 | 1885 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -1893,7 +1894,10 @@ fn spawn_work<'a, B: ExtraBackendMethods>( |
| 1893 | 1894 | let cgcx = cgcx.clone(); |
| 1894 | 1895 | let prof = prof.clone(); |
| 1895 | 1896 | |
| 1896 | B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { | |
| 1897 | let name = work.short_description(); | |
| 1898 | let f = move || { | |
| 1899 | let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) }; | |
| 1900 | ||
| 1897 | 1901 | let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { |
| 1898 | 1902 | WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, &prof, shared_emitter, m), |
| 1899 | 1903 | WorkItem::CopyPostLtoArtifacts(m) => WorkItemResult::Finished( |
| ... | ... | @@ -1914,11 +1918,11 @@ fn spawn_work<'a, B: ExtraBackendMethods>( |
| 1914 | 1918 | Err(_) => Message::WorkItem::<B> { result: Err(None) }, |
| 1915 | 1919 | }; |
| 1916 | 1920 | drop(coordinator_send.send(msg)); |
| 1917 | }) | |
| 1918 | .expect("failed to spawn work thread"); | |
| 1921 | }; | |
| 1922 | std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread"); | |
| 1919 | 1923 | } |
| 1920 | 1924 | |
| 1921 | fn spawn_thin_lto_work<B: ExtraBackendMethods>( | |
| 1925 | fn spawn_thin_lto_work<B: WriteBackendMethods>( | |
| 1922 | 1926 | cgcx: &CodegenContext, |
| 1923 | 1927 | prof: &SelfProfilerRef, |
| 1924 | 1928 | shared_emitter: SharedEmitter, |
| ... | ... | @@ -1929,7 +1933,10 @@ fn spawn_thin_lto_work<B: ExtraBackendMethods>( |
| 1929 | 1933 | let cgcx = cgcx.clone(); |
| 1930 | 1934 | let prof = prof.clone(); |
| 1931 | 1935 | |
| 1932 | B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || { | |
| 1936 | let name = work.short_description(); | |
| 1937 | let f = move || { | |
| 1938 | let _profiler = if cgcx.time_trace { B::thread_profiler() } else { Box::new(()) }; | |
| 1939 | ||
| 1933 | 1940 | let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work { |
| 1934 | 1941 | ThinLtoWorkItem::CopyPostLtoArtifacts(m) => { |
| 1935 | 1942 | execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m) |
| ... | ... | @@ -1952,8 +1959,8 @@ fn spawn_thin_lto_work<B: ExtraBackendMethods>( |
| 1952 | 1959 | Err(_) => ThinLtoMessage::WorkItem { result: Err(None) }, |
| 1953 | 1960 | }; |
| 1954 | 1961 | drop(coordinator_send.send(msg)); |
| 1955 | }) | |
| 1956 | .expect("failed to spawn work thread"); | |
| 1962 | }; | |
| 1963 | std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread"); | |
| 1957 | 1964 | } |
| 1958 | 1965 | |
| 1959 | 1966 | enum SharedEmitterMessage { |
| ... | ... | @@ -2102,20 +2109,20 @@ impl SharedEmitterMain { |
| 2102 | 2109 | } |
| 2103 | 2110 | } |
| 2104 | 2111 | |
| 2105 | pub struct Coordinator<B: ExtraBackendMethods> { | |
| 2112 | pub struct Coordinator<B: WriteBackendMethods> { | |
| 2106 | 2113 | sender: Sender<Message<B>>, |
| 2107 | 2114 | future: Option<thread::JoinHandle<Result<MaybeLtoModules<B>, ()>>>, |
| 2108 | 2115 | // Only used for the Message type. |
| 2109 | 2116 | phantom: PhantomData<B>, |
| 2110 | 2117 | } |
| 2111 | 2118 | |
| 2112 | impl<B: ExtraBackendMethods> Coordinator<B> { | |
| 2119 | impl<B: WriteBackendMethods> Coordinator<B> { | |
| 2113 | 2120 | fn join(mut self) -> std::thread::Result<Result<MaybeLtoModules<B>, ()>> { |
| 2114 | 2121 | self.future.take().unwrap().join() |
| 2115 | 2122 | } |
| 2116 | 2123 | } |
| 2117 | 2124 | |
| 2118 | impl<B: ExtraBackendMethods> Drop for Coordinator<B> { | |
| 2125 | impl<B: WriteBackendMethods> Drop for Coordinator<B> { | |
| 2119 | 2126 | fn drop(&mut self) { |
| 2120 | 2127 | if let Some(future) = self.future.take() { |
| 2121 | 2128 | // If we haven't joined yet, signal to the coordinator that it should spawn no more |
| ... | ... | @@ -2126,7 +2133,7 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> { |
| 2126 | 2133 | } |
| 2127 | 2134 | } |
| 2128 | 2135 | |
| 2129 | pub struct OngoingCodegen<B: ExtraBackendMethods> { | |
| 2136 | pub struct OngoingCodegen<B: WriteBackendMethods> { | |
| 2130 | 2137 | pub backend: B, |
| 2131 | 2138 | pub output_filenames: Arc<OutputFilenames>, |
| 2132 | 2139 | // Field order below is intended to terminate the coordinator thread before two fields below |
| ... | ... | @@ -2137,7 +2144,7 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> { |
| 2137 | 2144 | pub shared_emitter_main: SharedEmitterMain, |
| 2138 | 2145 | } |
| 2139 | 2146 | |
| 2140 | impl<B: ExtraBackendMethods> OngoingCodegen<B> { | |
| 2147 | impl<B: WriteBackendMethods> OngoingCodegen<B> { | |
| 2141 | 2148 | pub fn join(self, sess: &Session) -> (CompiledModules, FxIndexMap<WorkProductId, WorkProduct>) { |
| 2142 | 2149 | self.shared_emitter_main.check(sess, true); |
| 2143 | 2150 | |
| ... | ... | @@ -2234,16 +2241,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { |
| 2234 | 2241 | copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules); |
| 2235 | 2242 | produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames); |
| 2236 | 2243 | |
| 2237 | // FIXME: time_llvm_passes support - does this use a global context or | |
| 2238 | // something? | |
| 2239 | if sess.codegen_units().as_usize() == 1 && sess.opts.unstable_opts.time_llvm_passes { | |
| 2240 | self.backend.print_pass_timings() | |
| 2241 | } | |
| 2242 | ||
| 2243 | if sess.print_llvm_stats() { | |
| 2244 | self.backend.print_statistics() | |
| 2245 | } | |
| 2246 | ||
| 2247 | 2244 | (compiled_modules, work_products) |
| 2248 | 2245 | } |
| 2249 | 2246 | |
| ... | ... | @@ -2270,7 +2267,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { |
| 2270 | 2267 | } |
| 2271 | 2268 | } |
| 2272 | 2269 | |
| 2273 | pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>( | |
| 2270 | pub(crate) fn submit_codegened_module_to_llvm<B: WriteBackendMethods>( | |
| 2274 | 2271 | coordinator: &Coordinator<B>, |
| 2275 | 2272 | module: ModuleCodegen<B::Module>, |
| 2276 | 2273 | cost: u64, |
| ... | ... | @@ -2279,7 +2276,7 @@ pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>( |
| 2279 | 2276 | drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost })); |
| 2280 | 2277 | } |
| 2281 | 2278 | |
| 2282 | pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>( | |
| 2279 | pub(crate) fn submit_post_lto_module_to_llvm<B: WriteBackendMethods>( | |
| 2283 | 2280 | coordinator: &Coordinator<B>, |
| 2284 | 2281 | module: CachedModuleCodegen, |
| 2285 | 2282 | ) { |
| ... | ... | @@ -2287,7 +2284,7 @@ pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>( |
| 2287 | 2284 | drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost: 0 })); |
| 2288 | 2285 | } |
| 2289 | 2286 | |
| 2290 | pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>( | |
| 2287 | pub(crate) fn submit_pre_lto_module_to_llvm<B: WriteBackendMethods>( | |
| 2291 | 2288 | tcx: TyCtxt<'_>, |
| 2292 | 2289 | coordinator: &Coordinator<B>, |
| 2293 | 2290 | module: CachedModuleCodegen, |
compiler/rustc_codegen_ssa/src/traits/backend.rs+5-22| ... | ... | @@ -10,14 +10,13 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; |
| 10 | 10 | use rustc_middle::ty::TyCtxt; |
| 11 | 11 | use rustc_middle::util::Providers; |
| 12 | 12 | use rustc_session::Session; |
| 13 | use rustc_session::config::{self, CrateType, OutputFilenames, PrintRequest}; | |
| 13 | use rustc_session::config::{CrateType, OutputFilenames, PrintRequest}; | |
| 14 | 14 | use rustc_span::Symbol; |
| 15 | 15 | |
| 16 | 16 | use super::CodegenObject; |
| 17 | 17 | use super::write::WriteBackendMethods; |
| 18 | 18 | use crate::back::archive::ArArchiveBuilderBuilder; |
| 19 | 19 | use crate::back::link::link_binary; |
| 20 | use crate::back::write::TargetMachineFactoryFn; | |
| 21 | 20 | use crate::{CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; |
| 22 | 21 | |
| 23 | 22 | pub trait BackendTypes { |
| ... | ... | @@ -119,6 +118,10 @@ pub trait CodegenBackend { |
| 119 | 118 | outputs: &OutputFilenames, |
| 120 | 119 | ) -> (CompiledModules, FxIndexMap<WorkProductId, WorkProduct>); |
| 121 | 120 | |
| 121 | fn print_pass_timings(&self) {} | |
| 122 | ||
| 123 | fn print_statistics(&self) {} | |
| 124 | ||
| 122 | 125 | /// This is called on the returned [`CompiledModules`] from [`join_codegen`](Self::join_codegen). |
| 123 | 126 | fn link( |
| 124 | 127 | &self, |
| ... | ... | @@ -158,26 +161,6 @@ pub trait ExtraBackendMethods: |
| 158 | 161 | cgu_name: Symbol, |
| 159 | 162 | ) -> (ModuleCodegen<Self::Module>, u64); |
| 160 | 163 | |
| 161 | fn target_machine_factory( | |
| 162 | &self, | |
| 163 | sess: &Session, | |
| 164 | opt_level: config::OptLevel, | |
| 165 | target_features: &[String], | |
| 166 | ) -> TargetMachineFactoryFn<Self>; | |
| 167 | ||
| 168 | fn spawn_named_thread<F, T>( | |
| 169 | _time_trace: bool, | |
| 170 | name: String, | |
| 171 | f: F, | |
| 172 | ) -> std::io::Result<std::thread::JoinHandle<T>> | |
| 173 | where | |
| 174 | F: FnOnce() -> T, | |
| 175 | F: Send + 'static, | |
| 176 | T: Send + 'static, | |
| 177 | { | |
| 178 | std::thread::Builder::new().name(name).spawn(f) | |
| 179 | } | |
| 180 | ||
| 181 | 164 | /// Returns `true` if this backend can be safely called from multiple threads. |
| 182 | 165 | /// |
| 183 | 166 | /// Defaults to `true`. |
compiler/rustc_codegen_ssa/src/traits/write.rs+15-6| ... | ... | @@ -1,8 +1,10 @@ |
| 1 | use std::any::Any; | |
| 1 | 2 | use std::path::PathBuf; |
| 2 | 3 | |
| 3 | 4 | use rustc_data_structures::profiling::SelfProfilerRef; |
| 4 | 5 | use rustc_errors::DiagCtxtHandle; |
| 5 | 6 | use rustc_middle::dep_graph::WorkProduct; |
| 7 | use rustc_session::{Session, config}; | |
| 6 | 8 | |
| 7 | 9 | use crate::back::lto::{SerializedModule, ThinModule}; |
| 8 | 10 | use crate::back::write::{ |
| ... | ... | @@ -16,9 +18,18 @@ pub trait WriteBackendMethods: Clone + 'static { |
| 16 | 18 | type ModuleBuffer: ModuleBufferMethods; |
| 17 | 19 | type ThinData: Send + Sync; |
| 18 | 20 | |
| 21 | fn thread_profiler() -> Box<dyn Any> { | |
| 22 | Box::new(()) | |
| 23 | } | |
| 24 | fn target_machine_factory( | |
| 25 | &self, | |
| 26 | sess: &Session, | |
| 27 | opt_level: config::OptLevel, | |
| 28 | target_features: &[String], | |
| 29 | ) -> TargetMachineFactoryFn<Self>; | |
| 19 | 30 | /// Performs fat LTO by merging all modules into a single one, running autodiff |
| 20 | 31 | /// if necessary and running any further optimizations |
| 21 | fn run_and_optimize_fat_lto( | |
| 32 | fn optimize_and_codegen_fat_lto( | |
| 22 | 33 | cgcx: &CodegenContext, |
| 23 | 34 | prof: &SelfProfilerRef, |
| 24 | 35 | shared_emitter: &SharedEmitter, |
| ... | ... | @@ -26,7 +37,7 @@ pub trait WriteBackendMethods: Clone + 'static { |
| 26 | 37 | exported_symbols_for_lto: &[String], |
| 27 | 38 | each_linked_rlib_for_lto: &[PathBuf], |
| 28 | 39 | modules: Vec<FatLtoInput<Self>>, |
| 29 | ) -> ModuleCodegen<Self::Module>; | |
| 40 | ) -> CompiledModule; | |
| 30 | 41 | /// Performs thin LTO by performing necessary global analysis and returning two |
| 31 | 42 | /// lists, one of the modules that need optimization and another for modules that |
| 32 | 43 | /// can simply be copied over from the incr. comp. cache. |
| ... | ... | @@ -39,8 +50,6 @@ pub trait WriteBackendMethods: Clone + 'static { |
| 39 | 50 | modules: Vec<(String, Self::ModuleBuffer)>, |
| 40 | 51 | cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>, |
| 41 | 52 | ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>); |
| 42 | fn print_pass_timings(&self); | |
| 43 | fn print_statistics(&self); | |
| 44 | 53 | fn optimize( |
| 45 | 54 | cgcx: &CodegenContext, |
| 46 | 55 | prof: &SelfProfilerRef, |
| ... | ... | @@ -48,13 +57,13 @@ pub trait WriteBackendMethods: Clone + 'static { |
| 48 | 57 | module: &mut ModuleCodegen<Self::Module>, |
| 49 | 58 | config: &ModuleConfig, |
| 50 | 59 | ); |
| 51 | fn optimize_thin( | |
| 60 | fn optimize_and_codegen_thin( | |
| 52 | 61 | cgcx: &CodegenContext, |
| 53 | 62 | prof: &SelfProfilerRef, |
| 54 | 63 | shared_emitter: &SharedEmitter, |
| 55 | 64 | tm_factory: TargetMachineFactoryFn<Self>, |
| 56 | 65 | thin: ThinModule<Self>, |
| 57 | ) -> ModuleCodegen<Self::Module>; | |
| 66 | ) -> CompiledModule; | |
| 58 | 67 | fn codegen( |
| 59 | 68 | cgcx: &CodegenContext, |
| 60 | 69 | prof: &SelfProfilerRef, |
compiler/rustc_const_eval/src/errors.rs+6-6| ... | ... | @@ -366,7 +366,7 @@ impl Subdiagnostic for FrameNote { |
| 366 | 366 | if self.has_label && !self.span.is_dummy() { |
| 367 | 367 | span.push_span_label(self.span, msg!("the failure occurred here")); |
| 368 | 368 | } |
| 369 | let msg = diag.eagerly_translate(msg!( | |
| 369 | let msg = diag.eagerly_format(msg!( | |
| 370 | 370 | r#"{$times -> |
| 371 | 371 | [0] inside {$where_ -> |
| 372 | 372 | [closure] closure |
| ... | ... | @@ -624,7 +624,7 @@ pub trait ReportErrorExt { |
| 624 | 624 | let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into())); |
| 625 | 625 | let message = self.diagnostic_message(); |
| 626 | 626 | self.add_args(&mut diag); |
| 627 | let s = dcx.eagerly_translate_to_string(message, diag.args.iter()); | |
| 627 | let s = dcx.eagerly_format_to_string(message, diag.args.iter()); | |
| 628 | 628 | diag.cancel(); |
| 629 | 629 | s |
| 630 | 630 | }) |
| ... | ... | @@ -1086,12 +1086,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { |
| 1086 | 1086 | } |
| 1087 | 1087 | |
| 1088 | 1088 | let message = if let Some(path) = self.path { |
| 1089 | err.dcx.eagerly_translate_to_string( | |
| 1089 | err.dcx.eagerly_format_to_string( | |
| 1090 | 1090 | msg!("constructing invalid value at {$path}"), |
| 1091 | 1091 | [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), |
| 1092 | 1092 | ) |
| 1093 | 1093 | } else { |
| 1094 | err.dcx.eagerly_translate_to_string(msg!("constructing invalid value"), [].into_iter()) | |
| 1094 | err.dcx.eagerly_format_to_string(msg!("constructing invalid value"), [].into_iter()) | |
| 1095 | 1095 | }; |
| 1096 | 1096 | |
| 1097 | 1097 | err.arg("front_matter", message); |
| ... | ... | @@ -1122,7 +1122,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { |
| 1122 | 1122 | ("hi".into(), DiagArgValue::Str(hi.to_string().into())), |
| 1123 | 1123 | ]; |
| 1124 | 1124 | let args = args.iter().map(|(a, b)| (a, b)); |
| 1125 | let message = err.dcx.eagerly_translate_to_string(msg, args); | |
| 1125 | let message = err.dcx.eagerly_format_to_string(msg, args); | |
| 1126 | 1126 | err.arg("in_range", message); |
| 1127 | 1127 | } |
| 1128 | 1128 | |
| ... | ... | @@ -1144,7 +1144,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { |
| 1144 | 1144 | ExpectedKind::EnumTag => msg!("expected a valid enum tag"), |
| 1145 | 1145 | ExpectedKind::Str => msg!("expected a string"), |
| 1146 | 1146 | }; |
| 1147 | let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter()); | |
| 1147 | let msg = err.dcx.eagerly_format_to_string(msg, [].into_iter()); | |
| 1148 | 1148 | err.arg("expected", msg); |
| 1149 | 1149 | } |
| 1150 | 1150 | InvalidEnumTag { value } |
compiler/rustc_const_eval/src/interpret/eval_context.rs+1-1| ... | ... | @@ -235,7 +235,7 @@ pub fn format_interp_error<'tcx>(dcx: DiagCtxtHandle<'_>, e: InterpErrorInfo<'tc |
| 235 | 235 | let mut diag = dcx.struct_allow(""); |
| 236 | 236 | let msg = e.diagnostic_message(); |
| 237 | 237 | e.add_args(&mut diag); |
| 238 | let s = dcx.eagerly_translate_to_string(msg, diag.args.iter()); | |
| 238 | let s = dcx.eagerly_format_to_string(msg, diag.args.iter()); | |
| 239 | 239 | diag.cancel(); |
| 240 | 240 | s |
| 241 | 241 | } |
compiler/rustc_driver_impl/src/lib.rs+5-1| ... | ... | @@ -338,7 +338,11 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) |
| 338 | 338 | } |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)) | |
| 341 | let linker = Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend); | |
| 342 | ||
| 343 | tcx.report_unused_features(); | |
| 344 | ||
| 345 | Some(linker) | |
| 342 | 346 | }); |
| 343 | 347 | |
| 344 | 348 | // Linking is done outside the `compiler.enter()` so that the |
compiler/rustc_error_codes/src/error_codes/E0208.md-45| ... | ... | @@ -1,47 +1,2 @@ |
| 1 | 1 | #### This error code is internal to the compiler and will not be emitted with normal Rust code. |
| 2 | 2 | #### Note: this error code is no longer emitted by the compiler. |
| 3 | ||
| 4 | This error code shows the variance of a type's generic parameters. | |
| 5 | ||
| 6 | Erroneous code example: | |
| 7 | ||
| 8 | ```compile_fail | |
| 9 | // NOTE: this feature is perma-unstable and should *only* be used for | |
| 10 | // testing purposes. | |
| 11 | #![allow(internal_features)] | |
| 12 | #![feature(rustc_attrs)] | |
| 13 | ||
| 14 | #[rustc_variance] | |
| 15 | struct Foo<'a, T> { // error: deliberate error to display type's variance | |
| 16 | t: &'a mut T, | |
| 17 | } | |
| 18 | ``` | |
| 19 | ||
| 20 | which produces the following error: | |
| 21 | ||
| 22 | ```text | |
| 23 | error: [-, o] | |
| 24 | --> <anon>:4:1 | |
| 25 | | | |
| 26 | 4 | struct Foo<'a, T> { | |
| 27 | | ^^^^^^^^^^^^^^^^^ | |
| 28 | ``` | |
| 29 | ||
| 30 | *Note that while `#[rustc_variance]` still exists and is used within the* | |
| 31 | *compiler, it no longer is marked as `E0208` and instead has no error code.* | |
| 32 | ||
| 33 | This error is deliberately triggered with the `#[rustc_variance]` attribute | |
| 34 | (`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance | |
| 35 | of the type's generic parameters. You can read more about variance and | |
| 36 | subtyping in [this section of the Rustonomicon]. For a more in depth look at | |
| 37 | variance (including a more complete list of common variances) see | |
| 38 | [this section of the Reference]. For information on how variance is implemented | |
| 39 | in the compiler, see [this section of `rustc-dev-guide`]. | |
| 40 | ||
| 41 | This error can be easily fixed by removing the `#[rustc_variance]` attribute, | |
| 42 | the compiler's suggestion to comment it out can be applied automatically with | |
| 43 | `rustfix`. | |
| 44 | ||
| 45 | [this section of the Rustonomicon]: https://doc.rust-lang.org/nomicon/subtyping.html | |
| 46 | [this section of the Reference]: https://doc.rust-lang.org/reference/subtyping.html#variance | |
| 47 | [this section of `rustc-dev-guide`]: https://rustc-dev-guide.rust-lang.org/variance.html |
compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs+1-1| ... | ... | @@ -26,7 +26,7 @@ use crate::emitter::{ |
| 26 | 26 | ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different, |
| 27 | 27 | normalize_whitespace, should_show_source_code, |
| 28 | 28 | }; |
| 29 | use crate::translation::{format_diag_message, format_diag_messages}; | |
| 29 | use crate::formatting::{format_diag_message, format_diag_messages}; | |
| 30 | 30 | use crate::{ |
| 31 | 31 | CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag, |
| 32 | 32 | SuggestionStyle, TerminalUrl, |
compiler/rustc_errors/src/decorate_diag.rs+1-1| ... | ... | @@ -7,7 +7,7 @@ use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId}; |
| 7 | 7 | |
| 8 | 8 | use crate::{Diag, DiagCtxtHandle, Diagnostic, Level}; |
| 9 | 9 | |
| 10 | /// We can't implement `LintDiagnostic` for `BuiltinLintDiag`, because decorating some of its | |
| 10 | /// We can't implement `Diagnostic` for `BuiltinLintDiag`, because decorating some of its | |
| 11 | 11 | /// variants requires types we don't have yet. So, handle that case separately. |
| 12 | 12 | pub enum DecorateDiagCompat { |
| 13 | 13 | Dynamic(Box<dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>), |
compiler/rustc_errors/src/diagnostic.rs+4-12| ... | ... | @@ -138,14 +138,6 @@ where |
| 138 | 138 | fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>); |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | /// Trait implemented by lint types. This should not be implemented manually. Instead, use | |
| 142 | /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. | |
| 143 | #[rustc_diagnostic_item = "LintDiagnostic"] | |
| 144 | pub trait LintDiagnostic<'a, G: EmissionGuarantee> { | |
| 145 | /// Decorate a lint with the information from this type. | |
| 146 | fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>); | |
| 147 | } | |
| 148 | ||
| 149 | 141 | #[derive(Clone, Debug, Encodable, Decodable)] |
| 150 | 142 | pub(crate) struct DiagLocation { |
| 151 | 143 | file: Cow<'static, str>, |
| ... | ... | @@ -1143,7 +1135,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { |
| 1143 | 1135 | } } |
| 1144 | 1136 | |
| 1145 | 1137 | /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see |
| 1146 | /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages | |
| 1138 | /// [rustc_macros::Subdiagnostic]). Performs eager formatting of any messages | |
| 1147 | 1139 | /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of |
| 1148 | 1140 | /// interpolated variables). |
| 1149 | 1141 | pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self { |
| ... | ... | @@ -1153,12 +1145,12 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { |
| 1153 | 1145 | |
| 1154 | 1146 | /// Fluent variables are not namespaced from each other, so when |
| 1155 | 1147 | /// `Diagnostic`s and `Subdiagnostic`s use the same variable name, |
| 1156 | /// one value will clobber the other. Eagerly translating the | |
| 1148 | /// one value will clobber the other. Eagerly formatting the | |
| 1157 | 1149 | /// diagnostic uses the variables defined right then, before the |
| 1158 | 1150 | /// clobbering occurs. |
| 1159 | pub fn eagerly_translate(&self, msg: impl Into<DiagMessage>) -> DiagMessage { | |
| 1151 | pub fn eagerly_format(&self, msg: impl Into<DiagMessage>) -> DiagMessage { | |
| 1160 | 1152 | let args = self.args.iter(); |
| 1161 | self.dcx.eagerly_translate(msg.into(), args) | |
| 1153 | self.dcx.eagerly_format(msg.into(), args) | |
| 1162 | 1154 | } |
| 1163 | 1155 | |
| 1164 | 1156 | with_fn! { with_span, |
compiler/rustc_errors/src/emitter.rs+1-1| ... | ... | @@ -23,8 +23,8 @@ use rustc_span::source_map::SourceMap; |
| 23 | 23 | use rustc_span::{FileName, SourceFile, Span}; |
| 24 | 24 | use tracing::{debug, warn}; |
| 25 | 25 | |
| 26 | use crate::formatting::format_diag_message; | |
| 26 | 27 | use crate::timings::TimingRecord; |
| 27 | use crate::translation::format_diag_message; | |
| 28 | 28 | use crate::{ |
| 29 | 29 | CodeSuggestion, DiagInner, DiagMessage, Level, MultiSpan, Style, Subdiag, SuggestionStyle, |
| 30 | 30 | }; |
compiler/rustc_errors/src/formatting.rs created+62| ... | ... | @@ -0,0 +1,62 @@ |
| 1 | use std::borrow::Cow; | |
| 2 | ||
| 3 | pub use rustc_error_messages::FluentArgs; | |
| 4 | use rustc_error_messages::{DiagArgMap, langid, register_functions}; | |
| 5 | use tracing::{debug, trace}; | |
| 6 | ||
| 7 | use crate::fluent_bundle::FluentResource; | |
| 8 | use crate::{DiagArg, DiagMessage, Style, fluent_bundle}; | |
| 9 | ||
| 10 | /// Convert diagnostic arguments (a rustc internal type that exists to implement | |
| 11 | /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform formatting. | |
| 12 | fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> { | |
| 13 | let mut args = if let Some(size) = iter.size_hint().1 { | |
| 14 | FluentArgs::with_capacity(size) | |
| 15 | } else { | |
| 16 | FluentArgs::new() | |
| 17 | }; | |
| 18 | ||
| 19 | for (k, v) in iter { | |
| 20 | args.set(k.clone(), v.clone()); | |
| 21 | } | |
| 22 | ||
| 23 | args | |
| 24 | } | |
| 25 | ||
| 26 | /// Convert `DiagMessage`s to a string | |
| 27 | pub fn format_diag_messages( | |
| 28 | messages: &[(DiagMessage, Style)], | |
| 29 | args: &DiagArgMap, | |
| 30 | ) -> Cow<'static, str> { | |
| 31 | Cow::Owned(messages.iter().map(|(m, _)| format_diag_message(m, args)).collect::<String>()) | |
| 32 | } | |
| 33 | ||
| 34 | /// Convert a `DiagMessage` to a string | |
| 35 | pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &DiagArgMap) -> Cow<'a, str> { | |
| 36 | trace!(?message, ?args); | |
| 37 | ||
| 38 | match message { | |
| 39 | DiagMessage::Str(msg) => Cow::Borrowed(msg), | |
| 40 | DiagMessage::Inline(msg) => { | |
| 41 | const GENERATED_MSG_ID: &str = "generated_msg"; | |
| 42 | let resource = | |
| 43 | FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap(); | |
| 44 | let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); | |
| 45 | bundle.set_use_isolating(false); | |
| 46 | bundle.add_resource(resource).unwrap(); | |
| 47 | register_functions(&mut bundle); | |
| 48 | let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); | |
| 49 | let value = message.value().unwrap(); | |
| 50 | let args = to_fluent_args(args.iter()); | |
| 51 | ||
| 52 | let mut errs = vec![]; | |
| 53 | let formatted = bundle.format_pattern(value, Some(&args), &mut errs).to_string(); | |
| 54 | debug!(?formatted, ?errs); | |
| 55 | if errs.is_empty() { | |
| 56 | Cow::Owned(formatted) | |
| 57 | } else { | |
| 58 | panic!("Fluent errors while formatting message: {errs:?}"); | |
| 59 | } | |
| 60 | } | |
| 61 | } | |
| 62 | } |
compiler/rustc_errors/src/json.rs+7-7| ... | ... | @@ -30,8 +30,8 @@ use crate::emitter::{ |
| 30 | 30 | ColorConfig, Destination, Emitter, HumanReadableErrorType, OutputTheme, TimingEvent, |
| 31 | 31 | should_show_source_code, |
| 32 | 32 | }; |
| 33 | use crate::formatting::{format_diag_message, format_diag_messages}; | |
| 33 | 34 | use crate::timings::{TimingRecord, TimingSection}; |
| 34 | use crate::translation::{format_diag_message, format_diag_messages}; | |
| 35 | 35 | use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl}; |
| 36 | 36 | |
| 37 | 37 | #[cfg(test)] |
| ... | ... | @@ -299,9 +299,9 @@ impl Diagnostic { |
| 299 | 299 | /// Converts from `rustc_errors::DiagInner` to `Diagnostic`. |
| 300 | 300 | fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { |
| 301 | 301 | let sugg_to_diag = |sugg: &CodeSuggestion| { |
| 302 | let translated_message = format_diag_message(&sugg.msg, &diag.args); | |
| 302 | let formatted_message = format_diag_message(&sugg.msg, &diag.args); | |
| 303 | 303 | Diagnostic { |
| 304 | message: translated_message.to_string(), | |
| 304 | message: formatted_message.to_string(), | |
| 305 | 305 | code: None, |
| 306 | 306 | level: "help", |
| 307 | 307 | spans: DiagnosticSpan::from_suggestion(sugg, &diag.args, je), |
| ... | ... | @@ -330,7 +330,7 @@ impl Diagnostic { |
| 330 | 330 | } |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | let translated_message = format_diag_messages(&diag.messages, &diag.args); | |
| 333 | let formatted_message = format_diag_messages(&diag.messages, &diag.args); | |
| 334 | 334 | |
| 335 | 335 | let code = if let Some(code) = diag.code { |
| 336 | 336 | Some(DiagnosticCode { |
| ... | ... | @@ -380,7 +380,7 @@ impl Diagnostic { |
| 380 | 380 | let buf = String::from_utf8(buf).unwrap(); |
| 381 | 381 | |
| 382 | 382 | Diagnostic { |
| 383 | message: translated_message.to_string(), | |
| 383 | message: formatted_message.to_string(), | |
| 384 | 384 | code, |
| 385 | 385 | level, |
| 386 | 386 | spans, |
| ... | ... | @@ -390,9 +390,9 @@ impl Diagnostic { |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | 392 | fn from_sub_diagnostic(subdiag: &Subdiag, args: &DiagArgMap, je: &JsonEmitter) -> Diagnostic { |
| 393 | let translated_message = format_diag_messages(&subdiag.messages, args); | |
| 393 | let formatted_message = format_diag_messages(&subdiag.messages, args); | |
| 394 | 394 | Diagnostic { |
| 395 | message: translated_message.to_string(), | |
| 395 | message: formatted_message.to_string(), | |
| 396 | 396 | code: None, |
| 397 | 397 | level: subdiag.level.to_str(), |
| 398 | 398 | spans: DiagnosticSpan::from_multispan(&subdiag.span, args, je), |
compiler/rustc_errors/src/lib.rs+18-20| ... | ... | @@ -7,9 +7,7 @@ |
| 7 | 7 | #![allow(rustc::direct_use_of_rustc_type_ir)] |
| 8 | 8 | #![cfg_attr(bootstrap, feature(assert_matches))] |
| 9 | 9 | #![feature(associated_type_defaults)] |
| 10 | #![feature(box_patterns)] | |
| 11 | 10 | #![feature(default_field_values)] |
| 12 | #![feature(error_reporter)] | |
| 13 | 11 | #![feature(macro_metavar_expr_concat)] |
| 14 | 12 | #![feature(negative_impls)] |
| 15 | 13 | #![feature(never_type)] |
| ... | ... | @@ -40,7 +38,7 @@ pub use codes::*; |
| 40 | 38 | pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; |
| 41 | 39 | pub use diagnostic::{ |
| 42 | 40 | BugAbort, Diag, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort, |
| 43 | LintDiagnostic, StringPart, Subdiag, Subdiagnostic, | |
| 41 | StringPart, Subdiag, Subdiagnostic, | |
| 44 | 42 | }; |
| 45 | 43 | pub use diagnostic_impls::{ |
| 46 | 44 | DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, |
| ... | ... | @@ -68,8 +66,8 @@ use rustc_span::{DUMMY_SP, Span}; |
| 68 | 66 | use tracing::debug; |
| 69 | 67 | |
| 70 | 68 | use crate::emitter::TimingEvent; |
| 69 | use crate::formatting::format_diag_message; | |
| 71 | 70 | use crate::timings::TimingRecord; |
| 72 | use crate::translation::format_diag_message; | |
| 73 | 71 | |
| 74 | 72 | pub mod annotate_snippet_emitter_writer; |
| 75 | 73 | pub mod codes; |
| ... | ... | @@ -77,11 +75,11 @@ mod decorate_diag; |
| 77 | 75 | mod diagnostic; |
| 78 | 76 | mod diagnostic_impls; |
| 79 | 77 | pub mod emitter; |
| 78 | pub mod formatting; | |
| 80 | 79 | pub mod json; |
| 81 | 80 | mod lock; |
| 82 | 81 | pub mod markdown; |
| 83 | 82 | pub mod timings; |
| 84 | pub mod translation; | |
| 85 | 83 | |
| 86 | 84 | pub type PResult<'a, T> = Result<T, Diag<'a>>; |
| 87 | 85 | |
| ... | ... | @@ -484,24 +482,24 @@ impl DiagCtxt { |
| 484 | 482 | self.inner.borrow_mut().emitter = emitter; |
| 485 | 483 | } |
| 486 | 484 | |
| 487 | /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. | |
| 488 | pub fn eagerly_translate<'a>( | |
| 485 | /// Format `message` eagerly with `args` to `DiagMessage::Eager`. | |
| 486 | pub fn eagerly_format<'a>( | |
| 489 | 487 | &self, |
| 490 | 488 | message: DiagMessage, |
| 491 | 489 | args: impl Iterator<Item = DiagArg<'a>>, |
| 492 | 490 | ) -> DiagMessage { |
| 493 | 491 | let inner = self.inner.borrow(); |
| 494 | inner.eagerly_translate(message, args) | |
| 492 | inner.eagerly_format(message, args) | |
| 495 | 493 | } |
| 496 | 494 | |
| 497 | /// Translate `message` eagerly with `args` to `String`. | |
| 498 | pub fn eagerly_translate_to_string<'a>( | |
| 495 | /// Format `message` eagerly with `args` to `String`. | |
| 496 | pub fn eagerly_format_to_string<'a>( | |
| 499 | 497 | &self, |
| 500 | 498 | message: DiagMessage, |
| 501 | 499 | args: impl Iterator<Item = DiagArg<'a>>, |
| 502 | 500 | ) -> String { |
| 503 | 501 | let inner = self.inner.borrow(); |
| 504 | inner.eagerly_translate_to_string(message, args) | |
| 502 | inner.eagerly_format_to_string(message, args) | |
| 505 | 503 | } |
| 506 | 504 | |
| 507 | 505 | // This is here to not allow mutation of flags; |
| ... | ... | @@ -1419,17 +1417,17 @@ impl DiagCtxtInner { |
| 1419 | 1417 | self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) |
| 1420 | 1418 | } |
| 1421 | 1419 | |
| 1422 | /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. | |
| 1423 | fn eagerly_translate<'a>( | |
| 1420 | /// Format `message` eagerly with `args` to `DiagMessage::Eager`. | |
| 1421 | fn eagerly_format<'a>( | |
| 1424 | 1422 | &self, |
| 1425 | 1423 | message: DiagMessage, |
| 1426 | 1424 | args: impl Iterator<Item = DiagArg<'a>>, |
| 1427 | 1425 | ) -> DiagMessage { |
| 1428 | DiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) | |
| 1426 | DiagMessage::Str(Cow::from(self.eagerly_format_to_string(message, args))) | |
| 1429 | 1427 | } |
| 1430 | 1428 | |
| 1431 | /// Translate `message` eagerly with `args` to `String`. | |
| 1432 | fn eagerly_translate_to_string<'a>( | |
| 1429 | /// Format `message` eagerly with `args` to `String`. | |
| 1430 | fn eagerly_format_to_string<'a>( | |
| 1433 | 1431 | &self, |
| 1434 | 1432 | message: DiagMessage, |
| 1435 | 1433 | args: impl Iterator<Item = DiagArg<'a>>, |
| ... | ... | @@ -1438,12 +1436,12 @@ impl DiagCtxtInner { |
| 1438 | 1436 | format_diag_message(&message, &args).to_string() |
| 1439 | 1437 | } |
| 1440 | 1438 | |
| 1441 | fn eagerly_translate_for_subdiag( | |
| 1439 | fn eagerly_format_for_subdiag( | |
| 1442 | 1440 | &self, |
| 1443 | 1441 | diag: &DiagInner, |
| 1444 | 1442 | msg: impl Into<DiagMessage>, |
| 1445 | 1443 | ) -> DiagMessage { |
| 1446 | self.eagerly_translate(msg.into(), diag.args.iter()) | |
| 1444 | self.eagerly_format(msg.into(), diag.args.iter()) | |
| 1447 | 1445 | } |
| 1448 | 1446 | |
| 1449 | 1447 | fn flush_delayed(&mut self) { |
| ... | ... | @@ -1509,7 +1507,7 @@ impl DiagCtxtInner { |
| 1509 | 1507 | let msg = msg!( |
| 1510 | 1508 | "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`" |
| 1511 | 1509 | ); |
| 1512 | let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call | |
| 1510 | let msg = self.eagerly_format_for_subdiag(&bug, msg); // after the `arg` call | |
| 1513 | 1511 | bug.sub(Note, msg, bug.span.primary_span().unwrap().into()); |
| 1514 | 1512 | } |
| 1515 | 1513 | bug.level = Bug; |
| ... | ... | @@ -1560,7 +1558,7 @@ impl DelayedDiagInner { |
| 1560 | 1558 | }; |
| 1561 | 1559 | diag.arg("emitted_at", diag.emitted_at.clone()); |
| 1562 | 1560 | diag.arg("note", self.note); |
| 1563 | let msg = dcx.eagerly_translate_for_subdiag(&diag, msg); // after the `arg` calls | |
| 1561 | let msg = dcx.eagerly_format_for_subdiag(&diag, msg); // after the `arg` calls | |
| 1564 | 1562 | diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into()); |
| 1565 | 1563 | diag |
| 1566 | 1564 | } |
compiler/rustc_errors/src/translation.rs deleted-68| ... | ... | @@ -1,68 +0,0 @@ |
| 1 | use std::borrow::Cow; | |
| 2 | ||
| 3 | pub use rustc_error_messages::FluentArgs; | |
| 4 | use rustc_error_messages::{DiagArgMap, langid, register_functions}; | |
| 5 | use tracing::{debug, trace}; | |
| 6 | ||
| 7 | use crate::fluent_bundle::FluentResource; | |
| 8 | use crate::{DiagArg, DiagMessage, Style, fluent_bundle}; | |
| 9 | ||
| 10 | /// Convert diagnostic arguments (a rustc internal type that exists to implement | |
| 11 | /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. | |
| 12 | /// | |
| 13 | /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then | |
| 14 | /// passed around as a reference thereafter. | |
| 15 | fn to_fluent_args<'iter>(iter: impl Iterator<Item = DiagArg<'iter>>) -> FluentArgs<'static> { | |
| 16 | let mut args = if let Some(size) = iter.size_hint().1 { | |
| 17 | FluentArgs::with_capacity(size) | |
| 18 | } else { | |
| 19 | FluentArgs::new() | |
| 20 | }; | |
| 21 | ||
| 22 | for (k, v) in iter { | |
| 23 | args.set(k.clone(), v.clone()); | |
| 24 | } | |
| 25 | ||
| 26 | args | |
| 27 | } | |
| 28 | ||
| 29 | /// Convert `DiagMessage`s to a string | |
| 30 | pub fn format_diag_messages( | |
| 31 | messages: &[(DiagMessage, Style)], | |
| 32 | args: &DiagArgMap, | |
| 33 | ) -> Cow<'static, str> { | |
| 34 | Cow::Owned(messages.iter().map(|(m, _)| format_diag_message(m, args)).collect::<String>()) | |
| 35 | } | |
| 36 | ||
| 37 | /// Convert a `DiagMessage` to a string | |
| 38 | pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &DiagArgMap) -> Cow<'a, str> { | |
| 39 | trace!(?message, ?args); | |
| 40 | ||
| 41 | match message { | |
| 42 | DiagMessage::Str(msg) => Cow::Borrowed(msg), | |
| 43 | // This translates an inline fluent diagnostic message | |
| 44 | // It does this by creating a new `FluentBundle` with only one message, | |
| 45 | // and then translating using this bundle. | |
| 46 | DiagMessage::Inline(msg) => { | |
| 47 | const GENERATED_MSG_ID: &str = "generated_msg"; | |
| 48 | let resource = | |
| 49 | FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap(); | |
| 50 | let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); | |
| 51 | bundle.set_use_isolating(false); | |
| 52 | bundle.add_resource(resource).unwrap(); | |
| 53 | register_functions(&mut bundle); | |
| 54 | let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); | |
| 55 | let value = message.value().unwrap(); | |
| 56 | let args = to_fluent_args(args.iter()); | |
| 57 | ||
| 58 | let mut errs = vec![]; | |
| 59 | let translated = bundle.format_pattern(value, Some(&args), &mut errs).to_string(); | |
| 60 | debug!(?translated, ?errs); | |
| 61 | if errs.is_empty() { | |
| 62 | Cow::Owned(translated) | |
| 63 | } else { | |
| 64 | panic!("Fluent errors while formatting message: {errs:?}"); | |
| 65 | } | |
| 66 | } | |
| 67 | } | |
| 68 | } |
compiler/rustc_feature/src/builtin_attrs.rs+5-5| ... | ... | @@ -1330,7 +1330,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
| 1330 | 1330 | safety: AttributeSafety::Normal, |
| 1331 | 1331 | template: template!(NameValueStr: "name"), |
| 1332 | 1332 | duplicates: ErrorFollowing, |
| 1333 | gate: Gated{ | |
| 1333 | gate: Gated { | |
| 1334 | 1334 | feature: sym::rustc_attrs, |
| 1335 | 1335 | message: "use of an internal attribute", |
| 1336 | 1336 | check: Features::rustc_attrs, |
| ... | ... | @@ -1419,7 +1419,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
| 1419 | 1419 | |
| 1420 | 1420 | rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), |
| 1421 | 1421 | rustc_attr!( |
| 1422 | TEST, rustc_outlives, Normal, template!(Word), | |
| 1422 | TEST, rustc_dump_inferred_outlives, Normal, template!(Word), | |
| 1423 | 1423 | WarnFollowing, EncodeCrossCrate::No |
| 1424 | 1424 | ), |
| 1425 | 1425 | rustc_attr!( |
| ... | ... | @@ -1439,11 +1439,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
| 1439 | 1439 | WarnFollowing, EncodeCrossCrate::Yes |
| 1440 | 1440 | ), |
| 1441 | 1441 | rustc_attr!( |
| 1442 | TEST, rustc_variance, Normal, template!(Word), | |
| 1442 | TEST, rustc_dump_variances, Normal, template!(Word), | |
| 1443 | 1443 | WarnFollowing, EncodeCrossCrate::No |
| 1444 | 1444 | ), |
| 1445 | 1445 | rustc_attr!( |
| 1446 | TEST, rustc_variance_of_opaques, Normal, template!(Word), | |
| 1446 | TEST, rustc_dump_variances_of_opaques, Normal, template!(Word), | |
| 1447 | 1447 | WarnFollowing, EncodeCrossCrate::No |
| 1448 | 1448 | ), |
| 1449 | 1449 | rustc_attr!( |
| ... | ... | @@ -1531,7 +1531,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
| 1531 | 1531 | WarnFollowing, EncodeCrossCrate::No |
| 1532 | 1532 | ), |
| 1533 | 1533 | rustc_attr!( |
| 1534 | TEST, rustc_object_lifetime_default, Normal, template!(Word), | |
| 1534 | TEST, rustc_dump_object_lifetime_defaults, Normal, template!(Word), | |
| 1535 | 1535 | WarnFollowing, EncodeCrossCrate::No |
| 1536 | 1536 | ), |
| 1537 | 1537 | rustc_attr!( |
compiler/rustc_feature/src/lib.rs+1-1| ... | ... | @@ -137,5 +137,5 @@ pub use builtin_attrs::{ |
| 137 | 137 | pub use removed::REMOVED_LANG_FEATURES; |
| 138 | 138 | pub use unstable::{ |
| 139 | 139 | DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, |
| 140 | UNSTABLE_LANG_FEATURES, | |
| 140 | TRACK_FEATURE, UNSTABLE_LANG_FEATURES, | |
| 141 | 141 | }; |
compiler/rustc_feature/src/unstable.rs+14-2| ... | ... | @@ -3,11 +3,18 @@ |
| 3 | 3 | use std::path::PathBuf; |
| 4 | 4 | use std::time::{SystemTime, UNIX_EPOCH}; |
| 5 | 5 | |
| 6 | use rustc_data_structures::AtomicRef; | |
| 6 | 7 | use rustc_data_structures::fx::FxHashSet; |
| 7 | 8 | use rustc_span::{Span, Symbol, sym}; |
| 8 | 9 | |
| 9 | 10 | use super::{Feature, to_nonzero}; |
| 10 | 11 | |
| 12 | fn default_track_feature(_: Symbol) {} | |
| 13 | ||
| 14 | /// Recording used features in the dependency graph so incremental can | |
| 15 | /// replay used features when needed. | |
| 16 | pub static TRACK_FEATURE: AtomicRef<fn(Symbol)> = AtomicRef::new(&(default_track_feature as _)); | |
| 17 | ||
| 11 | 18 | #[derive(PartialEq)] |
| 12 | 19 | enum FeatureStatus { |
| 13 | 20 | Default, |
| ... | ... | @@ -103,7 +110,12 @@ impl Features { |
| 103 | 110 | |
| 104 | 111 | /// Is the given feature enabled (via `#[feature(...)]`)? |
| 105 | 112 | pub fn enabled(&self, feature: Symbol) -> bool { |
| 106 | self.enabled_features.contains(&feature) | |
| 113 | if self.enabled_features.contains(&feature) { | |
| 114 | TRACK_FEATURE(feature); | |
| 115 | true | |
| 116 | } else { | |
| 117 | false | |
| 118 | } | |
| 107 | 119 | } |
| 108 | 120 | } |
| 109 | 121 | |
| ... | ... | @@ -124,7 +136,7 @@ macro_rules! declare_features { |
| 124 | 136 | impl Features { |
| 125 | 137 | $( |
| 126 | 138 | pub fn $feature(&self) -> bool { |
| 127 | self.enabled_features.contains(&sym::$feature) | |
| 139 | self.enabled(sym::$feature) | |
| 128 | 140 | } |
| 129 | 141 | )* |
| 130 | 142 |
compiler/rustc_hir/src/attrs/data_structures.rs+12-12| ... | ... | @@ -1366,15 +1366,27 @@ pub enum AttributeKind { |
| 1366 | 1366 | /// Represents `#[rustc_dump_def_parents]` |
| 1367 | 1367 | RustcDumpDefParents, |
| 1368 | 1368 | |
| 1369 | /// Represents `#[rustc_dump_inferred_outlives]` | |
| 1370 | RustcDumpInferredOutlives, | |
| 1371 | ||
| 1369 | 1372 | /// Represents `#[rustc_dump_item_bounds]` |
| 1370 | 1373 | RustcDumpItemBounds, |
| 1371 | 1374 | |
| 1375 | /// Represents `#[rustc_dump_object_lifetime_defaults]`. | |
| 1376 | RustcDumpObjectLifetimeDefaults, | |
| 1377 | ||
| 1372 | 1378 | /// Represents `#[rustc_dump_predicates]` |
| 1373 | 1379 | RustcDumpPredicates, |
| 1374 | 1380 | |
| 1375 | 1381 | /// Represents `#[rustc_dump_user_args]` |
| 1376 | 1382 | RustcDumpUserArgs, |
| 1377 | 1383 | |
| 1384 | /// Represents `#[rustc_dump_variances]` | |
| 1385 | RustcDumpVariances, | |
| 1386 | ||
| 1387 | /// Represents `#[rustc_dump_variances_of_opaques]` | |
| 1388 | RustcDumpVariancesOfOpaques, | |
| 1389 | ||
| 1378 | 1390 | /// Represents `#[rustc_dump_vtable]` |
| 1379 | 1391 | RustcDumpVtable(Span), |
| 1380 | 1392 | |
| ... | ... | @@ -1493,15 +1505,9 @@ pub enum AttributeKind { |
| 1493 | 1505 | span: Span, |
| 1494 | 1506 | }, |
| 1495 | 1507 | |
| 1496 | /// Represents `#[rustc_object_lifetime_default]`. | |
| 1497 | RustcObjectLifetimeDefault, | |
| 1498 | ||
| 1499 | 1508 | /// Represents `#[rustc_offload_kernel]` |
| 1500 | 1509 | RustcOffloadKernel, |
| 1501 | 1510 | |
| 1502 | /// Represents `#[rustc_outlives]` | |
| 1503 | RustcOutlives, | |
| 1504 | ||
| 1505 | 1511 | /// Represents `#[rustc_paren_sugar]`. |
| 1506 | 1512 | RustcParenSugar(Span), |
| 1507 | 1513 | |
| ... | ... | @@ -1574,12 +1580,6 @@ pub enum AttributeKind { |
| 1574 | 1580 | /// Represents `#[rustc_unsafe_specialization_marker]`. |
| 1575 | 1581 | RustcUnsafeSpecializationMarker(Span), |
| 1576 | 1582 | |
| 1577 | /// Represents `#[rustc_variance]` | |
| 1578 | RustcVariance, | |
| 1579 | ||
| 1580 | /// Represents `#[rustc_variance_of_opaques]` | |
| 1581 | RustcVarianceOfOpaques, | |
| 1582 | ||
| 1583 | 1583 | /// Represents `#[sanitize]` |
| 1584 | 1584 | /// |
| 1585 | 1585 | /// the on set and off set are distjoint since there's a third option: unset. |
compiler/rustc_hir/src/attrs/encode_cross_crate.rs+4-4| ... | ... | @@ -124,9 +124,13 @@ impl AttributeKind { |
| 124 | 124 | RustcDocPrimitive(..) => Yes, |
| 125 | 125 | RustcDummy => No, |
| 126 | 126 | RustcDumpDefParents => No, |
| 127 | RustcDumpInferredOutlives => No, | |
| 127 | 128 | RustcDumpItemBounds => No, |
| 129 | RustcDumpObjectLifetimeDefaults => No, | |
| 128 | 130 | RustcDumpPredicates => No, |
| 129 | 131 | RustcDumpUserArgs => No, |
| 132 | RustcDumpVariances => No, | |
| 133 | RustcDumpVariancesOfOpaques => No, | |
| 130 | 134 | RustcDumpVtable(..) => No, |
| 131 | 135 | RustcDynIncompatibleTrait(..) => No, |
| 132 | 136 | RustcEffectiveVisibility => Yes, |
| ... | ... | @@ -161,9 +165,7 @@ impl AttributeKind { |
| 161 | 165 | RustcNounwind => No, |
| 162 | 166 | RustcObjcClass { .. } => No, |
| 163 | 167 | RustcObjcSelector { .. } => No, |
| 164 | RustcObjectLifetimeDefault => No, | |
| 165 | 168 | RustcOffloadKernel => Yes, |
| 166 | RustcOutlives => No, | |
| 167 | 169 | RustcParenSugar(..) => No, |
| 168 | 170 | RustcPassByValue(..) => Yes, |
| 169 | 171 | RustcPassIndirectlyInNonRusticAbis(..) => No, |
| ... | ... | @@ -185,8 +187,6 @@ impl AttributeKind { |
| 185 | 187 | RustcThenThisWouldNeed(..) => No, |
| 186 | 188 | RustcTrivialFieldReads => Yes, |
| 187 | 189 | RustcUnsafeSpecializationMarker(..) => No, |
| 188 | RustcVariance => No, | |
| 189 | RustcVarianceOfOpaques => No, | |
| 190 | 190 | Sanitize { .. } => No, |
| 191 | 191 | ShouldPanic { .. } => No, |
| 192 | 192 | Stability { .. } => Yes, |
compiler/rustc_hir_analysis/src/check/wfcheck.rs+1-1| ... | ... | @@ -997,7 +997,7 @@ fn check_type_defn<'tcx>( |
| 997 | 997 | item: &hir::Item<'tcx>, |
| 998 | 998 | all_sized: bool, |
| 999 | 999 | ) -> Result<(), ErrorGuaranteed> { |
| 1000 | let _ = tcx.representability(item.owner_id.def_id); | |
| 1000 | let _ = tcx.check_representability(item.owner_id.def_id); | |
| 1001 | 1001 | let adt_def = tcx.adt_def(item.owner_id); |
| 1002 | 1002 | |
| 1003 | 1003 | enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| { |
compiler/rustc_hir_analysis/src/collect/dump.rs+24-9| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | use rustc_hir as hir; |
| 2 | use rustc_hir::def::DefKind; | |
| 2 | 3 | use rustc_hir::def_id::LocalDefId; |
| 3 | 4 | use rustc_hir::{find_attr, intravisit}; |
| 4 | 5 | use rustc_middle::hir::nested_filter; |
| ... | ... | @@ -27,7 +28,10 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { |
| 27 | 28 | |
| 28 | 29 | pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { |
| 29 | 30 | for id in tcx.hir_crate_items(()).owners() { |
| 30 | if find_attr!(tcx, id, RustcDumpPredicates) { | |
| 31 | #[expect(deprecated)] // we don't want to unnecessarily retrieve the attrs twice in a row. | |
| 32 | let attrs = tcx.get_all_attrs(id); | |
| 33 | ||
| 34 | if find_attr!(attrs, RustcDumpPredicates) { | |
| 31 | 35 | let preds = tcx.predicates_of(id).instantiate_identity(tcx).predicates; |
| 32 | 36 | let span = tcx.def_span(id); |
| 33 | 37 | |
| ... | ... | @@ -37,15 +41,26 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) { |
| 37 | 41 | } |
| 38 | 42 | diag.emit(); |
| 39 | 43 | } |
| 40 | if find_attr!(tcx, id, RustcDumpItemBounds) { | |
| 41 | let bounds = tcx.item_bounds(id).instantiate_identity(); | |
| 42 | let span = tcx.def_span(id); | |
| 43 | 44 | |
| 44 | let mut diag = tcx.dcx().struct_span_err(span, sym::rustc_dump_item_bounds.as_str()); | |
| 45 | for bound in bounds { | |
| 46 | diag.note(format!("{bound:?}")); | |
| 47 | } | |
| 48 | diag.emit(); | |
| 45 | if find_attr!(attrs, RustcDumpItemBounds) { | |
| 46 | let name = sym::rustc_dump_item_bounds.as_str(); | |
| 47 | ||
| 48 | match tcx.def_kind(id) { | |
| 49 | DefKind::AssocTy => { | |
| 50 | let bounds = tcx.item_bounds(id).instantiate_identity(); | |
| 51 | let span = tcx.def_span(id); | |
| 52 | ||
| 53 | let mut diag = tcx.dcx().struct_span_err(span, name); | |
| 54 | for bound in bounds { | |
| 55 | diag.note(format!("{bound:?}")); | |
| 56 | } | |
| 57 | diag.emit() | |
| 58 | } | |
| 59 | kind => tcx.dcx().span_delayed_bug( | |
| 60 | tcx.def_span(id), | |
| 61 | format!("attr parsing didn't report an error for `#[{name}]` on {kind:?}"), | |
| 62 | ), | |
| 63 | }; | |
| 49 | 64 | } |
| 50 | 65 | } |
| 51 | 66 | } |
compiler/rustc_hir_analysis/src/errors.rs-8| ... | ... | @@ -735,14 +735,6 @@ pub(crate) enum CannotCaptureLateBound { |
| 735 | 735 | }, |
| 736 | 736 | } |
| 737 | 737 | |
| 738 | #[derive(Diagnostic)] | |
| 739 | #[diag("{$variances}")] | |
| 740 | pub(crate) struct VariancesOf { | |
| 741 | #[primary_span] | |
| 742 | pub span: Span, | |
| 743 | pub variances: String, | |
| 744 | } | |
| 745 | ||
| 746 | 738 | #[derive(Diagnostic)] |
| 747 | 739 | #[diag("{$ty}")] |
| 748 | 740 | pub(crate) struct TypeOf<'tcx> { |
compiler/rustc_hir_analysis/src/outlives/dump.rs+2-2| ... | ... | @@ -5,7 +5,7 @@ use rustc_span::sym; |
| 5 | 5 | |
| 6 | 6 | pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { |
| 7 | 7 | for id in tcx.hir_free_items() { |
| 8 | if !find_attr!(tcx, id.owner_id, RustcOutlives) { | |
| 8 | if !find_attr!(tcx, id.owner_id, RustcDumpInferredOutlives) { | |
| 9 | 9 | continue; |
| 10 | 10 | } |
| 11 | 11 | |
| ... | ... | @@ -21,7 +21,7 @@ pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { |
| 21 | 21 | preds.sort(); |
| 22 | 22 | |
| 23 | 23 | let span = tcx.def_span(id.owner_id); |
| 24 | let mut err = tcx.dcx().struct_span_err(span, sym::rustc_outlives.as_str()); | |
| 24 | let mut err = tcx.dcx().struct_span_err(span, sym::rustc_dump_inferred_outlives.as_str()); | |
| 25 | 25 | for pred in preds { |
| 26 | 26 | err.note(pred); |
| 27 | 27 | } |
compiler/rustc_hir_analysis/src/variance/dump.rs+19-11| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | use std::fmt::Write; |
| 2 | 2 | |
| 3 | use rustc_hir::def::DefKind; | |
| 3 | 4 | use rustc_hir::def_id::LocalDefId; |
| 4 | 5 | use rustc_hir::find_attr; |
| 5 | 6 | use rustc_middle::ty::{GenericArgs, TyCtxt}; |
| ... | ... | @@ -25,23 +26,30 @@ fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { |
| 25 | 26 | pub(crate) fn variances(tcx: TyCtxt<'_>) { |
| 26 | 27 | let crate_items = tcx.hir_crate_items(()); |
| 27 | 28 | |
| 28 | if find_attr!(tcx, crate, RustcVarianceOfOpaques) { | |
| 29 | if find_attr!(tcx, crate, RustcDumpVariancesOfOpaques) { | |
| 29 | 30 | for id in crate_items.opaques() { |
| 30 | tcx.dcx().emit_err(crate::errors::VariancesOf { | |
| 31 | span: tcx.def_span(id), | |
| 32 | variances: format_variances(tcx, id), | |
| 33 | }); | |
| 31 | tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id)); | |
| 34 | 32 | } |
| 35 | 33 | } |
| 36 | 34 | |
| 37 | for id in crate_items.free_items() { | |
| 38 | if !find_attr!(tcx, id.owner_id, RustcVariance) { | |
| 35 | for id in crate_items.owners() { | |
| 36 | if !find_attr!(tcx, id, RustcDumpVariances) { | |
| 39 | 37 | continue; |
| 40 | 38 | } |
| 41 | 39 | |
| 42 | tcx.dcx().emit_err(crate::errors::VariancesOf { | |
| 43 | span: tcx.def_span(id.owner_id), | |
| 44 | variances: format_variances(tcx, id.owner_id.def_id), | |
| 45 | }); | |
| 40 | match tcx.def_kind(id) { | |
| 41 | DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {} | |
| 42 | DefKind::TyAlias if tcx.type_alias_is_lazy(id) => {} | |
| 43 | kind => { | |
| 44 | let message = format!( | |
| 45 | "attr parsing didn't report an error for `#[{}]` on {kind:?}", | |
| 46 | rustc_span::sym::rustc_dump_variances, | |
| 47 | ); | |
| 48 | tcx.dcx().span_delayed_bug(tcx.def_span(id), message); | |
| 49 | continue; | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id)); | |
| 46 | 54 | } |
| 47 | 55 | } |
compiler/rustc_hir_typeck/src/errors.rs+3-3| ... | ... | @@ -987,13 +987,13 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { |
| 987 | 987 | fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { |
| 988 | 988 | match self { |
| 989 | 989 | CastUnknownPointerSub::To(span) => { |
| 990 | let msg = diag.eagerly_translate(msg!("needs more type information")); | |
| 990 | let msg = diag.eagerly_format(msg!("needs more type information")); | |
| 991 | 991 | diag.span_label(span, msg); |
| 992 | let msg = diag.eagerly_translate(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); | |
| 992 | let msg = diag.eagerly_format(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); | |
| 993 | 993 | diag.note(msg); |
| 994 | 994 | } |
| 995 | 995 | CastUnknownPointerSub::From(span) => { |
| 996 | let msg = diag.eagerly_translate(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); | |
| 996 | let msg = diag.eagerly_format(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); | |
| 997 | 997 | diag.span_label(span, msg); |
| 998 | 998 | } |
| 999 | 999 | } |
compiler/rustc_interface/src/callbacks.rs+22-1| ... | ... | @@ -12,8 +12,9 @@ |
| 12 | 12 | use std::fmt; |
| 13 | 13 | |
| 14 | 14 | use rustc_errors::DiagInner; |
| 15 | use rustc_middle::dep_graph::TaskDepsRef; | |
| 15 | use rustc_middle::dep_graph::{DepNodeIndex, QuerySideEffect, TaskDepsRef}; | |
| 16 | 16 | use rustc_middle::ty::tls; |
| 17 | use rustc_span::Symbol; | |
| 17 | 18 | |
| 18 | 19 | fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { |
| 19 | 20 | tls::with_context_opt(|icx| { |
| ... | ... | @@ -51,6 +52,25 @@ fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) |
| 51 | 52 | }) |
| 52 | 53 | } |
| 53 | 54 | |
| 55 | fn track_feature(feature: Symbol) { | |
| 56 | tls::with_context_opt(|icx| { | |
| 57 | let Some(icx) = icx else { | |
| 58 | return; | |
| 59 | }; | |
| 60 | let tcx = icx.tcx; | |
| 61 | ||
| 62 | if let Some(dep_node_index) = tcx.sess.used_features.lock().get(&feature).copied() { | |
| 63 | tcx.dep_graph.read_index(DepNodeIndex::from_u32(dep_node_index)); | |
| 64 | } else { | |
| 65 | let dep_node_index = tcx | |
| 66 | .dep_graph | |
| 67 | .encode_side_effect(tcx, QuerySideEffect::CheckFeature { symbol: feature }); | |
| 68 | tcx.sess.used_features.lock().insert(feature, dep_node_index.as_u32()); | |
| 69 | tcx.dep_graph.read_index(dep_node_index); | |
| 70 | } | |
| 71 | }) | |
| 72 | } | |
| 73 | ||
| 54 | 74 | /// This is a callback from `rustc_hir` as it cannot access the implicit state |
| 55 | 75 | /// in `rustc_middle` otherwise. |
| 56 | 76 | fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| ... | ... | @@ -70,4 +90,5 @@ pub fn setup_callbacks() { |
| 70 | 90 | rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); |
| 71 | 91 | rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); |
| 72 | 92 | rustc_errors::TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _)); |
| 93 | rustc_feature::TRACK_FEATURE.swap(&(track_feature as _)); | |
| 73 | 94 | } |
compiler/rustc_interface/src/queries.rs+9| ... | ... | @@ -58,6 +58,15 @@ impl Linker { |
| 58 | 58 | } |
| 59 | 59 | } |
| 60 | 60 | }); |
| 61 | ||
| 62 | if sess.codegen_units().as_usize() == 1 && sess.opts.unstable_opts.time_llvm_passes { | |
| 63 | codegen_backend.print_pass_timings() | |
| 64 | } | |
| 65 | ||
| 66 | if sess.print_llvm_stats() { | |
| 67 | codegen_backend.print_statistics() | |
| 68 | } | |
| 69 | ||
| 61 | 70 | sess.timings.end_section(sess.dcx(), TimingSection::Codegen); |
| 62 | 71 | |
| 63 | 72 | if sess.opts.incremental.is_some() |
compiler/rustc_lint/src/if_let_rescope.rs+1-1| ... | ... | @@ -354,7 +354,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { |
| 354 | 354 | .chain(repeat_n('}', closing_brackets.count)) |
| 355 | 355 | .collect(), |
| 356 | 356 | )); |
| 357 | let msg = diag.eagerly_translate(msg!( | |
| 357 | let msg = diag.eagerly_format(msg!( | |
| 358 | 358 | "a `match` with a single arm can preserve the drop order up to Edition 2021" |
| 359 | 359 | )); |
| 360 | 360 | diag.multipart_suggestion_with_style( |
compiler/rustc_lint/src/lints.rs+1-1| ... | ... | @@ -3629,7 +3629,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { |
| 3629 | 3629 | |
| 3630 | 3630 | Explicit { lifetime_name, suggestions, optional_alternative } => { |
| 3631 | 3631 | diag.arg("lifetime_name", lifetime_name); |
| 3632 | let msg = diag.eagerly_translate(msg!("consistently use `{$lifetime_name}`")); | |
| 3632 | let msg = diag.eagerly_format(msg!("consistently use `{$lifetime_name}`")); | |
| 3633 | 3633 | diag.remove_arg("lifetime_name"); |
| 3634 | 3634 | diag.multipart_suggestion_with_style( |
| 3635 | 3635 | msg, |
compiler/rustc_lint_defs/src/builtin.rs-5| ... | ... | @@ -1088,11 +1088,6 @@ declare_lint! { |
| 1088 | 1088 | /// crate-level [`feature` attributes]. |
| 1089 | 1089 | /// |
| 1090 | 1090 | /// [`feature` attributes]: https://doc.rust-lang.org/nightly/unstable-book/ |
| 1091 | /// | |
| 1092 | /// Note: This lint is currently not functional, see [issue #44232] for | |
| 1093 | /// more details. | |
| 1094 | /// | |
| 1095 | /// [issue #44232]: https://github.com/rust-lang/rust/issues/44232 | |
| 1096 | 1091 | pub UNUSED_FEATURES, |
| 1097 | 1092 | Warn, |
| 1098 | 1093 | "unused features found in crate-level `#[feature]` directives" |
compiler/rustc_macros/src/diagnostics/diagnostic.rs+2-52| ... | ... | @@ -4,7 +4,7 @@ use proc_macro2::TokenStream; |
| 4 | 4 | use quote::quote; |
| 5 | 5 | use synstructure::Structure; |
| 6 | 6 | |
| 7 | use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind; | |
| 7 | use crate::diagnostics::diagnostic_builder::each_variant; | |
| 8 | 8 | use crate::diagnostics::error::DiagnosticDeriveError; |
| 9 | 9 | |
| 10 | 10 | /// The central struct for constructing the `into_diag` method from an annotated struct. |
| ... | ... | @@ -19,8 +19,7 @@ impl<'a> DiagnosticDerive<'a> { |
| 19 | 19 | |
| 20 | 20 | pub(crate) fn into_tokens(self) -> TokenStream { |
| 21 | 21 | let DiagnosticDerive { mut structure } = self; |
| 22 | let kind = DiagnosticDeriveKind::Diagnostic; | |
| 23 | let implementation = kind.each_variant(&mut structure, |mut builder, variant| { | |
| 22 | let implementation = each_variant(&mut structure, |mut builder, variant| { | |
| 24 | 23 | let preamble = builder.preamble(variant); |
| 25 | 24 | let body = builder.body(variant); |
| 26 | 25 | |
| ... | ... | @@ -64,52 +63,3 @@ impl<'a> DiagnosticDerive<'a> { |
| 64 | 63 | }) |
| 65 | 64 | } |
| 66 | 65 | } |
| 67 | ||
| 68 | /// The central struct for constructing the `decorate_lint` method from an annotated struct. | |
| 69 | pub(crate) struct LintDiagnosticDerive<'a> { | |
| 70 | structure: Structure<'a>, | |
| 71 | } | |
| 72 | ||
| 73 | impl<'a> LintDiagnosticDerive<'a> { | |
| 74 | pub(crate) fn new(structure: Structure<'a>) -> Self { | |
| 75 | Self { structure } | |
| 76 | } | |
| 77 | ||
| 78 | pub(crate) fn into_tokens(self) -> TokenStream { | |
| 79 | let LintDiagnosticDerive { mut structure } = self; | |
| 80 | let kind = DiagnosticDeriveKind::LintDiagnostic; | |
| 81 | let implementation = kind.each_variant(&mut structure, |mut builder, variant| { | |
| 82 | let preamble = builder.preamble(variant); | |
| 83 | let body = builder.body(variant); | |
| 84 | ||
| 85 | let Some(message) = builder.primary_message() else { | |
| 86 | return DiagnosticDeriveError::ErrorHandled.to_compile_error(); | |
| 87 | }; | |
| 88 | let message = message.diag_message(Some(variant)); | |
| 89 | let primary_message = quote! { | |
| 90 | diag.primary_message(#message); | |
| 91 | }; | |
| 92 | ||
| 93 | let formatting_init = &builder.formatting_init; | |
| 94 | quote! { | |
| 95 | #primary_message | |
| 96 | #preamble | |
| 97 | #formatting_init | |
| 98 | #body | |
| 99 | diag | |
| 100 | } | |
| 101 | }); | |
| 102 | ||
| 103 | structure.gen_impl(quote! { | |
| 104 | gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self { | |
| 105 | #[track_caller] | |
| 106 | fn decorate_lint<'__b>( | |
| 107 | self, | |
| 108 | diag: &'__b mut rustc_errors::Diag<'__a, ()> | |
| 109 | ) { | |
| 110 | #implementation; | |
| 111 | } | |
| 112 | } | |
| 113 | }) | |
| 114 | } | |
| 115 | } |
compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs+48-77| ... | ... | @@ -18,20 +18,54 @@ use crate::diagnostics::utils::{ |
| 18 | 18 | should_generate_arg, type_is_bool, type_is_unit, type_matches_path, |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? | |
| 22 | #[derive(Clone, Copy, PartialEq, Eq)] | |
| 23 | pub(crate) enum DiagnosticDeriveKind { | |
| 24 | Diagnostic, | |
| 25 | LintDiagnostic, | |
| 21 | pub(crate) fn each_variant<'s, F>(structure: &mut Structure<'s>, f: F) -> TokenStream | |
| 22 | where | |
| 23 | F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, | |
| 24 | { | |
| 25 | let ast = structure.ast(); | |
| 26 | let span = ast.span().unwrap(); | |
| 27 | match ast.data { | |
| 28 | syn::Data::Struct(..) | syn::Data::Enum(..) => (), | |
| 29 | syn::Data::Union(..) => { | |
| 30 | span_err(span, "diagnostic derives can only be used on structs and enums").emit(); | |
| 31 | } | |
| 32 | } | |
| 33 | ||
| 34 | if matches!(ast.data, syn::Data::Enum(..)) { | |
| 35 | for attr in &ast.attrs { | |
| 36 | span_err(attr.span().unwrap(), "unsupported type attribute for diagnostic derive enum") | |
| 37 | .emit(); | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | structure.bind_with(|_| synstructure::BindStyle::Move); | |
| 42 | let variants = structure.each_variant(|variant| { | |
| 43 | let span = match structure.ast().data { | |
| 44 | syn::Data::Struct(..) => span, | |
| 45 | // There isn't a good way to get the span of the variant, so the variant's | |
| 46 | // name will need to do. | |
| 47 | _ => variant.ast().ident.span().unwrap(), | |
| 48 | }; | |
| 49 | let builder = DiagnosticDeriveVariantBuilder { | |
| 50 | span, | |
| 51 | field_map: build_field_mapping(variant), | |
| 52 | formatting_init: TokenStream::new(), | |
| 53 | message: None, | |
| 54 | code: None, | |
| 55 | }; | |
| 56 | f(builder, variant) | |
| 57 | }); | |
| 58 | ||
| 59 | quote! { | |
| 60 | match self { | |
| 61 | #variants | |
| 62 | } | |
| 63 | } | |
| 26 | 64 | } |
| 27 | 65 | |
| 28 | 66 | /// Tracks persistent information required for a specific variant when building up individual calls |
| 29 | /// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for | |
| 30 | /// fatal/errors/warnings and `LintDiagnostic` for lints. | |
| 67 | /// to diagnostic methods for generated diagnostic derives. | |
| 31 | 68 | pub(crate) struct DiagnosticDeriveVariantBuilder { |
| 32 | /// The kind for the entire type. | |
| 33 | pub kind: DiagnosticDeriveKind, | |
| 34 | ||
| 35 | 69 | /// Initialization of format strings for code suggestions. |
| 36 | 70 | pub formatting_init: TokenStream, |
| 37 | 71 | |
| ... | ... | @@ -51,60 +85,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { |
| 51 | 85 | pub code: SpannedOption<()>, |
| 52 | 86 | } |
| 53 | 87 | |
| 54 | impl DiagnosticDeriveKind { | |
| 55 | /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the | |
| 56 | /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions | |
| 57 | /// or attributes on the type itself when input is an enum. | |
| 58 | pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream | |
| 59 | where | |
| 60 | F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, | |
| 61 | { | |
| 62 | let ast = structure.ast(); | |
| 63 | let span = ast.span().unwrap(); | |
| 64 | match ast.data { | |
| 65 | syn::Data::Struct(..) | syn::Data::Enum(..) => (), | |
| 66 | syn::Data::Union(..) => { | |
| 67 | span_err(span, "diagnostic derives can only be used on structs and enums").emit(); | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | if matches!(ast.data, syn::Data::Enum(..)) { | |
| 72 | for attr in &ast.attrs { | |
| 73 | span_err( | |
| 74 | attr.span().unwrap(), | |
| 75 | "unsupported type attribute for diagnostic derive enum", | |
| 76 | ) | |
| 77 | .emit(); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | structure.bind_with(|_| synstructure::BindStyle::Move); | |
| 82 | let variants = structure.each_variant(|variant| { | |
| 83 | let span = match structure.ast().data { | |
| 84 | syn::Data::Struct(..) => span, | |
| 85 | // There isn't a good way to get the span of the variant, so the variant's | |
| 86 | // name will need to do. | |
| 87 | _ => variant.ast().ident.span().unwrap(), | |
| 88 | }; | |
| 89 | let builder = DiagnosticDeriveVariantBuilder { | |
| 90 | kind: self, | |
| 91 | span, | |
| 92 | field_map: build_field_mapping(variant), | |
| 93 | formatting_init: TokenStream::new(), | |
| 94 | message: None, | |
| 95 | code: None, | |
| 96 | }; | |
| 97 | f(builder, variant) | |
| 98 | }); | |
| 99 | ||
| 100 | quote! { | |
| 101 | match self { | |
| 102 | #variants | |
| 103 | } | |
| 104 | } | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | 88 | impl DiagnosticDeriveVariantBuilder { |
| 109 | 89 | pub(crate) fn primary_message(&self) -> Option<&Message> { |
| 110 | 90 | match self.message.as_ref() { |
| ... | ... | @@ -358,20 +338,11 @@ impl DiagnosticDeriveVariantBuilder { |
| 358 | 338 | // `arg` call will not be generated. |
| 359 | 339 | (Meta::Path(_), "skip_arg") => return Ok(quote! {}), |
| 360 | 340 | (Meta::Path(_), "primary_span") => { |
| 361 | match self.kind { | |
| 362 | DiagnosticDeriveKind::Diagnostic => { | |
| 363 | report_error_if_not_applied_to_span(attr, &info)?; | |
| 341 | report_error_if_not_applied_to_span(attr, &info)?; | |
| 364 | 342 | |
| 365 | return Ok(quote! { | |
| 366 | diag.span(#binding); | |
| 367 | }); | |
| 368 | } | |
| 369 | DiagnosticDeriveKind::LintDiagnostic => { | |
| 370 | throw_invalid_attr!(attr, |diag| { | |
| 371 | diag.help("the `primary_span` field attribute is not valid for lint diagnostics") | |
| 372 | }) | |
| 373 | } | |
| 374 | } | |
| 343 | return Ok(quote! { | |
| 344 | diag.span(#binding); | |
| 345 | }); | |
| 375 | 346 | } |
| 376 | 347 | (Meta::Path(_), "subdiagnostic") => { |
| 377 | 348 | return Ok(quote! { diag.subdiagnostic(#binding); }); |
compiler/rustc_macros/src/diagnostics/mod.rs+2-34| ... | ... | @@ -6,7 +6,7 @@ mod msg_macro; |
| 6 | 6 | mod subdiagnostic; |
| 7 | 7 | mod utils; |
| 8 | 8 | |
| 9 | use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; | |
| 9 | use diagnostic::DiagnosticDerive; | |
| 10 | 10 | pub(super) use msg_macro::msg_macro; |
| 11 | 11 | use proc_macro2::TokenStream; |
| 12 | 12 | use subdiagnostic::SubdiagnosticDerive; |
| ... | ... | @@ -51,38 +51,6 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream { |
| 51 | 51 | DiagnosticDerive::new(s).into_tokens() |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, | |
| 55 | /// independent from the actual lint emitting code. | |
| 56 | /// | |
| 57 | /// ```ignore (rust) | |
| 58 | /// #[derive(LintDiagnostic)] | |
| 59 | /// #[diag("unused attribute")] | |
| 60 | /// pub(crate) struct UnusedAttribute { | |
| 61 | /// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] | |
| 62 | /// pub this: Span, | |
| 63 | /// #[note("attribute also specified here")] | |
| 64 | /// pub other: Span, | |
| 65 | /// #[warning( | |
| 66 | /// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" | |
| 67 | /// )] | |
| 68 | /// pub warning: bool, | |
| 69 | /// } | |
| 70 | /// ``` | |
| 71 | /// | |
| 72 | /// Then, later, to emit the error: | |
| 73 | /// | |
| 74 | /// ```ignore (rust) | |
| 75 | /// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute { | |
| 76 | /// ... | |
| 77 | /// }); | |
| 78 | /// ``` | |
| 79 | /// | |
| 80 | /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: | |
| 81 | /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference> | |
| 82 | pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { | |
| 83 | LintDiagnosticDerive::new(s).into_tokens() | |
| 84 | } | |
| 85 | ||
| 86 | 54 | /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and |
| 87 | 55 | /// suggestions to be specified as a structs or enums, independent from the actual diagnostics |
| 88 | 56 | /// emitting code or diagnostic derives. |
| ... | ... | @@ -99,7 +67,7 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { |
| 99 | 67 | /// Then, later, use the subdiagnostic in a diagnostic: |
| 100 | 68 | /// |
| 101 | 69 | /// ```ignore (rust) |
| 102 | /// #[derive(LintDiagnostic)] | |
| 70 | /// #[derive(Diagnostic)] | |
| 103 | 71 | /// #[diag("unused doc comment")] |
| 104 | 72 | /// pub(crate) struct BuiltinUnusedDocComment<'a> { |
| 105 | 73 | /// pub kind: &'a str, |
compiler/rustc_macros/src/diagnostics/subdiagnostic.rs+1-1| ... | ... | @@ -536,7 +536,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { |
| 536 | 536 | for (kind, messages) in kind_messages { |
| 537 | 537 | let message = format_ident!("__message"); |
| 538 | 538 | let message_stream = messages.diag_message(Some(self.variant)); |
| 539 | calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); | |
| 539 | calls.extend(quote! { let #message = #diag.eagerly_format(#message_stream); }); | |
| 540 | 540 | |
| 541 | 541 | let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); |
| 542 | 542 | let call = match kind { |
compiler/rustc_macros/src/lib.rs-19| ... | ... | @@ -196,25 +196,6 @@ decl_derive!( |
| 196 | 196 | suggestion_hidden, |
| 197 | 197 | suggestion_verbose)] => diagnostics::diagnostic_derive |
| 198 | 198 | ); |
| 199 | decl_derive!( | |
| 200 | [LintDiagnostic, attributes( | |
| 201 | // struct attributes | |
| 202 | diag, | |
| 203 | help, | |
| 204 | help_once, | |
| 205 | note, | |
| 206 | note_once, | |
| 207 | warning, | |
| 208 | // field attributes | |
| 209 | skip_arg, | |
| 210 | primary_span, | |
| 211 | label, | |
| 212 | subdiagnostic, | |
| 213 | suggestion, | |
| 214 | suggestion_short, | |
| 215 | suggestion_hidden, | |
| 216 | suggestion_verbose)] => diagnostics::lint_diagnostic_derive | |
| 217 | ); | |
| 218 | 199 | decl_derive!( |
| 219 | 200 | [Subdiagnostic, attributes( |
| 220 | 201 | // struct/variant attributes |
compiler/rustc_macros/src/query.rs-9| ... | ... | @@ -144,7 +144,6 @@ struct QueryModifiers { |
| 144 | 144 | arena_cache: Option<Ident>, |
| 145 | 145 | cache_on_disk_if: Option<CacheOnDiskIf>, |
| 146 | 146 | cycle_delay_bug: Option<Ident>, |
| 147 | cycle_fatal: Option<Ident>, | |
| 148 | 147 | cycle_stash: Option<Ident>, |
| 149 | 148 | depth_limit: Option<Ident>, |
| 150 | 149 | desc: Desc, |
| ... | ... | @@ -160,7 +159,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { |
| 160 | 159 | let mut arena_cache = None; |
| 161 | 160 | let mut cache_on_disk_if = None; |
| 162 | 161 | let mut desc = None; |
| 163 | let mut cycle_fatal = None; | |
| 164 | 162 | let mut cycle_delay_bug = None; |
| 165 | 163 | let mut cycle_stash = None; |
| 166 | 164 | let mut no_hash = None; |
| ... | ... | @@ -197,8 +195,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { |
| 197 | 195 | try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block }); |
| 198 | 196 | } else if modifier == "arena_cache" { |
| 199 | 197 | try_insert!(arena_cache = modifier); |
| 200 | } else if modifier == "cycle_fatal" { | |
| 201 | try_insert!(cycle_fatal = modifier); | |
| 202 | 198 | } else if modifier == "cycle_delay_bug" { |
| 203 | 199 | try_insert!(cycle_delay_bug = modifier); |
| 204 | 200 | } else if modifier == "cycle_stash" { |
| ... | ... | @@ -228,7 +224,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> { |
| 228 | 224 | arena_cache, |
| 229 | 225 | cache_on_disk_if, |
| 230 | 226 | desc, |
| 231 | cycle_fatal, | |
| 232 | 227 | cycle_delay_bug, |
| 233 | 228 | cycle_stash, |
| 234 | 229 | no_hash, |
| ... | ... | @@ -248,7 +243,6 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr |
| 248 | 243 | arena_cache, |
| 249 | 244 | cache_on_disk_if, |
| 250 | 245 | cycle_delay_bug, |
| 251 | cycle_fatal, | |
| 252 | 246 | cycle_stash, |
| 253 | 247 | depth_limit, |
| 254 | 248 | desc: _, |
| ... | ... | @@ -266,8 +260,6 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr |
| 266 | 260 | |
| 267 | 261 | let cycle_error_handling = if cycle_delay_bug.is_some() { |
| 268 | 262 | quote! { DelayBug } |
| 269 | } else if cycle_fatal.is_some() { | |
| 270 | quote! { Fatal } | |
| 271 | 263 | } else if cycle_stash.is_some() { |
| 272 | 264 | quote! { Stash } |
| 273 | 265 | } else { |
| ... | ... | @@ -407,7 +399,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke |
| 407 | 399 | |
| 408 | 400 | doc_link!( |
| 409 | 401 | arena_cache, |
| 410 | cycle_fatal, | |
| 411 | 402 | cycle_delay_bug, |
| 412 | 403 | cycle_stash, |
| 413 | 404 | no_hash, |
compiler/rustc_middle/src/dep_graph/graph.rs+48-24| ... | ... | @@ -17,6 +17,7 @@ use rustc_index::IndexVec; |
| 17 | 17 | use rustc_macros::{Decodable, Encodable}; |
| 18 | 18 | use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; |
| 19 | 19 | use rustc_session::Session; |
| 20 | use rustc_span::Symbol; | |
| 20 | 21 | use tracing::{debug, instrument}; |
| 21 | 22 | #[cfg(debug_assertions)] |
| 22 | 23 | use {super::debug::EdgeFilter, std::env}; |
| ... | ... | @@ -45,6 +46,11 @@ pub enum QuerySideEffect { |
| 45 | 46 | /// the query as green, as that query will have the side |
| 46 | 47 | /// effect dep node as a dependency. |
| 47 | 48 | Diagnostic(DiagInner), |
| 49 | /// Records the feature used during query execution. | |
| 50 | /// This feature will be inserted into `sess.used_features` | |
| 51 | /// if we mark the query as green, as that query will have | |
| 52 | /// the side effect dep node as a dependency. | |
| 53 | CheckFeature { symbol: Symbol }, | |
| 48 | 54 | } |
| 49 | 55 | #[derive(Clone)] |
| 50 | 56 | pub struct DepGraph { |
| ... | ... | @@ -514,29 +520,40 @@ impl DepGraph { |
| 514 | 520 | } |
| 515 | 521 | } |
| 516 | 522 | |
| 517 | /// This encodes a diagnostic by creating a node with an unique index and associating | |
| 518 | /// `diagnostic` with it, for use in the next session. | |
| 523 | /// This encodes a side effect by creating a node with an unique index and associating | |
| 524 | /// it with the node, for use in the next session. | |
| 519 | 525 | #[inline] |
| 520 | 526 | pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) { |
| 521 | 527 | if let Some(ref data) = self.data { |
| 522 | 528 | read_deps(|task_deps| match task_deps { |
| 523 | 529 | TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, |
| 524 | 530 | TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { |
| 525 | self.read_index(data.encode_diagnostic(tcx, diagnostic)); | |
| 531 | let dep_node_index = data | |
| 532 | .encode_side_effect(tcx, QuerySideEffect::Diagnostic(diagnostic.clone())); | |
| 533 | self.read_index(dep_node_index); | |
| 526 | 534 | } |
| 527 | 535 | }) |
| 528 | 536 | } |
| 529 | 537 | } |
| 530 | /// This forces a diagnostic node green by running its side effect. `prev_index` would | |
| 531 | /// refer to a node created used `encode_diagnostic` in the previous session. | |
| 538 | /// This forces a side effect node green by running its side effect. `prev_index` would | |
| 539 | /// refer to a node created used `encode_side_effect` in the previous session. | |
| 532 | 540 | #[inline] |
| 533 | pub fn force_diagnostic_node<'tcx>( | |
| 541 | pub fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { | |
| 542 | if let Some(ref data) = self.data { | |
| 543 | data.force_side_effect(tcx, prev_index); | |
| 544 | } | |
| 545 | } | |
| 546 | ||
| 547 | #[inline] | |
| 548 | pub fn encode_side_effect<'tcx>( | |
| 534 | 549 | &self, |
| 535 | 550 | tcx: TyCtxt<'tcx>, |
| 536 | prev_index: SerializedDepNodeIndex, | |
| 537 | ) { | |
| 551 | side_effect: QuerySideEffect, | |
| 552 | ) -> DepNodeIndex { | |
| 538 | 553 | if let Some(ref data) = self.data { |
| 539 | data.force_diagnostic_node(tcx, prev_index); | |
| 554 | data.encode_side_effect(tcx, side_effect) | |
| 555 | } else { | |
| 556 | self.next_virtual_depnode_index() | |
| 540 | 557 | } |
| 541 | 558 | } |
| 542 | 559 | |
| ... | ... | @@ -673,10 +690,14 @@ impl DepGraphData { |
| 673 | 690 | self.debug_loaded_from_disk.lock().insert(dep_node); |
| 674 | 691 | } |
| 675 | 692 | |
| 676 | /// This encodes a diagnostic by creating a node with an unique index and associating | |
| 677 | /// `diagnostic` with it, for use in the next session. | |
| 693 | /// This encodes a side effect by creating a node with an unique index and associating | |
| 694 | /// it with the node, for use in the next session. | |
| 678 | 695 | #[inline] |
| 679 | fn encode_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) -> DepNodeIndex { | |
| 696 | fn encode_side_effect<'tcx>( | |
| 697 | &self, | |
| 698 | tcx: TyCtxt<'tcx>, | |
| 699 | side_effect: QuerySideEffect, | |
| 700 | ) -> DepNodeIndex { | |
| 680 | 701 | // Use `send_new` so we get an unique index, even though the dep node is not. |
| 681 | 702 | let dep_node_index = self.current.encoder.send_new( |
| 682 | 703 | DepNode { |
| ... | ... | @@ -684,28 +705,21 @@ impl DepGraphData { |
| 684 | 705 | key_fingerprint: PackedFingerprint::from(Fingerprint::ZERO), |
| 685 | 706 | }, |
| 686 | 707 | Fingerprint::ZERO, |
| 687 | // We want the side effect node to always be red so it will be forced and emit the | |
| 688 | // diagnostic. | |
| 708 | // We want the side effect node to always be red so it will be forced and run the | |
| 709 | // side effect. | |
| 689 | 710 | std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), |
| 690 | 711 | ); |
| 691 | let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone()); | |
| 692 | 712 | tcx.store_side_effect(dep_node_index, side_effect); |
| 693 | 713 | dep_node_index |
| 694 | 714 | } |
| 695 | 715 | |
| 696 | /// This forces a diagnostic node green by running its side effect. `prev_index` would | |
| 697 | /// refer to a node created used `encode_diagnostic` in the previous session. | |
| 716 | /// This forces a side effect node green by running its side effect. `prev_index` would | |
| 717 | /// refer to a node created used `encode_side_effect` in the previous session. | |
| 698 | 718 | #[inline] |
| 699 | fn force_diagnostic_node<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { | |
| 719 | fn force_side_effect<'tcx>(&self, tcx: TyCtxt<'tcx>, prev_index: SerializedDepNodeIndex) { | |
| 700 | 720 | with_deps(TaskDepsRef::Ignore, || { |
| 701 | 721 | let side_effect = tcx.load_side_effect(prev_index).unwrap(); |
| 702 | 722 | |
| 703 | match &side_effect { | |
| 704 | QuerySideEffect::Diagnostic(diagnostic) => { | |
| 705 | tcx.dcx().emit_diagnostic(diagnostic.clone()); | |
| 706 | } | |
| 707 | } | |
| 708 | ||
| 709 | 723 | // Use `send_and_color` as `promote_node_and_deps_to_current` expects all |
| 710 | 724 | // green dependencies. `send_and_color` will also prevent multiple nodes |
| 711 | 725 | // being encoded for concurrent calls. |
| ... | ... | @@ -720,6 +734,16 @@ impl DepGraphData { |
| 720 | 734 | std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), |
| 721 | 735 | true, |
| 722 | 736 | ); |
| 737 | ||
| 738 | match &side_effect { | |
| 739 | QuerySideEffect::Diagnostic(diagnostic) => { | |
| 740 | tcx.dcx().emit_diagnostic(diagnostic.clone()); | |
| 741 | } | |
| 742 | QuerySideEffect::CheckFeature { symbol } => { | |
| 743 | tcx.sess.used_features.lock().insert(*symbol, dep_node_index.as_u32()); | |
| 744 | } | |
| 745 | } | |
| 746 | ||
| 723 | 747 | // This will just overwrite the same value for concurrent calls. |
| 724 | 748 | tcx.store_side_effect(dep_node_index, side_effect); |
| 725 | 749 | }) |
compiler/rustc_middle/src/lint.rs+2-2| ... | ... | @@ -492,8 +492,8 @@ pub fn lint_level( |
| 492 | 492 | /// - [`TyCtxt::node_lint`] |
| 493 | 493 | /// - `LintContext::opt_span_lint` |
| 494 | 494 | /// |
| 495 | /// This function will replace `lint_level` once all `LintDiagnostic` items have been migrated to | |
| 496 | /// `Diagnostic`. | |
| 495 | /// This function will replace `lint_level` once all its callers have been replaced | |
| 496 | /// with `diag_lint_level`. | |
| 497 | 497 | #[track_caller] |
| 498 | 498 | pub fn diag_lint_level<'a, D: Diagnostic<'a, ()> + 'a>( |
| 499 | 499 | sess: &'a Session, |
compiler/rustc_middle/src/middle/stability.rs+10-16| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | use std::num::NonZero; |
| 5 | 5 | |
| 6 | 6 | use rustc_ast::NodeId; |
| 7 | use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, LintDiagnostic, msg}; | |
| 7 | use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, msg}; | |
| 8 | 8 | use rustc_feature::GateIssue; |
| 9 | 9 | use rustc_hir::attrs::{DeprecatedSince, Deprecation}; |
| 10 | 10 | use rustc_hir::def_id::{DefId, LocalDefId}; |
| ... | ... | @@ -131,15 +131,8 @@ impl<'a, G: EmissionGuarantee> rustc_errors::Diagnostic<'a, G> for Deprecated { |
| 131 | 131 | dcx: rustc_errors::DiagCtxtHandle<'a>, |
| 132 | 132 | level: rustc_errors::Level, |
| 133 | 133 | ) -> Diag<'a, G> { |
| 134 | let mut diag = Diag::new(dcx, level, ""); | |
| 135 | self.decorate_lint(&mut diag); | |
| 136 | diag | |
| 137 | } | |
| 138 | } | |
| 139 | ||
| 140 | impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for Deprecated { | |
| 141 | fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { | |
| 142 | diag.primary_message(match &self.since_kind { | |
| 134 | let Self { sub, kind, path, note, since_kind } = self; | |
| 135 | let mut diag = Diag::new(dcx, level, match &since_kind { | |
| 143 | 136 | DeprecatedSinceKind::InEffect => msg!( |
| 144 | 137 | "use of deprecated {$kind} `{$path}`{$has_note -> |
| 145 | 138 | [true] : {$note} |
| ... | ... | @@ -160,21 +153,22 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for Deprecated { |
| 160 | 153 | }" |
| 161 | 154 | ) |
| 162 | 155 | } |
| 163 | }); | |
| 164 | diag.arg("kind", self.kind); | |
| 165 | diag.arg("path", self.path); | |
| 166 | if let DeprecatedSinceKind::InVersion(version) = self.since_kind { | |
| 156 | }) | |
| 157 | .with_arg("kind", kind) | |
| 158 | .with_arg("path", path); | |
| 159 | if let DeprecatedSinceKind::InVersion(version) = since_kind { | |
| 167 | 160 | diag.arg("version", version); |
| 168 | 161 | } |
| 169 | if let Some(note) = self.note { | |
| 162 | if let Some(note) = note { | |
| 170 | 163 | diag.arg("has_note", true); |
| 171 | 164 | diag.arg("note", note); |
| 172 | 165 | } else { |
| 173 | 166 | diag.arg("has_note", false); |
| 174 | 167 | } |
| 175 | if let Some(sub) = self.sub { | |
| 168 | if let Some(sub) = sub { | |
| 176 | 169 | diag.subdiagnostic(sub); |
| 177 | 170 | } |
| 171 | diag | |
| 178 | 172 | } |
| 179 | 173 | } |
| 180 | 174 |
compiler/rustc_middle/src/queries.rs+20-28| ... | ... | @@ -32,7 +32,6 @@ |
| 32 | 32 | //! - `arena_cache`: Use an arena for in-memory caching of the query result. |
| 33 | 33 | //! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to |
| 34 | 34 | //! true. The query key identifier is available for use within the block, as is `tcx`. |
| 35 | //! - `cycle_fatal`: If a dependency cycle is detected, abort compilation with a fatal error. | |
| 36 | 35 | //! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. |
| 37 | 36 | //! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. |
| 38 | 37 | //! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. |
| ... | ... | @@ -149,11 +148,11 @@ use crate::{dep_graph, mir, thir}; |
| 149 | 148 | // which memoizes and does dep-graph tracking, wrapping around the actual |
| 150 | 149 | // `Providers` that the driver creates (using several `rustc_*` crates). |
| 151 | 150 | // |
| 152 | // The result type of each query must implement `Clone`, and additionally | |
| 153 | // `ty::query::from_cycle_error::FromCycleError`, which produces an appropriate | |
| 151 | // The result type of each query must implement `Clone`. Additionally | |
| 152 | // `ty::query::from_cycle_error::FromCycleError` can be implemented which produces an appropriate | |
| 154 | 153 | // placeholder (error) value if the query resulted in a query cycle. |
| 155 | // Queries marked with `cycle_fatal` do not need the latter implementation, | |
| 156 | // as they will raise a fatal error on query cycles instead. | |
| 154 | // Queries without a `FromCycleError` implementation will raise a fatal error on query | |
| 155 | // cycles instead. | |
| 157 | 156 | rustc_queries! { |
| 158 | 157 | /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`. |
| 159 | 158 | /// The key is: |
| ... | ... | @@ -587,24 +586,28 @@ rustc_queries! { |
| 587 | 586 | } |
| 588 | 587 | |
| 589 | 588 | query is_panic_runtime(_: CrateNum) -> bool { |
| 590 | cycle_fatal | |
| 591 | 589 | desc { "checking if the crate is_panic_runtime" } |
| 592 | 590 | separate_provide_extern |
| 593 | 591 | } |
| 594 | 592 | |
| 595 | 593 | /// Checks whether a type is representable or infinitely sized |
| 596 | query representability(key: LocalDefId) -> rustc_middle::ty::Representability { | |
| 594 | query check_representability(key: LocalDefId) -> rustc_middle::ty::Representability { | |
| 597 | 595 | desc { "checking if `{}` is representable", tcx.def_path_str(key) } |
| 598 | // infinitely sized types will cause a cycle | |
| 596 | // Infinitely sized types will cause a cycle. The custom `FromCycleError` impl for | |
| 597 | // `Representability` will print a custom error about the infinite size and then abort | |
| 598 | // compilation. (In the past we recovered and continued, but in practice that leads to | |
| 599 | // confusing subsequent error messages about cycles that then abort.) | |
| 599 | 600 | cycle_delay_bug |
| 600 | // we don't want recursive representability calls to be forced with | |
| 601 | // We don't want recursive representability calls to be forced with | |
| 601 | 602 | // incremental compilation because, if a cycle occurs, we need the |
| 602 | // entire cycle to be in memory for diagnostics | |
| 603 | // entire cycle to be in memory for diagnostics. This means we can't | |
| 604 | // use `ensure_ok()` with this query. | |
| 603 | 605 | anon |
| 604 | 606 | } |
| 605 | 607 | |
| 606 | /// An implementation detail for the `representability` query | |
| 607 | query representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability { | |
| 608 | /// An implementation detail for the `check_representability` query. See that query for more | |
| 609 | /// details, particularly on the modifiers. | |
| 610 | query check_representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability { | |
| 608 | 611 | desc { "checking if `{}` is representable", key } |
| 609 | 612 | cycle_delay_bug |
| 610 | 613 | anon |
| ... | ... | @@ -838,8 +841,8 @@ rustc_queries! { |
| 838 | 841 | /// |
| 839 | 842 | /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`. |
| 840 | 843 | /// |
| 841 | /// **Tip**: You can use `#[rustc_outlives]` on an item to basically print the | |
| 842 | /// result of this query for use in UI tests or for debugging purposes. | |
| 844 | /// **Tip**: You can use `#[rustc_dump_inferred_outlives]` on an item to basically | |
| 845 | /// print the result of this query for use in UI tests or for debugging purposes. | |
| 843 | 846 | query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] { |
| 844 | 847 | desc { "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) } |
| 845 | 848 | cache_on_disk_if { key.is_local() } |
| ... | ... | @@ -1046,8 +1049,8 @@ rustc_queries! { |
| 1046 | 1049 | /// The list of variances corresponds to the list of (early-bound) generic |
| 1047 | 1050 | /// parameters of the item (including its parents). |
| 1048 | 1051 | /// |
| 1049 | /// **Tip**: You can use `#[rustc_variance]` on an item to basically print the | |
| 1050 | /// result of this query for use in UI tests or for debugging purposes. | |
| 1052 | /// **Tip**: You can use `#[rustc_dump_variances]` on an item to basically print | |
| 1053 | /// the result of this query for use in UI tests or for debugging purposes. | |
| 1051 | 1054 | query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { |
| 1052 | 1055 | desc { "computing the variances of `{}`", tcx.def_path_str(def_id) } |
| 1053 | 1056 | cache_on_disk_if { def_id.is_local() } |
| ... | ... | @@ -1318,7 +1321,6 @@ rustc_queries! { |
| 1318 | 1321 | /// Return the set of (transitive) callees that may result in a recursive call to `key`, |
| 1319 | 1322 | /// if we were able to walk all callees. |
| 1320 | 1323 | query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option<UnordSet<LocalDefId>> { |
| 1321 | cycle_fatal | |
| 1322 | 1324 | arena_cache |
| 1323 | 1325 | desc { |
| 1324 | 1326 | "computing (transitive) callees of `{}` that may recurse", |
| ... | ... | @@ -1329,7 +1331,6 @@ rustc_queries! { |
| 1329 | 1331 | |
| 1330 | 1332 | /// Obtain all the calls into other local functions |
| 1331 | 1333 | query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] { |
| 1332 | cycle_fatal | |
| 1333 | 1334 | desc { |
| 1334 | 1335 | "computing all local function calls in `{}`", |
| 1335 | 1336 | tcx.def_path_str(key.def_id()), |
| ... | ... | @@ -1850,31 +1851,26 @@ rustc_queries! { |
| 1850 | 1851 | } |
| 1851 | 1852 | |
| 1852 | 1853 | query is_compiler_builtins(_: CrateNum) -> bool { |
| 1853 | cycle_fatal | |
| 1854 | 1854 | desc { "checking if the crate is_compiler_builtins" } |
| 1855 | 1855 | separate_provide_extern |
| 1856 | 1856 | } |
| 1857 | 1857 | query has_global_allocator(_: CrateNum) -> bool { |
| 1858 | 1858 | // This query depends on untracked global state in CStore |
| 1859 | 1859 | eval_always |
| 1860 | cycle_fatal | |
| 1861 | 1860 | desc { "checking if the crate has_global_allocator" } |
| 1862 | 1861 | separate_provide_extern |
| 1863 | 1862 | } |
| 1864 | 1863 | query has_alloc_error_handler(_: CrateNum) -> bool { |
| 1865 | 1864 | // This query depends on untracked global state in CStore |
| 1866 | 1865 | eval_always |
| 1867 | cycle_fatal | |
| 1868 | 1866 | desc { "checking if the crate has_alloc_error_handler" } |
| 1869 | 1867 | separate_provide_extern |
| 1870 | 1868 | } |
| 1871 | 1869 | query has_panic_handler(_: CrateNum) -> bool { |
| 1872 | cycle_fatal | |
| 1873 | 1870 | desc { "checking if the crate has_panic_handler" } |
| 1874 | 1871 | separate_provide_extern |
| 1875 | 1872 | } |
| 1876 | 1873 | query is_profiler_runtime(_: CrateNum) -> bool { |
| 1877 | cycle_fatal | |
| 1878 | 1874 | desc { "checking if a crate is `#![profiler_runtime]`" } |
| 1879 | 1875 | separate_provide_extern |
| 1880 | 1876 | } |
| ... | ... | @@ -1883,22 +1879,18 @@ rustc_queries! { |
| 1883 | 1879 | cache_on_disk_if { true } |
| 1884 | 1880 | } |
| 1885 | 1881 | query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> { |
| 1886 | cycle_fatal | |
| 1887 | 1882 | desc { "getting a crate's required panic strategy" } |
| 1888 | 1883 | separate_provide_extern |
| 1889 | 1884 | } |
| 1890 | 1885 | query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { |
| 1891 | cycle_fatal | |
| 1892 | 1886 | desc { "getting a crate's configured panic-in-drop strategy" } |
| 1893 | 1887 | separate_provide_extern |
| 1894 | 1888 | } |
| 1895 | 1889 | query is_no_builtins(_: CrateNum) -> bool { |
| 1896 | cycle_fatal | |
| 1897 | 1890 | desc { "getting whether a crate has `#![no_builtins]`" } |
| 1898 | 1891 | separate_provide_extern |
| 1899 | 1892 | } |
| 1900 | 1893 | query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { |
| 1901 | cycle_fatal | |
| 1902 | 1894 | desc { "getting a crate's symbol mangling version" } |
| 1903 | 1895 | separate_provide_extern |
| 1904 | 1896 | } |
| ... | ... | @@ -2145,7 +2137,7 @@ rustc_queries! { |
| 2145 | 2137 | /// Returns the *default lifetime* to be used if a trait object type were to be passed for |
| 2146 | 2138 | /// the type parameter given by `DefId`. |
| 2147 | 2139 | /// |
| 2148 | /// **Tip**: You can use `#[rustc_object_lifetime_default]` on an item to basically | |
| 2140 | /// **Tip**: You can use `#[rustc_dump_object_lifetime_defaults]` on an item to basically | |
| 2149 | 2141 | /// print the result of this query for use in UI tests or for debugging purposes. |
| 2150 | 2142 | /// |
| 2151 | 2143 | /// # Examples |
compiler/rustc_middle/src/query/modifiers.rs-5| ... | ... | @@ -28,11 +28,6 @@ pub(crate) struct cache_on_disk_if; |
| 28 | 28 | /// A cycle error results in a delay_bug call |
| 29 | 29 | pub(crate) struct cycle_delay_bug; |
| 30 | 30 | |
| 31 | /// # `cycle_fatal` query modifier | |
| 32 | /// | |
| 33 | /// A cycle error for this query aborting the compilation with a fatal error. | |
| 34 | pub(crate) struct cycle_fatal; | |
| 35 | ||
| 36 | 31 | /// # `cycle_stash` query modifier |
| 37 | 32 | /// |
| 38 | 33 | /// A cycle error results in a stashed cycle error that can be unstashed and canceled later |
compiler/rustc_middle/src/query/plumbing.rs-1| ... | ... | @@ -57,7 +57,6 @@ pub enum ActiveKeyStatus<'tcx> { |
| 57 | 57 | #[derive(Copy, Clone)] |
| 58 | 58 | pub enum CycleErrorHandling { |
| 59 | 59 | Error, |
| 60 | Fatal, | |
| 61 | 60 | DelayBug, |
| 62 | 61 | Stash, |
| 63 | 62 | } |
compiler/rustc_middle/src/ty/adt.rs+3-4| ... | ... | @@ -741,8 +741,7 @@ impl<'tcx> AdtDef<'tcx> { |
| 741 | 741 | } |
| 742 | 742 | } |
| 743 | 743 | |
| 744 | /// This type exists just so a `FromCycleError` impl can be made for the `check_representability` | |
| 745 | /// query. | |
| 744 | 746 | #[derive(Clone, Copy, Debug, HashStable)] |
| 745 | pub enum Representability { | |
| 746 | Representable, | |
| 747 | Infinite(ErrorGuaranteed), | |
| 748 | } | |
| 747 | pub struct Representability; |
compiler/rustc_middle/src/ty/context.rs+31-1| ... | ... | @@ -36,7 +36,7 @@ use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; |
| 36 | 36 | use rustc_hir::intravisit::VisitorExt; |
| 37 | 37 | use rustc_hir::lang_items::LangItem; |
| 38 | 38 | use rustc_hir::limit::Limit; |
| 39 | use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr}; | |
| 39 | use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, Node, TraitCandidate, find_attr}; | |
| 40 | 40 | use rustc_index::IndexVec; |
| 41 | 41 | use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; |
| 42 | 42 | use rustc_session::Session; |
| ... | ... | @@ -1688,6 +1688,36 @@ impl<'tcx> TyCtxt<'tcx> { |
| 1688 | 1688 | self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error }); |
| 1689 | 1689 | } |
| 1690 | 1690 | } |
| 1691 | ||
| 1692 | pub fn report_unused_features(self) { | |
| 1693 | // Collect first to avoid holding the lock while linting. | |
| 1694 | let used_features = self.sess.used_features.lock(); | |
| 1695 | let unused_features = self | |
| 1696 | .features() | |
| 1697 | .enabled_features_iter_stable_order() | |
| 1698 | .filter(|(f, _)| { | |
| 1699 | !used_features.contains_key(f) | |
| 1700 | // FIXME: `restricted_std` is used to tell a standard library built | |
| 1701 | // for a platform that it doesn't know how to support. But it | |
| 1702 | // could only gate a private mod (see `__restricted_std_workaround`) | |
| 1703 | // with `cfg(not(restricted_std))`, so it cannot be recorded as used | |
| 1704 | // in downstream crates. It should never be linted, but should we | |
| 1705 | // hack this in the linter to ignore it? | |
| 1706 | && f.as_str() != "restricted_std" | |
| 1707 | }) | |
| 1708 | .collect::<Vec<_>>(); | |
| 1709 | ||
| 1710 | for (feature, span) in unused_features { | |
| 1711 | self.node_span_lint( | |
| 1712 | rustc_session::lint::builtin::UNUSED_FEATURES, | |
| 1713 | CRATE_HIR_ID, | |
| 1714 | span, | |
| 1715 | |lint| { | |
| 1716 | lint.primary_message(format!("feature `{}` is declared but not used", feature)); | |
| 1717 | }, | |
| 1718 | ); | |
| 1719 | } | |
| 1720 | } | |
| 1691 | 1721 | } |
| 1692 | 1722 | |
| 1693 | 1723 | macro_rules! nop_lift { |
compiler/rustc_middle/src/ty/inhabitedness/mod.rs+2-3| ... | ... | @@ -61,10 +61,9 @@ pub(crate) fn provide(providers: &mut Providers) { |
| 61 | 61 | /// requires calling [`InhabitedPredicate::instantiate`] |
| 62 | 62 | fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { |
| 63 | 63 | if let Some(def_id) = def_id.as_local() { |
| 64 | if matches!(tcx.representability(def_id), ty::Representability::Infinite(_)) { | |
| 65 | return InhabitedPredicate::True; | |
| 66 | } | |
| 64 | let _ = tcx.check_representability(def_id); | |
| 67 | 65 | } |
| 66 | ||
| 68 | 67 | let adt = tcx.adt_def(def_id); |
| 69 | 68 | InhabitedPredicate::any( |
| 70 | 69 | tcx, |
compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs+2-2| ... | ... | @@ -531,7 +531,7 @@ impl Subdiagnostic for LocalLabel<'_> { |
| 531 | 531 | diag.arg("is_generated_name", self.is_generated_name); |
| 532 | 532 | diag.remove_arg("is_dropped_first_edition_2024"); |
| 533 | 533 | diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); |
| 534 | let msg = diag.eagerly_translate(msg!( | |
| 534 | let msg = diag.eagerly_format(msg!( | |
| 535 | 535 | "{$is_generated_name -> |
| 536 | 536 | [true] this value will be stored in a temporary; let us call it `{$name}` |
| 537 | 537 | *[false] `{$name}` calls a custom destructor |
| ... | ... | @@ -542,7 +542,7 @@ impl Subdiagnostic for LocalLabel<'_> { |
| 542 | 542 | dtor.add_to_diag(diag); |
| 543 | 543 | } |
| 544 | 544 | let msg = |
| 545 | diag.eagerly_translate(msg!( | |
| 545 | diag.eagerly_format(msg!( | |
| 546 | 546 | "{$is_dropped_first_edition_2024 -> |
| 547 | 547 | [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 |
| 548 | 548 | *[false] `{$name}` will be dropped later as of Edition 2024 |
compiler/rustc_passes/src/check_attr.rs+8-8| ... | ... | @@ -184,8 +184,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 184 | 184 | Attribute::Parsed(AttributeKind::TargetFeature{ attr_span, ..}) => { |
| 185 | 185 | self.check_target_feature(hir_id, *attr_span, target, attrs) |
| 186 | 186 | } |
| 187 | Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { | |
| 188 | self.check_object_lifetime_default(hir_id); | |
| 187 | Attribute::Parsed(AttributeKind::RustcDumpObjectLifetimeDefaults) => { | |
| 188 | self.check_dump_object_lifetime_defaults(hir_id); | |
| 189 | 189 | } |
| 190 | 190 | &Attribute::Parsed(AttributeKind::RustcPubTransparent(attr_span)) => { |
| 191 | 191 | self.check_rustc_pub_transparent(attr_span, span, attrs) |
| ... | ... | @@ -319,9 +319,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 319 | 319 | | AttributeKind::RustcDocPrimitive(..) |
| 320 | 320 | | AttributeKind::RustcDummy |
| 321 | 321 | | AttributeKind::RustcDumpDefParents |
| 322 | | AttributeKind::RustcDumpInferredOutlives | |
| 322 | 323 | | AttributeKind::RustcDumpItemBounds |
| 323 | 324 | | AttributeKind::RustcDumpPredicates |
| 324 | 325 | | AttributeKind::RustcDumpUserArgs |
| 326 | | AttributeKind::RustcDumpVariances | |
| 327 | | AttributeKind::RustcDumpVariancesOfOpaques | |
| 325 | 328 | | AttributeKind::RustcDumpVtable(..) |
| 326 | 329 | | AttributeKind::RustcDynIncompatibleTrait(..) |
| 327 | 330 | | AttributeKind::RustcEffectiveVisibility |
| ... | ... | @@ -355,7 +358,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 355 | 358 | | AttributeKind::RustcObjcClass { .. } |
| 356 | 359 | | AttributeKind::RustcObjcSelector { .. } |
| 357 | 360 | | AttributeKind::RustcOffloadKernel |
| 358 | | AttributeKind::RustcOutlives | |
| 359 | 361 | | AttributeKind::RustcParenSugar(..) |
| 360 | 362 | | AttributeKind::RustcPassByValue (..) |
| 361 | 363 | | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) |
| ... | ... | @@ -376,8 +378,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 376 | 378 | | AttributeKind::RustcThenThisWouldNeed(..) |
| 377 | 379 | | AttributeKind::RustcTrivialFieldReads |
| 378 | 380 | | AttributeKind::RustcUnsafeSpecializationMarker(..) |
| 379 | | AttributeKind::RustcVariance | |
| 380 | | AttributeKind::RustcVarianceOfOpaques | |
| 381 | 381 | | AttributeKind::ShouldPanic { .. } |
| 382 | 382 | | AttributeKind::TestRunner(..) |
| 383 | 383 | | AttributeKind::ThreadLocal |
| ... | ... | @@ -781,8 +781,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 781 | 781 | } |
| 782 | 782 | } |
| 783 | 783 | |
| 784 | /// Debugging aid for `object_lifetime_default` query. | |
| 785 | fn check_object_lifetime_default(&self, hir_id: HirId) { | |
| 784 | /// Debugging aid for the `object_lifetime_default` query. | |
| 785 | fn check_dump_object_lifetime_defaults(&self, hir_id: HirId) { | |
| 786 | 786 | let tcx = self.tcx; |
| 787 | 787 | if let Some(owner_id) = hir_id.as_owner() |
| 788 | 788 | && let Some(generics) = tcx.hir_get_generics(owner_id.def_id) |
| ... | ... | @@ -796,7 +796,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 796 | 796 | ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(), |
| 797 | 797 | ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(), |
| 798 | 798 | }; |
| 799 | tcx.dcx().emit_err(errors::ObjectLifetimeErr { span: p.span, repr }); | |
| 799 | tcx.dcx().span_err(p.span, repr); | |
| 800 | 800 | } |
| 801 | 801 | } |
| 802 | 802 | } |
compiler/rustc_passes/src/errors.rs-8| ... | ... | @@ -814,14 +814,6 @@ pub(crate) struct UselessAssignment<'a> { |
| 814 | 814 | )] |
| 815 | 815 | pub(crate) struct InlineIgnoredForExported; |
| 816 | 816 | |
| 817 | #[derive(Diagnostic)] | |
| 818 | #[diag("{$repr}")] | |
| 819 | pub(crate) struct ObjectLifetimeErr { | |
| 820 | #[primary_span] | |
| 821 | pub span: Span, | |
| 822 | pub repr: String, | |
| 823 | } | |
| 824 | ||
| 825 | 817 | #[derive(Diagnostic)] |
| 826 | 818 | pub(crate) enum AttrApplication { |
| 827 | 819 | #[diag("attribute should be applied to an enum", code = E0517)] |
compiler/rustc_pattern_analysis/src/errors.rs+5-4| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; |
| 2 | use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; | |
| 2 | use rustc_macros::{Diagnostic, Subdiagnostic}; | |
| 3 | 3 | use rustc_middle::ty::Ty; |
| 4 | 4 | use rustc_span::Span; |
| 5 | 5 | |
| ... | ... | @@ -109,8 +109,7 @@ impl Subdiagnostic for GappedRange { |
| 109 | 109 | fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { |
| 110 | 110 | let GappedRange { span, gap, first_range } = self; |
| 111 | 111 | |
| 112 | // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` | |
| 113 | // does not support `#[subdiagnostic(eager)]`... | |
| 112 | // FIXME(mejrs) Use `#[subdiagnostic(eager)]` instead | |
| 114 | 113 | let message = format!( |
| 115 | 114 | "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \ |
| 116 | 115 | either of them" |
| ... | ... | @@ -131,10 +130,12 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { |
| 131 | 130 | pub uncovered: Uncovered, |
| 132 | 131 | } |
| 133 | 132 | |
| 134 | #[derive(LintDiagnostic)] | |
| 133 | #[derive(Diagnostic)] | |
| 135 | 134 | #[diag("the lint level must be set on the whole match")] |
| 136 | 135 | #[help("it no longer has any effect to set the lint level on an individual match arm")] |
| 137 | 136 | pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { |
| 137 | #[primary_span] | |
| 138 | pub span: Span, | |
| 138 | 139 | #[label("remove this attribute")] |
| 139 | 140 | pub lint_span: Span, |
| 140 | 141 | #[suggestion( |
compiler/rustc_pattern_analysis/src/lints.rs+3-7| ... | ... | @@ -92,17 +92,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( |
| 92 | 92 | let LevelAndSource { level, src, .. } = |
| 93 | 93 | rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); |
| 94 | 94 | if !matches!(level, rustc_session::lint::Level::Allow) { |
| 95 | let decorator = NonExhaustiveOmittedPatternLintOnArm { | |
| 95 | rcx.tcx.dcx().emit_warn(NonExhaustiveOmittedPatternLintOnArm { | |
| 96 | span: arm.pat.data().span, | |
| 96 | 97 | lint_span: src.span(), |
| 97 | 98 | suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), |
| 98 | 99 | lint_level: level.as_str(), |
| 99 | 100 | lint_name: "non_exhaustive_omitted_patterns", |
| 100 | }; | |
| 101 | ||
| 102 | use rustc_errors::LintDiagnostic; | |
| 103 | let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().span, ""); | |
| 104 | decorator.decorate_lint(&mut err); | |
| 105 | err.emit(); | |
| 101 | }); | |
| 106 | 102 | } |
| 107 | 103 | } |
| 108 | 104 | } |
compiler/rustc_query_impl/src/dep_kind_vtables.rs+1-1| ... | ... | @@ -40,7 +40,7 @@ mod non_query { |
| 40 | 40 | is_eval_always: false, |
| 41 | 41 | key_fingerprint_style: KeyFingerprintStyle::Unit, |
| 42 | 42 | force_from_dep_node_fn: Some(|tcx, _, prev_index| { |
| 43 | tcx.dep_graph.force_diagnostic_node(tcx, prev_index); | |
| 43 | tcx.dep_graph.force_side_effect(tcx, prev_index); | |
| 44 | 44 | true |
| 45 | 45 | }), |
| 46 | 46 | promote_from_disk_fn: None, |
compiler/rustc_query_impl/src/execution.rs-4| ... | ... | @@ -131,10 +131,6 @@ fn mk_cycle<'tcx, C: QueryCache>( |
| 131 | 131 | let guar = error.emit(); |
| 132 | 132 | query.value_from_cycle_error(tcx, cycle_error, guar) |
| 133 | 133 | } |
| 134 | CycleErrorHandling::Fatal => { | |
| 135 | let guar = error.emit(); | |
| 136 | guar.raise_fatal(); | |
| 137 | } | |
| 138 | 134 | CycleErrorHandling::DelayBug => { |
| 139 | 135 | let guar = error.delay_as_bug(); |
| 140 | 136 | query.value_from_cycle_error(tcx, cycle_error, guar) |
compiler/rustc_query_impl/src/from_cycle_error.rs+5-3| ... | ... | @@ -95,7 +95,7 @@ impl<'tcx> FromCycleError<'tcx> for Representability { |
| 95 | 95 | let mut item_and_field_ids = Vec::new(); |
| 96 | 96 | let mut representable_ids = FxHashSet::default(); |
| 97 | 97 | for info in &cycle_error.cycle { |
| 98 | if info.frame.dep_kind == DepKind::representability | |
| 98 | if info.frame.dep_kind == DepKind::check_representability | |
| 99 | 99 | && let Some(field_id) = info.frame.def_id |
| 100 | 100 | && let Some(field_id) = field_id.as_local() |
| 101 | 101 | && let Some(DefKind::Field) = info.frame.info.def_kind |
| ... | ... | @@ -109,7 +109,7 @@ impl<'tcx> FromCycleError<'tcx> for Representability { |
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | for info in &cycle_error.cycle { |
| 112 | if info.frame.dep_kind == DepKind::representability_adt_ty | |
| 112 | if info.frame.dep_kind == DepKind::check_representability_adt_ty | |
| 113 | 113 | && let Some(def_id) = info.frame.def_id_for_ty_in_cycle |
| 114 | 114 | && let Some(def_id) = def_id.as_local() |
| 115 | 115 | && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) |
| ... | ... | @@ -117,8 +117,10 @@ impl<'tcx> FromCycleError<'tcx> for Representability { |
| 117 | 117 | representable_ids.insert(def_id); |
| 118 | 118 | } |
| 119 | 119 | } |
| 120 | // We used to continue here, but the cycle error printed next is actually less useful than | |
| 121 | // the error produced by `recursive_type_error`. | |
| 120 | 122 | let guar = recursive_type_error(tcx, item_and_field_ids, &representable_ids); |
| 121 | Representability::Infinite(guar) | |
| 123 | guar.raise_fatal(); | |
| 122 | 124 | } |
| 123 | 125 | } |
| 124 | 126 |
compiler/rustc_resolve/src/errors.rs+1-1| ... | ... | @@ -1366,7 +1366,7 @@ impl Subdiagnostic for FoundItemConfigureOut { |
| 1366 | 1366 | ItemWas::BehindFeature { feature, span } => { |
| 1367 | 1367 | let key = "feature".into(); |
| 1368 | 1368 | let value = feature.into_diag_arg(&mut None); |
| 1369 | let msg = diag.dcx.eagerly_translate_to_string( | |
| 1369 | let msg = diag.dcx.eagerly_format_to_string( | |
| 1370 | 1370 | msg!("the item is gated behind the `{$feature}` feature"), |
| 1371 | 1371 | [(&key, &value)].into_iter(), |
| 1372 | 1372 | ); |
compiler/rustc_session/src/session.rs+6| ... | ... | @@ -166,6 +166,11 @@ pub struct Session { |
| 166 | 166 | /// Used by `-Zmir-opt-bisect-limit` to assign an index to each |
| 167 | 167 | /// optimization-pass execution candidate during this compilation. |
| 168 | 168 | pub mir_opt_bisect_eval_count: AtomicUsize, |
| 169 | ||
| 170 | /// Enabled features that are used in the current compilation. | |
| 171 | /// | |
| 172 | /// The value is the `DepNodeIndex` of the node encodes the used feature. | |
| 173 | pub used_features: Lock<FxHashMap<Symbol, u32>>, | |
| 169 | 174 | } |
| 170 | 175 | |
| 171 | 176 | #[derive(Clone, Copy)] |
| ... | ... | @@ -1096,6 +1101,7 @@ pub fn build_session( |
| 1096 | 1101 | replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler` |
| 1097 | 1102 | thin_lto_supported: true, // filled by `run_compiler` |
| 1098 | 1103 | mir_opt_bisect_eval_count: AtomicUsize::new(0), |
| 1104 | used_features: Lock::default(), | |
| 1099 | 1105 | }; |
| 1100 | 1106 | |
| 1101 | 1107 | validate_commandline_args_with_session_available(&sess); |
compiler/rustc_span/src/symbol.rs+4-4| ... | ... | @@ -1708,9 +1708,13 @@ symbols! { |
| 1708 | 1708 | rustc_driver, |
| 1709 | 1709 | rustc_dummy, |
| 1710 | 1710 | rustc_dump_def_parents, |
| 1711 | rustc_dump_inferred_outlives, | |
| 1711 | 1712 | rustc_dump_item_bounds, |
| 1713 | rustc_dump_object_lifetime_defaults, | |
| 1712 | 1714 | rustc_dump_predicates, |
| 1713 | 1715 | rustc_dump_user_args, |
| 1716 | rustc_dump_variances, | |
| 1717 | rustc_dump_variances_of_opaques, | |
| 1714 | 1718 | rustc_dump_vtable, |
| 1715 | 1719 | rustc_dyn_incompatible_trait, |
| 1716 | 1720 | rustc_effective_visibility, |
| ... | ... | @@ -1747,10 +1751,8 @@ symbols! { |
| 1747 | 1751 | rustc_nounwind, |
| 1748 | 1752 | rustc_objc_class, |
| 1749 | 1753 | rustc_objc_selector, |
| 1750 | rustc_object_lifetime_default, | |
| 1751 | 1754 | rustc_offload_kernel, |
| 1752 | 1755 | rustc_on_unimplemented, |
| 1753 | rustc_outlives, | |
| 1754 | 1756 | rustc_paren_sugar, |
| 1755 | 1757 | rustc_partition_codegened, |
| 1756 | 1758 | rustc_partition_reused, |
| ... | ... | @@ -1780,8 +1782,6 @@ symbols! { |
| 1780 | 1782 | rustc_then_this_would_need, |
| 1781 | 1783 | rustc_trivial_field_reads, |
| 1782 | 1784 | rustc_unsafe_specialization_marker, |
| 1783 | rustc_variance, | |
| 1784 | rustc_variance_of_opaques, | |
| 1785 | 1785 | rustdoc, |
| 1786 | 1786 | rustdoc_internals, |
| 1787 | 1787 | rustdoc_missing_doc_code_examples, |
compiler/rustc_trait_selection/src/errors.rs+8-10| ... | ... | @@ -456,7 +456,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { |
| 456 | 456 | // See https://github.com/rust-lang/rust/issues/143872 for details. |
| 457 | 457 | diag.store_args(); |
| 458 | 458 | diag.arg("requirement", requirement); |
| 459 | let msg = diag.eagerly_translate(msg!( | |
| 459 | let msg = diag.eagerly_format(msg!( | |
| 460 | 460 | "...so that the {$requirement -> |
| 461 | 461 | [method_compat] method type is compatible with trait |
| 462 | 462 | [type_compat] associated type is compatible with trait |
| ... | ... | @@ -482,7 +482,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { |
| 482 | 482 | // *terrible*. |
| 483 | 483 | diag.store_args(); |
| 484 | 484 | diag.arg("requirement", requirement); |
| 485 | let msg = diag.eagerly_translate(msg!( | |
| 485 | let msg = diag.eagerly_format(msg!( | |
| 486 | 486 | "...so that {$requirement -> |
| 487 | 487 | [method_compat] method type is compatible with trait |
| 488 | 488 | [type_compat] associated type is compatible with trait |
| ... | ... | @@ -1174,7 +1174,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { |
| 1174 | 1174 | type_param_span |
| 1175 | 1175 | .push_span_label(span, msg!("consider borrowing this type parameter in the trait")); |
| 1176 | 1176 | } |
| 1177 | let msg = diag.eagerly_translate(msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); | |
| 1177 | let msg = diag.eagerly_format(msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); | |
| 1178 | 1178 | diag.span_help(type_param_span, msg); |
| 1179 | 1179 | } |
| 1180 | 1180 | } |
| ... | ... | @@ -1218,10 +1218,9 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { |
| 1218 | 1218 | self.ident.span, |
| 1219 | 1219 | msg!("calling this method introduces the `impl`'s `'static` requirement"), |
| 1220 | 1220 | ); |
| 1221 | let msg = diag.eagerly_translate(msg!("the used `impl` has a `'static` requirement")); | |
| 1221 | let msg = diag.eagerly_format(msg!("the used `impl` has a `'static` requirement")); | |
| 1222 | 1222 | diag.span_note(multi_span, msg); |
| 1223 | let msg = | |
| 1224 | diag.eagerly_translate(msg!("consider relaxing the implicit `'static` requirement")); | |
| 1223 | let msg = diag.eagerly_format(msg!("consider relaxing the implicit `'static` requirement")); | |
| 1225 | 1224 | diag.span_suggestion_verbose( |
| 1226 | 1225 | self.span.shrink_to_hi(), |
| 1227 | 1226 | msg, |
| ... | ... | @@ -1284,9 +1283,8 @@ impl Subdiagnostic for ReqIntroducedLocations { |
| 1284 | 1283 | ); |
| 1285 | 1284 | } |
| 1286 | 1285 | self.span.push_span_label(self.cause_span, msg!("because of this returned expression")); |
| 1287 | let msg = diag.eagerly_translate(msg!( | |
| 1288 | "\"`'static` lifetime requirement introduced by the return type" | |
| 1289 | )); | |
| 1286 | let msg = diag | |
| 1287 | .eagerly_format(msg!("\"`'static` lifetime requirement introduced by the return type")); | |
| 1290 | 1288 | diag.span_note(self.span, msg); |
| 1291 | 1289 | } |
| 1292 | 1290 | } |
| ... | ... | @@ -1727,7 +1725,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { |
| 1727 | 1725 | fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { |
| 1728 | 1726 | diag.arg("path", self.path); |
| 1729 | 1727 | let message = |
| 1730 | diag.eagerly_translate(msg!("try wrapping the pattern in a variant of `{$path}`")); | |
| 1728 | diag.eagerly_format(msg!("try wrapping the pattern in a variant of `{$path}`")); | |
| 1731 | 1729 | diag.multipart_suggestions( |
| 1732 | 1730 | message, |
| 1733 | 1731 | self.compatible_variants.into_iter().map(|variant| { |
compiler/rustc_trait_selection/src/errors/note_and_explain.rs+1-1| ... | ... | @@ -169,7 +169,7 @@ impl Subdiagnostic for RegionExplanation<'_> { |
| 169 | 169 | diag.arg("desc_kind", self.desc.kind); |
| 170 | 170 | diag.arg("desc_arg", self.desc.arg); |
| 171 | 171 | |
| 172 | let msg = diag.eagerly_translate(msg!( | |
| 172 | let msg = diag.eagerly_format(msg!( | |
| 173 | 173 | "{$pref_kind -> |
| 174 | 174 | *[should_not_happen] [{$pref_kind}] |
| 175 | 175 | [ref_valid_for] ...the reference is valid for |
compiler/rustc_ty_utils/src/representability.rs+42-40| ... | ... | @@ -6,69 +6,71 @@ use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; |
| 6 | 6 | use rustc_span::def_id::LocalDefId; |
| 7 | 7 | |
| 8 | 8 | pub(crate) fn provide(providers: &mut Providers) { |
| 9 | *providers = | |
| 10 | Providers { representability, representability_adt_ty, params_in_repr, ..*providers }; | |
| 11 | } | |
| 12 | ||
| 13 | macro_rules! rtry { | |
| 14 | ($e:expr) => { | |
| 15 | match $e { | |
| 16 | e @ Representability::Infinite(_) => return e, | |
| 17 | Representability::Representable => {} | |
| 18 | } | |
| 9 | *providers = Providers { | |
| 10 | check_representability, | |
| 11 | check_representability_adt_ty, | |
| 12 | params_in_repr, | |
| 13 | ..*providers | |
| 19 | 14 | }; |
| 20 | 15 | } |
| 21 | 16 | |
| 22 | fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { | |
| 17 | fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { | |
| 23 | 18 | match tcx.def_kind(def_id) { |
| 24 | 19 | DefKind::Struct | DefKind::Union | DefKind::Enum => { |
| 25 | 20 | for variant in tcx.adt_def(def_id).variants() { |
| 26 | 21 | for field in variant.fields.iter() { |
| 27 | rtry!(tcx.representability(field.did.expect_local())); | |
| 22 | let _ = tcx.check_representability(field.did.expect_local()); | |
| 28 | 23 | } |
| 29 | 24 | } |
| 30 | Representability::Representable | |
| 31 | 25 | } |
| 32 | DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()), | |
| 26 | DefKind::Field => { | |
| 27 | check_representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()); | |
| 28 | } | |
| 33 | 29 | def_kind => bug!("unexpected {def_kind:?}"), |
| 34 | 30 | } |
| 31 | Representability | |
| 35 | 32 | } |
| 36 | 33 | |
| 37 | fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { | |
| 34 | fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) { | |
| 38 | 35 | match *ty.kind() { |
| 39 | ty::Adt(..) => tcx.representability_adt_ty(ty), | |
| 36 | // This one must be a query rather than a vanilla `check_representability_adt_ty` call. See | |
| 37 | // the comment on `check_representability_adt_ty` below for why. | |
| 38 | ty::Adt(..) => { | |
| 39 | let _ = tcx.check_representability_adt_ty(ty); | |
| 40 | } | |
| 40 | 41 | // FIXME(#11924) allow zero-length arrays? |
| 41 | ty::Array(ty, _) => representability_ty(tcx, ty), | |
| 42 | ty::Array(ty, _) => { | |
| 43 | check_representability_ty(tcx, ty); | |
| 44 | } | |
| 42 | 45 | ty::Tuple(tys) => { |
| 43 | 46 | for ty in tys { |
| 44 | rtry!(representability_ty(tcx, ty)); | |
| 47 | check_representability_ty(tcx, ty); | |
| 45 | 48 | } |
| 46 | Representability::Representable | |
| 47 | 49 | } |
| 48 | _ => Representability::Representable, | |
| 50 | _ => {} | |
| 49 | 51 | } |
| 50 | 52 | } |
| 51 | 53 | |
| 52 | /* | |
| 53 | The reason for this being a separate query is very subtle: | |
| 54 | Consider this infinitely sized struct: `struct Foo(Box<Foo>, Bar<Foo>)`: | |
| 55 | When calling representability(Foo), a query cycle will occur: | |
| 56 | representability(Foo) | |
| 57 | -> representability_adt_ty(Bar<Foo>) | |
| 58 | -> representability(Foo) | |
| 59 | For the diagnostic output (in `Value::from_cycle_error`), we want to detect that | |
| 60 | the `Foo` in the *second* field of the struct is culpable. This requires | |
| 61 | traversing the HIR of the struct and calling `params_in_repr(Bar)`. But we can't | |
| 62 | call params_in_repr for a given type unless it is known to be representable. | |
| 63 | params_in_repr will cycle/panic on infinitely sized types. Looking at the query | |
| 64 | cycle above, we know that `Bar` is representable because | |
| 65 | representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is | |
| 66 | *not* in the cycle. | |
| 67 | */ | |
| 68 | fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { | |
| 54 | // The reason for this being a separate query is very subtle. Consider this | |
| 55 | // infinitely sized struct: `struct Foo(Box<Foo>, Bar<Foo>)`. When calling | |
| 56 | // check_representability(Foo), a query cycle will occur: | |
| 57 | // | |
| 58 | // check_representability(Foo) | |
| 59 | // -> check_representability_adt_ty(Bar<Foo>) | |
| 60 | // -> check_representability(Foo) | |
| 61 | // | |
| 62 | // For the diagnostic output (in `Value::from_cycle_error`), we want to detect | |
| 63 | // that the `Foo` in the *second* field of the struct is culpable. This | |
| 64 | // requires traversing the HIR of the struct and calling `params_in_repr(Bar)`. | |
| 65 | // But we can't call params_in_repr for a given type unless it is known to be | |
| 66 | // representable. params_in_repr will cycle/panic on infinitely sized types. | |
| 67 | // Looking at the query cycle above, we know that `Bar` is representable | |
| 68 | // because `check_representability_adt_ty(Bar<..>)` is in the cycle and | |
| 69 | // `check_representability(Bar)` is *not* in the cycle. | |
| 70 | fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { | |
| 69 | 71 | let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") }; |
| 70 | 72 | if let Some(def_id) = adt.did().as_local() { |
| 71 | rtry!(tcx.representability(def_id)); | |
| 73 | let _ = tcx.check_representability(def_id); | |
| 72 | 74 | } |
| 73 | 75 | // At this point, we know that the item of the ADT type is representable; |
| 74 | 76 | // but the type parameters may cause a cycle with an upstream type |
| ... | ... | @@ -76,11 +78,11 @@ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representab |
| 76 | 78 | for (i, arg) in args.iter().enumerate() { |
| 77 | 79 | if let ty::GenericArgKind::Type(ty) = arg.kind() { |
| 78 | 80 | if params_in_repr.contains(i as u32) { |
| 79 | rtry!(representability_ty(tcx, ty)); | |
| 81 | check_representability_ty(tcx, ty); | |
| 80 | 82 | } |
| 81 | 83 | } |
| 82 | 84 | } |
| 83 | Representability::Representable | |
| 85 | Representability | |
| 84 | 86 | } |
| 85 | 87 | |
| 86 | 88 | fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DenseBitSet<u32> { |
compiler/rustc_ty_utils/src/ty.rs+3-4| ... | ... | @@ -116,11 +116,10 @@ fn adt_sizedness_constraint<'tcx>( |
| 116 | 116 | tcx: TyCtxt<'tcx>, |
| 117 | 117 | (def_id, sizedness): (DefId, SizedTraitKind), |
| 118 | 118 | ) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> { |
| 119 | if let Some(def_id) = def_id.as_local() | |
| 120 | && let ty::Representability::Infinite(_) = tcx.representability(def_id) | |
| 121 | { | |
| 122 | return None; | |
| 119 | if let Some(def_id) = def_id.as_local() { | |
| 120 | let _ = tcx.check_representability(def_id); | |
| 123 | 121 | } |
| 122 | ||
| 124 | 123 | let def = tcx.adt_def(def_id); |
| 125 | 124 | |
| 126 | 125 | if !def.is_struct() { |
library/alloc/src/collections/btree/map.rs+1| ... | ... | @@ -693,6 +693,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> { |
| 693 | 693 | /// map.insert(1, "a"); |
| 694 | 694 | /// ``` |
| 695 | 695 | #[unstable(feature = "btreemap_alloc", issue = "32838")] |
| 696 | #[must_use] | |
| 696 | 697 | pub const fn new_in(alloc: A) -> BTreeMap<K, V, A> { |
| 697 | 698 | BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData } |
| 698 | 699 | } |
library/alloc/src/collections/btree/set.rs+1| ... | ... | @@ -361,6 +361,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> { |
| 361 | 361 | /// let mut set: BTreeSet<i32> = BTreeSet::new_in(Global); |
| 362 | 362 | /// ``` |
| 363 | 363 | #[unstable(feature = "btreemap_alloc", issue = "32838")] |
| 364 | #[must_use] | |
| 364 | 365 | pub const fn new_in(alloc: A) -> BTreeSet<T, A> { |
| 365 | 366 | BTreeSet { map: BTreeMap::new_in(alloc) } |
| 366 | 367 | } |
library/alloctests/tests/lib.rs-1| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | #![feature(allocator_api)] |
| 2 | 2 | #![feature(binary_heap_pop_if)] |
| 3 | #![feature(btree_merge)] | |
| 4 | 3 | #![feature(const_heap)] |
| 5 | 4 | #![feature(deque_extend_front)] |
| 6 | 5 | #![feature(iter_array_chunks)] |
library/core/src/num/f16.rs+5-1| ... | ... | @@ -1521,7 +1521,11 @@ impl f16 { |
| 1521 | 1521 | // Functions in this module fall into `core_float_math` |
| 1522 | 1522 | // #[unstable(feature = "core_float_math", issue = "137578")] |
| 1523 | 1523 | #[cfg(not(test))] |
| 1524 | #[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))] | |
| 1524 | #[doc(test(attr( | |
| 1525 | feature(cfg_target_has_reliable_f16_f128), | |
| 1526 | expect(internal_features), | |
| 1527 | allow(unused_features) | |
| 1528 | )))] | |
| 1525 | 1529 | impl f16 { |
| 1526 | 1530 | /// Returns the largest integer less than or equal to `self`. |
| 1527 | 1531 | /// |
library/core/src/num/f32.rs+1| ... | ... | @@ -393,6 +393,7 @@ pub mod consts { |
| 393 | 393 | pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | #[doc(test(attr(allow(unused_features))))] | |
| 396 | 397 | impl f32 { |
| 397 | 398 | /// The radix or base of the internal representation of `f32`. |
| 398 | 399 | #[stable(feature = "assoc_int_consts", since = "1.43.0")] |
library/core/src/num/f64.rs+1| ... | ... | @@ -393,6 +393,7 @@ pub mod consts { |
| 393 | 393 | pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | #[doc(test(attr(allow(unused_features))))] | |
| 396 | 397 | impl f64 { |
| 397 | 398 | /// The radix or base of the internal representation of `f64`. |
| 398 | 399 | #[stable(feature = "assoc_int_consts", since = "1.43.0")] |
library/coretests/tests/lib.rs-1| ... | ... | @@ -50,7 +50,6 @@ |
| 50 | 50 | #![feature(f16)] |
| 51 | 51 | #![feature(f128)] |
| 52 | 52 | #![feature(float_algebraic)] |
| 53 | #![feature(float_bits_const)] | |
| 54 | 53 | #![feature(float_exact_integer_constants)] |
| 55 | 54 | #![feature(float_gamma)] |
| 56 | 55 | #![feature(float_minimum_maximum)] |
library/std/src/collections/hash/map.rs+4| ... | ... | @@ -357,6 +357,7 @@ impl<K, V, S> HashMap<K, V, S> { |
| 357 | 357 | /// map.insert(1, 2); |
| 358 | 358 | /// ``` |
| 359 | 359 | #[inline] |
| 360 | #[must_use] | |
| 360 | 361 | #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] |
| 361 | 362 | #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")] |
| 362 | 363 | pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> { |
| ... | ... | @@ -389,6 +390,7 @@ impl<K, V, S> HashMap<K, V, S> { |
| 389 | 390 | /// map.insert(1, 2); |
| 390 | 391 | /// ``` |
| 391 | 392 | #[inline] |
| 393 | #[must_use] | |
| 392 | 394 | #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] |
| 393 | 395 | pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashMap<K, V, S> { |
| 394 | 396 | HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hasher) } |
| ... | ... | @@ -409,6 +411,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> { |
| 409 | 411 | /// The `hash_builder` passed should implement the [`BuildHasher`] trait for |
| 410 | 412 | /// the `HashMap` to be useful, see its documentation for details. |
| 411 | 413 | #[inline] |
| 414 | #[must_use] | |
| 412 | 415 | #[unstable(feature = "allocator_api", issue = "32838")] |
| 413 | 416 | pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self { |
| 414 | 417 | HashMap { base: base::HashMap::with_hasher_in(hash_builder, alloc) } |
| ... | ... | @@ -430,6 +433,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> { |
| 430 | 433 | /// the `HashMap` to be useful, see its documentation for details. |
| 431 | 434 | /// |
| 432 | 435 | #[inline] |
| 436 | #[must_use] | |
| 433 | 437 | #[unstable(feature = "allocator_api", issue = "32838")] |
| 434 | 438 | pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self { |
| 435 | 439 | HashMap { base: base::HashMap::with_capacity_and_hasher_in(capacity, hash_builder, alloc) } |
library/std/src/collections/hash/set.rs+4| ... | ... | @@ -229,6 +229,7 @@ impl<T, S> HashSet<T, S> { |
| 229 | 229 | /// set.insert(2); |
| 230 | 230 | /// ``` |
| 231 | 231 | #[inline] |
| 232 | #[must_use] | |
| 232 | 233 | #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] |
| 233 | 234 | #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")] |
| 234 | 235 | pub const fn with_hasher(hasher: S) -> HashSet<T, S> { |
| ... | ... | @@ -261,6 +262,7 @@ impl<T, S> HashSet<T, S> { |
| 261 | 262 | /// set.insert(1); |
| 262 | 263 | /// ``` |
| 263 | 264 | #[inline] |
| 265 | #[must_use] | |
| 264 | 266 | #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] |
| 265 | 267 | pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> { |
| 266 | 268 | HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, hasher) } |
| ... | ... | @@ -281,6 +283,7 @@ impl<T, S, A: Allocator> HashSet<T, S, A> { |
| 281 | 283 | /// The `hash_builder` passed should implement the [`BuildHasher`] trait for |
| 282 | 284 | /// the `HashSet` to be useful, see its documentation for details. |
| 283 | 285 | #[inline] |
| 286 | #[must_use] | |
| 284 | 287 | #[unstable(feature = "allocator_api", issue = "32838")] |
| 285 | 288 | pub fn with_hasher_in(hasher: S, alloc: A) -> HashSet<T, S, A> { |
| 286 | 289 | HashSet { base: base::HashSet::with_hasher_in(hasher, alloc) } |
| ... | ... | @@ -301,6 +304,7 @@ impl<T, S, A: Allocator> HashSet<T, S, A> { |
| 301 | 304 | /// The `hash_builder` passed should implement the [`BuildHasher`] trait for |
| 302 | 305 | /// the `HashSet` to be useful, see its documentation for details. |
| 303 | 306 | #[inline] |
| 307 | #[must_use] | |
| 304 | 308 | #[unstable(feature = "allocator_api", issue = "32838")] |
| 305 | 309 | pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> HashSet<T, S, A> { |
| 306 | 310 | HashSet { base: base::HashSet::with_capacity_and_hasher_in(capacity, hasher, alloc) } |
library/std/src/num/f16.rs+1| ... | ... | @@ -16,6 +16,7 @@ use crate::intrinsics; |
| 16 | 16 | use crate::sys::cmath; |
| 17 | 17 | |
| 18 | 18 | #[cfg(not(test))] |
| 19 | #[doc(test(attr(allow(unused_features))))] | |
| 19 | 20 | impl f16 { |
| 20 | 21 | /// Raises a number to a floating point power. |
| 21 | 22 | /// |
library/std/src/path.rs+24-13| ... | ... | @@ -93,7 +93,7 @@ use crate::ops::{self, Deref}; |
| 93 | 93 | use crate::rc::Rc; |
| 94 | 94 | use crate::str::FromStr; |
| 95 | 95 | use crate::sync::Arc; |
| 96 | use crate::sys::path::{HAS_PREFIXES, MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix}; | |
| 96 | use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix}; | |
| 97 | 97 | use crate::{cmp, fmt, fs, io, sys}; |
| 98 | 98 | |
| 99 | 99 | //////////////////////////////////////////////////////////////////////////////// |
| ... | ... | @@ -266,22 +266,33 @@ impl<'a> Prefix<'a> { |
| 266 | 266 | /// ``` |
| 267 | 267 | #[must_use] |
| 268 | 268 | #[stable(feature = "rust1", since = "1.0.0")] |
| 269 | pub fn is_separator(c: char) -> bool { | |
| 269 | #[rustc_const_unstable(feature = "const_path_separators", issue = "153106")] | |
| 270 | pub const fn is_separator(c: char) -> bool { | |
| 270 | 271 | c.is_ascii() && is_sep_byte(c as u8) |
| 271 | 272 | } |
| 272 | 273 | |
| 273 | /// The primary separator of path components for the current platform. | |
| 274 | /// | |
| 275 | /// For example, `/` on Unix and `\` on Windows. | |
| 274 | /// All path separators recognized on the current platform, represented as [`char`]s; for example, | |
| 275 | /// this is `&['/'][..]` on Unix and `&['\\', '/'][..]` on Windows. The [primary | |
| 276 | /// separator](MAIN_SEPARATOR) is always element 0 of the slice. | |
| 277 | #[unstable(feature = "const_path_separators", issue = "153106")] | |
| 278 | pub const SEPARATORS: &[char] = crate::sys::path::SEPARATORS; | |
| 279 | ||
| 280 | /// All path separators recognized on the current platform, represented as [`&str`]s; for example, | |
| 281 | /// this is `&["/"][..]` on Unix and `&["\\", "/"][..]` on Windows. The [primary | |
| 282 | /// separator](MAIN_SEPARATOR_STR) is always element 0 of the slice. | |
| 283 | #[unstable(feature = "const_path_separators", issue = "153106")] | |
| 284 | pub const SEPARATORS_STR: &[&str] = crate::sys::path::SEPARATORS_STR; | |
| 285 | ||
| 286 | /// The primary separator of path components for the current platform, represented as a [`char`]; | |
| 287 | /// for example, this is `'/'` on Unix and `'\\'` on Windows. | |
| 276 | 288 | #[stable(feature = "rust1", since = "1.0.0")] |
| 277 | 289 | #[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")] |
| 278 | pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP; | |
| 290 | pub const MAIN_SEPARATOR: char = SEPARATORS[0]; | |
| 279 | 291 | |
| 280 | /// The primary separator of path components for the current platform. | |
| 281 | /// | |
| 282 | /// For example, `/` on Unix and `\` on Windows. | |
| 292 | /// The primary separator of path components for the current platform, represented as a [`&str`]; | |
| 293 | /// for example, this is `"/"` on Unix and `"\\"` on Windows. | |
| 283 | 294 | #[stable(feature = "main_separator_str", since = "1.68.0")] |
| 284 | pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR; | |
| 295 | pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0]; | |
| 285 | 296 | |
| 286 | 297 | //////////////////////////////////////////////////////////////////////////////// |
| 287 | 298 | // Misc helpers |
| ... | ... | @@ -562,7 +573,7 @@ impl<'a> Component<'a> { |
| 562 | 573 | pub fn as_os_str(self) -> &'a OsStr { |
| 563 | 574 | match self { |
| 564 | 575 | Component::Prefix(p) => p.as_os_str(), |
| 565 | Component::RootDir => OsStr::new(MAIN_SEP_STR), | |
| 576 | Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR), | |
| 566 | 577 | Component::CurDir => OsStr::new("."), |
| 567 | 578 | Component::ParentDir => OsStr::new(".."), |
| 568 | 579 | Component::Normal(path) => path, |
| ... | ... | @@ -1379,7 +1390,7 @@ impl PathBuf { |
| 1379 | 1390 | |
| 1380 | 1391 | for c in buf { |
| 1381 | 1392 | if need_sep && c != Component::RootDir { |
| 1382 | res.push(MAIN_SEP_STR); | |
| 1393 | res.push(MAIN_SEPARATOR_STR); | |
| 1383 | 1394 | } |
| 1384 | 1395 | res.push(c.as_os_str()); |
| 1385 | 1396 | |
| ... | ... | @@ -1402,7 +1413,7 @@ impl PathBuf { |
| 1402 | 1413 | |
| 1403 | 1414 | // `path` is a pure relative path |
| 1404 | 1415 | } else if need_sep { |
| 1405 | self.inner.push(MAIN_SEP_STR); | |
| 1416 | self.inner.push(MAIN_SEPARATOR_STR); | |
| 1406 | 1417 | } |
| 1407 | 1418 | |
| 1408 | 1419 | self.inner.push(path); |
library/std/src/process.rs+2| ... | ... | @@ -1381,6 +1381,7 @@ impl Output { |
| 1381 | 1381 | /// # Examples |
| 1382 | 1382 | /// |
| 1383 | 1383 | /// ``` |
| 1384 | /// # #![allow(unused_features)] | |
| 1384 | 1385 | /// #![feature(exit_status_error)] |
| 1385 | 1386 | /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] { |
| 1386 | 1387 | /// use std::process::Command; |
| ... | ... | @@ -1960,6 +1961,7 @@ impl crate::sealed::Sealed for ExitStatusError {} |
| 1960 | 1961 | pub struct ExitStatusError(imp::ExitStatusError); |
| 1961 | 1962 | |
| 1962 | 1963 | #[unstable(feature = "exit_status_error", issue = "84908")] |
| 1964 | #[doc(test(attr(allow(unused_features))))] | |
| 1963 | 1965 | impl ExitStatusError { |
| 1964 | 1966 | /// Reports the exit code, if applicable, from an `ExitStatusError`. |
| 1965 | 1967 | /// |
library/std/src/sys/path/cygwin.rs+3-8| ... | ... | @@ -5,25 +5,20 @@ use crate::sys::cvt; |
| 5 | 5 | use crate::sys::helpers::run_path_with_cstr; |
| 6 | 6 | use crate::{io, ptr}; |
| 7 | 7 | |
| 8 | #[inline] | |
| 9 | pub fn is_sep_byte(b: u8) -> bool { | |
| 10 | b == b'/' || b == b'\\' | |
| 11 | } | |
| 8 | path_separator_bytes!(b'/', b'\\'); | |
| 12 | 9 | |
| 13 | 10 | /// Cygwin always prefers `/` over `\`, and it always converts all `/` to `\` |
| 14 | 11 | /// internally when calling Win32 APIs. Therefore, the server component of path |
| 15 | 12 | /// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost` |
| 16 | 13 | /// on Cygwin. |
| 17 | 14 | #[inline] |
| 18 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 19 | b == b'/' || b == b'\\' | |
| 15 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 16 | is_sep_byte(b) | |
| 20 | 17 | } |
| 21 | 18 | |
| 22 | 19 | pub use super::windows_prefix::parse_prefix; |
| 23 | 20 | |
| 24 | 21 | pub const HAS_PREFIXES: bool = true; |
| 25 | pub const MAIN_SEP_STR: &str = "/"; | |
| 26 | pub const MAIN_SEP: char = '/'; | |
| 27 | 22 | |
| 28 | 23 | unsafe extern "C" { |
| 29 | 24 | // Doc: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html |
library/std/src/sys/path/mod.rs+19| ... | ... | @@ -1,3 +1,22 @@ |
| 1 | // There's a lot of necessary redundancy in separator definition. Consolidated into a macro to | |
| 2 | // prevent transcription errors. | |
| 3 | macro_rules! path_separator_bytes { | |
| 4 | ($($sep:literal),+) => ( | |
| 5 | pub const SEPARATORS: &[char] = &[$($sep as char,)+]; | |
| 6 | pub const SEPARATORS_STR: &[&str] = &[$( | |
| 7 | match str::from_utf8(&[$sep]) { | |
| 8 | Ok(s) => s, | |
| 9 | Err(_) => panic!("path_separator_bytes must be ASCII bytes"), | |
| 10 | } | |
| 11 | ),+]; | |
| 12 | ||
| 13 | #[inline] | |
| 14 | pub const fn is_sep_byte(b: u8) -> bool { | |
| 15 | $(b == $sep) ||+ | |
| 16 | } | |
| 17 | ) | |
| 18 | } | |
| 19 | ||
| 1 | 20 | cfg_select! { |
| 2 | 21 | target_os = "windows" => { |
| 3 | 22 | mod windows; |
library/std/src/sys/path/sgx.rs+3-8| ... | ... | @@ -3,14 +3,11 @@ use crate::io; |
| 3 | 3 | use crate::path::{Path, PathBuf, Prefix}; |
| 4 | 4 | use crate::sys::unsupported; |
| 5 | 5 | |
| 6 | #[inline] | |
| 7 | pub fn is_sep_byte(b: u8) -> bool { | |
| 8 | b == b'/' | |
| 9 | } | |
| 6 | path_separator_bytes!(b'/'); | |
| 10 | 7 | |
| 11 | 8 | #[inline] |
| 12 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 13 | b == b'/' | |
| 9 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 10 | is_sep_byte(b) | |
| 14 | 11 | } |
| 15 | 12 | |
| 16 | 13 | pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| ... | ... | @@ -18,8 +15,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| 18 | 15 | } |
| 19 | 16 | |
| 20 | 17 | pub const HAS_PREFIXES: bool = false; |
| 21 | pub const MAIN_SEP_STR: &str = "/"; | |
| 22 | pub const MAIN_SEP: char = '/'; | |
| 23 | 18 | |
| 24 | 19 | pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { |
| 25 | 20 | unsupported() |
library/std/src/sys/path/uefi.rs+4-9| ... | ... | @@ -5,17 +5,14 @@ use crate::path::{Path, PathBuf, Prefix}; |
| 5 | 5 | use crate::sys::pal::helpers; |
| 6 | 6 | use crate::sys::unsupported_err; |
| 7 | 7 | |
| 8 | path_separator_bytes!(b'\\'); | |
| 9 | ||
| 8 | 10 | const FORWARD_SLASH: u8 = b'/'; |
| 9 | 11 | const COLON: u8 = b':'; |
| 10 | 12 | |
| 11 | 13 | #[inline] |
| 12 | pub fn is_sep_byte(b: u8) -> bool { | |
| 13 | b == b'\\' | |
| 14 | } | |
| 15 | ||
| 16 | #[inline] | |
| 17 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 18 | b == b'\\' | |
| 14 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 15 | is_sep_byte(b) | |
| 19 | 16 | } |
| 20 | 17 | |
| 21 | 18 | pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| ... | ... | @@ -23,8 +20,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| 23 | 20 | } |
| 24 | 21 | |
| 25 | 22 | pub const HAS_PREFIXES: bool = true; |
| 26 | pub const MAIN_SEP_STR: &str = "\\"; | |
| 27 | pub const MAIN_SEP: char = '\\'; | |
| 28 | 23 | |
| 29 | 24 | /// UEFI paths can be of 4 types: |
| 30 | 25 | /// |
library/std/src/sys/path/unix.rs+3-8| ... | ... | @@ -2,14 +2,11 @@ use crate::ffi::OsStr; |
| 2 | 2 | use crate::path::{Path, PathBuf, Prefix}; |
| 3 | 3 | use crate::{env, io}; |
| 4 | 4 | |
| 5 | #[inline] | |
| 6 | pub fn is_sep_byte(b: u8) -> bool { | |
| 7 | b == b'/' | |
| 8 | } | |
| 5 | path_separator_bytes!(b'/'); | |
| 9 | 6 | |
| 10 | 7 | #[inline] |
| 11 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 12 | b == b'/' | |
| 8 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 9 | is_sep_byte(b) | |
| 13 | 10 | } |
| 14 | 11 | |
| 15 | 12 | #[inline] |
| ... | ... | @@ -18,8 +15,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| 18 | 15 | } |
| 19 | 16 | |
| 20 | 17 | pub const HAS_PREFIXES: bool = false; |
| 21 | pub const MAIN_SEP_STR: &str = "/"; | |
| 22 | pub const MAIN_SEP: char = '/'; | |
| 23 | 18 | |
| 24 | 19 | /// Make a POSIX path absolute without changing its semantics. |
| 25 | 20 | pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { |
library/std/src/sys/path/unsupported_backslash.rs+3-8| ... | ... | @@ -4,14 +4,11 @@ use crate::io; |
| 4 | 4 | use crate::path::{Path, PathBuf, Prefix}; |
| 5 | 5 | use crate::sys::unsupported; |
| 6 | 6 | |
| 7 | #[inline] | |
| 8 | pub fn is_sep_byte(b: u8) -> bool { | |
| 9 | b == b'\\' | |
| 10 | } | |
| 7 | path_separator_bytes!(b'\\'); | |
| 11 | 8 | |
| 12 | 9 | #[inline] |
| 13 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 14 | b == b'\\' | |
| 10 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 11 | is_sep_byte(b) | |
| 15 | 12 | } |
| 16 | 13 | |
| 17 | 14 | pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| ... | ... | @@ -19,8 +16,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { |
| 19 | 16 | } |
| 20 | 17 | |
| 21 | 18 | pub const HAS_PREFIXES: bool = true; |
| 22 | pub const MAIN_SEP_STR: &str = "\\"; | |
| 23 | pub const MAIN_SEP: char = '\\'; | |
| 24 | 19 | |
| 25 | 20 | pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { |
| 26 | 21 | unsupported() |
library/std/src/sys/path/windows.rs+3-8| ... | ... | @@ -9,9 +9,9 @@ mod tests; |
| 9 | 9 | |
| 10 | 10 | pub use super::windows_prefix::parse_prefix; |
| 11 | 11 | |
| 12 | path_separator_bytes!(b'\\', b'/'); | |
| 13 | ||
| 12 | 14 | pub const HAS_PREFIXES: bool = true; |
| 13 | pub const MAIN_SEP_STR: &str = "\\"; | |
| 14 | pub const MAIN_SEP: char = '\\'; | |
| 15 | 15 | |
| 16 | 16 | /// A null terminated wide string. |
| 17 | 17 | #[repr(transparent)] |
| ... | ... | @@ -48,12 +48,7 @@ pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) -> |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | #[inline] |
| 51 | pub fn is_sep_byte(b: u8) -> bool { | |
| 52 | b == b'/' || b == b'\\' | |
| 53 | } | |
| 54 | ||
| 55 | #[inline] | |
| 56 | pub fn is_verbatim_sep(b: u8) -> bool { | |
| 51 | pub const fn is_verbatim_sep(b: u8) -> bool { | |
| 57 | 52 | b == b'\\' |
| 58 | 53 | } |
| 59 | 54 |
src/doc/rustc-dev-guide/src/compiler-debugging.md+3-3| ... | ... | @@ -275,16 +275,16 @@ Here are some notable ones: |
| 275 | 275 | |----------------|-------------| |
| 276 | 276 | | `rustc_def_path` | Dumps the [`def_path_str`] of an item. | |
| 277 | 277 | | `rustc_dump_def_parents` | Dumps the chain of `DefId` parents of certain definitions. | |
| 278 | | `rustc_dump_inferred_outlives` | Dumps implied bounds of an item. More precisely, the [`inferred_outlives_of`] an item. | | |
| 278 | 279 | | `rustc_dump_item_bounds` | Dumps the [`item_bounds`] of an item. | |
| 280 | | `rustc_dump_object_lifetime_defaults` | Dumps the [object lifetime defaults] of an item. | | |
| 279 | 281 | | `rustc_dump_predicates` | Dumps the [`predicates_of`] an item. | |
| 282 | | `rustc_dump_variances` | Dumps the [variances] of an item. | | |
| 280 | 283 | | `rustc_dump_vtable` | Dumps the vtable layout of an impl, or a type alias of a dyn type. | |
| 281 | 284 | | `rustc_hidden_type_of_opaques` | Dumps the [hidden type of each opaque types][opaq] in the crate. | |
| 282 | 285 | | `rustc_layout` | [See this section](#debugging-type-layouts). | |
| 283 | | `rustc_object_lifetime_default` | Dumps the [object lifetime defaults] of an item. | | |
| 284 | | `rustc_outlives` | Dumps implied bounds of an item. More precisely, the [`inferred_outlives_of`] an item. | | |
| 285 | 286 | | `rustc_regions` | Dumps NLL closure region requirements. | |
| 286 | 287 | | `rustc_symbol_name` | Dumps the mangled & demangled [`symbol_name`] of an item. | |
| 287 | | `rustc_variances` | Dumps the [variances] of an item. | | |
| 288 | 288 | |
| 289 | 289 | Right below you can find elaborate explainers on a selected few. |
| 290 | 290 |
src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md+6-7| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | # Diagnostic and subdiagnostic structs |
| 2 | rustc has three diagnostic traits that can be used to create diagnostics: | |
| 3 | `Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. | |
| 2 | rustc has two diagnostic traits that can be used to create diagnostics: | |
| 3 | `Diagnostic` and `Subdiagnostic`. | |
| 4 | 4 | |
| 5 | 5 | For simple diagnostics, |
| 6 | 6 | derived impls can be used, e.g. `#[derive(Diagnostic)]`. They are only suitable for simple diagnostics that |
| ... | ... | @@ -8,12 +8,12 @@ don't require much logic in deciding whether or not to add additional subdiagnos |
| 8 | 8 | |
| 9 | 9 | In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics, |
| 10 | 10 | customizing the rendering logic, or selecting messages at runtime, you will need to manually implement |
| 11 | the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`). | |
| 11 | the corresponding trait (`Diagnostic` or `Subdiagnostic`). | |
| 12 | 12 | This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures. |
| 13 | 13 | |
| 14 | 14 | Diagnostic can be translated into different languages. |
| 15 | 15 | |
| 16 | ## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` | |
| 16 | ## `#[derive(Diagnostic)]` | |
| 17 | 17 | |
| 18 | 18 | Consider the [definition][defn] of the "field already declared" diagnostic shown below: |
| 19 | 19 | |
| ... | ... | @@ -123,8 +123,8 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { |
| 123 | 123 | }); |
| 124 | 124 | ``` |
| 125 | 125 | |
| 126 | ### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` | |
| 127 | `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the following attributes: | |
| 126 | ### Reference for `#[derive(Diagnostic)]` | |
| 127 | `#[derive(Diagnostic)]` supports the following attributes: | |
| 128 | 128 | |
| 129 | 129 | - `#[diag("message", code = "...")]` |
| 130 | 130 | - _Applied to struct or enum variant._ |
| ... | ... | @@ -171,7 +171,6 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { |
| 171 | 171 | - Adds the subdiagnostic represented by the subdiagnostic struct. |
| 172 | 172 | - `#[primary_span]` (_Optional_) |
| 173 | 173 | - _Applied to `Span` fields on `Subdiagnostic`s. |
| 174 | Not used for `LintDiagnostic`s._ | |
| 175 | 174 | - Indicates the primary span of the diagnostic. |
| 176 | 175 | - `#[skip_arg]` (_Optional_) |
| 177 | 176 | - _Applied to any field._ |
src/doc/rustc-dev-guide/src/diagnostics/translation.md+1-1| ... | ... | @@ -32,7 +32,7 @@ There are two ways of writing translatable diagnostics: |
| 32 | 32 | deciding to emit subdiagnostics and can therefore be represented as diagnostic structs). |
| 33 | 33 | See [the diagnostic and subdiagnostic structs documentation](./diagnostic-structs.md). |
| 34 | 34 | 2. Using typed identifiers with `Diag` APIs (in |
| 35 | `Diagnostic` or `Subdiagnostic` or `LintDiagnostic` implementations). | |
| 35 | `Diagnostic` or `Subdiagnostic` implementations). | |
| 36 | 36 | |
| 37 | 37 | When adding or changing a translatable diagnostic, |
| 38 | 38 | you don't need to worry about the translations. |
src/librustdoc/passes/lint/check_code_block_syntax.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ use std::sync::Arc; |
| 5 | 5 | |
| 6 | 6 | use rustc_data_structures::sync::Lock; |
| 7 | 7 | use rustc_errors::emitter::Emitter; |
| 8 | use rustc_errors::translation::format_diag_message; | |
| 8 | use rustc_errors::formatting::format_diag_message; | |
| 9 | 9 | use rustc_errors::{Applicability, DiagCtxt, DiagInner}; |
| 10 | 10 | use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; |
| 11 | 11 | use rustc_resolve::rustdoc::source_span_for_markdown_range; |
src/tools/miri/CONTRIBUTING.md+2| ... | ... | @@ -189,6 +189,8 @@ you can visualize in [Perfetto](https://ui.perfetto.dev/). For example: |
| 189 | 189 | MIRI_TRACING=1 ./miri run --features=tracing tests/pass/hello.rs |
| 190 | 190 | ``` |
| 191 | 191 | |
| 192 | See [doc/tracing.md](./doc/tracing.md) for more information. | |
| 193 | ||
| 192 | 194 | ### UI testing |
| 193 | 195 | |
| 194 | 196 | We use ui-testing in Miri, meaning we generate `.stderr` and `.stdout` files for the output |
src/tools/miri/doc/tracing.md+9-3| ... | ... | @@ -2,6 +2,9 @@ |
| 2 | 2 | |
| 3 | 3 | Miri can be traced to understand how much time is spent in its various components (e.g. borrow tracker, data race checker, etc.). When tracing is enabled, running Miri will create a `.json` trace file that can be opened and analyzed in [Perfetto](https://ui.perfetto.dev/). For any questions regarding this documentation you may contact [Stypox](https://rust-lang.zulipchat.com/#narrow/dm/627563-Stypox) on Zulip. |
| 4 | 4 | |
| 5 | > [!WARNING] | |
| 6 | > Tracing in Miri at the moment is broken due to two bugs in tracing libraries: https://github.com/tokio-rs/tracing/pull/3392 and https://github.com/davidbarsky/tracing-tree/issues/93. Also see https://github.com/rust-lang/miri/issues/4752. | |
| 7 | ||
| 5 | 8 | ## Obtaining a trace file |
| 6 | 9 | |
| 7 | 10 | ### From the Miri codebase |
| ... | ... | @@ -240,7 +243,7 @@ let _trace = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_p |
| 240 | 243 | |
| 241 | 244 | ### `tracing_separate_thread` parameter |
| 242 | 245 | |
| 243 | Miri saves traces using the the `tracing_chrome` `tracing::Layer` so that they can be visualized in Perfetto. To instruct `tracing_chrome` to put some spans on a separate trace thread/line than other spans when viewed in Perfetto, you can pass `tracing_separate_thread = tracing::field::Empty` to the tracing macros. This is useful to separate out spans which just indicate the current step or program frame being processed by the interpreter. As explained in [The timeline](#the-timeline), those spans end up under the "Global Legacy Events" track. You should use a value of `tracing::field::Empty` so that other tracing layers (e.g. the logger) will ignore the `tracing_separate_thread` field. For example: | |
| 246 | Miri saves traces using the `tracing_chrome` `tracing::Layer` so that they can be visualized in Perfetto. To instruct `tracing_chrome` to put some spans on a separate trace thread/line than other spans when viewed in Perfetto, you can pass `tracing_separate_thread = tracing::field::Empty` to the tracing macros. This is useful to separate out spans which just indicate the current step or program frame being processed by the interpreter. As explained in [The timeline](#the-timeline), those spans end up under the "Global Legacy Events" track. You should use a value of `tracing::field::Empty` so that other tracing layers (e.g. the logger) will ignore the `tracing_separate_thread` field. For example: | |
| 244 | 247 | ```rust |
| 245 | 248 | let _trace = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty); |
| 246 | 249 | ``` |
| ... | ... | @@ -277,9 +280,12 @@ So the solution was to copy-paste [the only file](https://github.com/thoren-d/tr |
| 277 | 280 | |
| 278 | 281 | ### Time measurements |
| 279 | 282 | |
| 280 | tracing-chrome originally used `std::time::Instant` to measure time, however on some x86/x86_64 Linux systems it might be unbearably slow since the underlying system call (`clock_gettime`) would take ≈1.3µs. Read more [here](https://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/) about how the Linux kernel chooses the clock source. | |
| 283 | tracing-chrome uses `std::time::Instant` to measure time. On most modern systems this is ok, since the underlying system call (`clock_gettime`) uses very fast hardware counters (e.g. `tsc`) and has a latency of ≈16ns. | |
| 284 | ||
| 285 | On some x86/x86_64 Linux systems, however, `tsc` is not "reliable" and the system thus relies on other timers, e.g. `hpet` which takes ≈1.3µs. Read [here](https://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/) how the Linux kernel chooses the clock source, and how to check if your system is using `tsc`. If it doesn't use `tsc`, then expect most of the trace time being spent in time measurements, which degrades traces' usefulness... See [here](https://github.com/rust-lang/miri/issues/4563) for some discussion. | |
| 281 | 286 | |
| 282 | Therefore, on x86/x86_64 Linux systems with a CPU that has an invariant TSC counter, we read from that instead to measure time, which takes only ≈13ns. There are unfortunately a lot of caveats to this approach though, as explained [in the code](https://github.com/rust-lang/miri/blob/master/src/bin/log/tracing_chrome_instant.rs) and [in the PR](https://github.com/rust-lang/miri/pull/4524). The most impactful one is that: every thread spawned in Miri that wants to trace something (which requires measuring time) needs to pin itself to a single CPU core (using `sched_setaffinity`). | |
| 287 | > [!WARNING] | |
| 288 | > A (somewhat risky) workaround is to add `tsc=reliable clocksource=tsc hpet=disable` to the kernel boot parameters, which forces it to use `tsc` even if it is unreliable. But this may render the system unstable, so try it at your own risk! | |
| 283 | 289 | |
| 284 | 290 | ## Other useful stuff |
| 285 | 291 |
src/tools/miri/rust-version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | 7bee525095c0872e87c038c412c781b9bbb3f5dc | |
| 1 | d933cf483edf1605142ac6899ff32536c0ad8b22 |
src/tools/miri/src/alloc_addresses/mod.rs+5-1| ... | ... | @@ -168,7 +168,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 168 | 168 | if let Some(GlobalAlloc::Function { instance, .. }) = |
| 169 | 169 | this.tcx.try_get_global_alloc(alloc_id) |
| 170 | 170 | { |
| 171 | let fn_sig = this.tcx.fn_sig(instance.def_id()).skip_binder().skip_binder(); | |
| 171 | let fn_sig = this.tcx.instantiate_bound_regions_with_erased( | |
| 172 | this.tcx | |
| 173 | .fn_sig(instance.def_id()) | |
| 174 | .instantiate(*this.tcx, instance.args), | |
| 175 | ); | |
| 172 | 176 | let fn_ptr = crate::shims::native_lib::build_libffi_closure(this, fn_sig)?; |
| 173 | 177 | |
| 174 | 178 | #[expect( |
src/tools/miri/src/bin/log/mod.rs-1| ... | ... | @@ -1,3 +1,2 @@ |
| 1 | 1 | pub mod setup; |
| 2 | 2 | mod tracing_chrome; |
| 3 | mod tracing_chrome_instant; |
src/tools/miri/src/bin/log/tracing_chrome.rs+39-22| ... | ... | @@ -50,9 +50,8 @@ use std::{ |
| 50 | 50 | thread::JoinHandle, |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | use crate::log::tracing_chrome_instant::TracingChromeInstant; | |
| 54 | ||
| 55 | 53 | /// Contains thread-local data for threads that send tracing spans or events. |
| 54 | #[derive(Clone)] | |
| 56 | 55 | struct ThreadData { |
| 57 | 56 | /// A unique ID for this thread, will populate "tid" field in the output trace file. |
| 58 | 57 | tid: usize, |
| ... | ... | @@ -61,7 +60,7 @@ struct ThreadData { |
| 61 | 60 | out: Sender<Message>, |
| 62 | 61 | /// The instant in time this thread was started. All events happening on this thread will be |
| 63 | 62 | /// saved to the trace file with a timestamp (the "ts" field) measured relative to this instant. |
| 64 | start: TracingChromeInstant, | |
| 63 | start: std::time::Instant, | |
| 65 | 64 | } |
| 66 | 65 | |
| 67 | 66 | thread_local! { |
| ... | ... | @@ -562,28 +561,46 @@ where |
| 562 | 561 | #[inline(always)] |
| 563 | 562 | fn with_elapsed_micros_subtracting_tracing(&self, f: impl Fn(f64, usize, &Sender<Message>)) { |
| 564 | 563 | THREAD_DATA.with(|value| { |
| 565 | let mut thread_data = value.borrow_mut(); | |
| 566 | let (ThreadData { tid, out, start }, new_thread) = match thread_data.as_mut() { | |
| 567 | Some(thread_data) => (thread_data, false), | |
| 568 | None => { | |
| 569 | let tid = self.max_tid.fetch_add(1, Ordering::SeqCst); | |
| 570 | let out = self.out.lock().unwrap().clone(); | |
| 571 | let start = TracingChromeInstant::setup_for_thread_and_start(tid); | |
| 572 | *thread_data = Some(ThreadData { tid, out, start }); | |
| 573 | (thread_data.as_mut().unwrap(), true) | |
| 564 | // Make sure not to keep `value` borrowed when calling `f` below, since the user tracing | |
| 565 | // code that `f` might invoke (e.g. fmt::Debug argument formatting) may contain nested | |
| 566 | // tracing calls that would cause `value` to be doubly-borrowed mutably. | |
| 567 | let (ThreadData { tid, out, start }, new_thread) = { | |
| 568 | let mut thread_data = value.borrow_mut(); | |
| 569 | match thread_data.as_mut() { | |
| 570 | Some(thread_data) => (thread_data.clone(), false), | |
| 571 | None => { | |
| 572 | let tid = self.max_tid.fetch_add(1, Ordering::SeqCst); | |
| 573 | let out = self.out.lock().unwrap().clone(); | |
| 574 | let start = std::time::Instant::now(); | |
| 575 | *thread_data = Some(ThreadData { tid, out: out.clone(), start }); | |
| 576 | (ThreadData { tid, out, start }, true) | |
| 577 | } | |
| 574 | 578 | } |
| 575 | 579 | }; |
| 576 | 580 | |
| 577 | start.with_elapsed_micros_subtracting_tracing(|ts| { | |
| 578 | if new_thread { | |
| 579 | let name = match std::thread::current().name() { | |
| 580 | Some(name) => name.to_owned(), | |
| 581 | None => tid.to_string(), | |
| 582 | }; | |
| 583 | let _ignored = out.send(Message::NewThread(*tid, name)); | |
| 584 | } | |
| 585 | f(ts, *tid, out); | |
| 586 | }); | |
| 581 | // Obtain the current time (before executing `f`). | |
| 582 | let instant_before_f = std::time::Instant::now(); | |
| 583 | ||
| 584 | // Using the current time (`instant_before_f`), calculate the elapsed time (in | |
| 585 | // microseconds) since `start` was instantiated, accounting for any time that was | |
| 586 | // previously spent executing `f`. The "accounting" part is not computed in this | |
| 587 | // line, but is rather done by shifting forward the `start` down below. | |
| 588 | let ts = (instant_before_f - start).as_nanos() as f64 / 1000.0; | |
| 589 | ||
| 590 | // Run the function (supposedly a function internal to the tracing infrastructure). | |
| 591 | if new_thread { | |
| 592 | let name = match std::thread::current().name() { | |
| 593 | Some(name) => name.to_owned(), | |
| 594 | None => tid.to_string(), | |
| 595 | }; | |
| 596 | let _ignored = out.send(Message::NewThread(tid, name)); | |
| 597 | } | |
| 598 | f(ts, tid, &out); | |
| 599 | ||
| 600 | // Measure how much time was spent executing `f` and shift `start` forward | |
| 601 | // by that amount. This "removes" that time from the trace. | |
| 602 | // See comment at the top of this function for why we have to re-borrow here. | |
| 603 | value.borrow_mut().as_mut().unwrap().start += std::time::Instant::now() - instant_before_f; | |
| 587 | 604 | }); |
| 588 | 605 | } |
| 589 | 606 | } |
src/tools/miri/src/bin/log/tracing_chrome_instant.rs deleted-183| ... | ... | @@ -1,183 +0,0 @@ |
| 1 | //! Code in this class was in part inspired by | |
| 2 | //! <https://github.com/tikv/minstant/blob/27c9ec5ec90b5b67113a748a4defee0d2519518c/src/tsc_now.rs>. | |
| 3 | //! A useful resource is also | |
| 4 | //! <https://www.pingcap.com/blog/how-we-trace-a-kv-database-with-less-than-5-percent-performance-impact/>, | |
| 5 | //! although this file does not implement TSC synchronization but instead pins threads to CPUs, | |
| 6 | //! since the former is not reliable (i.e. it might lead to non-monotonic time measurements). | |
| 7 | //! Another useful resource for future improvements might be measureme's time measurement utils: | |
| 8 | //! <https://github.com/rust-lang/measureme/blob/master/measureme/src/counters.rs>. | |
| 9 | //! Documentation about how the Linux kernel chooses a clock source can be found here: | |
| 10 | //! <https://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/>. | |
| 11 | #![cfg(feature = "tracing")] | |
| 12 | ||
| 13 | /// This alternative `TracingChromeInstant` implementation was made entirely to suit the needs of | |
| 14 | /// [crate::log::tracing_chrome], and shouldn't be used for anything else. It features two functions: | |
| 15 | /// - [TracingChromeInstant::setup_for_thread_and_start], which sets up the current thread to do | |
| 16 | /// proper time tracking and returns a point in time to use as "t=0", and | |
| 17 | /// - [TracingChromeInstant::with_elapsed_micros_subtracting_tracing], which allows | |
| 18 | /// obtaining how much time elapsed since [TracingChromeInstant::setup_for_thread_and_start] was | |
| 19 | /// called while accounting for (and subtracting) the time spent inside tracing-related functions. | |
| 20 | /// | |
| 21 | /// This measures time using [std::time::Instant], except for x86/x86_64 Linux machines, where | |
| 22 | /// [std::time::Instant] is too slow (~1.5us) and thus `rdtsc` is used instead (~5ns). | |
| 23 | pub enum TracingChromeInstant { | |
| 24 | WallTime { | |
| 25 | /// The time at which this instant was created, shifted forward to account | |
| 26 | /// for time spent in tracing functions as explained in | |
| 27 | /// [TracingChromeInstant::with_elapsed_micros_subtracting_tracing]'s comments. | |
| 28 | start_instant: std::time::Instant, | |
| 29 | }, | |
| 30 | #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")))] | |
| 31 | Tsc { | |
| 32 | /// The value in the TSC counter when this instant was created, shifted forward to account | |
| 33 | /// for time spent in tracing functions as explained in | |
| 34 | /// [TracingChromeInstant::with_elapsed_micros_subtracting_tracing]'s comments. | |
| 35 | start_tsc: u64, | |
| 36 | /// The period of the TSC counter in microseconds. | |
| 37 | tsc_to_microseconds: f64, | |
| 38 | }, | |
| 39 | } | |
| 40 | ||
| 41 | impl TracingChromeInstant { | |
| 42 | /// Can be thought of as the same as [std::time::Instant::now()], but also does some setup to | |
| 43 | /// make TSC stable in case TSC is available. This is supposed to be called (at most) once per | |
| 44 | /// thread since the thread setup takes a few milliseconds. | |
| 45 | /// | |
| 46 | /// WARNING: If TSC is available, `incremental_thread_id` is used to pick to which CPU to pin | |
| 47 | /// the current thread. Thread IDs should be assigned contiguously starting from 0. Be aware | |
| 48 | /// that the current thread will be restricted to one CPU for the rest of the execution! | |
| 49 | pub fn setup_for_thread_and_start(incremental_thread_id: usize) -> TracingChromeInstant { | |
| 50 | #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")))] | |
| 51 | if *tsc::IS_TSC_AVAILABLE.get_or_init(tsc::is_tsc_available) { | |
| 52 | // We need to lock this thread to a specific CPU, because CPUs' TSC timers might be out | |
| 53 | // of sync. | |
| 54 | tsc::set_cpu_affinity(incremental_thread_id); | |
| 55 | ||
| 56 | // Can only use tsc_to_microseconds() and rdtsc() after having set the CPU affinity! | |
| 57 | // We compute tsc_to_microseconds anew for every new thread just in case some CPU core | |
| 58 | // has a different TSC frequency. | |
| 59 | let tsc_to_microseconds = tsc::tsc_to_microseconds(); | |
| 60 | let start_tsc = tsc::rdtsc(); | |
| 61 | return TracingChromeInstant::Tsc { start_tsc, tsc_to_microseconds }; | |
| 62 | } | |
| 63 | ||
| 64 | let _ = incremental_thread_id; // otherwise we get a warning when the TSC branch is disabled | |
| 65 | TracingChromeInstant::WallTime { start_instant: std::time::Instant::now() } | |
| 66 | } | |
| 67 | ||
| 68 | /// Calls `f` with the time elapsed in microseconds since this [TracingChromeInstant] was built | |
| 69 | /// by [TracingChromeInstant::setup_for_thread_and_start], while subtracting all time previously | |
| 70 | /// spent executing other `f`s passed to this function. This behavior allows subtracting time | |
| 71 | /// spent in functions that log tracing data (which `f` is supposed to be) from the tracing time | |
| 72 | /// measurements. | |
| 73 | /// | |
| 74 | /// Note: microseconds are used as the time unit since that's what Chrome trace files should | |
| 75 | /// contain, see the definition of the "ts" field in | |
| 76 | /// <https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview>. | |
| 77 | #[inline(always)] | |
| 78 | pub fn with_elapsed_micros_subtracting_tracing(&mut self, f: impl Fn(f64)) { | |
| 79 | match self { | |
| 80 | TracingChromeInstant::WallTime { start_instant } => { | |
| 81 | // Obtain the current time (before executing `f`). | |
| 82 | let instant_before_f = std::time::Instant::now(); | |
| 83 | ||
| 84 | // Using the current time (`instant_before_f`) and the `start_instant` stored in | |
| 85 | // `self`, calculate the elapsed time (in microseconds) since this instant was | |
| 86 | // instantiated, accounting for any time that was previously spent executing `f`. | |
| 87 | // The "accounting" part is not computed in this line, but is rather done by | |
| 88 | // shifting forward the `start_instant` down below. | |
| 89 | let ts = (instant_before_f - *start_instant).as_nanos() as f64 / 1000.0; | |
| 90 | ||
| 91 | // Run the function (supposedly a function internal to the tracing infrastructure). | |
| 92 | f(ts); | |
| 93 | ||
| 94 | // Measure how much time was spent executing `f` and shift `start_instant` forward | |
| 95 | // by that amount. This "removes" that time from the trace. | |
| 96 | *start_instant += std::time::Instant::now() - instant_before_f; | |
| 97 | } | |
| 98 | ||
| 99 | #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")))] | |
| 100 | TracingChromeInstant::Tsc { start_tsc, tsc_to_microseconds } => { | |
| 101 | // the comments above also apply here, since it's the same logic | |
| 102 | let tsc_before_f = tsc::rdtsc(); | |
| 103 | let ts = ((tsc_before_f - *start_tsc) as f64) * (*tsc_to_microseconds); | |
| 104 | f(ts); | |
| 105 | *start_tsc += tsc::rdtsc() - tsc_before_f; | |
| 106 | } | |
| 107 | } | |
| 108 | } | |
| 109 | } | |
| 110 | ||
| 111 | #[cfg(all(target_os = "linux", any(target_arch = "x86", target_arch = "x86_64")))] | |
| 112 | mod tsc { | |
| 113 | ||
| 114 | pub static IS_TSC_AVAILABLE: std::sync::OnceLock<bool> = std::sync::OnceLock::new(); | |
| 115 | ||
| 116 | /// Reads the timestamp-counter register. Will give monotonic answers only when called from the | |
| 117 | /// same thread, because the TSC of different CPUs might be out of sync. | |
| 118 | #[inline(always)] | |
| 119 | pub(super) fn rdtsc() -> u64 { | |
| 120 | #[cfg(target_arch = "x86")] | |
| 121 | use core::arch::x86::_rdtsc; | |
| 122 | #[cfg(target_arch = "x86_64")] | |
| 123 | use core::arch::x86_64::_rdtsc; | |
| 124 | ||
| 125 | unsafe { _rdtsc() } | |
| 126 | } | |
| 127 | ||
| 128 | /// Estimates the frequency of the TSC counter by waiting 10ms in a busy loop and | |
| 129 | /// looking at how much the TSC increased in the meantime. | |
| 130 | pub(super) fn tsc_to_microseconds() -> f64 { | |
| 131 | const BUSY_WAIT: std::time::Duration = std::time::Duration::from_millis(10); | |
| 132 | let tsc_start = rdtsc(); | |
| 133 | let instant_start = std::time::Instant::now(); | |
| 134 | while instant_start.elapsed() < BUSY_WAIT { | |
| 135 | // `thread::sleep()` is not very precise at waking up the program at the right time, | |
| 136 | // so use a busy loop instead. | |
| 137 | core::hint::spin_loop(); | |
| 138 | } | |
| 139 | let tsc_end = rdtsc(); | |
| 140 | (BUSY_WAIT.as_nanos() as f64) / 1000.0 / ((tsc_end - tsc_start) as f64) | |
| 141 | } | |
| 142 | ||
| 143 | /// Checks whether the TSC counter is available and runs at a constant rate independently | |
| 144 | /// of CPU frequency even across different power states of the CPU (i.e. checks for the | |
| 145 | /// `invariant_tsc` CPUID flag). | |
| 146 | pub(super) fn is_tsc_available() -> bool { | |
| 147 | #[cfg(target_arch = "x86")] | |
| 148 | use core::arch::x86::__cpuid; | |
| 149 | #[cfg(target_arch = "x86_64")] | |
| 150 | use core::arch::x86_64::__cpuid; | |
| 151 | ||
| 152 | // implemented like https://docs.rs/raw-cpuid/latest/src/raw_cpuid/extended.rs.html#965-967 | |
| 153 | const LEAF: u32 = 0x80000007; // this is the leaf for "advanced power management info" | |
| 154 | let cpuid = __cpuid(LEAF); | |
| 155 | (cpuid.edx & (1 << 8)) != 0 // EDX bit 8 indicates invariant TSC | |
| 156 | } | |
| 157 | ||
| 158 | /// Forces the current thread to run on a single CPU, which ensures the TSC counter is monotonic | |
| 159 | /// (since TSCs of different CPUs might be out-of-sync). `incremental_thread_id` is used to pick | |
| 160 | /// to which CPU to pin the current thread, and should be an incremental number that starts from | |
| 161 | /// 0. | |
| 162 | pub(super) fn set_cpu_affinity(incremental_thread_id: usize) { | |
| 163 | let cpu_id = match std::thread::available_parallelism() { | |
| 164 | Ok(available_parallelism) => incremental_thread_id % available_parallelism, | |
| 165 | _ => panic!("Could not determine CPU count to properly set CPU affinity"), | |
| 166 | }; | |
| 167 | ||
| 168 | let mut set = unsafe { std::mem::zeroed::<libc::cpu_set_t>() }; | |
| 169 | unsafe { libc::CPU_SET(cpu_id, &mut set) }; | |
| 170 | ||
| 171 | // Set the current thread's core affinity. | |
| 172 | if unsafe { | |
| 173 | libc::sched_setaffinity( | |
| 174 | 0, // Defaults to current thread | |
| 175 | size_of::<libc::cpu_set_t>(), | |
| 176 | &set as *const _, | |
| 177 | ) | |
| 178 | } != 0 | |
| 179 | { | |
| 180 | panic!("Could not set CPU affinity") | |
| 181 | } | |
| 182 | } | |
| 183 | } |
src/tools/miri/src/bin/miri.rs+7| ... | ... | @@ -193,7 +193,11 @@ fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box<dyn Codegen |
| 193 | 193 | |
| 194 | 194 | impl rustc_driver::Callbacks for MiriCompilerCalls { |
| 195 | 195 | fn config(&mut self, config: &mut rustc_interface::interface::Config) { |
| 196 | // We never reach codegen anyway. | |
| 196 | 197 | config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend)); |
| 198 | ||
| 199 | // Register our custom extra symbols. | |
| 200 | config.extra_symbols = miri::sym::EXTRA_SYMBOLS.into(); | |
| 197 | 201 | } |
| 198 | 202 | |
| 199 | 203 | fn after_analysis<'tcx>( |
| ... | ... | @@ -354,6 +358,9 @@ impl rustc_driver::Callbacks for MiriDepCompilerCalls { |
| 354 | 358 | ) |
| 355 | 359 | } |
| 356 | 360 | }); |
| 361 | ||
| 362 | // Register our custom extra symbols. | |
| 363 | config.extra_symbols = miri::sym::EXTRA_SYMBOLS.into(); | |
| 357 | 364 | } |
| 358 | 365 | |
| 359 | 366 | fn after_analysis<'tcx>( |
src/tools/miri/src/concurrency/genmc/scheduling.rs+5-4| ... | ... | @@ -5,7 +5,8 @@ use rustc_middle::ty::{self, Ty}; |
| 5 | 5 | |
| 6 | 6 | use super::GenmcCtx; |
| 7 | 7 | use crate::{ |
| 8 | InterpCx, InterpResult, MiriMachine, TerminationInfo, ThreadId, interp_ok, throw_machine_stop, | |
| 8 | InterpCx, InterpResult, MiriMachine, TerminationInfo, ThreadId, interp_ok, sym, | |
| 9 | throw_machine_stop, | |
| 9 | 10 | }; |
| 10 | 11 | |
| 11 | 12 | enum NextInstrKind { |
| ... | ... | @@ -76,11 +77,11 @@ fn get_function_kind<'tcx>( |
| 76 | 77 | // NOTE: Functions intercepted by Miri in `concurrency/genmc/intercep.rs` must also be added here. |
| 77 | 78 | // Such intercepted functions, like `sys::Mutex::lock`, should be treated as atomics to ensure we call the scheduler when we encounter one of them. |
| 78 | 79 | // These functions must also be classified whether they may have load semantics. |
| 79 | if ecx.tcx.is_diagnostic_item(rustc_span::sym::sys_mutex_lock, callee_def_id) | |
| 80 | || ecx.tcx.is_diagnostic_item(rustc_span::sym::sys_mutex_try_lock, callee_def_id) | |
| 80 | if ecx.tcx.is_diagnostic_item(sym::sys_mutex_lock, callee_def_id) | |
| 81 | || ecx.tcx.is_diagnostic_item(sym::sys_mutex_try_lock, callee_def_id) | |
| 81 | 82 | { |
| 82 | 83 | return interp_ok(MaybeAtomic(ActionKind::Load)); |
| 83 | } else if ecx.tcx.is_diagnostic_item(rustc_span::sym::sys_mutex_unlock, callee_def_id) { | |
| 84 | } else if ecx.tcx.is_diagnostic_item(sym::sys_mutex_unlock, callee_def_id) { | |
| 84 | 85 | return interp_ok(MaybeAtomic(ActionKind::NonLoad)); |
| 85 | 86 | } |
| 86 | 87 | // The next step is a call to a regular Rust function. |
src/tools/miri/src/concurrency/genmc/shims.rs+15-18| ... | ... | @@ -24,24 +24,22 @@ impl GenmcCtx { |
| 24 | 24 | } |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | /// Small helper to get the arguments of an intercepted function call. | |
| 28 | fn get_fn_args<'tcx, const N: usize>( | |
| 29 | instance: ty::Instance<'tcx>, | |
| 30 | args: &[FnArg<'tcx>], | |
| 31 | ) -> InterpResult<'tcx, [OpTy<'tcx>; N]> { | |
| 32 | let args = MiriInterpCx::copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? | |
| 33 | if let Ok(ops) = args.try_into() { | |
| 34 | return interp_ok(ops); | |
| 35 | } | |
| 36 | panic!("{} is a diagnostic item expected to have {} arguments", instance, N); | |
| 37 | } | |
| 38 | ||
| 27 | 39 | // Handling of code intercepted by Miri in GenMC mode, such as assume statement or `std::sync::Mutex`. |
| 28 | 40 | |
| 29 | 41 | impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 30 | 42 | trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 31 | /// Small helper to get the arguments of an intercepted function call. | |
| 32 | fn get_fn_args<const N: usize>( | |
| 33 | &self, | |
| 34 | instance: ty::Instance<'tcx>, | |
| 35 | args: &[FnArg<'tcx>], | |
| 36 | ) -> InterpResult<'tcx, [OpTy<'tcx>; N]> { | |
| 37 | let this = self.eval_context_ref(); | |
| 38 | let args = this.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit? | |
| 39 | if let Ok(ops) = args.try_into() { | |
| 40 | return interp_ok(ops); | |
| 41 | } | |
| 42 | panic!("{} is a diagnostic item expected to have {} arguments", instance, N); | |
| 43 | } | |
| 44 | ||
| 45 | 43 | /**** Blocking functionality ****/ |
| 46 | 44 | |
| 47 | 45 | /// Handle a thread getting blocked by a user assume (not an automatically generated assume). |
| ... | ... | @@ -200,17 +198,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 200 | 198 | ); |
| 201 | 199 | |
| 202 | 200 | // NOTE: When adding new intercepted functions here, they must also be added to `fn get_function_kind` in `concurrency/genmc/scheduling.rs`. |
| 203 | use rustc_span::sym; | |
| 204 | 201 | if this.tcx.is_diagnostic_item(sym::sys_mutex_lock, instance.def_id()) { |
| 205 | let [mutex] = this.get_fn_args(instance, args)?; | |
| 202 | let [mutex] = get_fn_args(instance, args)?; | |
| 206 | 203 | let mutex = this.deref_pointer(&mutex)?; |
| 207 | 204 | this.intercept_mutex_lock(mutex)?; |
| 208 | 205 | } else if this.tcx.is_diagnostic_item(sym::sys_mutex_try_lock, instance.def_id()) { |
| 209 | let [mutex] = this.get_fn_args(instance, args)?; | |
| 206 | let [mutex] = get_fn_args(instance, args)?; | |
| 210 | 207 | let mutex = this.deref_pointer(&mutex)?; |
| 211 | 208 | this.intercept_mutex_try_lock(mutex, dest)?; |
| 212 | 209 | } else if this.tcx.is_diagnostic_item(sym::sys_mutex_unlock, instance.def_id()) { |
| 213 | let [mutex] = this.get_fn_args(instance, args)?; | |
| 210 | let [mutex] = get_fn_args(instance, args)?; | |
| 214 | 211 | let mutex = this.deref_pointer(&mutex)?; |
| 215 | 212 | this.intercept_mutex_unlock(mutex)?; |
| 216 | 213 | } else { |
src/tools/miri/src/diagnostics.rs+3| ... | ... | @@ -149,6 +149,7 @@ pub enum NonHaltingDiagnostic { |
| 149 | 149 | failure_ordering: AtomicReadOrd, |
| 150 | 150 | effective_failure_ordering: AtomicReadOrd, |
| 151 | 151 | }, |
| 152 | FileInProcOpened, | |
| 152 | 153 | } |
| 153 | 154 | |
| 154 | 155 | /// Level of Miri specific diagnostics |
| ... | ... | @@ -655,6 +656,7 @@ impl<'tcx> MiriMachine<'tcx> { |
| 655 | 656 | | ProgressReport { .. } |
| 656 | 657 | | WeakMemoryOutdatedLoad { .. } => |
| 657 | 658 | ("tracking was triggered here".to_string(), DiagLevel::Note), |
| 659 | FileInProcOpened => ("open a file in `/proc`".to_string(), DiagLevel::Warning), | |
| 658 | 660 | }; |
| 659 | 661 | |
| 660 | 662 | let title = match &e { |
| ... | ... | @@ -702,6 +704,7 @@ impl<'tcx> MiriMachine<'tcx> { |
| 702 | 704 | }; |
| 703 | 705 | format!("GenMC currently does not model the failure ordering for `compare_exchange`. {was_upgraded_msg}. Miri with GenMC might miss bugs related to this memory access.") |
| 704 | 706 | } |
| 707 | FileInProcOpened => format!("files in `/proc` can bypass the Abstract Machine and might not work properly in Miri") | |
| 705 | 708 | }; |
| 706 | 709 | |
| 707 | 710 | let notes = match &e { |
src/tools/miri/src/intrinsics/mod.rs+1-1| ... | ... | @@ -10,7 +10,7 @@ pub use self::atomic::AtomicRmwOp; |
| 10 | 10 | use rand::Rng; |
| 11 | 11 | use rustc_abi::Size; |
| 12 | 12 | use rustc_middle::{mir, ty}; |
| 13 | use rustc_span::{Symbol, sym}; | |
| 13 | use rustc_span::Symbol; | |
| 14 | 14 | |
| 15 | 15 | use self::atomic::EvalContextExt as _; |
| 16 | 16 | use self::math::EvalContextExt as _; |
src/tools/miri/src/lib.rs+6-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | #![cfg_attr(bootstrap, feature(if_let_guard))] |
| 2 | #![cfg_attr(bootstrap, feature(cfg_select))] | |
| 2 | 3 | #![feature(abort_unwind)] |
| 3 | 4 | #![feature(rustc_private)] |
| 4 | 5 | #![feature(float_gamma)] |
| ... | ... | @@ -16,7 +17,7 @@ |
| 16 | 17 | #![feature(derive_coerce_pointee)] |
| 17 | 18 | #![feature(arbitrary_self_types)] |
| 18 | 19 | #![feature(iter_advance_by)] |
| 19 | #![cfg_attr(bootstrap, feature(cfg_select))] | |
| 20 | #![feature(macro_metavar_expr)] | |
| 20 | 21 | // Configure clippy and other lints |
| 21 | 22 | #![allow( |
| 22 | 23 | clippy::collapsible_else_if, |
| ... | ... | @@ -39,8 +40,11 @@ |
| 39 | 40 | clippy::needless_lifetimes, |
| 40 | 41 | clippy::too_long_first_doc_paragraph, |
| 41 | 42 | clippy::len_zero, |
| 43 | clippy::collapsible_match, | |
| 42 | 44 | // We are not implementing queries here so it's fine |
| 43 | 45 | rustc::potential_query_instability, |
| 46 | // FIXME: Unused features should be removed in the future | |
| 47 | unused_features, | |
| 44 | 48 | )] |
| 45 | 49 | #![warn( |
| 46 | 50 | rust_2018_idioms, |
| ... | ... | @@ -87,6 +91,7 @@ mod math; |
| 87 | 91 | mod operator; |
| 88 | 92 | mod provenance_gc; |
| 89 | 93 | mod shims; |
| 94 | pub mod sym; | |
| 90 | 95 | |
| 91 | 96 | // Establish a "crate-wide prelude": we often import `crate::*`. |
| 92 | 97 | // Make all those symbols available in the same place as our own. |
src/tools/miri/src/machine.rs+2-1| ... | ... | @@ -300,7 +300,8 @@ pub enum ProvenanceExtra { |
| 300 | 300 | |
| 301 | 301 | #[cfg(target_pointer_width = "64")] |
| 302 | 302 | static_assert_size!(StrictPointer, 24); |
| 303 | // FIXME: this would with in 24bytes but layout optimizations are not smart enough | |
| 303 | // Pointer does not fit as the layout algorithm isn't smart enough (but also, we tried using | |
| 304 | // pattern types to get a larger niche that makes this fit and it didn't improve performance). | |
| 304 | 305 | // #[cfg(target_pointer_width = "64")] |
| 305 | 306 | //static_assert_size!(Pointer, 24); |
| 306 | 307 | #[cfg(target_pointer_width = "64")] |
src/tools/miri/src/shims/unix/fd.rs+13-1| ... | ... | @@ -196,7 +196,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 196 | 196 | let [flag] = check_min_vararg_count("fcntl(fd, F_SETFL, ...)", varargs)?; |
| 197 | 197 | let flag = this.read_scalar(flag)?.to_i32()?; |
| 198 | 198 | |
| 199 | fd.set_flags(flag, this) | |
| 199 | // Ignore flags that never get stored by SETFL. | |
| 200 | // "File access mode (O_RDONLY, O_WRONLY, O_RDWR) and file | |
| 201 | // creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) | |
| 202 | // in arg are ignored." | |
| 203 | let ignored_flags = this.eval_libc_i32("O_RDONLY") | |
| 204 | | this.eval_libc_i32("O_WRONLY") | |
| 205 | | this.eval_libc_i32("O_RDWR") | |
| 206 | | this.eval_libc_i32("O_CREAT") | |
| 207 | | this.eval_libc_i32("O_EXCL") | |
| 208 | | this.eval_libc_i32("O_NOCTTY") | |
| 209 | | this.eval_libc_i32("O_TRUNC"); | |
| 210 | ||
| 211 | fd.set_flags(flag & !ignored_flags, this) | |
| 200 | 212 | } |
| 201 | 213 | cmd if this.tcx.sess.target.os == Os::MacOs |
| 202 | 214 | && cmd == this.eval_libc_i32("F_FULLFSYNC") => |
src/tools/miri/src/shims/unix/foreign_items.rs+12| ... | ... | @@ -539,6 +539,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 539 | 539 | this.write_scalar(result, dest)?; |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | // Network sockets | |
| 543 | "socket" => { | |
| 544 | let [domain, type_, protocol] = this.check_shim_sig( | |
| 545 | shim_sig!(extern "C" fn(i32, i32, i32) -> i32), | |
| 546 | link_name, | |
| 547 | abi, | |
| 548 | args, | |
| 549 | )?; | |
| 550 | let result = this.socket(domain, type_, protocol)?; | |
| 551 | this.write_scalar(result, dest)?; | |
| 552 | } | |
| 553 | ||
| 542 | 554 | // Time |
| 543 | 555 | "gettimeofday" => { |
| 544 | 556 | let [tv, tz] = this.check_shim_sig( |
src/tools/miri/src/shims/unix/fs.rs+9-2| ... | ... | @@ -7,7 +7,7 @@ use std::fs::{ |
| 7 | 7 | rename, |
| 8 | 8 | }; |
| 9 | 9 | use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; |
| 10 | use std::path::{Path, PathBuf}; | |
| 10 | use std::path::{self, Path, PathBuf}; | |
| 11 | 11 | use std::time::SystemTime; |
| 12 | 12 | |
| 13 | 13 | use rustc_abi::Size; |
| ... | ... | @@ -354,9 +354,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 354 | 354 | let this = self.eval_context_mut(); |
| 355 | 355 | |
| 356 | 356 | let path_raw = this.read_pointer(path_raw)?; |
| 357 | let path = this.read_path_from_c_str(path_raw)?; | |
| 358 | 357 | let flag = this.read_scalar(flag)?.to_i32()?; |
| 359 | 358 | |
| 359 | let path = this.read_path_from_c_str(path_raw)?; | |
| 360 | // Files in `/proc` won't work properly. | |
| 361 | if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android | Os::Illumos | Os::Solaris) | |
| 362 | && path::absolute(&path).is_ok_and(|path| path.starts_with("/proc")) | |
| 363 | { | |
| 364 | this.machine.emit_diagnostic(NonHaltingDiagnostic::FileInProcOpened); | |
| 365 | } | |
| 366 | ||
| 360 | 367 | let mut options = OpenOptions::new(); |
| 361 | 368 | |
| 362 | 369 | let o_rdonly = this.eval_libc_i32("O_RDONLY"); |
src/tools/miri/src/shims/unix/mod.rs+2| ... | ... | @@ -4,6 +4,7 @@ mod env; |
| 4 | 4 | mod fd; |
| 5 | 5 | mod fs; |
| 6 | 6 | mod mem; |
| 7 | mod socket; | |
| 7 | 8 | mod sync; |
| 8 | 9 | mod thread; |
| 9 | 10 | mod unnamed_socket; |
| ... | ... | @@ -21,6 +22,7 @@ pub use self::fd::{EvalContextExt as _, UnixFileDescription}; |
| 21 | 22 | pub use self::fs::{DirTable, EvalContextExt as _}; |
| 22 | 23 | pub use self::linux_like::epoll::EpollInterestTable; |
| 23 | 24 | pub use self::mem::EvalContextExt as _; |
| 25 | pub use self::socket::EvalContextExt as _; | |
| 24 | 26 | pub use self::sync::EvalContextExt as _; |
| 25 | 27 | pub use self::thread::{EvalContextExt as _, ThreadNameResult}; |
| 26 | 28 | pub use self::unnamed_socket::EvalContextExt as _; |
src/tools/miri/src/shims/unix/socket.rs created+157| ... | ... | @@ -0,0 +1,157 @@ |
| 1 | use std::cell::Cell; | |
| 2 | use std::net::{TcpListener, TcpStream}; | |
| 3 | ||
| 4 | use rustc_const_eval::interpret::{InterpResult, interp_ok}; | |
| 5 | use rustc_middle::throw_unsup_format; | |
| 6 | use rustc_target::spec::Os; | |
| 7 | ||
| 8 | use crate::shims::files::{FdId, FileDescription}; | |
| 9 | use crate::{OpTy, Scalar, *}; | |
| 10 | ||
| 11 | #[derive(Debug, PartialEq)] | |
| 12 | enum SocketFamily { | |
| 13 | // IPv4 internet protocols | |
| 14 | IPv4, | |
| 15 | // IPv6 internet protocols | |
| 16 | IPv6, | |
| 17 | } | |
| 18 | ||
| 19 | #[derive(Debug)] | |
| 20 | enum SocketType { | |
| 21 | /// Reliable full-duplex communication, based on connections. | |
| 22 | Stream, | |
| 23 | } | |
| 24 | ||
| 25 | #[allow(unused)] | |
| 26 | #[derive(Debug)] | |
| 27 | enum SocketKind { | |
| 28 | TcpListener(TcpListener), | |
| 29 | TcpStream(TcpStream), | |
| 30 | } | |
| 31 | ||
| 32 | #[allow(unused)] | |
| 33 | #[derive(Debug)] | |
| 34 | struct Socket { | |
| 35 | /// Family of the socket, used to ensure socket only binds/connects to address of | |
| 36 | /// same family. | |
| 37 | family: SocketFamily, | |
| 38 | /// Type of the socket, either datagram or stream. | |
| 39 | /// Only stream is supported at the moment! | |
| 40 | socket_type: SocketType, | |
| 41 | /// Whether this fd is non-blocking or not. | |
| 42 | is_non_block: Cell<bool>, | |
| 43 | } | |
| 44 | ||
| 45 | impl FileDescription for Socket { | |
| 46 | fn name(&self) -> &'static str { | |
| 47 | "socket" | |
| 48 | } | |
| 49 | ||
| 50 | fn destroy<'tcx>( | |
| 51 | self, | |
| 52 | _self_id: FdId, | |
| 53 | _communicate_allowed: bool, | |
| 54 | _ecx: &mut MiriInterpCx<'tcx>, | |
| 55 | ) -> InterpResult<'tcx, std::io::Result<()>> | |
| 56 | where | |
| 57 | Self: Sized, | |
| 58 | { | |
| 59 | interp_ok(Ok(())) | |
| 60 | } | |
| 61 | ||
| 62 | fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { | |
| 63 | let mut flags = ecx.eval_libc_i32("O_RDWR"); | |
| 64 | ||
| 65 | if self.is_non_block.get() { | |
| 66 | flags |= ecx.eval_libc_i32("O_NONBLOCK"); | |
| 67 | } | |
| 68 | ||
| 69 | interp_ok(Scalar::from_i32(flags)) | |
| 70 | } | |
| 71 | ||
| 72 | fn set_flags<'tcx>( | |
| 73 | &self, | |
| 74 | mut _flag: i32, | |
| 75 | _ecx: &mut MiriInterpCx<'tcx>, | |
| 76 | ) -> InterpResult<'tcx, Scalar> { | |
| 77 | throw_unsup_format!("fcntl: socket flags aren't supported") | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} | |
| 82 | pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |
| 83 | /// For more information on the arguments see the socket manpage: | |
| 84 | /// <https://linux.die.net/man/2/socket> | |
| 85 | fn socket( | |
| 86 | &mut self, | |
| 87 | domain: &OpTy<'tcx>, | |
| 88 | type_: &OpTy<'tcx>, | |
| 89 | protocol: &OpTy<'tcx>, | |
| 90 | ) -> InterpResult<'tcx, Scalar> { | |
| 91 | let this = self.eval_context_mut(); | |
| 92 | ||
| 93 | let domain = this.read_scalar(domain)?.to_i32()?; | |
| 94 | let mut flags = this.read_scalar(type_)?.to_i32()?; | |
| 95 | let protocol = this.read_scalar(protocol)?.to_i32()?; | |
| 96 | ||
| 97 | // Reject if isolation is enabled | |
| 98 | if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { | |
| 99 | this.reject_in_isolation("`socket`", reject_with)?; | |
| 100 | this.set_last_error(LibcError("EACCES"))?; | |
| 101 | return interp_ok(Scalar::from_i32(-1)); | |
| 102 | } | |
| 103 | ||
| 104 | let mut is_sock_nonblock = false; | |
| 105 | ||
| 106 | // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so | |
| 107 | // if there is anything left at the end, that's an unsupported flag. | |
| 108 | if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android | Os::FreeBsd) { | |
| 109 | // SOCK_NONBLOCK and SOCK_CLOEXEC only exist on Linux, Android and FreeBSD. | |
| 110 | let sock_nonblock = this.eval_libc_i32("SOCK_NONBLOCK"); | |
| 111 | let sock_cloexec = this.eval_libc_i32("SOCK_CLOEXEC"); | |
| 112 | if flags & sock_nonblock == sock_nonblock { | |
| 113 | is_sock_nonblock = true; | |
| 114 | flags &= !sock_nonblock; | |
| 115 | } | |
| 116 | if flags & sock_cloexec == sock_cloexec { | |
| 117 | // We don't support `exec` so we can ignore this. | |
| 118 | flags &= !sock_cloexec; | |
| 119 | } | |
| 120 | } | |
| 121 | ||
| 122 | let family = if domain == this.eval_libc_i32("AF_INET") { | |
| 123 | SocketFamily::IPv4 | |
| 124 | } else if domain == this.eval_libc_i32("AF_INET6") { | |
| 125 | SocketFamily::IPv6 | |
| 126 | } else { | |
| 127 | throw_unsup_format!( | |
| 128 | "socket: domain {:#x} is unsupported, only AF_INET and \ | |
| 129 | AF_INET6 are allowed.", | |
| 130 | domain | |
| 131 | ); | |
| 132 | }; | |
| 133 | ||
| 134 | if flags != this.eval_libc_i32("SOCK_STREAM") { | |
| 135 | throw_unsup_format!( | |
| 136 | "socket: type {:#x} is unsupported, only SOCK_STREAM, \ | |
| 137 | SOCK_CLOEXEC and SOCK_NONBLOCK are allowed", | |
| 138 | flags | |
| 139 | ); | |
| 140 | } | |
| 141 | if protocol != 0 { | |
| 142 | throw_unsup_format!( | |
| 143 | "socket: socket protocol {protocol} is unsupported, \ | |
| 144 | only 0 is allowed" | |
| 145 | ); | |
| 146 | } | |
| 147 | ||
| 148 | let fds = &mut this.machine.fds; | |
| 149 | let fd = fds.new_ref(Socket { | |
| 150 | family, | |
| 151 | is_non_block: Cell::new(is_sock_nonblock), | |
| 152 | socket_type: SocketType::Stream, | |
| 153 | }); | |
| 154 | ||
| 155 | interp_ok(Scalar::from_i32(fds.insert(fd))) | |
| 156 | } | |
| 157 | } |
src/tools/miri/src/shims/unix/unnamed_socket.rs-8| ... | ... | @@ -170,12 +170,7 @@ impl FileDescription for AnonSocket { |
| 170 | 170 | mut flag: i32, |
| 171 | 171 | ecx: &mut MiriInterpCx<'tcx>, |
| 172 | 172 | ) -> InterpResult<'tcx, Scalar> { |
| 173 | // FIXME: File creation flags should be ignored. | |
| 174 | ||
| 175 | 173 | let o_nonblock = ecx.eval_libc_i32("O_NONBLOCK"); |
| 176 | let o_rdonly = ecx.eval_libc_i32("O_RDONLY"); | |
| 177 | let o_wronly = ecx.eval_libc_i32("O_WRONLY"); | |
| 178 | let o_rdwr = ecx.eval_libc_i32("O_RDWR"); | |
| 179 | 174 | |
| 180 | 175 | // O_NONBLOCK flag can be set / unset by user. |
| 181 | 176 | if flag & o_nonblock == o_nonblock { |
| ... | ... | @@ -185,9 +180,6 @@ impl FileDescription for AnonSocket { |
| 185 | 180 | self.is_nonblock.set(false); |
| 186 | 181 | } |
| 187 | 182 | |
| 188 | // Ignore all file access mode flags. | |
| 189 | flag &= !(o_rdonly | o_wronly | o_rdwr); | |
| 190 | ||
| 191 | 183 | // Throw error if there is any unsupported flag. |
| 192 | 184 | if flag != 0 { |
| 193 | 185 | throw_unsup_format!( |
src/tools/miri/src/sym.rs created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | #![allow(non_upper_case_globals)] | |
| 2 | ||
| 3 | #[doc(no_inline)] | |
| 4 | pub use rustc_span::sym::*; | |
| 5 | ||
| 6 | macro_rules! val { | |
| 7 | ($name:ident) => { | |
| 8 | stringify!($name) | |
| 9 | }; | |
| 10 | ($name:ident $value:literal) => { | |
| 11 | $value | |
| 12 | }; | |
| 13 | } | |
| 14 | ||
| 15 | macro_rules! generate { | |
| 16 | ($($name:ident $(: $value:literal)? ,)*) => { | |
| 17 | /// To be supplied to `rustc_interface::Config` | |
| 18 | pub const EXTRA_SYMBOLS: &[&str] = &[ | |
| 19 | $( | |
| 20 | val!($name $($value)?), | |
| 21 | )* | |
| 22 | ]; | |
| 23 | ||
| 24 | $( | |
| 25 | pub const $name: rustc_span::Symbol = rustc_span::Symbol::new(rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT + ${index()}); | |
| 26 | )* | |
| 27 | }; | |
| 28 | } | |
| 29 | ||
| 30 | // List of extra symbols to be included in Miri. | |
| 31 | // An alternative content can be specified using a colon after the symbol name. | |
| 32 | generate! { | |
| 33 | sys_mutex_lock, | |
| 34 | sys_mutex_try_lock, | |
| 35 | sys_mutex_unlock, | |
| 36 | } |
src/tools/miri/tests/fail/both_borrows/mixed_cell_deallocate.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | //@revisions: stack tree | |
| 2 | //@[tree]compile-flags: -Zmiri-tree-borrows | |
| 3 | ||
| 4 | use std::alloc; | |
| 5 | use std::cell::Cell; | |
| 6 | ||
| 7 | type T = (Cell<i32>, i32); | |
| 8 | ||
| 9 | // Deallocating `x` is UB because not all bytes are in an `UnsafeCell`. | |
| 10 | fn foo(x: &T) { | |
| 11 | let layout = alloc::Layout::new::<T>(); | |
| 12 | unsafe { alloc::dealloc(x as *const _ as *mut T as *mut u8, layout) }; //~ERROR: dealloc | |
| 13 | } | |
| 14 | ||
| 15 | fn main() { | |
| 16 | let b: Box<T> = Box::new((Cell::new(0), 0)); | |
| 17 | foo(unsafe { std::mem::transmute(Box::into_raw(b)) }); | |
| 18 | } |
src/tools/miri/tests/fail/both_borrows/mixed_cell_deallocate.stack.stderr created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | error: Undefined Behavior: attempting deallocation using <TAG> at ALLOC, but that tag only grants SharedReadOnly permission for this location | |
| 2 | --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 3 | | | |
| 4 | LL | unsafe { alloc::dealloc(x as *const _ as *mut T as *mut u8, layout) }; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | |
| 6 | | | |
| 7 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental | |
| 8 | = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information | |
| 9 | help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0xc] | |
| 10 | --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 11 | | | |
| 12 | LL | unsafe { alloc::dealloc(x as *const _ as *mut T as *mut u8, layout) }; | |
| 13 | | ^ | |
| 14 | = note: stack backtrace: | |
| 15 | 0: foo | |
| 16 | at tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 17 | 1: main | |
| 18 | at tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 19 | ||
| 20 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 21 | ||
| 22 | error: aborting due to 1 previous error | |
| 23 |
src/tools/miri/tests/fail/both_borrows/mixed_cell_deallocate.tree.stderr created+24| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x4] is forbidden | |
| 2 | --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 3 | | | |
| 4 | LL | unsafe { alloc::dealloc(x as *const _ as *mut T as *mut u8, layout) }; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | |
| 6 | | | |
| 7 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental | |
| 8 | = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information | |
| 9 | = help: the accessed tag <TAG> has state Frozen which forbids this deallocation (acting as a child write access) | |
| 10 | help: the accessed tag <TAG> was created here, in the initial state Cell | |
| 11 | --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 12 | | | |
| 13 | LL | fn foo(x: &T) { | |
| 14 | | ^ | |
| 15 | = note: stack backtrace: | |
| 16 | 0: foo | |
| 17 | at tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 18 | 1: main | |
| 19 | at tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC | |
| 20 | ||
| 21 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 22 | ||
| 23 | error: aborting due to 1 previous error | |
| 24 |
src/tools/miri/tests/native-lib/fail/call_fn_ptr.notrace.stderr created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(Some(nop)); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri stops tracking initialization and provenance for that memory | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has access to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = note: stack backtrace: | |
| 12 | 0: pass_fn_ptr | |
| 13 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 14 | 1: main | |
| 15 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 16 | ||
| 17 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 18 | --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 19 | | | |
| 20 | LL | call_fn_ptr(Some(nop)); | |
| 21 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 22 | | | |
| 23 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 24 | = note: stack backtrace: | |
| 25 | 0: pass_fn_ptr | |
| 26 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 27 | 1: main | |
| 28 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 29 | ||
| 30 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 31 |
src/tools/miri/tests/native-lib/fail/call_fn_ptr.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | //@revisions: trace notrace | |
| 2 | //@[trace] only-target: x86_64-unknown-linux-gnu i686-unknown-linux-gnu | |
| 3 | //@[trace] compile-flags: -Zmiri-native-lib-enable-tracing | |
| 4 | //@compile-flags: -Zmiri-permissive-provenance | |
| 5 | ||
| 6 | fn main() { | |
| 7 | pass_fn_ptr() | |
| 8 | } | |
| 9 | ||
| 10 | fn pass_fn_ptr() { | |
| 11 | extern "C" { | |
| 12 | fn call_fn_ptr(s: Option<extern "C" fn()>); | |
| 13 | } | |
| 14 | ||
| 15 | extern "C" fn nop() {} | |
| 16 | ||
| 17 | unsafe { | |
| 18 | call_fn_ptr(None); // this one is fine | |
| 19 | call_fn_ptr(Some(nop)); //~ ERROR: unsupported operation: calling a function pointer through the FFI boundary | |
| 20 | } | |
| 21 | } |
src/tools/miri/tests/native-lib/fail/call_fn_ptr.trace.stderr created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(Some(nop)); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri can only track initialisation and provenance on a best-effort basis | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has written to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = help: tracing memory accesses in native code is not yet fully implemented, so there can be further imprecisions beyond what is documented here | |
| 12 | = note: stack backtrace: | |
| 13 | 0: pass_fn_ptr | |
| 14 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 15 | 1: main | |
| 16 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 17 | ||
| 18 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 19 | --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 20 | | | |
| 21 | LL | call_fn_ptr(Some(nop)); | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 23 | | | |
| 24 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 25 | = note: stack backtrace: | |
| 26 | 0: pass_fn_ptr | |
| 27 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 28 | 1: main | |
| 29 | at tests/native-lib/fail/call_fn_ptr.rs:LL:CC | |
| 30 | ||
| 31 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 32 |
src/tools/miri/tests/native-lib/fail/call_fn_ptr_with_generic.notrace.stderr created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(id::<i32>); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri stops tracking initialization and provenance for that memory | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has access to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = note: stack backtrace: | |
| 12 | 0: pass_fn_ptr | |
| 13 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 14 | 1: main | |
| 15 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 16 | ||
| 17 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 18 | --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 19 | | | |
| 20 | LL | call_fn_ptr(id::<i32>); | |
| 21 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 22 | | | |
| 23 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 24 | = note: stack backtrace: | |
| 25 | 0: pass_fn_ptr | |
| 26 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 27 | 1: main | |
| 28 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 29 | ||
| 30 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 31 |
src/tools/miri/tests/native-lib/fail/call_fn_ptr_with_generic.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | //@revisions: trace notrace | |
| 2 | //@[trace] only-target: x86_64-unknown-linux-gnu i686-unknown-linux-gnu | |
| 3 | //@[trace] compile-flags: -Zmiri-native-lib-enable-tracing | |
| 4 | //@compile-flags: -Zmiri-permissive-provenance | |
| 5 | ||
| 6 | fn main() { | |
| 7 | pass_fn_ptr() | |
| 8 | } | |
| 9 | ||
| 10 | fn pass_fn_ptr() { | |
| 11 | extern "C" { | |
| 12 | fn call_fn_ptr(s: extern "C" fn(i32) -> i32); | |
| 13 | } | |
| 14 | ||
| 15 | extern "C" fn id<T>(x: T) -> T { | |
| 16 | x | |
| 17 | } | |
| 18 | ||
| 19 | unsafe { | |
| 20 | call_fn_ptr(id::<i32>); //~ ERROR: unsupported operation: calling a function pointer through the FFI boundary | |
| 21 | } | |
| 22 | } |
src/tools/miri/tests/native-lib/fail/call_fn_ptr_with_generic.trace.stderr created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(id::<i32>); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri can only track initialisation and provenance on a best-effort basis | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has written to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = help: tracing memory accesses in native code is not yet fully implemented, so there can be further imprecisions beyond what is documented here | |
| 12 | = note: stack backtrace: | |
| 13 | 0: pass_fn_ptr | |
| 14 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 15 | 1: main | |
| 16 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 17 | ||
| 18 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 19 | --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 20 | | | |
| 21 | LL | call_fn_ptr(id::<i32>); | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 23 | | | |
| 24 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 25 | = note: stack backtrace: | |
| 26 | 0: pass_fn_ptr | |
| 27 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 28 | 1: main | |
| 29 | at tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC | |
| 30 | ||
| 31 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 32 |
src/tools/miri/tests/native-lib/fail/call_function_ptr.notrace.stderr deleted-31| ... | ... | @@ -1,31 +0,0 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(Some(nop)); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri stops tracking initialization and provenance for that memory | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has access to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = note: stack backtrace: | |
| 12 | 0: pass_fn_ptr | |
| 13 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 14 | 1: main | |
| 15 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 16 | ||
| 17 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 18 | --> tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 19 | | | |
| 20 | LL | call_fn_ptr(Some(nop)); | |
| 21 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 22 | | | |
| 23 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 24 | = note: stack backtrace: | |
| 25 | 0: pass_fn_ptr | |
| 26 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 27 | 1: main | |
| 28 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 29 | ||
| 30 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 31 |
src/tools/miri/tests/native-lib/fail/call_function_ptr.rs deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | //@revisions: trace notrace | |
| 2 | //@[trace] only-target: x86_64-unknown-linux-gnu i686-unknown-linux-gnu | |
| 3 | //@[trace] compile-flags: -Zmiri-native-lib-enable-tracing | |
| 4 | //@compile-flags: -Zmiri-permissive-provenance | |
| 5 | ||
| 6 | fn main() { | |
| 7 | pass_fn_ptr() | |
| 8 | } | |
| 9 | ||
| 10 | fn pass_fn_ptr() { | |
| 11 | extern "C" { | |
| 12 | fn call_fn_ptr(s: Option<extern "C" fn()>); | |
| 13 | } | |
| 14 | ||
| 15 | extern "C" fn nop() {} | |
| 16 | ||
| 17 | unsafe { | |
| 18 | call_fn_ptr(None); // this one is fine | |
| 19 | call_fn_ptr(Some(nop)); //~ ERROR: unsupported operation: calling a function pointer through the FFI boundary | |
| 20 | } | |
| 21 | } |
src/tools/miri/tests/native-lib/fail/call_function_ptr.trace.stderr deleted-32| ... | ... | @@ -1,32 +0,0 @@ |
| 1 | warning: sharing memory with a native function called via FFI | |
| 2 | --> tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 3 | | | |
| 4 | LL | call_fn_ptr(Some(nop)); | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^ sharing memory with a native function | |
| 6 | | | |
| 7 | = help: when memory is shared with a native function call, Miri can only track initialisation and provenance on a best-effort basis | |
| 8 | = help: in particular, Miri assumes that the native call initializes all memory it has written to | |
| 9 | = help: Miri also assumes that any part of this memory may be a pointer that is permitted to point to arbitrary exposed memory | |
| 10 | = help: what this means is that Miri will easily miss Undefined Behavior related to incorrect usage of this shared memory, so you should not take a clean Miri run as a signal that your FFI code is UB-free | |
| 11 | = help: tracing memory accesses in native code is not yet fully implemented, so there can be further imprecisions beyond what is documented here | |
| 12 | = note: stack backtrace: | |
| 13 | 0: pass_fn_ptr | |
| 14 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 15 | 1: main | |
| 16 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 17 | ||
| 18 | error: unsupported operation: calling a function pointer through the FFI boundary | |
| 19 | --> tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 20 | | | |
| 21 | LL | call_fn_ptr(Some(nop)); | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^ unsupported operation occurred here | |
| 23 | | | |
| 24 | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support | |
| 25 | = note: stack backtrace: | |
| 26 | 0: pass_fn_ptr | |
| 27 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 28 | 1: main | |
| 29 | at tests/native-lib/fail/call_function_ptr.rs:LL:CC | |
| 30 | ||
| 31 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 32 |
src/tools/miri/tests/native-lib/fn_ptr.c created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | #include <stddef.h> | |
| 2 | #include <stdint.h> | |
| 3 | ||
| 4 | // See comments in build_native_lib() | |
| 5 | #define EXPORT __attribute__((visibility("default"))) | |
| 6 | ||
| 7 | EXPORT void call_fn_ptr(void f(void)) { | |
| 8 | if (f != NULL) { | |
| 9 | f(); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | EXPORT void call_fn_ptr_with_arg(int32_t f(int32_t)) { | |
| 14 | if (f != NULL) { | |
| 15 | f(42); | |
| 16 | } | |
| 17 | } |
src/tools/miri/tests/native-lib/pass/ptr_read_access.rs-14| ... | ... | @@ -10,7 +10,6 @@ fn main() { |
| 10 | 10 | test_access_simple(); |
| 11 | 11 | test_access_nested(); |
| 12 | 12 | test_access_static(); |
| 13 | pass_fn_ptr(); | |
| 14 | 13 | } |
| 15 | 14 | |
| 16 | 15 | /// Test function that dereferences an int pointer and prints its contents from C. |
| ... | ... | @@ -82,16 +81,3 @@ fn test_access_static() { |
| 82 | 81 | |
| 83 | 82 | assert_eq!(unsafe { access_static(&STATIC) }, 9001); |
| 84 | 83 | } |
| 85 | ||
| 86 | fn pass_fn_ptr() { | |
| 87 | extern "C" { | |
| 88 | fn pass_fn_ptr(s: Option<extern "C" fn()>); | |
| 89 | } | |
| 90 | ||
| 91 | extern "C" fn nop() {} | |
| 92 | ||
| 93 | unsafe { | |
| 94 | pass_fn_ptr(None); // this one is fine | |
| 95 | pass_fn_ptr(Some(nop)); // this one is not | |
| 96 | } | |
| 97 | } |
src/tools/miri/tests/native-lib/ptr_read_access.c-13| ... | ... | @@ -62,16 +62,3 @@ EXPORT int32_t access_static(const Static *s_ptr) { |
| 62 | 62 | EXPORT uintptr_t do_one_deref(const int32_t ***ptr) { |
| 63 | 63 | return (uintptr_t)*ptr; |
| 64 | 64 | } |
| 65 | ||
| 66 | /* Test: pass_fn_ptr */ | |
| 67 | ||
| 68 | EXPORT void pass_fn_ptr(void f(void)) { | |
| 69 | (void)f; // suppress unused warning | |
| 70 | } | |
| 71 | ||
| 72 | /* Test: function_ptrs */ | |
| 73 | EXPORT void call_fn_ptr(void f(void)) { | |
| 74 | if (f != NULL) { | |
| 75 | f(); | |
| 76 | } | |
| 77 | } |
src/tools/miri/tests/pass-dep/libc/libc-pipe.rs+18| ... | ... | @@ -148,6 +148,24 @@ fn test_pipe_setfl_getfl() { |
| 148 | 148 | errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(), |
| 149 | 149 | libc::O_RDONLY |
| 150 | 150 | ); |
| 151 | ||
| 152 | // Test if ignored flags are indeed ignored. | |
| 153 | errno_check(unsafe { | |
| 154 | libc::fcntl( | |
| 155 | fds[0], | |
| 156 | libc::F_SETFL, | |
| 157 | libc::O_RDWR | |
| 158 | | libc::O_CREAT | |
| 159 | | libc::O_EXCL | |
| 160 | | libc::O_NOCTTY | |
| 161 | | libc::O_TRUNC | |
| 162 | | libc::O_NONBLOCK, | |
| 163 | ) | |
| 164 | }); | |
| 165 | assert_eq!( | |
| 166 | errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(), | |
| 167 | libc::O_NONBLOCK | libc::O_RDONLY | |
| 168 | ); | |
| 151 | 169 | } |
| 152 | 170 | |
| 153 | 171 | /// Test the behaviour of F_SETFL/F_GETFL when a fd is blocking. |
src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.rs created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | //@ignore-target: windows # No libc socket on Windows | |
| 2 | //@ignore-target: solaris # Socket is a macro for __xnet7_socket which has no shim | |
| 3 | //@ignore-target: illumos # Socket is a macro for __xnet7_socket which has no shim | |
| 4 | //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace | |
| 5 | ||
| 6 | use std::io::ErrorKind; | |
| 7 | ||
| 8 | #[path = "../../utils/libc.rs"] | |
| 9 | mod libc_utils; | |
| 10 | use libc_utils::*; | |
| 11 | ||
| 12 | fn main() { | |
| 13 | unsafe { | |
| 14 | let err = errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap_err(); | |
| 15 | assert_eq!(err.kind(), ErrorKind::PermissionDenied); | |
| 16 | // check that it is the right kind of `PermissionDenied` | |
| 17 | assert_eq!(err.raw_os_error(), Some(libc::EACCES)); | |
| 18 | } | |
| 19 | } |
src/tools/miri/tests/pass-dep/libc/libc-socket-with-isolation.stderr created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | warning: `socket` was made to return an error due to isolation | |
| 2 |
src/tools/miri/tests/pass-dep/libc/libc-socket.rs created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | //@ignore-target: windows # No libc socket on Windows | |
| 2 | //@ignore-target: solaris # Does socket is a macro for __xnet7_socket which has no shim | |
| 3 | //@ignore-target: illumos # Does socket is a macro for __xnet7_socket which has no shim | |
| 4 | //@compile-flags: -Zmiri-disable-isolation | |
| 5 | ||
| 6 | #[path = "../../utils/libc.rs"] | |
| 7 | mod libc_utils; | |
| 8 | use libc_utils::*; | |
| 9 | ||
| 10 | fn main() { | |
| 11 | test_socket_close(); | |
| 12 | } | |
| 13 | ||
| 14 | fn test_socket_close() { | |
| 15 | unsafe { | |
| 16 | let sockfd = errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap(); | |
| 17 | errno_check(libc::close(sockfd)); | |
| 18 | } | |
| 19 | } |
src/tools/miri/tests/pass/open_a_file_in_proc.rs created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | //@compile-flags: -Zmiri-disable-isolation | |
| 2 | //@only-target: linux android illumos | |
| 3 | //@ignore-host: windows | |
| 4 | ||
| 5 | fn main() { | |
| 6 | let _ = match std::fs::File::open("/proc/doesnotexist ") { | |
| 7 | Ok(_f) => {} | |
| 8 | Err(_msg) => {} | |
| 9 | }; | |
| 10 | (); | |
| 11 | } |
src/tools/miri/tests/pass/open_a_file_in_proc.stderr created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | warning: files in `/proc` can bypass the Abstract Machine and might not work properly in Miri | |
| 2 | --> RUSTLIB/std/src/sys/fs/PLATFORM.rs:LL:CC | |
| 3 | | | |
| 4 | LL | let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode as c_int) })?; | |
| 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ open a file in `/proc` | |
| 6 | | | |
| 7 | = note: stack backtrace: | |
| 8 | 0: std::sys::fs::PLATFORM::File::open_c::{closure#0} | |
| 9 | at RUSTLIB/std/src/sys/fs/PLATFORM.rs:LL:CC | |
| 10 | 1: std::sys::pal::PLATFORM::cvt_r | |
| 11 | at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC | |
| 12 | 2: std::sys::fs::PLATFORM::File::open_c | |
| 13 | at RUSTLIB/std/src/sys/fs/PLATFORM.rs:LL:CC | |
| 14 | 3: std::sys::fs::PLATFORM::File::open::{closure#0} | |
| 15 | at RUSTLIB/std/src/sys/fs/PLATFORM.rs:LL:CC | |
| 16 | 4: std::sys::helpers::small_c_string::run_with_cstr_stack | |
| 17 | at RUSTLIB/std/src/sys/helpers/small_c_string.rs:LL:CC | |
| 18 | 5: std::sys::helpers::small_c_string::run_with_cstr | |
| 19 | at RUSTLIB/std/src/sys/helpers/small_c_string.rs:LL:CC | |
| 20 | 6: std::sys::helpers::small_c_string::run_path_with_cstr | |
| 21 | at RUSTLIB/std/src/sys/helpers/small_c_string.rs:LL:CC | |
| 22 | 7: std::sys::fs::PLATFORM::File::open | |
| 23 | at RUSTLIB/std/src/sys/fs/PLATFORM.rs:LL:CC | |
| 24 | 8: std::fs::OpenOptions::_open | |
| 25 | at RUSTLIB/std/src/fs.rs:LL:CC | |
| 26 | 9: std::fs::OpenOptions::open | |
| 27 | at RUSTLIB/std/src/fs.rs:LL:CC | |
| 28 | 10: std::fs::File::open | |
| 29 | at RUSTLIB/std/src/fs.rs:LL:CC | |
| 30 | 11: main | |
| 31 | at tests/pass/open_a_file_in_proc.rs:LL:CC | |
| 32 |
src/tools/miri/tests/ui.rs+2-1| ... | ... | @@ -42,7 +42,7 @@ fn build_native_lib(target: &str) -> PathBuf { |
| 42 | 42 | std::fs::create_dir_all(&so_target_dir) |
| 43 | 43 | .expect("Failed to create directory for shared object file"); |
| 44 | 44 | // We use a platform-neutral file extension to avoid having to hard-code alternatives. |
| 45 | let native_lib_path = so_target_dir.join("native-lib.module"); | |
| 45 | let native_lib_path = so_target_dir.join("native-lib-tests.so"); | |
| 46 | 46 | let cc_output = Command::new(cc) |
| 47 | 47 | .args([ |
| 48 | 48 | "-shared", |
| ... | ... | @@ -58,6 +58,7 @@ fn build_native_lib(target: &str) -> PathBuf { |
| 58 | 58 | "tests/native-lib/aggregate_arguments.c", |
| 59 | 59 | "tests/native-lib/ptr_read_access.c", |
| 60 | 60 | "tests/native-lib/ptr_write_access.c", |
| 61 | "tests/native-lib/fn_ptr.c", | |
| 61 | 62 | // Ensure we notice serious problems in the C code. |
| 62 | 63 | "-Wall", |
| 63 | 64 | "-Wextra", |
src/tools/run-make-support/src/external_deps/rustc.rs+32-1| ... | ... | @@ -4,7 +4,7 @@ use std::str::FromStr as _; |
| 4 | 4 | |
| 5 | 5 | use crate::command::Command; |
| 6 | 6 | use crate::env::env_var; |
| 7 | use crate::path_helpers::cwd; | |
| 7 | use crate::path_helpers::{cwd, source_root}; | |
| 8 | 8 | use crate::util::set_host_compiler_dylib_path; |
| 9 | 9 | use crate::{is_aix, is_darwin, is_windows, is_windows_msvc, target, uname}; |
| 10 | 10 | |
| ... | ... | @@ -22,6 +22,37 @@ pub fn bare_rustc() -> Rustc { |
| 22 | 22 | Rustc::bare() |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | /// Construct a `rustc` invocation for building `minicore`. | |
| 26 | /// | |
| 27 | /// This function: | |
| 28 | /// | |
| 29 | /// - adds `tests/auxiliary/minicore.rs` as an input | |
| 30 | /// - sets the crate name to `"minicore"` | |
| 31 | /// - sets the crate type to `rlib` | |
| 32 | /// | |
| 33 | /// # Example | |
| 34 | /// | |
| 35 | /// ```ignore (illustrative) | |
| 36 | /// rustc_minicore().target("wasm32-wasip1").target_cpu("mvp").output("libminicore.rlib").run(); | |
| 37 | /// | |
| 38 | /// rustc() | |
| 39 | /// .input("foo.rs") | |
| 40 | /// .target("wasm32-wasip1") | |
| 41 | /// .target_cpu("mvp") | |
| 42 | /// .extern_("minicore", path("libminicore.rlib")) | |
| 43 | /// // ... | |
| 44 | /// .run() | |
| 45 | /// ``` | |
| 46 | #[track_caller] | |
| 47 | pub fn rustc_minicore() -> Rustc { | |
| 48 | let mut builder = rustc(); | |
| 49 | ||
| 50 | let minicore_path = source_root().join("tests/auxiliary/minicore.rs"); | |
| 51 | builder.input(minicore_path).crate_name("minicore").crate_type("rlib"); | |
| 52 | ||
| 53 | builder | |
| 54 | } | |
| 55 | ||
| 25 | 56 | /// A `rustc` invocation builder. |
| 26 | 57 | #[derive(Debug)] |
| 27 | 58 | #[must_use] |
src/tools/run-make-support/src/lib.rs+1-1| ... | ... | @@ -72,7 +72,7 @@ pub use crate::external_deps::llvm::{ |
| 72 | 72 | llvm_readobj, |
| 73 | 73 | }; |
| 74 | 74 | pub use crate::external_deps::python::python_command; |
| 75 | pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_path}; | |
| 75 | pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path}; | |
| 76 | 76 | pub use crate::external_deps::rustdoc::{Rustdoc, bare_rustdoc, rustdoc}; |
| 77 | 77 | // Path-related helpers. |
| 78 | 78 | pub use crate::path_helpers::{ |
src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs+1-1| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | feature = "sysroot-abi", |
| 11 | 11 | feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span) |
| 12 | 12 | )] |
| 13 | #![allow(internal_features)] | |
| 13 | #![allow(internal_features, unused_features)] | |
| 14 | 14 | #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] |
| 15 | 15 | |
| 16 | 16 | #[cfg(feature = "in-rust-tree")] |
src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs+2-1| ... | ... | @@ -18,7 +18,8 @@ |
| 18 | 18 | internal_features, |
| 19 | 19 | clippy::disallowed_types, |
| 20 | 20 | clippy::print_stderr, |
| 21 | unused_crate_dependencies | |
| 21 | unused_crate_dependencies, | |
| 22 | unused_features | |
| 22 | 23 | )] |
| 23 | 24 | #![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)] |
| 24 | 25 |
src/tools/test-float-parse/src/lib.rs+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | #![feature(f16)] | |
| 2 | 1 | #![feature(cfg_target_has_reliable_f16_f128)] |
| 2 | #![cfg_attr(target_has_reliable_f16, feature(f16))] | |
| 3 | 3 | #![expect(internal_features)] // reliable_f16_f128 |
| 4 | 4 | |
| 5 | 5 | mod traits; |
tests/auxiliary/minicore.rs+11| ... | ... | @@ -288,6 +288,17 @@ pub mod mem { |
| 288 | 288 | pub const fn align_of<T>() -> usize; |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | pub mod ptr { | |
| 292 | #[inline] | |
| 293 | #[rustc_diagnostic_item = "ptr_write_volatile"] | |
| 294 | pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { | |
| 295 | #[rustc_intrinsic] | |
| 296 | pub unsafe fn volatile_store<T>(dst: *mut T, val: T); | |
| 297 | ||
| 298 | unsafe { volatile_store(dst, src) }; | |
| 299 | } | |
| 300 | } | |
| 301 | ||
| 291 | 302 | #[lang = "c_void"] |
| 292 | 303 | #[repr(u8)] |
| 293 | 304 | pub enum c_void { |
tests/incremental/add_private_fn_at_krate_root_cc/struct_point.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | //@ ignore-backends: gcc |
| 10 | 10 | |
| 11 | 11 | #![feature(rustc_attrs)] |
| 12 | #![feature(stmt_expr_attributes)] | |
| 13 | 12 | #![allow(dead_code)] |
| 14 | 13 | #![crate_type = "rlib"] |
| 15 | 14 |
tests/incremental/change_add_field/struct_point.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | //@ ignore-backends: gcc |
| 10 | 10 | |
| 11 | 11 | #![feature(rustc_attrs)] |
| 12 | #![feature(stmt_expr_attributes)] | |
| 13 | 12 | #![allow(dead_code)] |
| 14 | 13 | #![crate_type = "rlib"] |
| 15 | 14 |
tests/incremental/change_crate_dep_kind.rs+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | //@ build-pass (FIXME(62277): could be check-pass?) |
| 9 | 9 | //@ ignore-backends: gcc |
| 10 | 10 | |
| 11 | #![feature(panic_unwind)] | |
| 11 | #![cfg_attr(cfail1, feature(panic_unwind))] | |
| 12 | 12 | |
| 13 | 13 | // Turn the panic_unwind crate from an explicit into an implicit query: |
| 14 | 14 | #[cfg(cfail1)] |
tests/incremental/change_private_fn/struct_point.rs-1| ... | ... | @@ -7,7 +7,6 @@ |
| 7 | 7 | //@ ignore-backends: gcc |
| 8 | 8 | |
| 9 | 9 | #![feature(rustc_attrs)] |
| 10 | #![feature(stmt_expr_attributes)] | |
| 11 | 10 | #![allow(dead_code)] |
| 12 | 11 | #![crate_type = "rlib"] |
| 13 | 12 |
tests/incremental/change_private_fn_cc/struct_point.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | |
| 10 | 10 | #![crate_type = "rlib"] |
| 11 | 11 | #![feature(rustc_attrs)] |
| 12 | #![feature(stmt_expr_attributes)] | |
| 13 | 12 | #![allow(dead_code)] |
| 14 | 13 | |
| 15 | 14 | #![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")] |
tests/incremental/change_private_impl_method/struct_point.rs-1| ... | ... | @@ -7,7 +7,6 @@ |
| 7 | 7 | //@ ignore-backends: gcc |
| 8 | 8 | |
| 9 | 9 | #![feature(rustc_attrs)] |
| 10 | #![feature(stmt_expr_attributes)] | |
| 11 | 10 | #![allow(dead_code)] |
| 12 | 11 | #![crate_type = "rlib"] |
| 13 | 12 |
tests/incremental/change_private_impl_method_cc/struct_point.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | |
| 10 | 10 | #![crate_type = "rlib"] |
| 11 | 11 | #![feature(rustc_attrs)] |
| 12 | #![feature(stmt_expr_attributes)] | |
| 13 | 12 | #![allow(dead_code)] |
| 14 | 13 | |
| 15 | 14 | #![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")] |
tests/incremental/change_pub_inherent_method_body/struct_point.rs-1| ... | ... | @@ -7,7 +7,6 @@ |
| 7 | 7 | |
| 8 | 8 | #![crate_type = "rlib"] |
| 9 | 9 | #![feature(rustc_attrs)] |
| 10 | #![feature(stmt_expr_attributes)] | |
| 11 | 10 | #![allow(dead_code)] |
| 12 | 11 | |
| 13 | 12 | #![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")] |
tests/incremental/change_pub_inherent_method_sig/struct_point.rs-1| ... | ... | @@ -7,7 +7,6 @@ |
| 7 | 7 | |
| 8 | 8 | #![crate_type = "rlib"] |
| 9 | 9 | #![feature(rustc_attrs)] |
| 10 | #![feature(stmt_expr_attributes)] | |
| 11 | 10 | #![allow(dead_code)] |
| 12 | 11 | |
| 13 | 12 | // These are expected to require codegen. |
tests/incremental/lint-unused-features.rs created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | //@ revisions: rpass cfail | |
| 2 | //@ ignore-backends: gcc | |
| 3 | ||
| 4 | #![deny(unused_features)] | |
| 5 | ||
| 6 | // Used language features | |
| 7 | #![feature(box_patterns)] | |
| 8 | #![feature(decl_macro)] | |
| 9 | #![cfg_attr(all(), feature(rustc_attrs))] | |
| 10 | ||
| 11 | // Used library features | |
| 12 | #![feature(error_iter)] | |
| 13 | //[cfail]~^ ERROR feature `error_iter` is declared but not used | |
| 14 | #![cfg_attr(all(), feature(allocator_api))] | |
| 15 | //[cfail]~^ ERROR feature `allocator_api` is declared but not used | |
| 16 | ||
| 17 | pub fn use_box_patterns(b: Box<i32>) -> i32 { | |
| 18 | let box x = b; | |
| 19 | x | |
| 20 | } | |
| 21 | ||
| 22 | macro m() {} | |
| 23 | pub fn use_decl_macro() { | |
| 24 | m!(); | |
| 25 | } | |
| 26 | ||
| 27 | #[rustc_dummy] | |
| 28 | pub fn use_rustc_attrs() {} | |
| 29 | ||
| 30 | #[cfg(rpass)] | |
| 31 | pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) { | |
| 32 | for _ in e.sources() {} | |
| 33 | } | |
| 34 | ||
| 35 | #[cfg(rpass)] | |
| 36 | pub fn use_allocator_api() { | |
| 37 | use std::alloc::Global; | |
| 38 | let _ = Vec::<i32>::new_in(Global); | |
| 39 | } | |
| 40 | ||
| 41 | fn main() {} |
tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs+2-30| ... | ... | @@ -7,7 +7,8 @@ |
| 7 | 7 | #![no_main] |
| 8 | 8 | #![allow(internal_features)] |
| 9 | 9 | |
| 10 | use minicore::ptr; | |
| 10 | extern crate minicore; | |
| 11 | use minicore::*; | |
| 11 | 12 | |
| 12 | 13 | #[no_mangle] |
| 13 | 14 | pub fn main() -> ! { |
| ... | ... | @@ -21,32 +22,3 @@ pub fn main() -> ! { |
| 21 | 22 | unsafe { ptr::write_volatile(port_b, 2) }; |
| 22 | 23 | } |
| 23 | 24 | } |
| 24 | ||
| 25 | // FIXME: replace with proper minicore once available (#130693) | |
| 26 | mod minicore { | |
| 27 | #[lang = "pointee_sized"] | |
| 28 | pub trait PointeeSized {} | |
| 29 | ||
| 30 | #[lang = "meta_sized"] | |
| 31 | pub trait MetaSized: PointeeSized {} | |
| 32 | ||
| 33 | #[lang = "sized"] | |
| 34 | pub trait Sized: MetaSized {} | |
| 35 | ||
| 36 | #[lang = "copy"] | |
| 37 | pub trait Copy {} | |
| 38 | impl Copy for u32 {} | |
| 39 | impl Copy for &u32 {} | |
| 40 | impl<T: PointeeSized> Copy for *mut T {} | |
| 41 | ||
| 42 | pub mod ptr { | |
| 43 | #[inline] | |
| 44 | #[rustc_diagnostic_item = "ptr_write_volatile"] | |
| 45 | pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { | |
| 46 | #[rustc_intrinsic] | |
| 47 | pub unsafe fn volatile_store<T>(dst: *mut T, val: T); | |
| 48 | ||
| 49 | unsafe { volatile_store(dst, src) }; | |
| 50 | } | |
| 51 | } | |
| 52 | } |
tests/run-make/avr-rjmp-offset/rmake.rs+4-1| ... | ... | @@ -15,9 +15,11 @@ |
| 15 | 15 | // crashes... so I'm going to disable this test for windows for now. |
| 16 | 16 | //@ ignore-windows-gnu |
| 17 | 17 | |
| 18 | use run_make_support::{llvm_objdump, rustc}; | |
| 18 | use run_make_support::{llvm_objdump, path, rustc, rustc_minicore}; | |
| 19 | 19 | |
| 20 | 20 | fn main() { |
| 21 | rustc_minicore().target("avr-none").target_cpu("avr").output("libminicore.rlib").run(); | |
| 22 | ||
| 21 | 23 | rustc() |
| 22 | 24 | .input("avr-rjmp-offsets.rs") |
| 23 | 25 | .opt_level("s") |
| ... | ... | @@ -36,6 +38,7 @@ fn main() { |
| 36 | 38 | .linker("rust-lld") |
| 37 | 39 | .link_arg("--entry=main") |
| 38 | 40 | .output("compiled") |
| 41 | .extern_("minicore", path("libminicore.rlib")) | |
| 39 | 42 | .run(); |
| 40 | 43 | |
| 41 | 44 | let disassembly = llvm_objdump().disassemble().input("compiled").run().stdout_utf8(); |
tests/run-make/thumb-interworking/rmake.rs+5-11| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | //@ needs-llvm-components: arm |
| 2 | 2 | //@ needs-rust-lld |
| 3 | use run_make_support::{llvm_filecheck, llvm_objdump, path, rfs, run, rustc, source_root}; | |
| 3 | use run_make_support::{ | |
| 4 | llvm_filecheck, llvm_objdump, path, rfs, run, rustc, rustc_minicore, source_root, | |
| 5 | }; | |
| 4 | 6 | |
| 5 | 7 | // Test a thumb target calling arm functions. Doing so requires switching from thumb mode to arm |
| 6 | 8 | // mode, calling the arm code, then switching back to thumb mode. Depending on the thumb version, |
| ... | ... | @@ -25,21 +27,13 @@ fn main() { |
| 25 | 27 | } |
| 26 | 28 | |
| 27 | 29 | fn helper(prefix: &str, target: &str) { |
| 28 | rustc() | |
| 29 | .input(source_root().join("tests/auxiliary/minicore.rs")) | |
| 30 | .crate_name("minicore") | |
| 31 | .crate_type("rlib") | |
| 32 | .target(target) | |
| 33 | .output("libminicore.rlib") | |
| 34 | .run(); | |
| 35 | let minicore = path("libminicore.rlib"); | |
| 30 | rustc_minicore().target(target).output("libminicore.rlib").run(); | |
| 36 | 31 | |
| 37 | 32 | rustc() |
| 38 | 33 | .input("main.rs") |
| 39 | 34 | .panic("abort") |
| 40 | 35 | .link_arg("-Tlink.ld") |
| 41 | .arg("--extern") | |
| 42 | .arg(format!("minicore={}", minicore.display())) | |
| 36 | .extern_("minicore", path("libminicore.rlib")) | |
| 43 | 37 | .target(target) |
| 44 | 38 | .output(prefix) |
| 45 | 39 | .run(); |
tests/run-make/wasm-unexpected-features/foo.rs+3-18| ... | ... | @@ -4,6 +4,9 @@ |
| 4 | 4 | #![needs_allocator] |
| 5 | 5 | #![allow(internal_features)] |
| 6 | 6 | |
| 7 | extern crate minicore; | |
| 8 | use minicore::*; | |
| 9 | ||
| 7 | 10 | #[rustc_std_internal_symbol] |
| 8 | 11 | unsafe fn __rust_alloc(_size: usize, _align: usize) -> *mut u8 { |
| 9 | 12 | 0 as *mut u8 |
| ... | ... | @@ -23,21 +26,3 @@ extern "C" fn init() { |
| 23 | 26 | __rust_alloc_error_handler(0, 0); |
| 24 | 27 | } |
| 25 | 28 | } |
| 26 | ||
| 27 | mod minicore { | |
| 28 | #[lang = "pointee_sized"] | |
| 29 | pub trait PointeeSized {} | |
| 30 | ||
| 31 | #[lang = "meta_sized"] | |
| 32 | pub trait MetaSized: PointeeSized {} | |
| 33 | ||
| 34 | #[lang = "sized"] | |
| 35 | pub trait Sized: MetaSized {} | |
| 36 | ||
| 37 | #[lang = "copy"] | |
| 38 | pub trait Copy {} | |
| 39 | impl Copy for u8 {} | |
| 40 | ||
| 41 | #[lang = "drop_in_place"] | |
| 42 | fn drop_in_place<T>(_: *mut T) {} | |
| 43 | } |
tests/run-make/wasm-unexpected-features/rmake.rs+5-3| ... | ... | @@ -1,10 +1,11 @@ |
| 1 | //@ only-wasm32-wasip1 | |
| 2 | ||
| 1 | //@ needs-rust-lld | |
| 3 | 2 | use std::path::Path; |
| 4 | 3 | |
| 5 | use run_make_support::{rfs, rustc, wasmparser}; | |
| 4 | use run_make_support::{path, rfs, rustc, rustc_minicore, wasmparser}; | |
| 6 | 5 | |
| 7 | 6 | fn main() { |
| 7 | rustc_minicore().target("wasm32-wasip1").target_cpu("mvp").output("libminicore.rlib").run(); | |
| 8 | ||
| 8 | 9 | rustc() |
| 9 | 10 | .input("foo.rs") |
| 10 | 11 | .target("wasm32-wasip1") |
| ... | ... | @@ -13,6 +14,7 @@ fn main() { |
| 13 | 14 | .lto("fat") |
| 14 | 15 | .linker_plugin_lto("on") |
| 15 | 16 | .link_arg("--import-memory") |
| 17 | .extern_("minicore", path("libminicore.rlib")) | |
| 16 | 18 | .run(); |
| 17 | 19 | verify_features(Path::new("foo.wasm")); |
| 18 | 20 | } |
tests/ui-fulldeps/rustc_public/check_abi.rs-1| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | //@ ignore-remote |
| 7 | 7 | |
| 8 | 8 | #![feature(rustc_private)] |
| 9 | #![feature(ascii_char, ascii_char_variants)] | |
| 10 | 9 | |
| 11 | 10 | extern crate rustc_driver; |
| 12 | 11 | extern crate rustc_hir; |
tests/ui-fulldeps/rustc_public/check_transform.rs-1| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | //@ ignore-remote |
| 7 | 7 | |
| 8 | 8 | #![feature(rustc_private)] |
| 9 | #![feature(ascii_char, ascii_char_variants)] | |
| 10 | 9 | |
| 11 | 10 | extern crate rustc_hir; |
| 12 | 11 | extern crate rustc_middle; |
tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs+1-28| ... | ... | @@ -20,7 +20,7 @@ use rustc_span::symbol::Ident; |
| 20 | 20 | use rustc_span::Span; |
| 21 | 21 | |
| 22 | 22 | extern crate rustc_macros; |
| 23 | use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; | |
| 23 | use rustc_macros::{Diagnostic, Subdiagnostic}; | |
| 24 | 24 | |
| 25 | 25 | extern crate rustc_middle; |
| 26 | 26 | use rustc_middle::ty::Ty; |
| ... | ... | @@ -495,18 +495,6 @@ struct LabelWithTrailingList { |
| 495 | 495 | span: Span, |
| 496 | 496 | } |
| 497 | 497 | |
| 498 | #[derive(LintDiagnostic)] | |
| 499 | #[diag("this is an example message")] | |
| 500 | struct LintsGood {} | |
| 501 | ||
| 502 | #[derive(LintDiagnostic)] | |
| 503 | #[diag("this is an example message")] | |
| 504 | struct PrimarySpanOnLint { | |
| 505 | #[primary_span] | |
| 506 | //~^ ERROR `#[primary_span]` is not a valid attribute | |
| 507 | span: Span, | |
| 508 | } | |
| 509 | ||
| 510 | 498 | #[derive(Diagnostic)] |
| 511 | 499 | #[diag("this is an example message", code = E0123)] |
| 512 | 500 | struct ErrorWithMultiSpan { |
| ... | ... | @@ -542,13 +530,6 @@ struct WarnAttribute {} |
| 542 | 530 | //~| ERROR cannot find attribute `lint` in this scope |
| 543 | 531 | struct LintAttributeOnSessionDiag {} |
| 544 | 532 | |
| 545 | #[derive(LintDiagnostic)] | |
| 546 | #[lint("this is an example message", code = E0123)] | |
| 547 | //~^ ERROR `#[lint(...)]` is not a valid attribute | |
| 548 | //~| ERROR diagnostic message not specified | |
| 549 | //~| ERROR cannot find attribute `lint` in this scope | |
| 550 | struct LintAttributeOnLintDiag {} | |
| 551 | ||
| 552 | 533 | #[derive(Diagnostic)] |
| 553 | 534 | #[diag("this is an example message", code = E0123)] |
| 554 | 535 | struct DuplicatedSuggestionCode { |
| ... | ... | @@ -670,14 +651,6 @@ struct SubdiagnosticBadLitStr { |
| 670 | 651 | note: Note, |
| 671 | 652 | } |
| 672 | 653 | |
| 673 | #[derive(LintDiagnostic)] | |
| 674 | #[diag("this is an example message")] | |
| 675 | struct SubdiagnosticEagerLint { | |
| 676 | #[subdiagnostic(eager)] | |
| 677 | //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute | |
| 678 | note: Note, | |
| 679 | } | |
| 680 | ||
| 681 | 654 | #[derive(Diagnostic)] |
| 682 | 655 | #[diag("this is an example message")] |
| 683 | 656 | struct SubdiagnosticEagerFormerlyCorrect { |
tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr+35-75| ... | ... | @@ -300,22 +300,14 @@ error: derive(Diagnostic): no nested attribute expected here |
| 300 | 300 | LL | #[label("with a label", foo("..."))] |
| 301 | 301 | | ^^^ |
| 302 | 302 | |
| 303 | error: derive(Diagnostic): `#[primary_span]` is not a valid attribute | |
| 304 | --> $DIR/diagnostic-derive-inline.rs:505:5 | |
| 305 | | | |
| 306 | LL | #[primary_span] | |
| 307 | | ^ | |
| 308 | | | |
| 309 | = help: the `primary_span` field attribute is not valid for lint diagnostics | |
| 310 | ||
| 311 | 303 | error: derive(Diagnostic): `#[error(...)]` is not a valid attribute |
| 312 | --> $DIR/diagnostic-derive-inline.rs:525:1 | |
| 304 | --> $DIR/diagnostic-derive-inline.rs:513:1 | |
| 313 | 305 | | |
| 314 | 306 | LL | #[error("this is an example message", code = E0123)] |
| 315 | 307 | | ^ |
| 316 | 308 | |
| 317 | 309 | error: derive(Diagnostic): diagnostic message not specified |
| 318 | --> $DIR/diagnostic-derive-inline.rs:525:1 | |
| 310 | --> $DIR/diagnostic-derive-inline.rs:513:1 | |
| 319 | 311 | | |
| 320 | 312 | LL | #[error("this is an example message", code = E0123)] |
| 321 | 313 | | ^ |
| ... | ... | @@ -323,13 +315,13 @@ LL | #[error("this is an example message", code = E0123)] |
| 323 | 315 | = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` |
| 324 | 316 | |
| 325 | 317 | error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute |
| 326 | --> $DIR/diagnostic-derive-inline.rs:532:1 | |
| 318 | --> $DIR/diagnostic-derive-inline.rs:520:1 | |
| 327 | 319 | | |
| 328 | 320 | LL | #[warn_("this is an example message", code = E0123)] |
| 329 | 321 | | ^ |
| 330 | 322 | |
| 331 | 323 | error: derive(Diagnostic): diagnostic message not specified |
| 332 | --> $DIR/diagnostic-derive-inline.rs:532:1 | |
| 324 | --> $DIR/diagnostic-derive-inline.rs:520:1 | |
| 333 | 325 | | |
| 334 | 326 | LL | #[warn_("this is an example message", code = E0123)] |
| 335 | 327 | | ^ |
| ... | ... | @@ -337,27 +329,13 @@ LL | #[warn_("this is an example message", code = E0123)] |
| 337 | 329 | = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` |
| 338 | 330 | |
| 339 | 331 | error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute |
| 340 | --> $DIR/diagnostic-derive-inline.rs:539:1 | |
| 341 | | | |
| 342 | LL | #[lint("this is an example message", code = E0123)] | |
| 343 | | ^ | |
| 344 | ||
| 345 | error: derive(Diagnostic): diagnostic message not specified | |
| 346 | --> $DIR/diagnostic-derive-inline.rs:539:1 | |
| 347 | | | |
| 348 | LL | #[lint("this is an example message", code = E0123)] | |
| 349 | | ^ | |
| 350 | | | |
| 351 | = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` | |
| 352 | ||
| 353 | error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute | |
| 354 | --> $DIR/diagnostic-derive-inline.rs:546:1 | |
| 332 | --> $DIR/diagnostic-derive-inline.rs:527:1 | |
| 355 | 333 | | |
| 356 | 334 | LL | #[lint("this is an example message", code = E0123)] |
| 357 | 335 | | ^ |
| 358 | 336 | |
| 359 | 337 | error: derive(Diagnostic): diagnostic message not specified |
| 360 | --> $DIR/diagnostic-derive-inline.rs:546:1 | |
| 338 | --> $DIR/diagnostic-derive-inline.rs:527:1 | |
| 361 | 339 | | |
| 362 | 340 | LL | #[lint("this is an example message", code = E0123)] |
| 363 | 341 | | ^ |
| ... | ... | @@ -365,19 +343,19 @@ LL | #[lint("this is an example message", code = E0123)] |
| 365 | 343 | = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` |
| 366 | 344 | |
| 367 | 345 | error: derive(Diagnostic): attribute specified multiple times |
| 368 | --> $DIR/diagnostic-derive-inline.rs:555:53 | |
| 346 | --> $DIR/diagnostic-derive-inline.rs:536:53 | |
| 369 | 347 | | |
| 370 | 348 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] |
| 371 | 349 | | ^^^^ |
| 372 | 350 | | |
| 373 | 351 | note: previously specified here |
| 374 | --> $DIR/diagnostic-derive-inline.rs:555:39 | |
| 352 | --> $DIR/diagnostic-derive-inline.rs:536:39 | |
| 375 | 353 | | |
| 376 | 354 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] |
| 377 | 355 | | ^^^^ |
| 378 | 356 | |
| 379 | 357 | error: derive(Diagnostic): wrong types for suggestion |
| 380 | --> $DIR/diagnostic-derive-inline.rs:564:24 | |
| 358 | --> $DIR/diagnostic-derive-inline.rs:545:24 | |
| 381 | 359 | | |
| 382 | 360 | LL | suggestion: (Span, usize), |
| 383 | 361 | | ^^^^^ |
| ... | ... | @@ -385,7 +363,7 @@ LL | suggestion: (Span, usize), |
| 385 | 363 | = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` |
| 386 | 364 | |
| 387 | 365 | error: derive(Diagnostic): wrong types for suggestion |
| 388 | --> $DIR/diagnostic-derive-inline.rs:572:17 | |
| 366 | --> $DIR/diagnostic-derive-inline.rs:553:17 | |
| 389 | 367 | | |
| 390 | 368 | LL | suggestion: (Span,), |
| 391 | 369 | | ^^^^^^^ |
| ... | ... | @@ -393,13 +371,13 @@ LL | suggestion: (Span,), |
| 393 | 371 | = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` |
| 394 | 372 | |
| 395 | 373 | error: derive(Diagnostic): suggestion without `code = "..."` |
| 396 | --> $DIR/diagnostic-derive-inline.rs:579:5 | |
| 374 | --> $DIR/diagnostic-derive-inline.rs:560:5 | |
| 397 | 375 | | |
| 398 | 376 | LL | #[suggestion("with a suggestion")] |
| 399 | 377 | | ^ |
| 400 | 378 | |
| 401 | 379 | error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute |
| 402 | --> $DIR/diagnostic-derive-inline.rs:586:1 | |
| 380 | --> $DIR/diagnostic-derive-inline.rs:567:1 | |
| 403 | 381 | | |
| 404 | 382 | LL | #[multipart_suggestion("with a suggestion")] |
| 405 | 383 | | ^ |
| ... | ... | @@ -407,7 +385,7 @@ LL | #[multipart_suggestion("with a suggestion")] |
| 407 | 385 | = help: consider creating a `Subdiagnostic` instead |
| 408 | 386 | |
| 409 | 387 | error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute |
| 410 | --> $DIR/diagnostic-derive-inline.rs:589:1 | |
| 388 | --> $DIR/diagnostic-derive-inline.rs:570:1 | |
| 411 | 389 | | |
| 412 | 390 | LL | #[multipart_suggestion()] |
| 413 | 391 | | ^ |
| ... | ... | @@ -415,7 +393,7 @@ LL | #[multipart_suggestion()] |
| 415 | 393 | = help: consider creating a `Subdiagnostic` instead |
| 416 | 394 | |
| 417 | 395 | error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute |
| 418 | --> $DIR/diagnostic-derive-inline.rs:593:5 | |
| 396 | --> $DIR/diagnostic-derive-inline.rs:574:5 | |
| 419 | 397 | | |
| 420 | 398 | LL | #[multipart_suggestion("with a suggestion")] |
| 421 | 399 | | ^ |
| ... | ... | @@ -423,7 +401,7 @@ LL | #[multipart_suggestion("with a suggestion")] |
| 423 | 401 | = help: consider creating a `Subdiagnostic` instead |
| 424 | 402 | |
| 425 | 403 | error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute |
| 426 | --> $DIR/diagnostic-derive-inline.rs:601:1 | |
| 404 | --> $DIR/diagnostic-derive-inline.rs:582:1 | |
| 427 | 405 | | |
| 428 | 406 | LL | #[suggestion("with a suggestion", code = "...")] |
| 429 | 407 | | ^ |
| ... | ... | @@ -431,7 +409,7 @@ LL | #[suggestion("with a suggestion", code = "...")] |
| 431 | 409 | = help: `#[label]` and `#[suggestion]` can only be applied to fields |
| 432 | 410 | |
| 433 | 411 | error: derive(Diagnostic): `#[label]` is not a valid attribute |
| 434 | --> $DIR/diagnostic-derive-inline.rs:610:1 | |
| 412 | --> $DIR/diagnostic-derive-inline.rs:591:1 | |
| 435 | 413 | | |
| 436 | 414 | LL | #[label] |
| 437 | 415 | | ^ |
| ... | ... | @@ -439,73 +417,67 @@ LL | #[label] |
| 439 | 417 | = help: subdiagnostic message is missing |
| 440 | 418 | |
| 441 | 419 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute |
| 442 | --> $DIR/diagnostic-derive-inline.rs:644:5 | |
| 420 | --> $DIR/diagnostic-derive-inline.rs:625:5 | |
| 443 | 421 | | |
| 444 | 422 | LL | #[subdiagnostic(bad)] |
| 445 | 423 | | ^ |
| 446 | 424 | |
| 447 | 425 | error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute |
| 448 | --> $DIR/diagnostic-derive-inline.rs:652:5 | |
| 426 | --> $DIR/diagnostic-derive-inline.rs:633:5 | |
| 449 | 427 | | |
| 450 | 428 | LL | #[subdiagnostic = "bad"] |
| 451 | 429 | | ^ |
| 452 | 430 | |
| 453 | 431 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute |
| 454 | --> $DIR/diagnostic-derive-inline.rs:660:5 | |
| 432 | --> $DIR/diagnostic-derive-inline.rs:641:5 | |
| 455 | 433 | | |
| 456 | 434 | LL | #[subdiagnostic(bad, bad)] |
| 457 | 435 | | ^ |
| 458 | 436 | |
| 459 | 437 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute |
| 460 | --> $DIR/diagnostic-derive-inline.rs:668:5 | |
| 438 | --> $DIR/diagnostic-derive-inline.rs:649:5 | |
| 461 | 439 | | |
| 462 | 440 | LL | #[subdiagnostic("bad")] |
| 463 | 441 | | ^ |
| 464 | 442 | |
| 465 | 443 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute |
| 466 | --> $DIR/diagnostic-derive-inline.rs:676:5 | |
| 444 | --> $DIR/diagnostic-derive-inline.rs:657:5 | |
| 467 | 445 | | |
| 468 | 446 | LL | #[subdiagnostic(eager)] |
| 469 | 447 | | ^ |
| 470 | 448 | |
| 471 | 449 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute |
| 472 | --> $DIR/diagnostic-derive-inline.rs:684:5 | |
| 473 | | | |
| 474 | LL | #[subdiagnostic(eager)] | |
| 475 | | ^ | |
| 476 | ||
| 477 | error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute | |
| 478 | --> $DIR/diagnostic-derive-inline.rs:705:5 | |
| 450 | --> $DIR/diagnostic-derive-inline.rs:678:5 | |
| 479 | 451 | | |
| 480 | 452 | LL | #[subdiagnostic(eager)] |
| 481 | 453 | | ^ |
| 482 | 454 | |
| 483 | 455 | error: derive(Diagnostic): expected at least one string literal for `code(...)` |
| 484 | --> $DIR/diagnostic-derive-inline.rs:736:44 | |
| 456 | --> $DIR/diagnostic-derive-inline.rs:709:44 | |
| 485 | 457 | | |
| 486 | 458 | LL | #[suggestion("with a suggestion", code())] |
| 487 | 459 | | ^ |
| 488 | 460 | |
| 489 | 461 | error: derive(Diagnostic): `code(...)` must contain only string literals |
| 490 | --> $DIR/diagnostic-derive-inline.rs:744:44 | |
| 462 | --> $DIR/diagnostic-derive-inline.rs:717:44 | |
| 491 | 463 | | |
| 492 | 464 | LL | #[suggestion("with a suggestion", code(foo))] |
| 493 | 465 | | ^^^ |
| 494 | 466 | |
| 495 | 467 | error: unexpected token, expected `)` |
| 496 | --> $DIR/diagnostic-derive-inline.rs:744:44 | |
| 468 | --> $DIR/diagnostic-derive-inline.rs:717:44 | |
| 497 | 469 | | |
| 498 | 470 | LL | #[suggestion("with a suggestion", code(foo))] |
| 499 | 471 | | ^^^ |
| 500 | 472 | |
| 501 | 473 | error: expected string literal |
| 502 | --> $DIR/diagnostic-derive-inline.rs:753:46 | |
| 474 | --> $DIR/diagnostic-derive-inline.rs:726:46 | |
| 503 | 475 | | |
| 504 | 476 | LL | #[suggestion("with a suggestion", code = 3)] |
| 505 | 477 | | ^ |
| 506 | 478 | |
| 507 | 479 | error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute |
| 508 | --> $DIR/diagnostic-derive-inline.rs:768:5 | |
| 480 | --> $DIR/diagnostic-derive-inline.rs:741:5 | |
| 509 | 481 | | |
| 510 | 482 | LL | #[suggestion("with a suggestion", code = "")] |
| 511 | 483 | | ^ |
| ... | ... | @@ -515,7 +487,7 @@ LL | #[suggestion("with a suggestion", code = "")] |
| 515 | 487 | = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` |
| 516 | 488 | |
| 517 | 489 | error: derive(Diagnostic): Variable `nosub` not found in diagnostic |
| 518 | --> $DIR/diagnostic-derive-inline.rs:780:8 | |
| 490 | --> $DIR/diagnostic-derive-inline.rs:753:8 | |
| 519 | 491 | | |
| 520 | 492 | LL | #[diag("does not exist: {$nosub}")] |
| 521 | 493 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -535,7 +507,7 @@ LL | #[nonsense] |
| 535 | 507 | | ^^^^^^^^ |
| 536 | 508 | |
| 537 | 509 | error: cannot find attribute `error` in this scope |
| 538 | --> $DIR/diagnostic-derive-inline.rs:525:3 | |
| 510 | --> $DIR/diagnostic-derive-inline.rs:513:3 | |
| 539 | 511 | | |
| 540 | 512 | LL | #[error("this is an example message", code = E0123)] |
| 541 | 513 | | ^^^^^ |
| ... | ... | @@ -547,7 +519,7 @@ LL | struct ErrorAttribute {} |
| 547 | 519 | | |
| 548 | 520 | |
| 549 | 521 | error: cannot find attribute `warn_` in this scope |
| 550 | --> $DIR/diagnostic-derive-inline.rs:532:3 | |
| 522 | --> $DIR/diagnostic-derive-inline.rs:520:3 | |
| 551 | 523 | | |
| 552 | 524 | LL | #[warn_("this is an example message", code = E0123)] |
| 553 | 525 | | ^^^^^ |
| ... | ... | @@ -559,19 +531,7 @@ LL + #[warn("this is an example message", code = E0123)] |
| 559 | 531 | | |
| 560 | 532 | |
| 561 | 533 | error: cannot find attribute `lint` in this scope |
| 562 | --> $DIR/diagnostic-derive-inline.rs:539:3 | |
| 563 | | | |
| 564 | LL | #[lint("this is an example message", code = E0123)] | |
| 565 | | ^^^^ | |
| 566 | | | |
| 567 | help: a built-in attribute with a similar name exists | |
| 568 | | | |
| 569 | LL - #[lint("this is an example message", code = E0123)] | |
| 570 | LL + #[link("this is an example message", code = E0123)] | |
| 571 | | | |
| 572 | ||
| 573 | error: cannot find attribute `lint` in this scope | |
| 574 | --> $DIR/diagnostic-derive-inline.rs:546:3 | |
| 534 | --> $DIR/diagnostic-derive-inline.rs:527:3 | |
| 575 | 535 | | |
| 576 | 536 | LL | #[lint("this is an example message", code = E0123)] |
| 577 | 537 | | ^^^^ |
| ... | ... | @@ -583,7 +543,7 @@ LL + #[link("this is an example message", code = E0123)] |
| 583 | 543 | | |
| 584 | 544 | |
| 585 | 545 | error: cannot find attribute `multipart_suggestion` in this scope |
| 586 | --> $DIR/diagnostic-derive-inline.rs:586:3 | |
| 546 | --> $DIR/diagnostic-derive-inline.rs:567:3 | |
| 587 | 547 | | |
| 588 | 548 | LL | #[multipart_suggestion("with a suggestion")] |
| 589 | 549 | | ^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -595,7 +555,7 @@ LL | struct MultipartSuggestion { |
| 595 | 555 | | |
| 596 | 556 | |
| 597 | 557 | error: cannot find attribute `multipart_suggestion` in this scope |
| 598 | --> $DIR/diagnostic-derive-inline.rs:589:3 | |
| 558 | --> $DIR/diagnostic-derive-inline.rs:570:3 | |
| 599 | 559 | | |
| 600 | 560 | LL | #[multipart_suggestion()] |
| 601 | 561 | | ^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -607,7 +567,7 @@ LL | struct MultipartSuggestion { |
| 607 | 567 | | |
| 608 | 568 | |
| 609 | 569 | error: cannot find attribute `multipart_suggestion` in this scope |
| 610 | --> $DIR/diagnostic-derive-inline.rs:593:7 | |
| 570 | --> $DIR/diagnostic-derive-inline.rs:574:7 | |
| 611 | 571 | | |
| 612 | 572 | LL | #[multipart_suggestion("with a suggestion")] |
| 613 | 573 | | ^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -636,6 +596,6 @@ note: required by a bound in `Diag::<'a, G>::arg` |
| 636 | 596 | = note: in this macro invocation |
| 637 | 597 | = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) |
| 638 | 598 | |
| 639 | error: aborting due to 81 previous errors | |
| 599 | error: aborting due to 76 previous errors | |
| 640 | 600 | |
| 641 | 601 | For more information about this error, try `rustc --explain E0277`. |
tests/ui/allocator/xcrate-use2.rs-1| ... | ... | @@ -5,7 +5,6 @@ |
| 5 | 5 | //@ aux-build:helper.rs |
| 6 | 6 | //@ no-prefer-dynamic |
| 7 | 7 | |
| 8 | #![feature(allocator_api)] | |
| 9 | 8 | |
| 10 | 9 | extern crate custom; |
| 11 | 10 | extern crate custom_as_global; |
tests/ui/associated-types/associated-types-impl-redirect.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | // for `ByRef`. The right answer was to consider the result ambiguous |
| 10 | 10 | // until more type information was available. |
| 11 | 11 | |
| 12 | #![feature(lang_items)] | |
| 13 | 12 | #![no_implicit_prelude] |
| 14 | 13 | |
| 15 | 14 | use std::marker::Sized; |
tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs-1| ... | ... | @@ -8,7 +8,6 @@ |
| 8 | 8 | // for `ByRef`. The right answer was to consider the result ambiguous |
| 9 | 9 | // until more type information was available. |
| 10 | 10 | |
| 11 | #![feature(lang_items)] | |
| 12 | 11 | #![no_implicit_prelude] |
| 13 | 12 | |
| 14 | 13 | use std::marker::Sized; |
tests/ui/async-await/async-drop/async-drop-initial.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | // please consider modifying miri's async drop test at |
| 6 | 6 | // `src/tools/miri/tests/pass/async-drop.rs`. |
| 7 | 7 | |
| 8 | #![feature(async_drop, impl_trait_in_assoc_type)] | |
| 8 | #![feature(async_drop)] | |
| 9 | 9 | #![allow(incomplete_features, dead_code)] |
| 10 | 10 | |
| 11 | 11 | //@ edition: 2021 |
tests/ui/backtrace/line-tables-only.rs-1| ... | ... | @@ -18,7 +18,6 @@ |
| 18 | 18 | //@ needs-unwind |
| 19 | 19 | //@ aux-build: line-tables-only-helper.rs |
| 20 | 20 | |
| 21 | #![feature(backtrace_frames)] | |
| 22 | 21 | |
| 23 | 22 | extern crate line_tables_only_helper; |
| 24 | 23 |
tests/ui/borrowck/super-let-lifetime-and-drop.rs+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | //@ [borrowck] check-fail |
| 8 | 8 | |
| 9 | 9 | #![allow(dropping_references)] |
| 10 | #![feature(super_let, stmt_expr_attributes)] | |
| 10 | #![feature(super_let)] | |
| 11 | 11 | |
| 12 | 12 | use std::convert::identity; |
| 13 | 13 |
tests/ui/cfg/cfg_stmt_expr.rs-1| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | #![allow(unused_mut)] |
| 4 | 4 | #![allow(unused_variables)] |
| 5 | 5 | #![deny(non_snake_case)] |
| 6 | #![feature(stmt_expr_attributes)] | |
| 7 | 6 | |
| 8 | 7 | fn main() { |
| 9 | 8 | let a = 413; |
tests/ui/const-generics/transmute.rs-1| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | #![feature(generic_const_exprs)] |
| 3 | #![feature(transmute_generic_consts)] | |
| 4 | 3 | #![allow(incomplete_features)] |
| 5 | 4 | |
| 6 | 5 | fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] { |
tests/ui/consts/const-fn-type-name.rs-1| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | 3 | #![feature(core_intrinsics)] |
| 4 | #![feature(const_type_name)] | |
| 5 | 4 | #![allow(dead_code)] |
| 6 | 5 | |
| 7 | 6 | const fn type_name_wrapper<T>(_: &T) -> &'static str { |
tests/ui/consts/const-ptr-nonnull-rpass.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(ptr_internals, test)] | |
| 3 | #![feature(test)] | |
| 4 | 4 | |
| 5 | 5 | extern crate test; |
| 6 | 6 | use test::black_box as b; // prevent promotion of the argument and const-propagation of the result |
tests/ui/consts/try-operator.rs-1| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //@ ignore-backends: gcc |
| 2 | 2 | //@ run-pass |
| 3 | 3 | |
| 4 | #![feature(try_trait_v2)] | |
| 5 | 4 | #![feature(const_trait_impl)] |
| 6 | 5 | #![feature(const_try)] |
| 7 | 6 |
tests/ui/contracts/internal_machinery/lowering/basics.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | #![expect(incomplete_features)] |
| 3 | #![feature(contracts, cfg_contract_checks, contracts_internals, core_intrinsics)] | |
| 3 | #![feature(contracts, contracts_internals, core_intrinsics)] | |
| 4 | 4 | |
| 5 | 5 | extern crate core; |
| 6 | 6 |
tests/ui/coroutine/control-flow.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@ revisions: default nomiropt |
| 4 | 4 | //@[nomiropt]compile-flags: -Z mir-opt-level=0 |
| 5 | 5 | |
| 6 | #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] | |
| 6 | #![feature(coroutines, coroutine_trait)] | |
| 7 | 7 | |
| 8 | 8 | use std::ops::{CoroutineState, Coroutine}; |
| 9 | 9 | use std::pin::Pin; |
tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-rustfix |
| 2 | 2 | |
| 3 | #![feature(coroutines, gen_blocks, stmt_expr_attributes)] | |
| 3 | #![feature(coroutines, stmt_expr_attributes)] | |
| 4 | 4 | |
| 5 | 5 | fn main() { |
| 6 | 6 | let _ = #[coroutine] || yield; |
tests/ui/coroutine/missing_coroutine_attr_suggestion.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-rustfix |
| 2 | 2 | |
| 3 | #![feature(coroutines, gen_blocks, stmt_expr_attributes)] | |
| 3 | #![feature(coroutines, stmt_expr_attributes)] | |
| 4 | 4 | |
| 5 | 5 | fn main() { |
| 6 | 6 | let _ = || yield; |
tests/ui/coroutine/non-static-is-unpin.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@[next] compile-flags: -Znext-solver |
| 4 | 4 | //@ run-pass |
| 5 | 5 | |
| 6 | #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] | |
| 6 | #![feature(coroutines)] | |
| 7 | 7 | #![allow(dropping_copy_types)] |
| 8 | 8 | |
| 9 | 9 | use std::marker::PhantomPinned; |
tests/ui/coroutine/other-attribute-on-gen.rs-1| ... | ... | @@ -2,7 +2,6 @@ |
| 2 | 2 | //@ run-pass |
| 3 | 3 | #![feature(gen_blocks)] |
| 4 | 4 | #![feature(optimize_attribute)] |
| 5 | #![feature(stmt_expr_attributes)] | |
| 6 | 5 | #![feature(async_iterator)] |
| 7 | 6 | #![allow(dead_code)] |
| 8 | 7 |
tests/ui/coroutine/pin-box-coroutine.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] | |
| 3 | #![feature(coroutines, coroutine_trait)] | |
| 4 | 4 | |
| 5 | 5 | use std::ops::Coroutine; |
| 6 | 6 |
tests/ui/coroutine/xcrate.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | //@ aux-build:xcrate.rs |
| 4 | 4 | |
| 5 | #![feature(coroutines, coroutine_trait)] | |
| 5 | #![feature(coroutine_trait)] | |
| 6 | 6 | |
| 7 | 7 | extern crate xcrate; |
| 8 | 8 |
tests/ui/eii/default/call_default.rs-1| ... | ... | @@ -7,7 +7,6 @@ |
| 7 | 7 | //@ ignore-windows |
| 8 | 8 | // Tests EIIs with default implementations. |
| 9 | 9 | // When there's no explicit declaration, the default should be called from the declaring crate. |
| 10 | #![feature(extern_item_impls)] | |
| 11 | 10 | |
| 12 | 11 | extern crate decl_with_default; |
| 13 | 12 |
tests/ui/eii/default/call_default_panics.rs-1| ... | ... | @@ -23,7 +23,6 @@ |
| 23 | 23 | // ``` |
| 24 | 24 | // This is a simple test to make sure that we can unwind through these, |
| 25 | 25 | // and that this wrapper function effectively doesn't show up in the trace. |
| 26 | #![feature(extern_item_impls)] | |
| 27 | 26 | |
| 28 | 27 | extern crate decl_with_default_panics; |
| 29 | 28 |
tests/ui/eii/default/call_impl.rs-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | // Tests EIIs with default implementations. |
| 10 | 10 | // When an explicit implementation is given in one dependency, and the declaration is in another, |
| 11 | 11 | // the explicit implementation is preferred. |
| 12 | #![feature(extern_item_impls)] | |
| 13 | 12 | |
| 14 | 13 | extern crate decl_with_default; |
| 15 | 14 | extern crate impl1; |
tests/ui/eii/linking/codegen_cross_crate.rs-1| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | // FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418 |
| 7 | 7 | //@ ignore-windows |
| 8 | 8 | // Tests whether calling EIIs works with the declaration in another crate. |
| 9 | #![feature(extern_item_impls)] | |
| 10 | 9 | |
| 11 | 10 | extern crate codegen_cross_crate_other_crate as codegen; |
| 12 | 11 |
tests/ui/eii/privacy1.rs-1| ... | ... | @@ -5,7 +5,6 @@ |
| 5 | 5 | // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 |
| 6 | 6 | //@ ignore-windows |
| 7 | 7 | // Tests whether re-exports work. |
| 8 | #![feature(extern_item_impls)] | |
| 9 | 8 | |
| 10 | 9 | extern crate other_crate_privacy1 as codegen; |
| 11 | 10 |
tests/ui/enum-discriminant/issue-72554.rs-1| ... | ... | @@ -3,7 +3,6 @@ use std::collections::BTreeSet; |
| 3 | 3 | #[derive(Hash)] |
| 4 | 4 | pub enum ElemDerived { |
| 5 | 5 | //~^ ERROR recursive type `ElemDerived` has infinite size |
| 6 | //~| ERROR cycle detected | |
| 7 | 6 | A(ElemDerived) |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/enum-discriminant/issue-72554.stderr+3-18| ... | ... | @@ -3,7 +3,7 @@ error[E0072]: recursive type `ElemDerived` has infinite size |
| 3 | 3 | | |
| 4 | 4 | LL | pub enum ElemDerived { |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^ |
| 6 | ... | |
| 6 | LL | | |
| 7 | 7 | LL | A(ElemDerived) |
| 8 | 8 | | ----------- recursive without indirection |
| 9 | 9 | | |
| ... | ... | @@ -12,21 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 12 | 12 | LL | A(Box<ElemDerived>) |
| 13 | 13 | | ++++ + |
| 14 | 14 | |
| 15 | error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived` | |
| 16 | --> $DIR/issue-72554.rs:4:1 | |
| 17 | | | |
| 18 | LL | pub enum ElemDerived { | |
| 19 | | ^^^^^^^^^^^^^^^^^^^^ | |
| 20 | | | |
| 21 | = note: ...which immediately requires computing drop-check constraints for `ElemDerived` again | |
| 22 | note: cycle used when computing drop-check constraints for `Elem` | |
| 23 | --> $DIR/issue-72554.rs:11:1 | |
| 24 | | | |
| 25 | LL | pub enum Elem { | |
| 26 | | ^^^^^^^^^^^^^ | |
| 27 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 28 | ||
| 29 | error: aborting due to 2 previous errors | |
| 15 | error: aborting due to 1 previous error | |
| 30 | 16 | |
| 31 | Some errors have detailed explanations: E0072, E0391. | |
| 32 | For more information about an error, try `rustc --explain E0072`. | |
| 17 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/error-codes/E0208.rs deleted-8| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | #![feature(rustc_attrs)] | |
| 2 | ||
| 3 | #[rustc_variance] | |
| 4 | struct Foo<'a, T> { //~ ERROR ['a: +, T: o] | |
| 5 | t: &'a mut T, | |
| 6 | } | |
| 7 | ||
| 8 | fn main() {} |
tests/ui/error-codes/E0208.stderr deleted-8| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | error: ['a: +, T: o] | |
| 2 | --> $DIR/E0208.rs:4:1 | |
| 3 | | | |
| 4 | LL | struct Foo<'a, T> { | |
| 5 | | ^^^^^^^^^^^^^^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 |
tests/ui/extern/extern-prelude-core.rs-1| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | //@ run-pass |
| 2 | #![feature(lang_items)] | |
| 3 | 2 | #![no_std] |
| 4 | 3 | |
| 5 | 4 | extern crate std as other; |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed-1| ... | ... | @@ -22,7 +22,6 @@ |
| 22 | 22 | //@ [future_feature] compile-flags: -Z unstable-options |
| 23 | 23 | |
| 24 | 24 | #![cfg_attr(future_feature, feature(explicit_extern_abis))] |
| 25 | #![cfg_attr(current_feature, feature(explicit_extern_abis))] | |
| 26 | 25 | |
| 27 | 26 | extern "C" fn _foo() {} |
| 28 | 27 | //[current]~^ WARN `extern` declarations without an explicit ABI are deprecated |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | warning: `extern` declarations without an explicit ABI are deprecated |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 | |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:26:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | extern fn _foo() {} |
| 5 | 5 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| ... | ... | @@ -7,13 +7,13 @@ LL | extern fn _foo() {} |
| 7 | 7 | = note: `#[warn(missing_abi)]` on by default |
| 8 | 8 | |
| 9 | 9 | warning: `extern` declarations without an explicit ABI are deprecated |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 | |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:32:8 | |
| 11 | 11 | | |
| 12 | 12 | LL | unsafe extern fn _bar() {} |
| 13 | 13 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| 14 | 14 | |
| 15 | 15 | warning: `extern` declarations without an explicit ABI are deprecated |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 | |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:38:8 | |
| 17 | 17 | | |
| 18 | 18 | LL | unsafe extern {} |
| 19 | 19 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed-1| ... | ... | @@ -22,7 +22,6 @@ |
| 22 | 22 | //@ [future_feature] compile-flags: -Z unstable-options |
| 23 | 23 | |
| 24 | 24 | #![cfg_attr(future_feature, feature(explicit_extern_abis))] |
| 25 | #![cfg_attr(current_feature, feature(explicit_extern_abis))] | |
| 26 | 25 | |
| 27 | 26 | extern "C" fn _foo() {} |
| 28 | 27 | //[current]~^ WARN `extern` declarations without an explicit ABI are deprecated |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | warning: `extern` declarations without an explicit ABI are deprecated |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 | |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:26:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | extern fn _foo() {} |
| 5 | 5 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| ... | ... | @@ -7,13 +7,13 @@ LL | extern fn _foo() {} |
| 7 | 7 | = note: `#[warn(missing_abi)]` on by default |
| 8 | 8 | |
| 9 | 9 | warning: `extern` declarations without an explicit ABI are deprecated |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 | |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:32:8 | |
| 11 | 11 | | |
| 12 | 12 | LL | unsafe extern fn _bar() {} |
| 13 | 13 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| 14 | 14 | |
| 15 | 15 | warning: `extern` declarations without an explicit ABI are deprecated |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 | |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:38:8 | |
| 17 | 17 | | |
| 18 | 18 | LL | unsafe extern {} |
| 19 | 19 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed-1| ... | ... | @@ -22,7 +22,6 @@ |
| 22 | 22 | //@ [future_feature] compile-flags: -Z unstable-options |
| 23 | 23 | |
| 24 | 24 | #![cfg_attr(future_feature, feature(explicit_extern_abis))] |
| 25 | #![cfg_attr(current_feature, feature(explicit_extern_abis))] | |
| 26 | 25 | |
| 27 | 26 | extern "C" fn _foo() {} |
| 28 | 27 | //[current]~^ WARN `extern` declarations without an explicit ABI are deprecated |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | warning: `extern` declarations without an explicit ABI are deprecated |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 | |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:26:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | extern fn _foo() {} |
| 5 | 5 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| ... | ... | @@ -7,13 +7,13 @@ LL | extern fn _foo() {} |
| 7 | 7 | = note: `#[warn(missing_abi)]` on by default |
| 8 | 8 | |
| 9 | 9 | warning: `extern` declarations without an explicit ABI are deprecated |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 | |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:32:8 | |
| 11 | 11 | | |
| 12 | 12 | LL | unsafe extern fn _bar() {} |
| 13 | 13 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
| 14 | 14 | |
| 15 | 15 | warning: `extern` declarations without an explicit ABI are deprecated |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 | |
| 16 | --> $DIR/feature-gate-explicit-extern-abis.rs:38:8 | |
| 17 | 17 | | |
| 18 | 18 | LL | unsafe extern {} |
| 19 | 19 | | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error: `extern` declarations without an explicit ABI are disallowed |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 | |
| 2 | --> $DIR/feature-gate-explicit-extern-abis.rs:26:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | extern fn _foo() {} |
| 5 | 5 | | ^^^^^^ help: specify an ABI: `extern "<abi>"` |
| ... | ... | @@ -7,7 +7,7 @@ LL | extern fn _foo() {} |
| 7 | 7 | = help: prior to Rust 2024, a default ABI was inferred |
| 8 | 8 | |
| 9 | 9 | error: `extern` declarations without an explicit ABI are disallowed |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 | |
| 10 | --> $DIR/feature-gate-explicit-extern-abis.rs:32:8 | |
| 11 | 11 | | |
| 12 | 12 | LL | unsafe extern fn _bar() {} |
| 13 | 13 | | ^^^^^^ help: specify an ABI: `extern "<abi>"` |
| ... | ... | @@ -15,7 +15,7 @@ LL | unsafe extern fn _bar() {} |
| 15 | 15 | = help: prior to Rust 2024, a default ABI was inferred |
| 16 | 16 | |
| 17 | 17 | error: `extern` declarations without an explicit ABI are disallowed |
| 18 | --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 | |
| 18 | --> $DIR/feature-gate-explicit-extern-abis.rs:38:8 | |
| 19 | 19 | | |
| 20 | 20 | LL | unsafe extern {} |
| 21 | 21 | | ^^^^^^ help: specify an ABI: `extern "<abi>"` |
tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs-1| ... | ... | @@ -22,7 +22,6 @@ |
| 22 | 22 | //@ [future_feature] compile-flags: -Z unstable-options |
| 23 | 23 | |
| 24 | 24 | #![cfg_attr(future_feature, feature(explicit_extern_abis))] |
| 25 | #![cfg_attr(current_feature, feature(explicit_extern_abis))] | |
| 26 | 25 | |
| 27 | 26 | extern fn _foo() {} |
| 28 | 27 | //[current]~^ WARN `extern` declarations without an explicit ABI are deprecated |
tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs+3-3| ... | ... | @@ -7,10 +7,10 @@ |
| 7 | 7 | //~| NOTE the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized |
| 8 | 8 | struct Foo {} |
| 9 | 9 | |
| 10 | #[rustc_variance] | |
| 10 | #[rustc_dump_variances] | |
| 11 | 11 | //~^ ERROR use of an internal attribute [E0658] |
| 12 | //~| NOTE the `#[rustc_variance]` attribute is an internal implementation detail that will never be stable | |
| 13 | //~| NOTE the `#[rustc_variance]` attribute is used for rustc unit tests | |
| 12 | //~| NOTE the `#[rustc_dump_variances]` attribute is an internal implementation detail that will never be stable | |
| 13 | //~| NOTE the `#[rustc_dump_variances]` attribute is used for rustc unit tests | |
| 14 | 14 | enum E {} |
| 15 | 15 | |
| 16 | 16 | fn main() {} |
tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr+4-4| ... | ... | @@ -12,12 +12,12 @@ LL | #[rustc_nonnull_optimization_guaranteed] |
| 12 | 12 | error[E0658]: use of an internal attribute |
| 13 | 13 | --> $DIR/feature-gate-rustc-attrs-1.rs:10:1 |
| 14 | 14 | | |
| 15 | LL | #[rustc_variance] | |
| 16 | | ^^^^^^^^^^^^^^^^^ | |
| 15 | LL | #[rustc_dump_variances] | |
| 16 | | ^^^^^^^^^^^^^^^^^^^^^^^ | |
| 17 | 17 | | |
| 18 | 18 | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable |
| 19 | = note: the `#[rustc_variance]` attribute is an internal implementation detail that will never be stable | |
| 20 | = note: the `#[rustc_variance]` attribute is used for rustc unit tests | |
| 19 | = note: the `#[rustc_dump_variances]` attribute is an internal implementation detail that will never be stable | |
| 20 | = note: the `#[rustc_dump_variances]` attribute is used for rustc unit tests | |
| 21 | 21 | |
| 22 | 22 | error: aborting due to 2 previous errors |
| 23 | 23 |
tests/ui/float/classify-runtime-const.rs-2| ... | ... | @@ -6,8 +6,6 @@ |
| 6 | 6 | |
| 7 | 7 | // This tests the float classification functions, for regular runtime code and for const evaluation. |
| 8 | 8 | |
| 9 | #![feature(f16)] | |
| 10 | #![feature(f128)] | |
| 11 | 9 | |
| 12 | 10 | use std::num::FpCategory::*; |
| 13 | 11 |
tests/ui/float/conv-bits-runtime-const.rs+3-2| ... | ... | @@ -3,9 +3,10 @@ |
| 3 | 3 | |
| 4 | 4 | // This tests the float classification functions, for regular runtime code and for const evaluation. |
| 5 | 5 | |
| 6 | #![feature(f16)] | |
| 7 | #![feature(f128)] | |
| 8 | 6 | #![feature(cfg_target_has_reliable_f16_f128)] |
| 7 | #![cfg_attr(target_has_reliable_f16, feature(f16))] | |
| 8 | #![cfg_attr(target_has_reliable_f128, feature(f128))] | |
| 9 | ||
| 9 | 10 | #![allow(unused_macro_rules)] |
| 10 | 11 | // expect the unexpected (`target_has_reliable_*` are not "known" configs since they are unstable) |
| 11 | 12 | #![expect(unexpected_cfgs)] |
tests/ui/fmt/format-macro-no-std.rs-1| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | //@ ignore-emscripten no no_std executables |
| 5 | 5 | //@ ignore-wasm different `main` convention |
| 6 | 6 | |
| 7 | #![feature(lang_items)] | |
| 8 | 7 | #![no_std] |
| 9 | 8 | #![no_main] |
| 10 | 9 |
tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs+2-2| ... | ... | @@ -6,8 +6,8 @@ |
| 6 | 6 | |
| 7 | 7 | #![allow(unreachable_patterns)] |
| 8 | 8 | #![feature(cfg_target_has_reliable_f16_f128)] |
| 9 | #![feature(f128)] | |
| 10 | #![feature(f16)] | |
| 9 | #![cfg_attr(target_has_reliable_f16, feature(f16))] | |
| 10 | #![cfg_attr(target_has_reliable_f128, feature(f128))] | |
| 11 | 11 | |
| 12 | 12 | macro_rules! yes { |
| 13 | 13 | ($scrutinee:expr, $($t:tt)+) => { |
tests/ui/hygiene/xcrate.rs-1| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | |
| 4 | 4 | //@ aux-build:xcrate.rs |
| 5 | 5 | |
| 6 | #![feature(decl_macro)] | |
| 7 | 6 | |
| 8 | 7 | extern crate xcrate; |
| 9 | 8 |
tests/ui/impl-trait/capture-lifetime-not-in-hir.rs+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | #![rustc_variance_of_opaques] | |
| 2 | #![rustc_dump_variances_of_opaques] | |
| 3 | 3 | |
| 4 | 4 | trait Bar<'a> { |
| 5 | 5 | type Assoc: From<()>; |
tests/ui/impl-trait/example-calendar.rs+1-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(fn_traits, | |
| 4 | step_trait, | |
| 3 | #![feature(step_trait, | |
| 5 | 4 | unboxed_closures, |
| 6 | 5 | )] |
| 7 | 6 |
tests/ui/impl-trait/implicit-capture-late.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(rustc_attrs)] |
| 4 | 4 | #![allow(internal_features)] |
| 5 | #![rustc_variance_of_opaques] | |
| 5 | #![rustc_dump_variances_of_opaques] | |
| 6 | 6 | |
| 7 | 7 | use std::ops::Deref; |
| 8 | 8 |
tests/ui/impl-trait/in-trait/variance.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | #![allow(internal_features)] |
| 3 | #![rustc_variance_of_opaques] | |
| 3 | #![rustc_dump_variances_of_opaques] | |
| 4 | 4 | |
| 5 | 5 | trait Foo<'i> { |
| 6 | 6 | fn implicit_capture_early<'a: 'a>() -> impl Sized {} |
tests/ui/impl-trait/precise-capturing/capturing-implicit.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(rustc_attrs)] |
| 4 | 4 | #![feature(type_alias_impl_trait)] |
| 5 | #![rustc_variance_of_opaques] | |
| 5 | #![rustc_dump_variances_of_opaques] | |
| 6 | 6 | |
| 7 | 7 | fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> { |
| 8 | 8 | //~^ ERROR ['_: o] |
tests/ui/impl-trait/variance.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(rustc_attrs)] |
| 5 | 5 | #![allow(internal_features)] |
| 6 | #![rustc_variance_of_opaques] | |
| 6 | #![rustc_dump_variances_of_opaques] | |
| 7 | 7 | |
| 8 | 8 | trait Captures<'a> {} |
| 9 | 9 | impl<T> Captures<'_> for T {} |
tests/ui/infinite/infinite-struct.rs-2| ... | ... | @@ -1,7 +1,5 @@ |
| 1 | 1 | struct Take(Take); |
| 2 | 2 | //~^ ERROR has infinite size |
| 3 | //~| ERROR cycle | |
| 4 | //~| ERROR reached the recursion limit finding the struct tail for `Take` | |
| 5 | 3 | |
| 6 | 4 | // check that we don't hang trying to find the tail of a recursive struct (#79437) |
| 7 | 5 | fn foo() -> Take { |
tests/ui/infinite/infinite-struct.stderr+3-22| ... | ... | @@ -10,7 +10,7 @@ LL | struct Take(Box<Take>); |
| 10 | 10 | | ++++ + |
| 11 | 11 | |
| 12 | 12 | error[E0072]: recursive type `Foo` has infinite size |
| 13 | --> $DIR/infinite-struct.rs:12:1 | |
| 13 | --> $DIR/infinite-struct.rs:10:1 | |
| 14 | 14 | | |
| 15 | 15 | LL | struct Foo { |
| 16 | 16 | | ^^^^^^^^^^ |
| ... | ... | @@ -22,25 +22,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 22 | 22 | LL | x: Bar<Box<Foo>>, |
| 23 | 23 | | ++++ + |
| 24 | 24 | |
| 25 | error: reached the recursion limit finding the struct tail for `Take` | |
| 26 | --> $DIR/infinite-struct.rs:1:1 | |
| 27 | | | |
| 28 | LL | struct Take(Take); | |
| 29 | | ^^^^^^^^^^^ | |
| 30 | | | |
| 31 | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` | |
| 32 | ||
| 33 | error[E0391]: cycle detected when computing when `Take` needs drop | |
| 34 | --> $DIR/infinite-struct.rs:1:1 | |
| 35 | | | |
| 36 | LL | struct Take(Take); | |
| 37 | | ^^^^^^^^^^^ | |
| 38 | | | |
| 39 | = note: ...which immediately requires computing when `Take` needs drop again | |
| 40 | = note: cycle used when computing whether `Take` needs drop | |
| 41 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 42 | ||
| 43 | error: aborting due to 4 previous errors | |
| 25 | error: aborting due to 2 previous errors | |
| 44 | 26 | |
| 45 | Some errors have detailed explanations: E0072, E0391. | |
| 46 | For more information about an error, try `rustc --explain E0072`. | |
| 27 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/infinite/infinite-tag-type-recursion.rs-1| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | enum MList { Cons(isize, MList), Nil } |
| 2 | 2 | //~^ ERROR recursive type `MList` has infinite size |
| 3 | //~| ERROR cycle | |
| 4 | 3 | |
| 5 | 4 | fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } |
tests/ui/infinite/infinite-tag-type-recursion.stderr+2-13| ... | ... | @@ -9,17 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 9 | 9 | LL | enum MList { Cons(isize, Box<MList>), Nil } |
| 10 | 10 | | ++++ + |
| 11 | 11 | |
| 12 | error[E0391]: cycle detected when computing when `MList` needs drop | |
| 13 | --> $DIR/infinite-tag-type-recursion.rs:1:1 | |
| 14 | | | |
| 15 | LL | enum MList { Cons(isize, MList), Nil } | |
| 16 | | ^^^^^^^^^^ | |
| 17 | | | |
| 18 | = note: ...which immediately requires computing when `MList` needs drop again | |
| 19 | = note: cycle used when computing whether `MList` needs drop | |
| 20 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 21 | ||
| 22 | error: aborting due to 2 previous errors | |
| 12 | error: aborting due to 1 previous error | |
| 23 | 13 | |
| 24 | Some errors have detailed explanations: E0072, E0391. | |
| 25 | For more information about an error, try `rustc --explain E0072`. | |
| 14 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/intrinsics/intrinsic-alignment.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(core_intrinsics, rustc_attrs)] | |
| 3 | #![feature(rustc_attrs)] | |
| 4 | 4 | |
| 5 | 5 | #[cfg(any( |
| 6 | 6 | target_os = "aix", |
tests/ui/io-checks/write-macro-error.rs-1| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | //@ run-pass |
| 5 | 5 | //@ needs-unwind |
| 6 | 6 | |
| 7 | #![feature(io_error_uncategorized)] | |
| 8 | 7 | |
| 9 | 8 | use std::fmt; |
| 10 | 9 | use std::io::{self, Error, Write}; |
tests/ui/linkage-attr/raw-dylib/elf/as_needed.rs+1-1| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | |
| 16 | 16 | #![allow(incomplete_features)] |
| 17 | 17 | #![feature(raw_dylib_elf)] |
| 18 | #![feature(native_link_modifiers_as_needed)] | |
| 18 | #![cfg_attr(not(no_modifier), feature(native_link_modifiers_as_needed))] | |
| 19 | 19 | |
| 20 | 20 | #[cfg_attr( |
| 21 | 21 | as_needed, |
tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs+5-6| ... | ... | @@ -3,17 +3,16 @@ |
| 3 | 3 | // Previously, this test ICEs when the `unused_must_use` lint is suppressed via the combination of |
| 4 | 4 | // `-A warnings` and `--cap-lints=warn`, because: |
| 5 | 5 | // |
| 6 | // - Its lint diagnostic struct `UnusedDef` implements `LintDiagnostic` manually and in the impl | |
| 6 | // - Its lint diagnostic struct `UnusedDef` implements `Diagnostic` manually and in the impl | |
| 7 | 7 | // `def_path_str` was called (which calls `trimmed_def_path`, which will produce a |
| 8 | 8 | // `must_produce_diag` ICE if a trimmed def path is constructed but never emitted in a diagnostic |
| 9 | 9 | // because it is expensive to compute). |
| 10 | // - A `LintDiagnostic` has a `decorate_lint` method which decorates a `Diag` with lint-specific | |
| 11 | // information. This method is wrapped by a `decorate` closure in `TyCtxt` diagnostic emission | |
| 12 | // machinery, and the `decorate` closure called as late as possible. | |
| 13 | // - `decorate`'s invocation is delayed as late as possible until `lint_level` is called. | |
| 10 | // - A `Diagnostic` has an `into_diag` method which generates a `Diag` with (potentially) | |
| 11 | // lint-specific information. | |
| 12 | // - The `into_diag` method is called as late as possible until `diag_lint_level` is called. | |
| 14 | 13 | // - If a lint's corresponding diagnostic is suppressed (to be effectively allow at the final |
| 15 | 14 | // emission time) via `-A warnings` or `--cap-lints=allow` (or `-A warnings` + `--cap-lints=warn` |
| 16 | // like in this test case), `decorate` is still called and a diagnostic is still constructed -- | |
| 15 | // like in this test case), `into_diag` is still called and a diagnostic is still constructed -- | |
| 17 | 16 | // but the diagnostic is never eventually emitted, triggering the aforementioned |
| 18 | 17 | // `must_produce_diag` ICE due to use of `trimmed_def_path`. |
| 19 | 18 | // |
tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs-1| ... | ... | @@ -1,6 +1,5 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(stmt_expr_attributes)] | |
| 4 | 3 | #![deny(unused_parens)] |
| 5 | 4 | |
| 6 | 5 | // Tests that lint attributes on statements/expressions are |
tests/ui/lint/lint-unknown-feature.rs-1| ... | ... | @@ -4,6 +4,5 @@ |
| 4 | 4 | |
| 5 | 5 | #![allow(stable_features)] |
| 6 | 6 | // FIXME(#44232) we should warn that this isn't used. |
| 7 | #![feature(rust1)] | |
| 8 | 7 | |
| 9 | 8 | fn main() {} |
tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //@ edition:2021 |
| 3 | 3 | #![deny(unused_qualifications)] |
| 4 | 4 | #![deny(unused_imports)] |
| 5 | #![feature(coroutines, coroutine_trait)] | |
| 5 | #![feature(coroutine_trait)] | |
| 6 | 6 | |
| 7 | 7 | use std::ops::{ |
| 8 | 8 | Coroutine, |
tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //@ edition:2021 |
| 3 | 3 | #![deny(unused_qualifications)] |
| 4 | 4 | #![deny(unused_imports)] |
| 5 | #![feature(coroutines, coroutine_trait)] | |
| 5 | #![feature(coroutine_trait)] | |
| 6 | 6 | |
| 7 | 7 | use std::ops::{ |
| 8 | 8 | Coroutine, |
tests/ui/lint/unused-features/unused-language-features.rs created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | #![crate_type = "lib"] | |
| 2 | #![deny(unused_features)] | |
| 3 | ||
| 4 | // Unused language features | |
| 5 | #![feature(coroutines)] | |
| 6 | //~^ ERROR feature `coroutines` is declared but not used | |
| 7 | #![feature(coroutine_clone)] | |
| 8 | //~^ ERROR feature `coroutine_clone` is declared but not used | |
| 9 | #![feature(stmt_expr_attributes)] | |
| 10 | //~^ ERROR feature `stmt_expr_attributes` is declared but not used | |
| 11 | #![feature(asm_unwind)] | |
| 12 | //~^ ERROR feature `asm_unwind` is declared but not used | |
| 13 | ||
| 14 | // Enabled via cfg_attr, unused | |
| 15 | #![cfg_attr(all(), feature(negative_impls))] | |
| 16 | //~^ ERROR feature `negative_impls` is declared but not used | |
| 17 | ||
| 18 | // Not enabled via cfg_attr, so should not warn even if unused | |
| 19 | #![cfg_attr(any(), feature(never_type))] | |
| 20 | ||
| 21 | macro_rules! use_asm_unwind { | |
| 22 | () => { | |
| 23 | unsafe { std::arch::asm!("", options(may_unwind)) }; | |
| 24 | } | |
| 25 | } |
tests/ui/lint/unused-features/unused-language-features.stderr created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | error: feature `coroutines` is declared but not used | |
| 2 | --> $DIR/unused-language-features.rs:5:12 | |
| 3 | | | |
| 4 | LL | #![feature(coroutines)] | |
| 5 | | ^^^^^^^^^^ | |
| 6 | | | |
| 7 | note: the lint level is defined here | |
| 8 | --> $DIR/unused-language-features.rs:2:9 | |
| 9 | | | |
| 10 | LL | #![deny(unused_features)] | |
| 11 | | ^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | error: feature `coroutine_clone` is declared but not used | |
| 14 | --> $DIR/unused-language-features.rs:7:12 | |
| 15 | | | |
| 16 | LL | #![feature(coroutine_clone)] | |
| 17 | | ^^^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | error: feature `stmt_expr_attributes` is declared but not used | |
| 20 | --> $DIR/unused-language-features.rs:9:12 | |
| 21 | | | |
| 22 | LL | #![feature(stmt_expr_attributes)] | |
| 23 | | ^^^^^^^^^^^^^^^^^^^^ | |
| 24 | ||
| 25 | error: feature `asm_unwind` is declared but not used | |
| 26 | --> $DIR/unused-language-features.rs:11:12 | |
| 27 | | | |
| 28 | LL | #![feature(asm_unwind)] | |
| 29 | | ^^^^^^^^^^ | |
| 30 | ||
| 31 | error: feature `negative_impls` is declared but not used | |
| 32 | --> $DIR/unused-language-features.rs:15:28 | |
| 33 | | | |
| 34 | LL | #![cfg_attr(all(), feature(negative_impls))] | |
| 35 | | ^^^^^^^^^^^^^^ | |
| 36 | ||
| 37 | error: aborting due to 5 previous errors | |
| 38 |
tests/ui/lint/unused-features/unused-library-features.rs created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | #![crate_type = "lib"] | |
| 2 | #![deny(unused_features)] | |
| 3 | ||
| 4 | // Unused library features | |
| 5 | #![feature(step_trait)] | |
| 6 | //~^ ERROR feature `step_trait` is declared but not used | |
| 7 | #![feature(is_sorted)] | |
| 8 | //~^ ERROR feature `is_sorted` is declared but not used | |
| 9 | //~^^ WARN the feature `is_sorted` has been stable since 1.82.0 and no longer requires an attribute to enable | |
| 10 | ||
| 11 | // Enabled via cfg_attr, unused | |
| 12 | #![cfg_attr(all(), feature(slice_ptr_get))] | |
| 13 | //~^ ERROR feature `slice_ptr_get` is declared but not used |
tests/ui/lint/unused-features/unused-library-features.stderr created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | warning: the feature `is_sorted` has been stable since 1.82.0 and no longer requires an attribute to enable | |
| 2 | --> $DIR/unused-library-features.rs:7:12 | |
| 3 | | | |
| 4 | LL | #![feature(is_sorted)] | |
| 5 | | ^^^^^^^^^ | |
| 6 | | | |
| 7 | = note: `#[warn(stable_features)]` on by default | |
| 8 | ||
| 9 | error: feature `step_trait` is declared but not used | |
| 10 | --> $DIR/unused-library-features.rs:5:12 | |
| 11 | | | |
| 12 | LL | #![feature(step_trait)] | |
| 13 | | ^^^^^^^^^^ | |
| 14 | | | |
| 15 | note: the lint level is defined here | |
| 16 | --> $DIR/unused-library-features.rs:2:9 | |
| 17 | | | |
| 18 | LL | #![deny(unused_features)] | |
| 19 | | ^^^^^^^^^^^^^^^ | |
| 20 | ||
| 21 | error: feature `is_sorted` is declared but not used | |
| 22 | --> $DIR/unused-library-features.rs:7:12 | |
| 23 | | | |
| 24 | LL | #![feature(is_sorted)] | |
| 25 | | ^^^^^^^^^ | |
| 26 | ||
| 27 | error: feature `slice_ptr_get` is declared but not used | |
| 28 | --> $DIR/unused-library-features.rs:12:28 | |
| 29 | | | |
| 30 | LL | #![cfg_attr(all(), feature(slice_ptr_get))] | |
| 31 | | ^^^^^^^^^^^^^ | |
| 32 | ||
| 33 | error: aborting due to 3 previous errors; 1 warning emitted | |
| 34 |
tests/ui/lint/unused-features/used-language-features.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | //@ check-pass | |
| 2 | ||
| 3 | #![crate_type = "lib"] | |
| 4 | #![deny(unused_features)] | |
| 5 | ||
| 6 | // Used language features | |
| 7 | #![feature(box_patterns)] | |
| 8 | #![feature(decl_macro)] | |
| 9 | #![cfg_attr(all(), feature(rustc_attrs))] | |
| 10 | ||
| 11 | pub fn use_box_patterns(b: Box<i32>) -> i32 { | |
| 12 | let box x = b; | |
| 13 | x | |
| 14 | } | |
| 15 | ||
| 16 | macro m() {} | |
| 17 | pub fn use_decl_macro() { | |
| 18 | m!(); | |
| 19 | } | |
| 20 | ||
| 21 | #[rustc_dummy] | |
| 22 | pub fn use_rustc_attrs() {} |
tests/ui/lint/unused-features/used-library-features.rs created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | //@ check-pass | |
| 2 | ||
| 3 | #![crate_type = "lib"] | |
| 4 | #![deny(unused_features)] | |
| 5 | ||
| 6 | // Used library features | |
| 7 | #![feature(error_iter)] | |
| 8 | #![cfg_attr(all(), feature(allocator_api))] | |
| 9 | ||
| 10 | pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) { | |
| 11 | for _ in e.sources() {} | |
| 12 | } | |
| 13 | ||
| 14 | pub fn use_allocator_api() { | |
| 15 | use std::alloc::Global; | |
| 16 | let _ = Vec::<i32>::new_in(Global); | |
| 17 | } |
tests/ui/lint/unused/unused_attributes-must_use.fixed+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-rustfix |
| 2 | 2 | |
| 3 | #![allow(dead_code, path_statements)] | |
| 3 | #![allow(dead_code, path_statements, unused_features)] | |
| 4 | 4 | #![deny(unused_attributes, unused_must_use)] |
| 5 | 5 | #![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] |
| 6 | 6 |
tests/ui/lint/unused/unused_attributes-must_use.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-rustfix |
| 2 | 2 | |
| 3 | #![allow(dead_code, path_statements)] | |
| 3 | #![allow(dead_code, path_statements, unused_features)] | |
| 4 | 4 | #![deny(unused_attributes, unused_must_use)] |
| 5 | 5 | #![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] |
| 6 | 6 |
tests/ui/lowering/issue-96847.rs-1| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | // Test that this doesn't abort during AST lowering. In #96847 it did abort |
| 4 | 4 | // because the attribute was being lowered twice. |
| 5 | 5 | |
| 6 | #![feature(stmt_expr_attributes)] | |
| 7 | 6 | #![feature(lang_items)] |
| 8 | 7 | |
| 9 | 8 | fn main() { |
tests/ui/lowering/issue-96847.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0522]: definition of an unknown lang item: `foo` |
| 2 | --> $DIR/issue-96847.rs:11:9 | |
| 2 | --> $DIR/issue-96847.rs:10:9 | |
| 3 | 3 | | |
| 4 | 4 | LL | #![lang="foo"] |
| 5 | 5 | | ^^^^^^^^^^^^^^ definition of unknown lang item `foo` |
tests/ui/macros/metavar_cross_edition_recursive_macros.rs-1| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | // This test captures the behavior of macro-generating-macros with fragment |
| 7 | 7 | // specifiers across edition boundaries. |
| 8 | 8 | |
| 9 | #![feature(macro_metavar_expr)] | |
| 10 | 9 | #![allow(incomplete_features)] |
| 11 | 10 | |
| 12 | 11 | extern crate metavar_2018; |
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | //@ needs-unwind Asserting on contents of error message |
| 6 | 6 | |
| 7 | 7 | #![allow(path_statements, unused_allocation)] |
| 8 | #![feature(core_intrinsics, generic_assert)] | |
| 8 | #![feature(generic_assert)] | |
| 9 | 9 | |
| 10 | 10 | macro_rules! test { |
| 11 | 11 | ( |
tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | //@ run-pass |
| 5 | 5 | //@ needs-unwind Asserting on contents of error message |
| 6 | 6 | |
| 7 | #![feature(core_intrinsics, generic_assert)] | |
| 7 | #![feature(generic_assert)] | |
| 8 | 8 | |
| 9 | 9 | extern crate common; |
| 10 | 10 |
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs-1| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | //@ compile-flags: --test -Zpanic_abort_tests |
| 4 | 4 | //@ run-pass |
| 5 | 5 | |
| 6 | #![feature(core_intrinsics, generic_assert)] | |
| 7 | 6 | |
| 8 | 7 | #[should_panic(expected = "Custom user message")] |
| 9 | 8 | #[test] |
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | //@ run-pass |
| 4 | 4 | //@ needs-unwind Asserting on contents of error message |
| 5 | 5 | |
| 6 | #![feature(core_intrinsics, generic_assert)] | |
| 6 | #![feature(generic_assert)] | |
| 7 | 7 | |
| 8 | 8 | extern crate common; |
| 9 | 9 |
tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | // ignore-tidy-linelength |
| 5 | 5 | //@ run-pass |
| 6 | 6 | |
| 7 | #![feature(core_intrinsics, generic_assert)] | |
| 7 | #![feature(generic_assert)] | |
| 8 | 8 | |
| 9 | 9 | use std::fmt::{Debug, Formatter}; |
| 10 | 10 |
tests/ui/macros/stringify.rs-2| ... | ... | @@ -9,12 +9,10 @@ |
| 9 | 9 | #![feature(const_trait_impl)] |
| 10 | 10 | #![feature(coroutines)] |
| 11 | 11 | #![feature(decl_macro)] |
| 12 | #![feature(explicit_tail_calls)] | |
| 13 | 12 | #![feature(more_qualified_paths)] |
| 14 | 13 | #![feature(never_patterns)] |
| 15 | 14 | #![feature(trait_alias)] |
| 16 | 15 | #![feature(try_blocks)] |
| 17 | #![feature(type_ascription)] | |
| 18 | 16 | #![feature(yeet_expr)] |
| 19 | 17 | #![deny(unused_macros)] |
| 20 | 18 |
tests/ui/match/match-float.rs+2-2| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | // Makes sure we use `==` (not bitwise) semantics for float comparison. |
| 4 | 4 | |
| 5 | 5 | #![feature(cfg_target_has_reliable_f16_f128)] |
| 6 | #![feature(f128)] | |
| 7 | #![feature(f16)] | |
| 6 | #![cfg_attr(target_has_reliable_f16, feature(f16))] | |
| 7 | #![cfg_attr(target_has_reliable_f128, feature(f128))] | |
| 8 | 8 | |
| 9 | 9 | #[cfg(target_has_reliable_f16)] |
| 10 | 10 | fn check_f16() { |
tests/ui/methods/supertrait-shadowing/out-of-scope.rs-1| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ check-run-results |
| 3 | 3 | |
| 4 | #![feature(supertrait_item_shadowing)] | |
| 5 | 4 | #![allow(dead_code)] |
| 6 | 5 | |
| 7 | 6 | mod out_of_scope { |
tests/ui/nll/issue-48623-coroutine.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | #![allow(path_statements)] |
| 3 | 3 | #![allow(dead_code)] |
| 4 | 4 | |
| 5 | #![feature(coroutines, coroutine_trait)] | |
| 5 | #![feature(coroutines)] | |
| 6 | 6 | |
| 7 | 7 | struct WithDrop; |
| 8 | 8 |
tests/ui/object-lifetime/object-lifetime-default.rs+7-7| ... | ... | @@ -1,37 +1,37 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_object_lifetime_default] | |
| 3 | #[rustc_dump_object_lifetime_defaults] | |
| 4 | 4 | struct A< |
| 5 | 5 | T, //~ ERROR BaseDefault |
| 6 | 6 | >(T); |
| 7 | 7 | |
| 8 | #[rustc_object_lifetime_default] | |
| 8 | #[rustc_dump_object_lifetime_defaults] | |
| 9 | 9 | struct B< |
| 10 | 10 | 'a, |
| 11 | 11 | T, //~ ERROR BaseDefault |
| 12 | 12 | >(&'a (), T); |
| 13 | 13 | |
| 14 | #[rustc_object_lifetime_default] | |
| 14 | #[rustc_dump_object_lifetime_defaults] | |
| 15 | 15 | struct C< |
| 16 | 16 | 'a, |
| 17 | 17 | T: 'a, //~ ERROR 'a |
| 18 | 18 | >(&'a T); |
| 19 | 19 | |
| 20 | #[rustc_object_lifetime_default] | |
| 20 | #[rustc_dump_object_lifetime_defaults] | |
| 21 | 21 | struct D< |
| 22 | 22 | 'a, |
| 23 | 23 | 'b, |
| 24 | 24 | T: 'a + 'b, //~ ERROR Ambiguous |
| 25 | 25 | >(&'a T, &'b T); |
| 26 | 26 | |
| 27 | #[rustc_object_lifetime_default] | |
| 27 | #[rustc_dump_object_lifetime_defaults] | |
| 28 | 28 | struct E< |
| 29 | 29 | 'a, |
| 30 | 30 | 'b: 'a, |
| 31 | 31 | T: 'b, //~ ERROR 'b |
| 32 | 32 | >(&'a T, &'b T); |
| 33 | 33 | |
| 34 | #[rustc_object_lifetime_default] | |
| 34 | #[rustc_dump_object_lifetime_defaults] | |
| 35 | 35 | struct F< |
| 36 | 36 | 'a, |
| 37 | 37 | 'b, |
| ... | ... | @@ -39,7 +39,7 @@ struct F< |
| 39 | 39 | U: 'b, //~ ERROR 'b |
| 40 | 40 | >(&'a T, &'b U); |
| 41 | 41 | |
| 42 | #[rustc_object_lifetime_default] | |
| 42 | #[rustc_dump_object_lifetime_defaults] | |
| 43 | 43 | struct G< |
| 44 | 44 | 'a, |
| 45 | 45 | 'b, |
tests/ui/overloaded/overloaded-calls-simple.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | |
| 3 | #![feature(lang_items, unboxed_closures, fn_traits)] | |
| 3 | #![feature(unboxed_closures, fn_traits)] | |
| 4 | 4 | |
| 5 | 5 | struct S1 { |
| 6 | 6 | x: i32, |
tests/ui/query-system/query-cycle-printing-issue-151226.rs-2| ... | ... | @@ -1,8 +1,6 @@ |
| 1 | 1 | struct A<T>(std::sync::OnceLock<Self>); |
| 2 | 2 | //~^ ERROR recursive type `A` has infinite size |
| 3 | //~| ERROR cycle detected when computing layout of `A<()>` | |
| 4 | 3 | |
| 5 | 4 | static B: A<()> = todo!(); |
| 6 | //~^ ERROR cycle occurred during layout computation | |
| 7 | 5 | |
| 8 | 6 | fn main() {} |
tests/ui/query-system/query-cycle-printing-issue-151226.stderr+2-24| ... | ... | @@ -9,28 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 9 | 9 | LL | struct A<T>(Box<std::sync::OnceLock<Self>>); |
| 10 | 10 | | ++++ + |
| 11 | 11 | |
| 12 | error[E0391]: cycle detected when computing layout of `A<()>` | |
| 13 | | | |
| 14 | = note: ...which requires computing layout of `std::sync::once_lock::OnceLock<A<()>>`... | |
| 15 | = note: ...which requires computing layout of `core::cell::UnsafeCell<core::mem::maybe_uninit::MaybeUninit<A<()>>>`... | |
| 16 | = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit<A<()>>`... | |
| 17 | = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<A<()>>`... | |
| 18 | = note: ...which requires computing layout of `core::mem::maybe_dangling::MaybeDangling<A<()>>`... | |
| 19 | = note: ...which again requires computing layout of `A<()>`, completing the cycle | |
| 20 | note: cycle used when checking that `B` is well-formed | |
| 21 | --> $DIR/query-cycle-printing-issue-151226.rs:5:1 | |
| 22 | | | |
| 23 | LL | static B: A<()> = todo!(); | |
| 24 | | ^^^^^^^^^^^^^^^ | |
| 25 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 26 | ||
| 27 | error[E0080]: a cycle occurred during layout computation | |
| 28 | --> $DIR/query-cycle-printing-issue-151226.rs:5:1 | |
| 29 | | | |
| 30 | LL | static B: A<()> = todo!(); | |
| 31 | | ^^^^^^^^^^^^^^^ evaluation of `B` failed here | |
| 32 | ||
| 33 | error: aborting due to 3 previous errors | |
| 12 | error: aborting due to 1 previous error | |
| 34 | 13 | |
| 35 | Some errors have detailed explanations: E0072, E0080, E0391. | |
| 36 | For more information about an error, try `rustc --explain E0072`. | |
| 14 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | bar: std::slice::IterMut<'a, T> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/cross-crate.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, T> { |
tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs+6-6| ... | ... | @@ -3,20 +3,20 @@ |
| 3 | 3 | // Needs an explicit where clause stating outlives condition. (RFC 2093) |
| 4 | 4 | |
| 5 | 5 | // Type T needs to outlive lifetime 'a. |
| 6 | #[rustc_outlives] | |
| 7 | enum Foo<'a, T> { //~ ERROR rustc_outlives | |
| 6 | #[rustc_dump_inferred_outlives] | |
| 7 | enum Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 8 | 8 | One(Bar<'a, T>) |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | 11 | // Type U needs to outlive lifetime 'b |
| 12 | #[rustc_outlives] | |
| 13 | struct Bar<'b, U> { //~ ERROR rustc_outlives | |
| 12 | #[rustc_dump_inferred_outlives] | |
| 13 | struct Bar<'b, U> { //~ ERROR rustc_dump_inferred_outlives | |
| 14 | 14 | field2: &'b U |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | 17 | // Type K needs to outlive lifetime 'c. |
| 18 | #[rustc_outlives] | |
| 19 | enum Ying<'c, K> { //~ ERROR rustc_outlives | |
| 18 | #[rustc_dump_inferred_outlives] | |
| 19 | enum Ying<'c, K> { //~ ERROR rustc_dump_inferred_outlives | |
| 20 | 20 | One(&'c Yang<K>) |
| 21 | 21 | } |
| 22 | 22 |
tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr+3-3| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/enum.rs:7:1 |
| 3 | 3 | | |
| 4 | 4 | LL | enum Foo<'a, T> { |
| ... | ... | @@ -6,7 +6,7 @@ LL | enum Foo<'a, T> { |
| 6 | 6 | | |
| 7 | 7 | = note: T: 'a |
| 8 | 8 | |
| 9 | error: rustc_outlives | |
| 9 | error: rustc_dump_inferred_outlives | |
| 10 | 10 | --> $DIR/enum.rs:13:1 |
| 11 | 11 | | |
| 12 | 12 | LL | struct Bar<'b, U> { |
| ... | ... | @@ -14,7 +14,7 @@ LL | struct Bar<'b, U> { |
| 14 | 14 | | |
| 15 | 15 | = note: U: 'b |
| 16 | 16 | |
| 17 | error: rustc_outlives | |
| 17 | error: rustc_dump_inferred_outlives | |
| 18 | 18 | --> $DIR/enum.rs:19:1 |
| 19 | 19 | | |
| 20 | 20 | LL | enum Ying<'c, K> { |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs+2-2| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | trait Trait<'x, T> where T: 'x { |
| 4 | 4 | } |
| 5 | 5 | |
| 6 | #[rustc_outlives] | |
| 7 | struct Foo<'a, A> //~ ERROR rustc_outlives | |
| 6 | #[rustc_dump_inferred_outlives] | |
| 7 | struct Foo<'a, A> //~ ERROR rustc_dump_inferred_outlives | |
| 8 | 8 | { |
| 9 | 9 | foo: Box<dyn Trait<'a, A>> |
| 10 | 10 | } |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/explicit-dyn.rs:7:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, A> |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | enum Foo<'a, U> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | enum Foo<'a, U> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | One(Bar<'a, U>) |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/explicit-enum.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | enum Foo<'a, U> { |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.rs+2-2| ... | ... | @@ -4,8 +4,8 @@ trait Trait<'x, T> where T: 'x { |
| 4 | 4 | type Type; |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | #[rustc_outlives] | |
| 8 | struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives | |
| 7 | #[rustc_dump_inferred_outlives] | |
| 8 | struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_dump_inferred_outlives | |
| 9 | 9 | { |
| 10 | 10 | foo: <A as Trait<'a, B>>::Type |
| 11 | 11 | } |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/explicit-projection.rs:8:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, A, B> where A: Trait<'a, B> |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'b, U> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'b, U> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | bar: Bar<'b, U> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/explicit-struct.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'b, U> { |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | union Foo<'b, U: Copy> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | union Foo<'b, U: Copy> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | bar: Bar<'b, U> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/explicit-union.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | union Foo<'b, U: Copy> { |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | enum Foo<'a, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | enum Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | |
| 6 | 6 | One(Bar<'a, T>) |
| 7 | 7 | } |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/nested-enum.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | enum Foo<'a, T> { |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, 'b, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | x: &'a &'b T |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/nested-regions.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, 'b, T> { |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | field1: Bar<'a, T> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/nested-structs.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, T> { |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | union Foo<'a, T: Copy> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | union Foo<'a, T: Copy> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | field1: Bar<'a, T> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/nested-union.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | union Foo<'a, T: Copy> { |
tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, T: Iterator> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | bar: &'a T::Item |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/projection.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, T: Iterator> { |
tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | bar: &'a T, |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/reference.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, T> { |
tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.rs+2-2| ... | ... | @@ -4,8 +4,8 @@ trait Trait<'x, 's, T> where T: 'x, |
| 4 | 4 | 's: { |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | #[rustc_outlives] | |
| 8 | struct Foo<'a, 'b, A> //~ ERROR rustc_outlives | |
| 7 | #[rustc_dump_inferred_outlives] | |
| 8 | struct Foo<'a, 'b, A> //~ ERROR rustc_dump_inferred_outlives | |
| 9 | 9 | { |
| 10 | 10 | foo: Box<dyn Trait<'a, 'b, A>> |
| 11 | 11 | } |
tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/self-dyn.rs:8:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, 'b, A> |
tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | #![feature(rustc_attrs)] |
| 2 | 2 | |
| 3 | #[rustc_outlives] | |
| 4 | struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives | |
| 3 | #[rustc_dump_inferred_outlives] | |
| 4 | struct Foo<'a, 'b, T> { //~ ERROR rustc_dump_inferred_outlives | |
| 5 | 5 | field1: dyn Bar<'a, 'b, T> |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: rustc_outlives | |
| 1 | error: rustc_dump_inferred_outlives | |
| 2 | 2 | --> $DIR/self-structs.rs:4:1 |
| 3 | 3 | | |
| 4 | 4 | LL | struct Foo<'a, 'b, T> { |
tests/ui/sanitizer/memory-passing.rs-1| ... | ... | @@ -13,7 +13,6 @@ |
| 13 | 13 | // This test case intentionally limits the usage of the std, |
| 14 | 14 | // since it will be linked with an uninstrumented version of it. |
| 15 | 15 | |
| 16 | #![feature(core_intrinsics)] | |
| 17 | 16 | #![allow(invalid_value)] |
| 18 | 17 | #![no_main] |
| 19 | 18 |
tests/ui/simd/monomorphize-shuffle-index.rs+1-1| ... | ... | @@ -4,12 +4,12 @@ |
| 4 | 4 | //@ ignore-backends: gcc |
| 5 | 5 | #![feature( |
| 6 | 6 | repr_simd, |
| 7 | core_intrinsics, | |
| 8 | 7 | intrinsics, |
| 9 | 8 | adt_const_params, |
| 10 | 9 | unsized_const_params, |
| 11 | 10 | generic_const_exprs |
| 12 | 11 | )] |
| 12 | #![cfg_attr(old, feature(core_intrinsics))] | |
| 13 | 13 | #![allow(incomplete_features)] |
| 14 | 14 | |
| 15 | 15 | #[path = "../../auxiliary/minisimd.rs"] |
tests/ui/structs-enums/enum-rec/issue-17431-6.rs-1| ... | ... | @@ -2,7 +2,6 @@ use std::cell::UnsafeCell; |
| 2 | 2 | |
| 3 | 3 | enum Foo { X(UnsafeCell<Option<Foo>>) } |
| 4 | 4 | //~^ ERROR recursive type `Foo` has infinite size |
| 5 | //~| ERROR cycle detected | |
| 6 | 5 | |
| 7 | 6 | impl Foo { fn bar(self) {} } |
| 8 | 7 |
tests/ui/structs-enums/enum-rec/issue-17431-6.stderr+2-13| ... | ... | @@ -9,17 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 9 | 9 | LL | enum Foo { X(UnsafeCell<Option<Box<Foo>>>) } |
| 10 | 10 | | ++++ + |
| 11 | 11 | |
| 12 | error[E0391]: cycle detected when computing when `Foo` needs drop | |
| 13 | --> $DIR/issue-17431-6.rs:3:1 | |
| 14 | | | |
| 15 | LL | enum Foo { X(UnsafeCell<Option<Foo>>) } | |
| 16 | | ^^^^^^^^ | |
| 17 | | | |
| 18 | = note: ...which immediately requires computing when `Foo` needs drop again | |
| 19 | = note: cycle used when computing whether `Foo` needs drop | |
| 20 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 21 | ||
| 22 | error: aborting due to 2 previous errors | |
| 12 | error: aborting due to 1 previous error | |
| 23 | 13 | |
| 24 | Some errors have detailed explanations: E0072, E0391. | |
| 25 | For more information about an error, try `rustc --explain E0072`. | |
| 14 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/structs-enums/rec-align-u32.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | #![allow(unused_unsafe)] |
| 4 | 4 | // Issue #2303 |
| 5 | 5 | |
| 6 | #![feature(core_intrinsics, rustc_attrs)] | |
| 6 | #![feature(rustc_attrs)] | |
| 7 | 7 | |
| 8 | 8 | use std::mem; |
| 9 | 9 |
tests/ui/structs-enums/rec-align-u64.rs+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | // Issue #2303 |
| 6 | 6 | |
| 7 | #![feature(core_intrinsics, rustc_attrs)] | |
| 7 | #![feature(rustc_attrs)] | |
| 8 | 8 | |
| 9 | 9 | use std::mem; |
| 10 | 10 |
tests/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs+2-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | #![feature(cfg_target_thread_local, thread_local)] | |
| 1 | #![feature(cfg_target_thread_local)] | |
| 2 | #![cfg_attr(target_thread_local, feature(thread_local))] | |
| 2 | 3 | #![crate_type = "lib"] |
| 3 | 4 | |
| 4 | 5 | #[cfg(target_thread_local)] |
tests/ui/threads-sendsync/thread-local-extern-static.rs+2-1| ... | ... | @@ -2,7 +2,8 @@ |
| 2 | 2 | //@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows |
| 3 | 3 | //@ aux-build:thread-local-extern-static.rs |
| 4 | 4 | |
| 5 | #![feature(cfg_target_thread_local, thread_local)] | |
| 5 | #![feature(cfg_target_thread_local)] | |
| 6 | #![cfg_attr(target_thread_local, feature(thread_local))] | |
| 6 | 7 | |
| 7 | 8 | #[cfg(target_thread_local)] |
| 8 | 9 | extern crate thread_local_extern_static; |
tests/ui/traits/alias/import-cross-crate.rs-1| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | //@ run-pass |
| 2 | 2 | //@ aux-build:greeter.rs |
| 3 | 3 | |
| 4 | #![feature(trait_alias)] | |
| 5 | 4 | |
| 6 | 5 | extern crate greeter; |
| 7 | 6 |
tests/ui/traits/const-traits/variance.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #![feature(rustc_attrs, const_trait_impl)] |
| 2 | 2 | #![allow(internal_features)] |
| 3 | #![rustc_variance_of_opaques] | |
| 3 | #![rustc_dump_variances_of_opaques] | |
| 4 | 4 | |
| 5 | 5 | const trait Foo {} |
| 6 | 6 |
tests/ui/traits/issue-105231.rs-1| ... | ... | @@ -6,5 +6,4 @@ struct B<T>(A<A<T>>); |
| 6 | 6 | trait Foo {} |
| 7 | 7 | impl<T> Foo for T where T: Send {} |
| 8 | 8 | impl Foo for B<u8> {} |
| 9 | //~^ ERROR conflicting implementations of trait `Foo` for type `B<u8>` | |
| 10 | 9 | fn main() {} |
tests/ui/traits/issue-105231.stderr+2-14| ... | ... | @@ -37,18 +37,6 @@ LL | struct B<T>(A<A<T>>); |
| 37 | 37 | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` |
| 38 | 38 | = note: all type parameters must be used in a non-recursive way in order to constrain their variance |
| 39 | 39 | |
| 40 | error[E0119]: conflicting implementations of trait `Foo` for type `B<u8>` | |
| 41 | --> $DIR/issue-105231.rs:8:1 | |
| 42 | | | |
| 43 | LL | impl<T> Foo for T where T: Send {} | |
| 44 | | ------------------------------- first implementation here | |
| 45 | LL | impl Foo for B<u8> {} | |
| 46 | | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B<u8>` | |
| 47 | | | |
| 48 | = note: overflow evaluating the requirement `B<u8>: Send` | |
| 49 | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) | |
| 50 | ||
| 51 | error: aborting due to 4 previous errors | |
| 40 | error: aborting due to 3 previous errors | |
| 52 | 41 | |
| 53 | Some errors have detailed explanations: E0072, E0119. | |
| 54 | For more information about an error, try `rustc --explain E0072`. | |
| 42 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/traits/overlap-permitted-for-marker-traits.rs-1| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | // `MyMarker` if it is either `Debug` or `Display`. |
| 5 | 5 | |
| 6 | 6 | #![feature(marker_trait_attr)] |
| 7 | #![feature(negative_impls)] | |
| 8 | 7 | |
| 9 | 8 | use std::fmt::{Debug, Display}; |
| 10 | 9 |
tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs-1| ... | ... | @@ -1,4 +1,3 @@ |
| 1 | //~ ERROR: cycle detected | |
| 2 | 1 | //! Safe transmute did not handle cycle errors that could occur during |
| 3 | 2 | //! layout computation. This test checks that we do not ICE in such |
| 4 | 3 | //! situations (see #117491). |
tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr+3-10| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0072]: recursive type `ExplicitlyPadded` has infinite size |
| 2 | --> $DIR/transmute_infinitely_recursive_type.rs:21:5 | |
| 2 | --> $DIR/transmute_infinitely_recursive_type.rs:20:5 | |
| 3 | 3 | | |
| 4 | 4 | LL | struct ExplicitlyPadded(ExplicitlyPadded); |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^ ---------------- recursive without indirection |
| ... | ... | @@ -9,13 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle |
| 9 | 9 | LL | struct ExplicitlyPadded(Box<ExplicitlyPadded>); |
| 10 | 10 | | ++++ + |
| 11 | 11 | |
| 12 | error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` | |
| 13 | | | |
| 14 | = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again | |
| 15 | = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom<should_pad_explicitly_packed_field::ExplicitlyPadded, ValTree(Branch([ValTree(Leaf(0x00): bool), ValTree(Leaf(0x00): bool), ValTree(Leaf(0x00): bool), ValTree(Leaf(0x00): bool)]): core::mem::transmutability::Assume)>` | |
| 16 | = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information | |
| 17 | ||
| 18 | error: aborting due to 2 previous errors | |
| 12 | error: aborting due to 1 previous error | |
| 19 | 13 | |
| 20 | Some errors have detailed explanations: E0072, E0391. | |
| 21 | For more information about an error, try `rustc --explain E0072`. | |
| 14 | For more information about this error, try `rustc --explain E0072`. |
tests/ui/type-alias-impl-trait/variance.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #![feature(rustc_attrs, type_alias_impl_trait, impl_trait_in_assoc_type)] |
| 2 | 2 | #![allow(internal_features)] |
| 3 | #![rustc_variance_of_opaques] | |
| 3 | #![rustc_dump_variances_of_opaques] | |
| 4 | 4 | |
| 5 | 5 | trait Captures<'a> {} |
| 6 | 6 | impl<T> Captures<'_> for T {} |
tests/ui/type/typeid-consistency.rs-1| ... | ... | @@ -3,7 +3,6 @@ |
| 3 | 3 | //@ run-pass |
| 4 | 4 | |
| 5 | 5 | #![allow(deprecated)] |
| 6 | #![feature(core_intrinsics)] | |
| 7 | 6 | |
| 8 | 7 | //@ aux-build:typeid-consistency-aux1.rs |
| 9 | 8 | //@ aux-build:typeid-consistency-aux2.rs |
tests/ui/typeck/type-name-intrinsic-usage-61894.rs-1| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | // https://github.com/rust-lang/rust/issues/61894 |
| 2 | 2 | //@ run-pass |
| 3 | 3 | |
| 4 | #![feature(core_intrinsics)] | |
| 5 | 4 | |
| 6 | 5 | use std::any::type_name; |
| 7 | 6 |
tests/ui/variance/variance-associated-consts.rs+1-1| ... | ... | @@ -9,7 +9,7 @@ trait Trait { |
| 9 | 9 | const Const: usize; |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | #[rustc_variance] | |
| 12 | #[rustc_dump_variances] | |
| 13 | 13 | struct Foo<T: Trait> { //~ ERROR [T: o] |
| 14 | 14 | field: [u8; <T as Trait>::Const] |
| 15 | 15 | //~^ ERROR: unconstrained generic constant |
tests/ui/variance/variance-associated-types.rs+2-2| ... | ... | @@ -9,12 +9,12 @@ trait Trait<'a> { |
| 9 | 9 | fn method(&'a self) { } |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | #[rustc_variance] | |
| 12 | #[rustc_dump_variances] | |
| 13 | 13 | struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +] |
| 14 | 14 | field: (T, &'a ()) |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | #[rustc_variance] | |
| 17 | #[rustc_dump_variances] | |
| 18 | 18 | struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o] |
| 19 | 19 | field: <T as Trait<'a>>::Type |
| 20 | 20 | } |
tests/ui/variance/variance-object-types.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | // For better or worse, associated types are invariant, and hence we |
| 5 | 5 | // get an invariant result for `'a`. |
| 6 | #[rustc_variance] | |
| 6 | #[rustc_dump_variances] | |
| 7 | 7 | struct Foo<'a> { //~ ERROR ['a: o] |
| 8 | 8 | x: Box<dyn Fn(i32) -> &'a i32 + 'static> |
| 9 | 9 | } |
tests/ui/variance/variance-regions-direct.rs+7-7| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | // Regions that just appear in normal spots are contravariant: |
| 7 | 7 | |
| 8 | #[rustc_variance] | |
| 8 | #[rustc_dump_variances] | |
| 9 | 9 | struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +] |
| 10 | 10 | x: &'a isize, |
| 11 | 11 | y: &'b [isize], |
| ... | ... | @@ -14,7 +14,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +] |
| 14 | 14 | |
| 15 | 15 | // Those same annotations in function arguments become covariant: |
| 16 | 16 | |
| 17 | #[rustc_variance] | |
| 17 | #[rustc_dump_variances] | |
| 18 | 18 | struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -] |
| 19 | 19 | x: extern "Rust" fn(&'a isize), |
| 20 | 20 | y: extern "Rust" fn(&'b [isize]), |
| ... | ... | @@ -23,7 +23,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -] |
| 23 | 23 | |
| 24 | 24 | // Mutability induces invariance: |
| 25 | 25 | |
| 26 | #[rustc_variance] | |
| 26 | #[rustc_dump_variances] | |
| 27 | 27 | struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] |
| 28 | 28 | x: &'a mut &'b isize, |
| 29 | 29 | } |
| ... | ... | @@ -31,7 +31,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] |
| 31 | 31 | // Mutability induces invariance, even when in a |
| 32 | 32 | // contravariant context: |
| 33 | 33 | |
| 34 | #[rustc_variance] | |
| 34 | #[rustc_dump_variances] | |
| 35 | 35 | struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o] |
| 36 | 36 | x: extern "Rust" fn(&'a mut &'b isize), |
| 37 | 37 | } |
| ... | ... | @@ -41,14 +41,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o] |
| 41 | 41 | // an argument list (which is contravariant), that |
| 42 | 42 | // argument list occurs in an invariant context. |
| 43 | 43 | |
| 44 | #[rustc_variance] | |
| 44 | #[rustc_dump_variances] | |
| 45 | 45 | struct Test6<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o] |
| 46 | 46 | x: &'a mut extern "Rust" fn(&'b isize), |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | // No uses at all is bivariant: |
| 50 | 50 | |
| 51 | #[rustc_variance] | |
| 51 | #[rustc_dump_variances] | |
| 52 | 52 | struct Test7<'a> { //~ ERROR ['a: *] |
| 53 | 53 | //~^ ERROR: `'a` is never used |
| 54 | 54 | x: isize |
| ... | ... | @@ -56,7 +56,7 @@ struct Test7<'a> { //~ ERROR ['a: *] |
| 56 | 56 | |
| 57 | 57 | // Try enums too. |
| 58 | 58 | |
| 59 | #[rustc_variance] | |
| 59 | #[rustc_dump_variances] | |
| 60 | 60 | enum Test8<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] |
| 61 | 61 | Test8A(extern "Rust" fn(&'a isize)), |
| 62 | 62 | Test8B(&'b [isize]), |
tests/ui/variance/variance-regions-indirect.rs+5-5| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | #![feature(rustc_attrs)] |
| 6 | 6 | |
| 7 | #[rustc_variance] | |
| 7 | #[rustc_dump_variances] | |
| 8 | 8 | enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *] |
| 9 | 9 | //~^ ERROR: `'d` is never used |
| 10 | 10 | Test8A(extern "Rust" fn(&'a isize)), |
| ... | ... | @@ -12,25 +12,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *] |
| 12 | 12 | Test8C(&'b mut &'c str), |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | #[rustc_variance] | |
| 15 | #[rustc_dump_variances] | |
| 16 | 16 | struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR ['w: *, 'x: o, 'y: +, 'z: -] |
| 17 | 17 | //~^ ERROR: `'w` is never used |
| 18 | 18 | f: Base<'z, 'y, 'x, 'w> |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | #[rustc_variance] // Combine - and + to yield o | |
| 21 | #[rustc_dump_variances] // Combine - and + to yield o | |
| 22 | 22 | struct Derived2<'a, 'b:'a, 'c> { //~ ERROR ['a: o, 'b: o, 'c: *] |
| 23 | 23 | //~^ ERROR: `'c` is never used |
| 24 | 24 | f: Base<'a, 'a, 'b, 'c> |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) | |
| 27 | #[rustc_dump_variances] // Combine + and o to yield o (just pay attention to 'a here) | |
| 28 | 28 | struct Derived3<'a:'b, 'b, 'c> { //~ ERROR ['a: o, 'b: +, 'c: *] |
| 29 | 29 | //~^ ERROR: `'c` is never used |
| 30 | 30 | f: Base<'a, 'b, 'a, 'c> |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) | |
| 33 | #[rustc_dump_variances] // Combine + and * to yield + (just pay attention to 'a here) | |
| 34 | 34 | struct Derived4<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o] |
| 35 | 35 | f: Base<'a, 'b, 'c, 'a> |
| 36 | 36 | } |
tests/ui/variance/variance-trait-bounds.rs+4-4| ... | ... | @@ -12,24 +12,24 @@ trait Setter<T> { |
| 12 | 12 | fn get(&self, _: T); |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | #[rustc_variance] | |
| 15 | #[rustc_dump_variances] | |
| 16 | 16 | struct TestStruct<U,T:Setter<U>> { //~ ERROR [U: +, T: +] |
| 17 | 17 | t: T, u: U |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | #[rustc_variance] | |
| 20 | #[rustc_dump_variances] | |
| 21 | 21 | enum TestEnum<U,T:Setter<U>> { //~ ERROR [U: *, T: +] |
| 22 | 22 | //~^ ERROR: `U` is never used |
| 23 | 23 | Foo(T) |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | #[rustc_variance] | |
| 26 | #[rustc_dump_variances] | |
| 27 | 27 | struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [U: *, T: +] |
| 28 | 28 | //~^ ERROR: `U` is never used |
| 29 | 29 | t: T |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | #[rustc_variance] | |
| 32 | #[rustc_dump_variances] | |
| 33 | 33 | struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [U: *, T: +] |
| 34 | 34 | //~^ ERROR: `U` is never used |
| 35 | 35 | t: T |
tests/ui/variance/variance-trait-object-bound.rs+1-1| ... | ... | @@ -10,7 +10,7 @@ use std::mem; |
| 10 | 10 | |
| 11 | 11 | trait T { fn foo(&self); } |
| 12 | 12 | |
| 13 | #[rustc_variance] | |
| 13 | #[rustc_dump_variances] | |
| 14 | 14 | struct TOption<'a> { //~ ERROR ['a: +] |
| 15 | 15 | v: Option<Box<dyn T + 'a>>, |
| 16 | 16 | } |
tests/ui/variance/variance-types-bounds.rs+5-5| ... | ... | @@ -3,24 +3,24 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(rustc_attrs)] |
| 5 | 5 | |
| 6 | #[rustc_variance] | |
| 6 | #[rustc_dump_variances] | |
| 7 | 7 | struct TestImm<A, B> { //~ ERROR [A: +, B: +] |
| 8 | 8 | x: A, |
| 9 | 9 | y: B, |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | #[rustc_variance] | |
| 12 | #[rustc_dump_variances] | |
| 13 | 13 | struct TestMut<A, B:'static> { //~ ERROR [A: +, B: o] |
| 14 | 14 | x: A, |
| 15 | 15 | y: &'static mut B, |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | #[rustc_variance] | |
| 18 | #[rustc_dump_variances] | |
| 19 | 19 | struct TestIndirect<A:'static, B:'static> { //~ ERROR [A: +, B: o] |
| 20 | 20 | m: TestMut<A, B> |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | #[rustc_variance] | |
| 23 | #[rustc_dump_variances] | |
| 24 | 24 | struct TestIndirect2<A:'static, B:'static> { //~ ERROR [A: o, B: o] |
| 25 | 25 | n: TestMut<A, B>, |
| 26 | 26 | m: TestMut<B, A> |
| ... | ... | @@ -34,7 +34,7 @@ trait Setter<A> { |
| 34 | 34 | fn set(&mut self, a: A); |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | #[rustc_variance] | |
| 37 | #[rustc_dump_variances] | |
| 38 | 38 | struct TestObject<A, R> { //~ ERROR [A: o, R: o] |
| 39 | 39 | n: Box<dyn Setter<A>+Send>, |
| 40 | 40 | m: Box<dyn Getter<R>+Send>, |
tests/ui/variance/variance-types.rs+6-6| ... | ... | @@ -6,32 +6,32 @@ use std::cell::Cell; |
| 6 | 6 | // Check that a type parameter which is only used in a trait bound is |
| 7 | 7 | // not considered bivariant. |
| 8 | 8 | |
| 9 | #[rustc_variance] | |
| 9 | #[rustc_dump_variances] | |
| 10 | 10 | struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o] |
| 11 | 11 | t: &'a mut (A,B) |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | #[rustc_variance] | |
| 14 | #[rustc_dump_variances] | |
| 15 | 15 | struct InvariantCell<A> { //~ ERROR [A: o] |
| 16 | 16 | t: Cell<A> |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | #[rustc_variance] | |
| 19 | #[rustc_dump_variances] | |
| 20 | 20 | struct InvariantIndirect<A> { //~ ERROR [A: o] |
| 21 | 21 | t: InvariantCell<A> |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | #[rustc_variance] | |
| 24 | #[rustc_dump_variances] | |
| 25 | 25 | struct Covariant<A> { //~ ERROR [A: +] |
| 26 | 26 | t: A, u: fn() -> A |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | #[rustc_variance] | |
| 29 | #[rustc_dump_variances] | |
| 30 | 30 | struct Contravariant<A> { //~ ERROR [A: -] |
| 31 | 31 | t: fn(A) |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | #[rustc_variance] | |
| 34 | #[rustc_dump_variances] | |
| 35 | 35 | enum Enum<A,B,C> { //~ ERROR [A: +, B: -, C: o] |
| 36 | 36 | Foo(Covariant<A>), |
| 37 | 37 | Bar(Contravariant<B>), |
triagebot.toml+4-4| ... | ... | @@ -534,7 +534,7 @@ trigger_files = [ |
| 534 | 534 | [autolabel."A-translation"] |
| 535 | 535 | trigger_files = [ |
| 536 | 536 | "compiler/rustc_error_messages", |
| 537 | "compiler/rustc_errors/src/translation.rs", | |
| 537 | "compiler/rustc_errors/src/formatting.rs", | |
| 538 | 538 | "compiler/rustc_macros/src/diagnostics" |
| 539 | 539 | ] |
| 540 | 540 | |
| ... | ... | @@ -1180,8 +1180,8 @@ cc = ["@Muscraft"] |
| 1180 | 1180 | message = "`rustc_errors::emitter` was changed" |
| 1181 | 1181 | cc = ["@Muscraft"] |
| 1182 | 1182 | |
| 1183 | [mentions."compiler/rustc_errors/src/translation.rs"] | |
| 1184 | message = "`rustc_errors::translation` was changed" | |
| 1183 | [mentions."compiler/rustc_errors/src/formatting.rs"] | |
| 1184 | message = "`rustc_errors::formatting` was changed" | |
| 1185 | 1185 | cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"] |
| 1186 | 1186 | |
| 1187 | 1187 | [mentions."compiler/rustc_macros/src/diagnostics"] |
| ... | ... | @@ -1371,7 +1371,7 @@ cc = ["@ehuss"] |
| 1371 | 1371 | |
| 1372 | 1372 | [mentions."src/doc/rustc-dev-guide"] |
| 1373 | 1373 | message = "The rustc-dev-guide subtree was changed. If this PR *only* touches the dev guide consider submitting a PR directly to [rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide/pulls) otherwise thank you for updating the dev guide with your changes." |
| 1374 | cc = ["@BoxyUwU", "@jieyouxu", "@tshepang"] | |
| 1374 | cc = ["@BoxyUwU", "@tshepang"] | |
| 1375 | 1375 | |
| 1376 | 1376 | [mentions."compiler/rustc_passes/src/check_attr.rs"] |
| 1377 | 1377 | cc = ["@jdonszelmann", "@JonathanBrouwer"] |