authorbors <bors@rust-lang.org> 2026-03-05 00:14:57 UTC
committerbors <bors@rust-lang.org> 2026-03-05 00:14:57 UTC
logf8704be04fe1150527fc2cf21dd44327f0fe87fb
tree8b92af487814146f5926991f963dc99b822aa811
parentb55e20ad905a336395ca80863488d0827712d067
parent53ef4d297ed951adf7f95f2ee6617c03436f208d

Auto merge of #153416 - JonathanBrouwer:rollup-eezxWTV, r=JonathanBrouwer

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 @@
1use rustc_hir::Target;
21use rustc_hir::attrs::AttributeKind;
2use rustc_hir::{MethodKind, Target};
33use rustc_span::{Span, Symbol, sym};
44
55use crate::attributes::prelude::Allow;
......@@ -25,6 +25,20 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpDefParentsParser {
2525 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents;
2626}
2727
28pub(crate) struct RustcDumpInferredOutlivesParser;
29
30impl<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
2842pub(crate) struct RustcDumpItemBoundsParser;
2943
3044impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
......@@ -34,21 +48,88 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpItemBoundsParser {
3448 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds;
3549}
3650
51pub(crate) struct RustcDumpObjectLifetimeDefaultsParser;
52
53impl<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
3778pub(crate) struct RustcDumpPredicatesParser;
3879
3980impl<S: Stage> NoArgsAttributeParser<S> for RustcDumpPredicatesParser {
4081 const PATH: &[Symbol] = &[sym::rustc_dump_predicates];
4182 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
4283 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 }),
4489 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),
4698 Allow(Target::Trait),
47 Allow(Target::AssocTy),
99 Allow(Target::TraitAlias),
100 Allow(Target::TyAlias),
101 Allow(Target::Union),
48102 ]);
49103 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates;
50104}
51105
106pub(crate) struct RustcDumpVariancesParser;
107
108impl<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
124pub(crate) struct RustcDumpVariancesOfOpaquesParser;
125
126impl<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
52133pub(crate) struct RustcDumpVtableParser;
53134
54135impl<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
588588 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;
589589}
590590
591pub(crate) struct RustcObjectLifetimeDefaultParser;
592
593impl<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
600591pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
601592
602593impl<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 {
9393 }
9494}
9595
96pub(crate) struct RustcVarianceParser;
97
98impl<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
109pub(crate) struct RustcVarianceOfOpaquesParser;
110
111impl<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
11896pub(crate) struct ReexportTestHarnessMainParser;
11997
12098impl<S: Stage> SingleAttributeParser<S> for ReexportTestHarnessMainParser {
......@@ -215,20 +193,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcEvaluateWhereClausesParser {
215193 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses;
216194}
217195
218pub(crate) struct RustcOutlivesParser;
219
220impl<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
232196pub(crate) struct TestRunnerParser;
233197
234198impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
compiler/rustc_attr_parsing/src/context.rs+4-4
......@@ -281,9 +281,13 @@ attribute_parsers!(
281281 Single<WithoutArgs<RustcDenyExplicitImplParser>>,
282282 Single<WithoutArgs<RustcDoNotConstCheckParser>>,
283283 Single<WithoutArgs<RustcDumpDefParentsParser>>,
284 Single<WithoutArgs<RustcDumpInferredOutlivesParser>>,
284285 Single<WithoutArgs<RustcDumpItemBoundsParser>>,
286 Single<WithoutArgs<RustcDumpObjectLifetimeDefaultsParser>>,
285287 Single<WithoutArgs<RustcDumpPredicatesParser>>,
286288 Single<WithoutArgs<RustcDumpUserArgsParser>>,
289 Single<WithoutArgs<RustcDumpVariancesOfOpaquesParser>>,
290 Single<WithoutArgs<RustcDumpVariancesParser>>,
287291 Single<WithoutArgs<RustcDumpVtableParser>>,
288292 Single<WithoutArgs<RustcDynIncompatibleTraitParser>>,
289293 Single<WithoutArgs<RustcEffectiveVisibilityParser>>,
......@@ -306,9 +310,7 @@ attribute_parsers!(
306310 Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
307311 Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
308312 Single<WithoutArgs<RustcNounwindParser>>,
309 Single<WithoutArgs<RustcObjectLifetimeDefaultParser>>,
310313 Single<WithoutArgs<RustcOffloadKernelParser>>,
311 Single<WithoutArgs<RustcOutlivesParser>>,
312314 Single<WithoutArgs<RustcParenSugarParser>>,
313315 Single<WithoutArgs<RustcPassByValueParser>>,
314316 Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
......@@ -323,8 +325,6 @@ attribute_parsers!(
323325 Single<WithoutArgs<RustcStrictCoherenceParser>>,
324326 Single<WithoutArgs<RustcTrivialFieldReadsParser>>,
325327 Single<WithoutArgs<RustcUnsafeSpecializationMarkerParser>>,
326 Single<WithoutArgs<RustcVarianceOfOpaquesParser>>,
327 Single<WithoutArgs<RustcVarianceParser>>,
328328 Single<WithoutArgs<ThreadLocalParser>>,
329329 Single<WithoutArgs<TrackCallerParser>>,
330330 // tidy-alphabetical-end
compiler/rustc_borrowck/src/diagnostics/mod.rs+1-1
......@@ -1310,7 +1310,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
13101310 {
13111311 let mut span: MultiSpan = spans.clone().into();
13121312 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(
13141314 msg!("`{$ty}` is made to be an `FnOnce` closure here"),
13151315 err.args.iter(),
13161316 );
compiler/rustc_builtin_macros/src/errors.rs+3-3
......@@ -764,7 +764,7 @@ pub(crate) struct FormatUnusedArg {
764764impl Subdiagnostic for FormatUnusedArg {
765765 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
766766 diag.arg("named", self.named);
767 let msg = diag.eagerly_translate(msg!(
767 let msg = diag.eagerly_format(msg!(
768768 "{$named ->
769769 [true] named argument
770770 *[false] argument
......@@ -947,8 +947,8 @@ pub(crate) struct AsmClobberNoReg {
947947impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg {
948948 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
949949 // 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());
952952 Diag::new(
953953 dcx,
954954 level,
compiler/rustc_codegen_gcc/src/back/lto.rs+6-6
......@@ -26,7 +26,7 @@ use object::read::archive::ArchiveFile;
2626use rustc_codegen_ssa::back::lto::SerializedModule;
2727use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter};
2828use rustc_codegen_ssa::traits::*;
29use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
29use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file};
3030use rustc_data_structures::memmap::Mmap;
3131use rustc_data_structures::profiling::SelfProfilerRef;
3232use rustc_errors::{DiagCtxt, DiagCtxtHandle};
......@@ -34,7 +34,7 @@ use rustc_log::tracing::info;
3434use rustc_session::config::Lto;
3535use tempfile::{TempDir, tempdir};
3636
37use crate::back::write::save_temp_bitcode;
37use crate::back::write::{codegen, save_temp_bitcode};
3838use crate::errors::LtoBitcodeFromRlib;
3939use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level};
4040
......@@ -112,7 +112,7 @@ pub(crate) fn run_fat(
112112 shared_emitter: &SharedEmitter,
113113 each_linked_rlib_for_lto: &[PathBuf],
114114 modules: Vec<FatLtoInput<GccCodegenBackend>>,
115) -> ModuleCodegen<GccContext> {
115) -> CompiledModule {
116116 let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
117117 let dcx = dcx.handle();
118118 let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
......@@ -132,12 +132,12 @@ pub(crate) fn run_fat(
132132fn fat_lto(
133133 cgcx: &CodegenContext,
134134 prof: &SelfProfilerRef,
135 _dcx: DiagCtxtHandle<'_>,
135 dcx: DiagCtxtHandle<'_>,
136136 modules: Vec<FatLtoInput<GccCodegenBackend>>,
137137 mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
138138 tmp_path: TempDir,
139139 //symbols_below_threshold: &[String],
140) -> ModuleCodegen<GccContext> {
140) -> CompiledModule {
141141 let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module");
142142 info!("going for a fat lto");
143143
......@@ -260,7 +260,7 @@ fn fat_lto(
260260 // of now.
261261 module.module_llvm.temp_dir = Some(tmp_path);
262262
263 module
263 codegen(cgcx, prof, dcx, module, &cgcx.module_config)
264264}
265265
266266pub struct ModuleBuffer(PathBuf);
compiler/rustc_codegen_gcc/src/back/write.rs+3-8
......@@ -2,12 +2,10 @@ use std::{env, fs};
22
33use gccjit::{Context, OutputKind};
44use rustc_codegen_ssa::back::link::ensure_removed;
5use rustc_codegen_ssa::back::write::{
6 BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter,
7};
5use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
86use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
97use rustc_data_structures::profiling::SelfProfilerRef;
10use rustc_errors::DiagCtxt;
8use rustc_errors::DiagCtxtHandle;
119use rustc_fs_util::link_or_copy;
1210use rustc_log::tracing::debug;
1311use rustc_session::config::OutputType;
......@@ -20,13 +18,10 @@ use crate::{GccContext, LtoMode};
2018pub(crate) fn codegen(
2119 cgcx: &CodegenContext,
2220 prof: &SelfProfilerRef,
23 shared_emitter: &SharedEmitter,
21 dcx: DiagCtxtHandle<'_>,
2422 module: ModuleCodegen<GccContext>,
2523 config: &ModuleConfig,
2624) -> CompiledModule {
27 let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
28 let dcx = dcx.handle();
29
3025 let _timer = prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
3126 {
3227 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
9292use rustc_data_structures::fx::FxIndexMap;
9393use rustc_data_structures::profiling::SelfProfilerRef;
9494use rustc_data_structures::sync::IntoDynSyncSend;
95use rustc_errors::DiagCtxtHandle;
95use rustc_errors::{DiagCtxt, DiagCtxtHandle};
9696use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
9797use rustc_middle::ty::TyCtxt;
9898use rustc_middle::util::Providers;
......@@ -371,16 +371,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
371371 self.lto_supported.load(Ordering::SeqCst),
372372 )
373373 }
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 }
384374}
385375
386376#[derive(Clone, Copy, PartialEq)]
......@@ -429,7 +419,17 @@ impl WriteBackendMethods for GccCodegenBackend {
429419 type ModuleBuffer = ModuleBuffer;
430420 type ThinData = ();
431421
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(
433433 cgcx: &CodegenContext,
434434 prof: &SelfProfilerRef,
435435 shared_emitter: &SharedEmitter,
......@@ -438,7 +438,7 @@ impl WriteBackendMethods for GccCodegenBackend {
438438 _exported_symbols_for_lto: &[String],
439439 each_linked_rlib_for_lto: &[PathBuf],
440440 modules: Vec<FatLtoInput<Self>>,
441 ) -> ModuleCodegen<Self::Module> {
441 ) -> CompiledModule {
442442 back::lto::run_fat(cgcx, prof, shared_emitter, each_linked_rlib_for_lto, modules)
443443 }
444444
......@@ -455,14 +455,6 @@ impl WriteBackendMethods for GccCodegenBackend {
455455 unreachable!()
456456 }
457457
458 fn print_pass_timings(&self) {
459 unimplemented!();
460 }
461
462 fn print_statistics(&self) {
463 unimplemented!()
464 }
465
466458 fn optimize(
467459 _cgcx: &CodegenContext,
468460 _prof: &SelfProfilerRef,
......@@ -473,13 +465,13 @@ impl WriteBackendMethods for GccCodegenBackend {
473465 module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
474466 }
475467
476 fn optimize_thin(
468 fn optimize_and_codegen_thin(
477469 _cgcx: &CodegenContext,
478470 _prof: &SelfProfilerRef,
479471 _shared_emitter: &SharedEmitter,
480472 _tm_factory: TargetMachineFactoryFn<Self>,
481473 _thin: ThinModule<Self>,
482 ) -> ModuleCodegen<Self::Module> {
474 ) -> CompiledModule {
483475 unreachable!()
484476 }
485477
......@@ -490,7 +482,9 @@ impl WriteBackendMethods for GccCodegenBackend {
490482 module: ModuleCodegen<Self::Module>,
491483 config: &ModuleConfig,
492484 ) -> 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)
494488 }
495489
496490 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::{
1212 CodegenContext, FatLtoInput, SharedEmitter, TargetMachineFactoryFn,
1313};
1414use rustc_codegen_ssa::traits::*;
15use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
15use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind, looks_like_rust_object_file};
1616use rustc_data_structures::fx::FxHashMap;
1717use rustc_data_structures::memmap::Mmap;
1818use rustc_data_structures::profiling::SelfProfilerRef;
......@@ -24,7 +24,8 @@ use rustc_session::config::{self, Lto};
2424use tracing::{debug, info};
2525
2626use 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,
2829};
2930use crate::errors::{LlvmError, LtoBitcodeFromRlib};
3031use crate::llvm::{self, build_string};
......@@ -709,13 +710,13 @@ impl ModuleBufferMethods for ModuleBuffer {
709710 }
710711}
711712
712pub(crate) fn optimize_thin_module(
713pub(crate) fn optimize_and_codegen_thin_module(
713714 cgcx: &CodegenContext,
714715 prof: &SelfProfilerRef,
715716 shared_emitter: &SharedEmitter,
716717 tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
717718 thin_module: ThinModule<LlvmCodegenBackend>,
718) -> ModuleCodegen<ModuleLlvm> {
719) -> CompiledModule {
719720 let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
720721 let dcx = dcx.handle();
721722
......@@ -794,7 +795,7 @@ pub(crate) fn optimize_thin_module(
794795 save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
795796 }
796797 }
797 module
798 codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config)
798799}
799800
800801/// 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(
335335 &module.name,
336336 cgcx.invocation_temp.as_deref(),
337337 );
338 write_bitcode_to_file(module, &path)
338 write_bitcode_to_file(&module.module_llvm, &path)
339339}
340340
341fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) {
341fn write_bitcode_to_file(module: &ModuleLlvm, path: &Path) {
342342 unsafe {
343343 let path = path_to_c_string(&path);
344 let llmod = module.module_llvm.llmod();
344 let llmod = module.llmod();
345345 llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr());
346346 }
347347}
......@@ -905,13 +905,8 @@ pub(crate) fn optimize(
905905 let _handlers =
906906 DiagnosticHandlers::new(cgcx, shared_emitter, llcx, module, CodegenDiagnosticsStage::Opt);
907907
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");
915910 }
916911
917912 // 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<'_> {
2424 fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
2525 let diag: Diag<'_, G> = self.0.into_diag(dcx, level);
2626 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());
2828 Diag::new(
2929 dcx,
3030 level,
compiler/rustc_codegen_llvm/src/lib.rs+30-47
......@@ -79,24 +79,18 @@ pub(crate) use macros::TryFromU32;
7979#[derive(Clone)]
8080pub struct LlvmCodegenBackend(());
8181
82struct TimeTraceProfiler {
83 enabled: bool,
84}
82struct TimeTraceProfiler {}
8583
8684impl 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 {}
9288 }
9389}
9490
9591impl Drop for TimeTraceProfiler {
9692 fn drop(&mut self) {
97 if self.enabled {
98 unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() }
99 }
93 unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() }
10094 }
10195}
10296
......@@ -122,30 +116,6 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
122116 ) -> (ModuleCodegen<ModuleLlvm>, u64) {
123117 base::compile_codegen_unit(tcx, cgu_name)
124118 }
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 }
149119}
150120
151121impl WriteBackendMethods for LlvmCodegenBackend {
......@@ -153,15 +123,18 @@ impl WriteBackendMethods for LlvmCodegenBackend {
153123 type ModuleBuffer = back::lto::ModuleBuffer;
154124 type TargetMachine = OwnedTargetMachine;
155125 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())
159128 }
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)
163136 }
164 fn run_and_optimize_fat_lto(
137 fn optimize_and_codegen_fat_lto(
165138 cgcx: &CodegenContext,
166139 prof: &SelfProfilerRef,
167140 shared_emitter: &SharedEmitter,
......@@ -169,7 +142,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
169142 exported_symbols_for_lto: &[String],
170143 each_linked_rlib_for_lto: &[PathBuf],
171144 modules: Vec<FatLtoInput<Self>>,
172 ) -> ModuleCodegen<Self::Module> {
145 ) -> CompiledModule {
173146 let mut module = back::lto::run_fat(
174147 cgcx,
175148 prof,
......@@ -184,7 +157,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
184157 let dcx = dcx.handle();
185158 back::lto::run_pass_manager(cgcx, prof, dcx, &mut module, false);
186159
187 module
160 back::write::codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config)
188161 }
189162 fn run_thin_lto(
190163 cgcx: &CodegenContext,
......@@ -214,14 +187,14 @@ impl WriteBackendMethods for LlvmCodegenBackend {
214187 ) {
215188 back::write::optimize(cgcx, prof, shared_emitter, module, config)
216189 }
217 fn optimize_thin(
190 fn optimize_and_codegen_thin(
218191 cgcx: &CodegenContext,
219192 prof: &SelfProfilerRef,
220193 shared_emitter: &SharedEmitter,
221194 tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
222195 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)
225198 }
226199 fn codegen(
227200 cgcx: &CodegenContext,
......@@ -389,6 +362,16 @@ impl CodegenBackend for LlvmCodegenBackend {
389362 (compiled_modules, work_products)
390363 }
391364
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
392375 fn link(
393376 &self,
394377 sess: &Session,
compiler/rustc_codegen_ssa/src/back/write.rs+38-41
......@@ -94,7 +94,6 @@ pub struct ModuleConfig {
9494
9595 // Flags indicating which outputs to produce.
9696 pub emit_pre_lto_bc: bool,
97 pub emit_no_opt_bc: bool,
9897 pub emit_bc: bool,
9998 pub emit_ir: bool,
10099 pub emit_asm: bool,
......@@ -195,7 +194,6 @@ impl ModuleConfig {
195194 save_temps || need_pre_lto_bitcode_for_incr_comp(sess),
196195 false
197196 ),
198 emit_no_opt_bc: if_regular!(save_temps, false),
199197 emit_bc: if_regular!(
200198 save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode),
201199 save_temps
......@@ -356,7 +354,7 @@ pub struct CodegenContext {
356354 pub parallel: bool,
357355}
358356
359fn generate_thin_lto_work<B: ExtraBackendMethods>(
357fn generate_thin_lto_work<B: WriteBackendMethods>(
360358 cgcx: &CodegenContext,
361359 prof: &SelfProfilerRef,
362360 dcx: DiagCtxtHandle<'_>,
......@@ -824,7 +822,7 @@ pub(crate) fn compute_per_cgu_lto_type(
824822 }
825823}
826824
827fn execute_optimize_work_item<B: ExtraBackendMethods>(
825fn execute_optimize_work_item<B: WriteBackendMethods>(
828826 cgcx: &CodegenContext,
829827 prof: &SelfProfilerRef,
830828 shared_emitter: SharedEmitter,
......@@ -969,7 +967,7 @@ fn execute_copy_from_cache_work_item(
969967 }
970968}
971969
972fn do_fat_lto<B: ExtraBackendMethods>(
970fn do_fat_lto<B: WriteBackendMethods>(
973971 cgcx: &CodegenContext,
974972 prof: &SelfProfilerRef,
975973 shared_emitter: SharedEmitter,
......@@ -990,7 +988,7 @@ fn do_fat_lto<B: ExtraBackendMethods>(
990988 needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module })
991989 }
992990
993 let module = B::run_and_optimize_fat_lto(
991 B::optimize_and_codegen_fat_lto(
994992 cgcx,
995993 prof,
996994 &shared_emitter,
......@@ -998,11 +996,10 @@ fn do_fat_lto<B: ExtraBackendMethods>(
998996 exported_symbols_for_lto,
999997 each_linked_rlib_for_lto,
1000998 needs_fat_lto,
1001 );
1002 B::codegen(cgcx, prof, &shared_emitter, module, &cgcx.module_config)
999 )
10031000}
10041001
1005fn do_thin_lto<B: ExtraBackendMethods>(
1002fn do_thin_lto<B: WriteBackendMethods>(
10061003 cgcx: &CodegenContext,
10071004 prof: &SelfProfilerRef,
10081005 shared_emitter: SharedEmitter,
......@@ -1155,7 +1152,7 @@ fn do_thin_lto<B: ExtraBackendMethods>(
11551152 compiled_modules
11561153}
11571154
1158fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
1155fn execute_thin_lto_work_item<B: WriteBackendMethods>(
11591156 cgcx: &CodegenContext,
11601157 prof: &SelfProfilerRef,
11611158 shared_emitter: SharedEmitter,
......@@ -1164,8 +1161,7 @@ fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
11641161) -> CompiledModule {
11651162 let _timer = prof.generic_activity_with_arg("codegen_module_perform_lto", module.name());
11661163
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)
11691165}
11701166
11711167/// Messages sent to the coordinator.
......@@ -1472,7 +1468,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
14721468 // Each LLVM module is automatically sent back to the coordinator for LTO if
14731469 // necessary. There's already optimizations in place to avoid sending work
14741470 // 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
14761474 // This is where we collect codegen units that have gone all the way
14771475 // through codegen and LLVM.
14781476 let mut compiled_modules = vec![];
......@@ -1813,8 +1811,11 @@ fn start_executing_work<B: ExtraBackendMethods>(
18131811 B::codegen(&cgcx, &prof, &shared_emitter, allocator_module, &allocator_config)
18141812 }),
18151813 }))
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");
18181819
18191820 // A heuristic that determines if we have enough LLVM WorkItems in the
18201821 // queue so that the main thread can do LLVM work instead of codegen
......@@ -1878,7 +1879,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
18781879#[must_use]
18791880pub(crate) struct WorkerFatalError;
18801881
1881fn spawn_work<'a, B: ExtraBackendMethods>(
1882fn spawn_work<'a, B: WriteBackendMethods>(
18821883 cgcx: &CodegenContext,
18831884 prof: &'a SelfProfilerRef,
18841885 shared_emitter: SharedEmitter,
......@@ -1893,7 +1894,10 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
18931894 let cgcx = cgcx.clone();
18941895 let prof = prof.clone();
18951896
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
18971901 let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work {
18981902 WorkItem::Optimize(m) => execute_optimize_work_item(&cgcx, &prof, shared_emitter, m),
18991903 WorkItem::CopyPostLtoArtifacts(m) => WorkItemResult::Finished(
......@@ -1914,11 +1918,11 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
19141918 Err(_) => Message::WorkItem::<B> { result: Err(None) },
19151919 };
19161920 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");
19191923}
19201924
1921fn spawn_thin_lto_work<B: ExtraBackendMethods>(
1925fn spawn_thin_lto_work<B: WriteBackendMethods>(
19221926 cgcx: &CodegenContext,
19231927 prof: &SelfProfilerRef,
19241928 shared_emitter: SharedEmitter,
......@@ -1929,7 +1933,10 @@ fn spawn_thin_lto_work<B: ExtraBackendMethods>(
19291933 let cgcx = cgcx.clone();
19301934 let prof = prof.clone();
19311935
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
19331940 let result = std::panic::catch_unwind(AssertUnwindSafe(|| match work {
19341941 ThinLtoWorkItem::CopyPostLtoArtifacts(m) => {
19351942 execute_copy_from_cache_work_item(&cgcx, &prof, shared_emitter, m)
......@@ -1952,8 +1959,8 @@ fn spawn_thin_lto_work<B: ExtraBackendMethods>(
19521959 Err(_) => ThinLtoMessage::WorkItem { result: Err(None) },
19531960 };
19541961 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");
19571964}
19581965
19591966enum SharedEmitterMessage {
......@@ -2102,20 +2109,20 @@ impl SharedEmitterMain {
21022109 }
21032110}
21042111
2105pub struct Coordinator<B: ExtraBackendMethods> {
2112pub struct Coordinator<B: WriteBackendMethods> {
21062113 sender: Sender<Message<B>>,
21072114 future: Option<thread::JoinHandle<Result<MaybeLtoModules<B>, ()>>>,
21082115 // Only used for the Message type.
21092116 phantom: PhantomData<B>,
21102117}
21112118
2112impl<B: ExtraBackendMethods> Coordinator<B> {
2119impl<B: WriteBackendMethods> Coordinator<B> {
21132120 fn join(mut self) -> std::thread::Result<Result<MaybeLtoModules<B>, ()>> {
21142121 self.future.take().unwrap().join()
21152122 }
21162123}
21172124
2118impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
2125impl<B: WriteBackendMethods> Drop for Coordinator<B> {
21192126 fn drop(&mut self) {
21202127 if let Some(future) = self.future.take() {
21212128 // 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> {
21262133 }
21272134}
21282135
2129pub struct OngoingCodegen<B: ExtraBackendMethods> {
2136pub struct OngoingCodegen<B: WriteBackendMethods> {
21302137 pub backend: B,
21312138 pub output_filenames: Arc<OutputFilenames>,
21322139 // Field order below is intended to terminate the coordinator thread before two fields below
......@@ -2137,7 +2144,7 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
21372144 pub shared_emitter_main: SharedEmitterMain,
21382145}
21392146
2140impl<B: ExtraBackendMethods> OngoingCodegen<B> {
2147impl<B: WriteBackendMethods> OngoingCodegen<B> {
21412148 pub fn join(self, sess: &Session) -> (CompiledModules, FxIndexMap<WorkProductId, WorkProduct>) {
21422149 self.shared_emitter_main.check(sess, true);
21432150
......@@ -2234,16 +2241,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
22342241 copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess, &compiled_modules);
22352242 produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);
22362243
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
22472244 (compiled_modules, work_products)
22482245 }
22492246
......@@ -2270,7 +2267,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
22702267 }
22712268}
22722269
2273pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>(
2270pub(crate) fn submit_codegened_module_to_llvm<B: WriteBackendMethods>(
22742271 coordinator: &Coordinator<B>,
22752272 module: ModuleCodegen<B::Module>,
22762273 cost: u64,
......@@ -2279,7 +2276,7 @@ pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>(
22792276 drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost }));
22802277}
22812278
2282pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>(
2279pub(crate) fn submit_post_lto_module_to_llvm<B: WriteBackendMethods>(
22832280 coordinator: &Coordinator<B>,
22842281 module: CachedModuleCodegen,
22852282) {
......@@ -2287,7 +2284,7 @@ pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>(
22872284 drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost: 0 }));
22882285}
22892286
2290pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
2287pub(crate) fn submit_pre_lto_module_to_llvm<B: WriteBackendMethods>(
22912288 tcx: TyCtxt<'_>,
22922289 coordinator: &Coordinator<B>,
22932290 module: CachedModuleCodegen,
compiler/rustc_codegen_ssa/src/traits/backend.rs+5-22
......@@ -10,14 +10,13 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
1010use rustc_middle::ty::TyCtxt;
1111use rustc_middle::util::Providers;
1212use rustc_session::Session;
13use rustc_session::config::{self, CrateType, OutputFilenames, PrintRequest};
13use rustc_session::config::{CrateType, OutputFilenames, PrintRequest};
1414use rustc_span::Symbol;
1515
1616use super::CodegenObject;
1717use super::write::WriteBackendMethods;
1818use crate::back::archive::ArArchiveBuilderBuilder;
1919use crate::back::link::link_binary;
20use crate::back::write::TargetMachineFactoryFn;
2120use crate::{CompiledModules, CrateInfo, ModuleCodegen, TargetConfig};
2221
2322pub trait BackendTypes {
......@@ -119,6 +118,10 @@ pub trait CodegenBackend {
119118 outputs: &OutputFilenames,
120119 ) -> (CompiledModules, FxIndexMap<WorkProductId, WorkProduct>);
121120
121 fn print_pass_timings(&self) {}
122
123 fn print_statistics(&self) {}
124
122125 /// This is called on the returned [`CompiledModules`] from [`join_codegen`](Self::join_codegen).
123126 fn link(
124127 &self,
......@@ -158,26 +161,6 @@ pub trait ExtraBackendMethods:
158161 cgu_name: Symbol,
159162 ) -> (ModuleCodegen<Self::Module>, u64);
160163
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
181164 /// Returns `true` if this backend can be safely called from multiple threads.
182165 ///
183166 /// Defaults to `true`.
compiler/rustc_codegen_ssa/src/traits/write.rs+15-6
......@@ -1,8 +1,10 @@
1use std::any::Any;
12use std::path::PathBuf;
23
34use rustc_data_structures::profiling::SelfProfilerRef;
45use rustc_errors::DiagCtxtHandle;
56use rustc_middle::dep_graph::WorkProduct;
7use rustc_session::{Session, config};
68
79use crate::back::lto::{SerializedModule, ThinModule};
810use crate::back::write::{
......@@ -16,9 +18,18 @@ pub trait WriteBackendMethods: Clone + 'static {
1618 type ModuleBuffer: ModuleBufferMethods;
1719 type ThinData: Send + Sync;
1820
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>;
1930 /// Performs fat LTO by merging all modules into a single one, running autodiff
2031 /// if necessary and running any further optimizations
21 fn run_and_optimize_fat_lto(
32 fn optimize_and_codegen_fat_lto(
2233 cgcx: &CodegenContext,
2334 prof: &SelfProfilerRef,
2435 shared_emitter: &SharedEmitter,
......@@ -26,7 +37,7 @@ pub trait WriteBackendMethods: Clone + 'static {
2637 exported_symbols_for_lto: &[String],
2738 each_linked_rlib_for_lto: &[PathBuf],
2839 modules: Vec<FatLtoInput<Self>>,
29 ) -> ModuleCodegen<Self::Module>;
40 ) -> CompiledModule;
3041 /// Performs thin LTO by performing necessary global analysis and returning two
3142 /// lists, one of the modules that need optimization and another for modules that
3243 /// can simply be copied over from the incr. comp. cache.
......@@ -39,8 +50,6 @@ pub trait WriteBackendMethods: Clone + 'static {
3950 modules: Vec<(String, Self::ModuleBuffer)>,
4051 cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
4152 ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>);
42 fn print_pass_timings(&self);
43 fn print_statistics(&self);
4453 fn optimize(
4554 cgcx: &CodegenContext,
4655 prof: &SelfProfilerRef,
......@@ -48,13 +57,13 @@ pub trait WriteBackendMethods: Clone + 'static {
4857 module: &mut ModuleCodegen<Self::Module>,
4958 config: &ModuleConfig,
5059 );
51 fn optimize_thin(
60 fn optimize_and_codegen_thin(
5261 cgcx: &CodegenContext,
5362 prof: &SelfProfilerRef,
5463 shared_emitter: &SharedEmitter,
5564 tm_factory: TargetMachineFactoryFn<Self>,
5665 thin: ThinModule<Self>,
57 ) -> ModuleCodegen<Self::Module>;
66 ) -> CompiledModule;
5867 fn codegen(
5968 cgcx: &CodegenContext,
6069 prof: &SelfProfilerRef,
compiler/rustc_const_eval/src/errors.rs+6-6
......@@ -366,7 +366,7 @@ impl Subdiagnostic for FrameNote {
366366 if self.has_label && !self.span.is_dummy() {
367367 span.push_span_label(self.span, msg!("the failure occurred here"));
368368 }
369 let msg = diag.eagerly_translate(msg!(
369 let msg = diag.eagerly_format(msg!(
370370 r#"{$times ->
371371 [0] inside {$where_ ->
372372 [closure] closure
......@@ -624,7 +624,7 @@ pub trait ReportErrorExt {
624624 let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into()));
625625 let message = self.diagnostic_message();
626626 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());
628628 diag.cancel();
629629 s
630630 })
......@@ -1086,12 +1086,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
10861086 }
10871087
10881088 let message = if let Some(path) = self.path {
1089 err.dcx.eagerly_translate_to_string(
1089 err.dcx.eagerly_format_to_string(
10901090 msg!("constructing invalid value at {$path}"),
10911091 [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
10921092 )
10931093 } 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())
10951095 };
10961096
10971097 err.arg("front_matter", message);
......@@ -1122,7 +1122,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
11221122 ("hi".into(), DiagArgValue::Str(hi.to_string().into())),
11231123 ];
11241124 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);
11261126 err.arg("in_range", message);
11271127 }
11281128
......@@ -1144,7 +1144,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
11441144 ExpectedKind::EnumTag => msg!("expected a valid enum tag"),
11451145 ExpectedKind::Str => msg!("expected a string"),
11461146 };
1147 let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter());
1147 let msg = err.dcx.eagerly_format_to_string(msg, [].into_iter());
11481148 err.arg("expected", msg);
11491149 }
11501150 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
235235 let mut diag = dcx.struct_allow("");
236236 let msg = e.diagnostic_message();
237237 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());
239239 diag.cancel();
240240 s
241241}
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))
338338 }
339339 }
340340
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)
342346 });
343347
344348 // Linking is done outside the `compiler.enter()` so that the
compiler/rustc_error_codes/src/error_codes/E0208.md-45
......@@ -1,47 +1,2 @@
11#### This error code is internal to the compiler and will not be emitted with normal Rust code.
22#### Note: this error code is no longer emitted by the compiler.
3
4This error code shows the variance of a type's generic parameters.
5
6Erroneous 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]
15struct Foo<'a, T> { // error: deliberate error to display type's variance
16 t: &'a mut T,
17}
18```
19
20which produces the following error:
21
22```text
23error: [-, o]
24 --> <anon>:4:1
25 |
264 | 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
33This error is deliberately triggered with the `#[rustc_variance]` attribute
34(`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance
35of the type's generic parameters. You can read more about variance and
36subtyping in [this section of the Rustonomicon]. For a more in depth look at
37variance (including a more complete list of common variances) see
38[this section of the Reference]. For information on how variance is implemented
39in the compiler, see [this section of `rustc-dev-guide`].
40
41This error can be easily fixed by removing the `#[rustc_variance]` attribute,
42the 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::{
2626 ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different,
2727 normalize_whitespace, should_show_source_code,
2828};
29use crate::translation::{format_diag_message, format_diag_messages};
29use crate::formatting::{format_diag_message, format_diag_messages};
3030use crate::{
3131 CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag,
3232 SuggestionStyle, TerminalUrl,
compiler/rustc_errors/src/decorate_diag.rs+1-1
......@@ -7,7 +7,7 @@ use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId};
77
88use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
99
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
1111/// variants requires types we don't have yet. So, handle that case separately.
1212pub enum DecorateDiagCompat {
1313 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
138138 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
139139}
140140
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"]
144pub 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
149141#[derive(Clone, Debug, Encodable, Decodable)]
150142pub(crate) struct DiagLocation {
151143 file: Cow<'static, str>,
......@@ -1143,7 +1135,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
11431135 } }
11441136
11451137 /// 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
11471139 /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
11481140 /// interpolated variables).
11491141 pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
......@@ -1153,12 +1145,12 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
11531145
11541146 /// Fluent variables are not namespaced from each other, so when
11551147 /// `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
11571149 /// diagnostic uses the variables defined right then, before the
11581150 /// clobbering occurs.
1159 pub fn eagerly_translate(&self, msg: impl Into<DiagMessage>) -> DiagMessage {
1151 pub fn eagerly_format(&self, msg: impl Into<DiagMessage>) -> DiagMessage {
11601152 let args = self.args.iter();
1161 self.dcx.eagerly_translate(msg.into(), args)
1153 self.dcx.eagerly_format(msg.into(), args)
11621154 }
11631155
11641156 with_fn! { with_span,
compiler/rustc_errors/src/emitter.rs+1-1
......@@ -23,8 +23,8 @@ use rustc_span::source_map::SourceMap;
2323use rustc_span::{FileName, SourceFile, Span};
2424use tracing::{debug, warn};
2525
26use crate::formatting::format_diag_message;
2627use crate::timings::TimingRecord;
27use crate::translation::format_diag_message;
2828use crate::{
2929 CodeSuggestion, DiagInner, DiagMessage, Level, MultiSpan, Style, Subdiag, SuggestionStyle,
3030};
compiler/rustc_errors/src/formatting.rs created+62
......@@ -0,0 +1,62 @@
1use std::borrow::Cow;
2
3pub use rustc_error_messages::FluentArgs;
4use rustc_error_messages::{DiagArgMap, langid, register_functions};
5use tracing::{debug, trace};
6
7use crate::fluent_bundle::FluentResource;
8use 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.
12fn 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
27pub 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
35pub 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::{
3030 ColorConfig, Destination, Emitter, HumanReadableErrorType, OutputTheme, TimingEvent,
3131 should_show_source_code,
3232};
33use crate::formatting::{format_diag_message, format_diag_messages};
3334use crate::timings::{TimingRecord, TimingSection};
34use crate::translation::{format_diag_message, format_diag_messages};
3535use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl};
3636
3737#[cfg(test)]
......@@ -299,9 +299,9 @@ impl Diagnostic {
299299 /// Converts from `rustc_errors::DiagInner` to `Diagnostic`.
300300 fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic {
301301 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);
303303 Diagnostic {
304 message: translated_message.to_string(),
304 message: formatted_message.to_string(),
305305 code: None,
306306 level: "help",
307307 spans: DiagnosticSpan::from_suggestion(sugg, &diag.args, je),
......@@ -330,7 +330,7 @@ impl Diagnostic {
330330 }
331331 }
332332
333 let translated_message = format_diag_messages(&diag.messages, &diag.args);
333 let formatted_message = format_diag_messages(&diag.messages, &diag.args);
334334
335335 let code = if let Some(code) = diag.code {
336336 Some(DiagnosticCode {
......@@ -380,7 +380,7 @@ impl Diagnostic {
380380 let buf = String::from_utf8(buf).unwrap();
381381
382382 Diagnostic {
383 message: translated_message.to_string(),
383 message: formatted_message.to_string(),
384384 code,
385385 level,
386386 spans,
......@@ -390,9 +390,9 @@ impl Diagnostic {
390390 }
391391
392392 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);
394394 Diagnostic {
395 message: translated_message.to_string(),
395 message: formatted_message.to_string(),
396396 code: None,
397397 level: subdiag.level.to_str(),
398398 spans: DiagnosticSpan::from_multispan(&subdiag.span, args, je),
compiler/rustc_errors/src/lib.rs+18-20
......@@ -7,9 +7,7 @@
77#![allow(rustc::direct_use_of_rustc_type_ir)]
88#![cfg_attr(bootstrap, feature(assert_matches))]
99#![feature(associated_type_defaults)]
10#![feature(box_patterns)]
1110#![feature(default_field_values)]
12#![feature(error_reporter)]
1311#![feature(macro_metavar_expr_concat)]
1412#![feature(negative_impls)]
1513#![feature(never_type)]
......@@ -40,7 +38,7 @@ pub use codes::*;
4038pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
4139pub use diagnostic::{
4240 BugAbort, Diag, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort,
43 LintDiagnostic, StringPart, Subdiag, Subdiagnostic,
41 StringPart, Subdiag, Subdiagnostic,
4442};
4543pub use diagnostic_impls::{
4644 DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
......@@ -68,8 +66,8 @@ use rustc_span::{DUMMY_SP, Span};
6866use tracing::debug;
6967
7068use crate::emitter::TimingEvent;
69use crate::formatting::format_diag_message;
7170use crate::timings::TimingRecord;
72use crate::translation::format_diag_message;
7371
7472pub mod annotate_snippet_emitter_writer;
7573pub mod codes;
......@@ -77,11 +75,11 @@ mod decorate_diag;
7775mod diagnostic;
7876mod diagnostic_impls;
7977pub mod emitter;
78pub mod formatting;
8079pub mod json;
8180mod lock;
8281pub mod markdown;
8382pub mod timings;
84pub mod translation;
8583
8684pub type PResult<'a, T> = Result<T, Diag<'a>>;
8785
......@@ -484,24 +482,24 @@ impl DiagCtxt {
484482 self.inner.borrow_mut().emitter = emitter;
485483 }
486484
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>(
489487 &self,
490488 message: DiagMessage,
491489 args: impl Iterator<Item = DiagArg<'a>>,
492490 ) -> DiagMessage {
493491 let inner = self.inner.borrow();
494 inner.eagerly_translate(message, args)
492 inner.eagerly_format(message, args)
495493 }
496494
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>(
499497 &self,
500498 message: DiagMessage,
501499 args: impl Iterator<Item = DiagArg<'a>>,
502500 ) -> String {
503501 let inner = self.inner.borrow();
504 inner.eagerly_translate_to_string(message, args)
502 inner.eagerly_format_to_string(message, args)
505503 }
506504
507505 // This is here to not allow mutation of flags;
......@@ -1419,17 +1417,17 @@ impl DiagCtxtInner {
14191417 self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
14201418 }
14211419
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>(
14241422 &self,
14251423 message: DiagMessage,
14261424 args: impl Iterator<Item = DiagArg<'a>>,
14271425 ) -> 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)))
14291427 }
14301428
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>(
14331431 &self,
14341432 message: DiagMessage,
14351433 args: impl Iterator<Item = DiagArg<'a>>,
......@@ -1438,12 +1436,12 @@ impl DiagCtxtInner {
14381436 format_diag_message(&message, &args).to_string()
14391437 }
14401438
1441 fn eagerly_translate_for_subdiag(
1439 fn eagerly_format_for_subdiag(
14421440 &self,
14431441 diag: &DiagInner,
14441442 msg: impl Into<DiagMessage>,
14451443 ) -> DiagMessage {
1446 self.eagerly_translate(msg.into(), diag.args.iter())
1444 self.eagerly_format(msg.into(), diag.args.iter())
14471445 }
14481446
14491447 fn flush_delayed(&mut self) {
......@@ -1509,7 +1507,7 @@ impl DiagCtxtInner {
15091507 let msg = msg!(
15101508 "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
15111509 );
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
15131511 bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
15141512 }
15151513 bug.level = Bug;
......@@ -1560,7 +1558,7 @@ impl DelayedDiagInner {
15601558 };
15611559 diag.arg("emitted_at", diag.emitted_at.clone());
15621560 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
15641562 diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into());
15651563 diag
15661564 }
compiler/rustc_errors/src/translation.rs deleted-68
......@@ -1,68 +0,0 @@
1use std::borrow::Cow;
2
3pub use rustc_error_messages::FluentArgs;
4use rustc_error_messages::{DiagArgMap, langid, register_functions};
5use tracing::{debug, trace};
6
7use crate::fluent_bundle::FluentResource;
8use 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.
15fn 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
30pub 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
38pub 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] = &[
13301330 safety: AttributeSafety::Normal,
13311331 template: template!(NameValueStr: "name"),
13321332 duplicates: ErrorFollowing,
1333 gate: Gated{
1333 gate: Gated {
13341334 feature: sym::rustc_attrs,
13351335 message: "use of an internal attribute",
13361336 check: Features::rustc_attrs,
......@@ -1419,7 +1419,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
14191419
14201420 rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
14211421 rustc_attr!(
1422 TEST, rustc_outlives, Normal, template!(Word),
1422 TEST, rustc_dump_inferred_outlives, Normal, template!(Word),
14231423 WarnFollowing, EncodeCrossCrate::No
14241424 ),
14251425 rustc_attr!(
......@@ -1439,11 +1439,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
14391439 WarnFollowing, EncodeCrossCrate::Yes
14401440 ),
14411441 rustc_attr!(
1442 TEST, rustc_variance, Normal, template!(Word),
1442 TEST, rustc_dump_variances, Normal, template!(Word),
14431443 WarnFollowing, EncodeCrossCrate::No
14441444 ),
14451445 rustc_attr!(
1446 TEST, rustc_variance_of_opaques, Normal, template!(Word),
1446 TEST, rustc_dump_variances_of_opaques, Normal, template!(Word),
14471447 WarnFollowing, EncodeCrossCrate::No
14481448 ),
14491449 rustc_attr!(
......@@ -1531,7 +1531,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
15311531 WarnFollowing, EncodeCrossCrate::No
15321532 ),
15331533 rustc_attr!(
1534 TEST, rustc_object_lifetime_default, Normal, template!(Word),
1534 TEST, rustc_dump_object_lifetime_defaults, Normal, template!(Word),
15351535 WarnFollowing, EncodeCrossCrate::No
15361536 ),
15371537 rustc_attr!(
compiler/rustc_feature/src/lib.rs+1-1
......@@ -137,5 +137,5 @@ pub use builtin_attrs::{
137137pub use removed::REMOVED_LANG_FEATURES;
138138pub use unstable::{
139139 DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES,
140 UNSTABLE_LANG_FEATURES,
140 TRACK_FEATURE, UNSTABLE_LANG_FEATURES,
141141};
compiler/rustc_feature/src/unstable.rs+14-2
......@@ -3,11 +3,18 @@
33use std::path::PathBuf;
44use std::time::{SystemTime, UNIX_EPOCH};
55
6use rustc_data_structures::AtomicRef;
67use rustc_data_structures::fx::FxHashSet;
78use rustc_span::{Span, Symbol, sym};
89
910use super::{Feature, to_nonzero};
1011
12fn default_track_feature(_: Symbol) {}
13
14/// Recording used features in the dependency graph so incremental can
15/// replay used features when needed.
16pub static TRACK_FEATURE: AtomicRef<fn(Symbol)> = AtomicRef::new(&(default_track_feature as _));
17
1118#[derive(PartialEq)]
1219enum FeatureStatus {
1320 Default,
......@@ -103,7 +110,12 @@ impl Features {
103110
104111 /// Is the given feature enabled (via `#[feature(...)]`)?
105112 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 }
107119 }
108120}
109121
......@@ -124,7 +136,7 @@ macro_rules! declare_features {
124136 impl Features {
125137 $(
126138 pub fn $feature(&self) -> bool {
127 self.enabled_features.contains(&sym::$feature)
139 self.enabled(sym::$feature)
128140 }
129141 )*
130142
compiler/rustc_hir/src/attrs/data_structures.rs+12-12
......@@ -1366,15 +1366,27 @@ pub enum AttributeKind {
13661366 /// Represents `#[rustc_dump_def_parents]`
13671367 RustcDumpDefParents,
13681368
1369 /// Represents `#[rustc_dump_inferred_outlives]`
1370 RustcDumpInferredOutlives,
1371
13691372 /// Represents `#[rustc_dump_item_bounds]`
13701373 RustcDumpItemBounds,
13711374
1375 /// Represents `#[rustc_dump_object_lifetime_defaults]`.
1376 RustcDumpObjectLifetimeDefaults,
1377
13721378 /// Represents `#[rustc_dump_predicates]`
13731379 RustcDumpPredicates,
13741380
13751381 /// Represents `#[rustc_dump_user_args]`
13761382 RustcDumpUserArgs,
13771383
1384 /// Represents `#[rustc_dump_variances]`
1385 RustcDumpVariances,
1386
1387 /// Represents `#[rustc_dump_variances_of_opaques]`
1388 RustcDumpVariancesOfOpaques,
1389
13781390 /// Represents `#[rustc_dump_vtable]`
13791391 RustcDumpVtable(Span),
13801392
......@@ -1493,15 +1505,9 @@ pub enum AttributeKind {
14931505 span: Span,
14941506 },
14951507
1496 /// Represents `#[rustc_object_lifetime_default]`.
1497 RustcObjectLifetimeDefault,
1498
14991508 /// Represents `#[rustc_offload_kernel]`
15001509 RustcOffloadKernel,
15011510
1502 /// Represents `#[rustc_outlives]`
1503 RustcOutlives,
1504
15051511 /// Represents `#[rustc_paren_sugar]`.
15061512 RustcParenSugar(Span),
15071513
......@@ -1574,12 +1580,6 @@ pub enum AttributeKind {
15741580 /// Represents `#[rustc_unsafe_specialization_marker]`.
15751581 RustcUnsafeSpecializationMarker(Span),
15761582
1577 /// Represents `#[rustc_variance]`
1578 RustcVariance,
1579
1580 /// Represents `#[rustc_variance_of_opaques]`
1581 RustcVarianceOfOpaques,
1582
15831583 /// Represents `#[sanitize]`
15841584 ///
15851585 /// 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 {
124124 RustcDocPrimitive(..) => Yes,
125125 RustcDummy => No,
126126 RustcDumpDefParents => No,
127 RustcDumpInferredOutlives => No,
127128 RustcDumpItemBounds => No,
129 RustcDumpObjectLifetimeDefaults => No,
128130 RustcDumpPredicates => No,
129131 RustcDumpUserArgs => No,
132 RustcDumpVariances => No,
133 RustcDumpVariancesOfOpaques => No,
130134 RustcDumpVtable(..) => No,
131135 RustcDynIncompatibleTrait(..) => No,
132136 RustcEffectiveVisibility => Yes,
......@@ -161,9 +165,7 @@ impl AttributeKind {
161165 RustcNounwind => No,
162166 RustcObjcClass { .. } => No,
163167 RustcObjcSelector { .. } => No,
164 RustcObjectLifetimeDefault => No,
165168 RustcOffloadKernel => Yes,
166 RustcOutlives => No,
167169 RustcParenSugar(..) => No,
168170 RustcPassByValue(..) => Yes,
169171 RustcPassIndirectlyInNonRusticAbis(..) => No,
......@@ -185,8 +187,6 @@ impl AttributeKind {
185187 RustcThenThisWouldNeed(..) => No,
186188 RustcTrivialFieldReads => Yes,
187189 RustcUnsafeSpecializationMarker(..) => No,
188 RustcVariance => No,
189 RustcVarianceOfOpaques => No,
190190 Sanitize { .. } => No,
191191 ShouldPanic { .. } => No,
192192 Stability { .. } => Yes,
compiler/rustc_hir_analysis/src/check/wfcheck.rs+1-1
......@@ -997,7 +997,7 @@ fn check_type_defn<'tcx>(
997997 item: &hir::Item<'tcx>,
998998 all_sized: bool,
999999) -> Result<(), ErrorGuaranteed> {
1000 let _ = tcx.representability(item.owner_id.def_id);
1000 let _ = tcx.check_representability(item.owner_id.def_id);
10011001 let adt_def = tcx.adt_def(item.owner_id);
10021002
10031003 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 @@
11use rustc_hir as hir;
2use rustc_hir::def::DefKind;
23use rustc_hir::def_id::LocalDefId;
34use rustc_hir::{find_attr, intravisit};
45use rustc_middle::hir::nested_filter;
......@@ -27,7 +28,10 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
2728
2829pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
2930 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) {
3135 let preds = tcx.predicates_of(id).instantiate_identity(tcx).predicates;
3236 let span = tcx.def_span(id);
3337
......@@ -37,15 +41,26 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
3741 }
3842 diag.emit();
3943 }
40 if find_attr!(tcx, id, RustcDumpItemBounds) {
41 let bounds = tcx.item_bounds(id).instantiate_identity();
42 let span = tcx.def_span(id);
4344
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 };
4964 }
5065 }
5166}
compiler/rustc_hir_analysis/src/errors.rs-8
......@@ -735,14 +735,6 @@ pub(crate) enum CannotCaptureLateBound {
735735 },
736736}
737737
738#[derive(Diagnostic)]
739#[diag("{$variances}")]
740pub(crate) struct VariancesOf {
741 #[primary_span]
742 pub span: Span,
743 pub variances: String,
744}
745
746738#[derive(Diagnostic)]
747739#[diag("{$ty}")]
748740pub(crate) struct TypeOf<'tcx> {
compiler/rustc_hir_analysis/src/outlives/dump.rs+2-2
......@@ -5,7 +5,7 @@ use rustc_span::sym;
55
66pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) {
77 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) {
99 continue;
1010 }
1111
......@@ -21,7 +21,7 @@ pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) {
2121 preds.sort();
2222
2323 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());
2525 for pred in preds {
2626 err.note(pred);
2727 }
compiler/rustc_hir_analysis/src/variance/dump.rs+19-11
......@@ -1,5 +1,6 @@
11use std::fmt::Write;
22
3use rustc_hir::def::DefKind;
34use rustc_hir::def_id::LocalDefId;
45use rustc_hir::find_attr;
56use rustc_middle::ty::{GenericArgs, TyCtxt};
......@@ -25,23 +26,30 @@ fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String {
2526pub(crate) fn variances(tcx: TyCtxt<'_>) {
2627 let crate_items = tcx.hir_crate_items(());
2728
28 if find_attr!(tcx, crate, RustcVarianceOfOpaques) {
29 if find_attr!(tcx, crate, RustcDumpVariancesOfOpaques) {
2930 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));
3432 }
3533 }
3634
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) {
3937 continue;
4038 }
4139
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));
4654 }
4755}
compiler/rustc_hir_typeck/src/errors.rs+3-3
......@@ -987,13 +987,13 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
987987 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
988988 match self {
989989 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"));
991991 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"));
993993 diag.note(msg);
994994 }
995995 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"));
997997 diag.span_label(span, msg);
998998 }
999999 }
compiler/rustc_interface/src/callbacks.rs+22-1
......@@ -12,8 +12,9 @@
1212use std::fmt;
1313
1414use rustc_errors::DiagInner;
15use rustc_middle::dep_graph::TaskDepsRef;
15use rustc_middle::dep_graph::{DepNodeIndex, QuerySideEffect, TaskDepsRef};
1616use rustc_middle::ty::tls;
17use rustc_span::Symbol;
1718
1819fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
1920 tls::with_context_opt(|icx| {
......@@ -51,6 +52,25 @@ fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R)
5152 })
5253}
5354
55fn 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
5474/// This is a callback from `rustc_hir` as it cannot access the implicit state
5575/// in `rustc_middle` otherwise.
5676fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
......@@ -70,4 +90,5 @@ pub fn setup_callbacks() {
7090 rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
7191 rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
7292 rustc_errors::TRACK_DIAGNOSTIC.swap(&(track_diagnostic as _));
93 rustc_feature::TRACK_FEATURE.swap(&(track_feature as _));
7394}
compiler/rustc_interface/src/queries.rs+9
......@@ -58,6 +58,15 @@ impl Linker {
5858 }
5959 }
6060 });
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
6170 sess.timings.end_section(sess.dcx(), TimingSection::Codegen);
6271
6372 if sess.opts.incremental.is_some()
compiler/rustc_lint/src/if_let_rescope.rs+1-1
......@@ -354,7 +354,7 @@ impl Subdiagnostic for IfLetRescopeRewrite {
354354 .chain(repeat_n('}', closing_brackets.count))
355355 .collect(),
356356 ));
357 let msg = diag.eagerly_translate(msg!(
357 let msg = diag.eagerly_format(msg!(
358358 "a `match` with a single arm can preserve the drop order up to Edition 2021"
359359 ));
360360 diag.multipart_suggestion_with_style(
compiler/rustc_lint/src/lints.rs+1-1
......@@ -3629,7 +3629,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion {
36293629
36303630 Explicit { lifetime_name, suggestions, optional_alternative } => {
36313631 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}`"));
36333633 diag.remove_arg("lifetime_name");
36343634 diag.multipart_suggestion_with_style(
36353635 msg,
compiler/rustc_lint_defs/src/builtin.rs-5
......@@ -1088,11 +1088,6 @@ declare_lint! {
10881088 /// crate-level [`feature` attributes].
10891089 ///
10901090 /// [`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
10961091 pub UNUSED_FEATURES,
10971092 Warn,
10981093 "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;
44use quote::quote;
55use synstructure::Structure;
66
7use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
7use crate::diagnostics::diagnostic_builder::each_variant;
88use crate::diagnostics::error::DiagnosticDeriveError;
99
1010/// The central struct for constructing the `into_diag` method from an annotated struct.
......@@ -19,8 +19,7 @@ impl<'a> DiagnosticDerive<'a> {
1919
2020 pub(crate) fn into_tokens(self) -> TokenStream {
2121 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| {
2423 let preamble = builder.preamble(variant);
2524 let body = builder.body(variant);
2625
......@@ -64,52 +63,3 @@ impl<'a> DiagnosticDerive<'a> {
6463 })
6564 }
6665}
67
68/// The central struct for constructing the `decorate_lint` method from an annotated struct.
69pub(crate) struct LintDiagnosticDerive<'a> {
70 structure: Structure<'a>,
71}
72
73impl<'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::{
1818 should_generate_arg, type_is_bool, type_is_unit, type_matches_path,
1919};
2020
21/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
22#[derive(Clone, Copy, PartialEq, Eq)]
23pub(crate) enum DiagnosticDeriveKind {
24 Diagnostic,
25 LintDiagnostic,
21pub(crate) fn each_variant<'s, F>(structure: &mut Structure<'s>, f: F) -> TokenStream
22where
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 }
2664}
2765
2866/// 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.
3168pub(crate) struct DiagnosticDeriveVariantBuilder {
32 /// The kind for the entire type.
33 pub kind: DiagnosticDeriveKind,
34
3569 /// Initialization of format strings for code suggestions.
3670 pub formatting_init: TokenStream,
3771
......@@ -51,60 +85,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder {
5185 pub code: SpannedOption<()>,
5286}
5387
54impl 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
10888impl DiagnosticDeriveVariantBuilder {
10989 pub(crate) fn primary_message(&self) -> Option<&Message> {
11090 match self.message.as_ref() {
......@@ -358,20 +338,11 @@ impl DiagnosticDeriveVariantBuilder {
358338 // `arg` call will not be generated.
359339 (Meta::Path(_), "skip_arg") => return Ok(quote! {}),
360340 (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)?;
364342
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 });
375346 }
376347 (Meta::Path(_), "subdiagnostic") => {
377348 return Ok(quote! { diag.subdiagnostic(#binding); });
compiler/rustc_macros/src/diagnostics/mod.rs+2-34
......@@ -6,7 +6,7 @@ mod msg_macro;
66mod subdiagnostic;
77mod utils;
88
9use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
9use diagnostic::DiagnosticDerive;
1010pub(super) use msg_macro::msg_macro;
1111use proc_macro2::TokenStream;
1212use subdiagnostic::SubdiagnosticDerive;
......@@ -51,38 +51,6 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream {
5151 DiagnosticDerive::new(s).into_tokens()
5252}
5353
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>
82pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
83 LintDiagnosticDerive::new(s).into_tokens()
84}
85
8654/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
8755/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
8856/// emitting code or diagnostic derives.
......@@ -99,7 +67,7 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
9967/// Then, later, use the subdiagnostic in a diagnostic:
10068///
10169/// ```ignore (rust)
102/// #[derive(LintDiagnostic)]
70/// #[derive(Diagnostic)]
10371/// #[diag("unused doc comment")]
10472/// pub(crate) struct BuiltinUnusedDocComment<'a> {
10573/// pub kind: &'a str,
compiler/rustc_macros/src/diagnostics/subdiagnostic.rs+1-1
......@@ -536,7 +536,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
536536 for (kind, messages) in kind_messages {
537537 let message = format_ident!("__message");
538538 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); });
540540
541541 let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
542542 let call = match kind {
compiler/rustc_macros/src/lib.rs-19
......@@ -196,25 +196,6 @@ decl_derive!(
196196 suggestion_hidden,
197197 suggestion_verbose)] => diagnostics::diagnostic_derive
198198);
199decl_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);
218199decl_derive!(
219200 [Subdiagnostic, attributes(
220201 // struct/variant attributes
compiler/rustc_macros/src/query.rs-9
......@@ -144,7 +144,6 @@ struct QueryModifiers {
144144 arena_cache: Option<Ident>,
145145 cache_on_disk_if: Option<CacheOnDiskIf>,
146146 cycle_delay_bug: Option<Ident>,
147 cycle_fatal: Option<Ident>,
148147 cycle_stash: Option<Ident>,
149148 depth_limit: Option<Ident>,
150149 desc: Desc,
......@@ -160,7 +159,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
160159 let mut arena_cache = None;
161160 let mut cache_on_disk_if = None;
162161 let mut desc = None;
163 let mut cycle_fatal = None;
164162 let mut cycle_delay_bug = None;
165163 let mut cycle_stash = None;
166164 let mut no_hash = None;
......@@ -197,8 +195,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
197195 try_insert!(cache_on_disk_if = CacheOnDiskIf { modifier, block });
198196 } else if modifier == "arena_cache" {
199197 try_insert!(arena_cache = modifier);
200 } else if modifier == "cycle_fatal" {
201 try_insert!(cycle_fatal = modifier);
202198 } else if modifier == "cycle_delay_bug" {
203199 try_insert!(cycle_delay_bug = modifier);
204200 } else if modifier == "cycle_stash" {
......@@ -228,7 +224,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
228224 arena_cache,
229225 cache_on_disk_if,
230226 desc,
231 cycle_fatal,
232227 cycle_delay_bug,
233228 cycle_stash,
234229 no_hash,
......@@ -248,7 +243,6 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr
248243 arena_cache,
249244 cache_on_disk_if,
250245 cycle_delay_bug,
251 cycle_fatal,
252246 cycle_stash,
253247 depth_limit,
254248 desc: _,
......@@ -266,8 +260,6 @@ fn make_modifiers_stream(query: &Query, modifiers: &QueryModifiers) -> proc_macr
266260
267261 let cycle_error_handling = if cycle_delay_bug.is_some() {
268262 quote! { DelayBug }
269 } else if cycle_fatal.is_some() {
270 quote! { Fatal }
271263 } else if cycle_stash.is_some() {
272264 quote! { Stash }
273265 } else {
......@@ -407,7 +399,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke
407399
408400 doc_link!(
409401 arena_cache,
410 cycle_fatal,
411402 cycle_delay_bug,
412403 cycle_stash,
413404 no_hash,
compiler/rustc_middle/src/dep_graph/graph.rs+48-24
......@@ -17,6 +17,7 @@ use rustc_index::IndexVec;
1717use rustc_macros::{Decodable, Encodable};
1818use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
1919use rustc_session::Session;
20use rustc_span::Symbol;
2021use tracing::{debug, instrument};
2122#[cfg(debug_assertions)]
2223use {super::debug::EdgeFilter, std::env};
......@@ -45,6 +46,11 @@ pub enum QuerySideEffect {
4546 /// the query as green, as that query will have the side
4647 /// effect dep node as a dependency.
4748 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 },
4854}
4955#[derive(Clone)]
5056pub struct DepGraph {
......@@ -514,29 +520,40 @@ impl DepGraph {
514520 }
515521 }
516522
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.
519525 #[inline]
520526 pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) {
521527 if let Some(ref data) = self.data {
522528 read_deps(|task_deps| match task_deps {
523529 TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
524530 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);
526534 }
527535 })
528536 }
529537 }
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.
532540 #[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>(
534549 &self,
535550 tcx: TyCtxt<'tcx>,
536 prev_index: SerializedDepNodeIndex,
537 ) {
551 side_effect: QuerySideEffect,
552 ) -> DepNodeIndex {
538553 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()
540557 }
541558 }
542559
......@@ -673,10 +690,14 @@ impl DepGraphData {
673690 self.debug_loaded_from_disk.lock().insert(dep_node);
674691 }
675692
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.
678695 #[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 {
680701 // Use `send_new` so we get an unique index, even though the dep node is not.
681702 let dep_node_index = self.current.encoder.send_new(
682703 DepNode {
......@@ -684,28 +705,21 @@ impl DepGraphData {
684705 key_fingerprint: PackedFingerprint::from(Fingerprint::ZERO),
685706 },
686707 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.
689710 std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
690711 );
691 let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone());
692712 tcx.store_side_effect(dep_node_index, side_effect);
693713 dep_node_index
694714 }
695715
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.
698718 #[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) {
700720 with_deps(TaskDepsRef::Ignore, || {
701721 let side_effect = tcx.load_side_effect(prev_index).unwrap();
702722
703 match &side_effect {
704 QuerySideEffect::Diagnostic(diagnostic) => {
705 tcx.dcx().emit_diagnostic(diagnostic.clone());
706 }
707 }
708
709723 // Use `send_and_color` as `promote_node_and_deps_to_current` expects all
710724 // green dependencies. `send_and_color` will also prevent multiple nodes
711725 // being encoded for concurrent calls.
......@@ -720,6 +734,16 @@ impl DepGraphData {
720734 std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(),
721735 true,
722736 );
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
723747 // This will just overwrite the same value for concurrent calls.
724748 tcx.store_side_effect(dep_node_index, side_effect);
725749 })
compiler/rustc_middle/src/lint.rs+2-2
......@@ -492,8 +492,8 @@ pub fn lint_level(
492492/// - [`TyCtxt::node_lint`]
493493/// - `LintContext::opt_span_lint`
494494///
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`.
497497#[track_caller]
498498pub fn diag_lint_level<'a, D: Diagnostic<'a, ()> + 'a>(
499499 sess: &'a Session,
compiler/rustc_middle/src/middle/stability.rs+10-16
......@@ -4,7 +4,7 @@
44use std::num::NonZero;
55
66use rustc_ast::NodeId;
7use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, LintDiagnostic, msg};
7use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, msg};
88use rustc_feature::GateIssue;
99use rustc_hir::attrs::{DeprecatedSince, Deprecation};
1010use rustc_hir::def_id::{DefId, LocalDefId};
......@@ -131,15 +131,8 @@ impl<'a, G: EmissionGuarantee> rustc_errors::Diagnostic<'a, G> for Deprecated {
131131 dcx: rustc_errors::DiagCtxtHandle<'a>,
132132 level: rustc_errors::Level,
133133 ) -> Diag<'a, G> {
134 let mut diag = Diag::new(dcx, level, "");
135 self.decorate_lint(&mut diag);
136 diag
137 }
138}
139
140impl<'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 {
143136 DeprecatedSinceKind::InEffect => msg!(
144137 "use of deprecated {$kind} `{$path}`{$has_note ->
145138 [true] : {$note}
......@@ -160,21 +153,22 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for Deprecated {
160153 }"
161154 )
162155 }
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 {
167160 diag.arg("version", version);
168161 }
169 if let Some(note) = self.note {
162 if let Some(note) = note {
170163 diag.arg("has_note", true);
171164 diag.arg("note", note);
172165 } else {
173166 diag.arg("has_note", false);
174167 }
175 if let Some(sub) = self.sub {
168 if let Some(sub) = sub {
176169 diag.subdiagnostic(sub);
177170 }
171 diag
178172 }
179173}
180174
compiler/rustc_middle/src/queries.rs+20-28
......@@ -32,7 +32,6 @@
3232//! - `arena_cache`: Use an arena for in-memory caching of the query result.
3333//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to
3434//! 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.
3635//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately.
3736//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling.
3837//! - `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};
149148// which memoizes and does dep-graph tracking, wrapping around the actual
150149// `Providers` that the driver creates (using several `rustc_*` crates).
151150//
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
154153// 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.
157156rustc_queries! {
158157 /// Caches the expansion of a derive proc macro, e.g. `#[derive(Serialize)]`.
159158 /// The key is:
......@@ -587,24 +586,28 @@ rustc_queries! {
587586 }
588587
589588 query is_panic_runtime(_: CrateNum) -> bool {
590 cycle_fatal
591589 desc { "checking if the crate is_panic_runtime" }
592590 separate_provide_extern
593591 }
594592
595593 /// 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 {
597595 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.)
599600 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
601602 // 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.
603605 anon
604606 }
605607
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 {
608611 desc { "checking if `{}` is representable", key }
609612 cycle_delay_bug
610613 anon
......@@ -838,8 +841,8 @@ rustc_queries! {
838841 ///
839842 /// E.g., for `struct Foo<'a, T> { x: &'a T }`, this would return `[T: 'a]`.
840843 ///
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.
843846 query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Clause<'tcx>, Span)] {
844847 desc { "computing inferred outlives-predicates of `{}`", tcx.def_path_str(key) }
845848 cache_on_disk_if { key.is_local() }
......@@ -1046,8 +1049,8 @@ rustc_queries! {
10461049 /// The list of variances corresponds to the list of (early-bound) generic
10471050 /// parameters of the item (including its parents).
10481051 ///
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.
10511054 query variances_of(def_id: DefId) -> &'tcx [ty::Variance] {
10521055 desc { "computing the variances of `{}`", tcx.def_path_str(def_id) }
10531056 cache_on_disk_if { def_id.is_local() }
......@@ -1318,7 +1321,6 @@ rustc_queries! {
13181321 /// Return the set of (transitive) callees that may result in a recursive call to `key`,
13191322 /// if we were able to walk all callees.
13201323 query mir_callgraph_cyclic(key: LocalDefId) -> &'tcx Option<UnordSet<LocalDefId>> {
1321 cycle_fatal
13221324 arena_cache
13231325 desc {
13241326 "computing (transitive) callees of `{}` that may recurse",
......@@ -1329,7 +1331,6 @@ rustc_queries! {
13291331
13301332 /// Obtain all the calls into other local functions
13311333 query mir_inliner_callees(key: ty::InstanceKind<'tcx>) -> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
1332 cycle_fatal
13331334 desc {
13341335 "computing all local function calls in `{}`",
13351336 tcx.def_path_str(key.def_id()),
......@@ -1850,31 +1851,26 @@ rustc_queries! {
18501851 }
18511852
18521853 query is_compiler_builtins(_: CrateNum) -> bool {
1853 cycle_fatal
18541854 desc { "checking if the crate is_compiler_builtins" }
18551855 separate_provide_extern
18561856 }
18571857 query has_global_allocator(_: CrateNum) -> bool {
18581858 // This query depends on untracked global state in CStore
18591859 eval_always
1860 cycle_fatal
18611860 desc { "checking if the crate has_global_allocator" }
18621861 separate_provide_extern
18631862 }
18641863 query has_alloc_error_handler(_: CrateNum) -> bool {
18651864 // This query depends on untracked global state in CStore
18661865 eval_always
1867 cycle_fatal
18681866 desc { "checking if the crate has_alloc_error_handler" }
18691867 separate_provide_extern
18701868 }
18711869 query has_panic_handler(_: CrateNum) -> bool {
1872 cycle_fatal
18731870 desc { "checking if the crate has_panic_handler" }
18741871 separate_provide_extern
18751872 }
18761873 query is_profiler_runtime(_: CrateNum) -> bool {
1877 cycle_fatal
18781874 desc { "checking if a crate is `#![profiler_runtime]`" }
18791875 separate_provide_extern
18801876 }
......@@ -1883,22 +1879,18 @@ rustc_queries! {
18831879 cache_on_disk_if { true }
18841880 }
18851881 query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> {
1886 cycle_fatal
18871882 desc { "getting a crate's required panic strategy" }
18881883 separate_provide_extern
18891884 }
18901885 query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
1891 cycle_fatal
18921886 desc { "getting a crate's configured panic-in-drop strategy" }
18931887 separate_provide_extern
18941888 }
18951889 query is_no_builtins(_: CrateNum) -> bool {
1896 cycle_fatal
18971890 desc { "getting whether a crate has `#![no_builtins]`" }
18981891 separate_provide_extern
18991892 }
19001893 query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion {
1901 cycle_fatal
19021894 desc { "getting a crate's symbol mangling version" }
19031895 separate_provide_extern
19041896 }
......@@ -2145,7 +2137,7 @@ rustc_queries! {
21452137 /// Returns the *default lifetime* to be used if a trait object type were to be passed for
21462138 /// the type parameter given by `DefId`.
21472139 ///
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
21492141 /// print the result of this query for use in UI tests or for debugging purposes.
21502142 ///
21512143 /// # Examples
compiler/rustc_middle/src/query/modifiers.rs-5
......@@ -28,11 +28,6 @@ pub(crate) struct cache_on_disk_if;
2828/// A cycle error results in a delay_bug call
2929pub(crate) struct cycle_delay_bug;
3030
31/// # `cycle_fatal` query modifier
32///
33/// A cycle error for this query aborting the compilation with a fatal error.
34pub(crate) struct cycle_fatal;
35
3631/// # `cycle_stash` query modifier
3732///
3833/// 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> {
5757#[derive(Copy, Clone)]
5858pub enum CycleErrorHandling {
5959 Error,
60 Fatal,
6160 DelayBug,
6261 Stash,
6362}
compiler/rustc_middle/src/ty/adt.rs+3-4
......@@ -741,8 +741,7 @@ impl<'tcx> AdtDef<'tcx> {
741741 }
742742}
743743
744/// This type exists just so a `FromCycleError` impl can be made for the `check_representability`
745/// query.
744746#[derive(Clone, Copy, Debug, HashStable)]
745pub enum Representability {
746 Representable,
747 Infinite(ErrorGuaranteed),
748}
747pub struct Representability;
compiler/rustc_middle/src/ty/context.rs+31-1
......@@ -36,7 +36,7 @@ use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
3636use rustc_hir::intravisit::VisitorExt;
3737use rustc_hir::lang_items::LangItem;
3838use rustc_hir::limit::Limit;
39use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr};
39use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, Node, TraitCandidate, find_attr};
4040use rustc_index::IndexVec;
4141use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
4242use rustc_session::Session;
......@@ -1688,6 +1688,36 @@ impl<'tcx> TyCtxt<'tcx> {
16881688 self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error });
16891689 }
16901690 }
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 }
16911721}
16921722
16931723macro_rules! nop_lift {
compiler/rustc_middle/src/ty/inhabitedness/mod.rs+2-3
......@@ -61,10 +61,9 @@ pub(crate) fn provide(providers: &mut Providers) {
6161/// requires calling [`InhabitedPredicate::instantiate`]
6262fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
6363 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);
6765 }
66
6867 let adt = tcx.adt_def(def_id);
6968 InhabitedPredicate::any(
7069 tcx,
compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs+2-2
......@@ -531,7 +531,7 @@ impl Subdiagnostic for LocalLabel<'_> {
531531 diag.arg("is_generated_name", self.is_generated_name);
532532 diag.remove_arg("is_dropped_first_edition_2024");
533533 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!(
535535 "{$is_generated_name ->
536536 [true] this value will be stored in a temporary; let us call it `{$name}`
537537 *[false] `{$name}` calls a custom destructor
......@@ -542,7 +542,7 @@ impl Subdiagnostic for LocalLabel<'_> {
542542 dtor.add_to_diag(diag);
543543 }
544544 let msg =
545 diag.eagerly_translate(msg!(
545 diag.eagerly_format(msg!(
546546 "{$is_dropped_first_edition_2024 ->
547547 [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024
548548 *[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> {
184184 Attribute::Parsed(AttributeKind::TargetFeature{ attr_span, ..}) => {
185185 self.check_target_feature(hir_id, *attr_span, target, attrs)
186186 }
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);
189189 }
190190 &Attribute::Parsed(AttributeKind::RustcPubTransparent(attr_span)) => {
191191 self.check_rustc_pub_transparent(attr_span, span, attrs)
......@@ -319,9 +319,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
319319 | AttributeKind::RustcDocPrimitive(..)
320320 | AttributeKind::RustcDummy
321321 | AttributeKind::RustcDumpDefParents
322 | AttributeKind::RustcDumpInferredOutlives
322323 | AttributeKind::RustcDumpItemBounds
323324 | AttributeKind::RustcDumpPredicates
324325 | AttributeKind::RustcDumpUserArgs
326 | AttributeKind::RustcDumpVariances
327 | AttributeKind::RustcDumpVariancesOfOpaques
325328 | AttributeKind::RustcDumpVtable(..)
326329 | AttributeKind::RustcDynIncompatibleTrait(..)
327330 | AttributeKind::RustcEffectiveVisibility
......@@ -355,7 +358,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
355358 | AttributeKind::RustcObjcClass { .. }
356359 | AttributeKind::RustcObjcSelector { .. }
357360 | AttributeKind::RustcOffloadKernel
358 | AttributeKind::RustcOutlives
359361 | AttributeKind::RustcParenSugar(..)
360362 | AttributeKind::RustcPassByValue (..)
361363 | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
......@@ -376,8 +378,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
376378 | AttributeKind::RustcThenThisWouldNeed(..)
377379 | AttributeKind::RustcTrivialFieldReads
378380 | AttributeKind::RustcUnsafeSpecializationMarker(..)
379 | AttributeKind::RustcVariance
380 | AttributeKind::RustcVarianceOfOpaques
381381 | AttributeKind::ShouldPanic { .. }
382382 | AttributeKind::TestRunner(..)
383383 | AttributeKind::ThreadLocal
......@@ -781,8 +781,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
781781 }
782782 }
783783
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) {
786786 let tcx = self.tcx;
787787 if let Some(owner_id) = hir_id.as_owner()
788788 && let Some(generics) = tcx.hir_get_generics(owner_id.def_id)
......@@ -796,7 +796,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
796796 ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
797797 ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
798798 };
799 tcx.dcx().emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
799 tcx.dcx().span_err(p.span, repr);
800800 }
801801 }
802802 }
compiler/rustc_passes/src/errors.rs-8
......@@ -814,14 +814,6 @@ pub(crate) struct UselessAssignment<'a> {
814814)]
815815pub(crate) struct InlineIgnoredForExported;
816816
817#[derive(Diagnostic)]
818#[diag("{$repr}")]
819pub(crate) struct ObjectLifetimeErr {
820 #[primary_span]
821 pub span: Span,
822 pub repr: String,
823}
824
825817#[derive(Diagnostic)]
826818pub(crate) enum AttrApplication {
827819 #[diag("attribute should be applied to an enum", code = E0517)]
compiler/rustc_pattern_analysis/src/errors.rs+5-4
......@@ -1,5 +1,5 @@
11use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic};
2use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
2use rustc_macros::{Diagnostic, Subdiagnostic};
33use rustc_middle::ty::Ty;
44use rustc_span::Span;
55
......@@ -109,8 +109,7 @@ impl Subdiagnostic for GappedRange {
109109 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
110110 let GappedRange { span, gap, first_range } = self;
111111
112 // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
113 // does not support `#[subdiagnostic(eager)]`...
112 // FIXME(mejrs) Use `#[subdiagnostic(eager)]` instead
114113 let message = format!(
115114 "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \
116115 either of them"
......@@ -131,10 +130,12 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
131130 pub uncovered: Uncovered,
132131}
133132
134#[derive(LintDiagnostic)]
133#[derive(Diagnostic)]
135134#[diag("the lint level must be set on the whole match")]
136135#[help("it no longer has any effect to set the lint level on an individual match arm")]
137136pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
137 #[primary_span]
138 pub span: Span,
138139 #[label("remove this attribute")]
139140 pub lint_span: Span,
140141 #[suggestion(
compiler/rustc_pattern_analysis/src/lints.rs+3-7
......@@ -92,17 +92,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
9292 let LevelAndSource { level, src, .. } =
9393 rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data);
9494 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,
9697 lint_span: src.span(),
9798 suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()),
9899 lint_level: level.as_str(),
99100 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 });
106102 }
107103 }
108104 }
compiler/rustc_query_impl/src/dep_kind_vtables.rs+1-1
......@@ -40,7 +40,7 @@ mod non_query {
4040 is_eval_always: false,
4141 key_fingerprint_style: KeyFingerprintStyle::Unit,
4242 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);
4444 true
4545 }),
4646 promote_from_disk_fn: None,
compiler/rustc_query_impl/src/execution.rs-4
......@@ -131,10 +131,6 @@ fn mk_cycle<'tcx, C: QueryCache>(
131131 let guar = error.emit();
132132 query.value_from_cycle_error(tcx, cycle_error, guar)
133133 }
134 CycleErrorHandling::Fatal => {
135 let guar = error.emit();
136 guar.raise_fatal();
137 }
138134 CycleErrorHandling::DelayBug => {
139135 let guar = error.delay_as_bug();
140136 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 {
9595 let mut item_and_field_ids = Vec::new();
9696 let mut representable_ids = FxHashSet::default();
9797 for info in &cycle_error.cycle {
98 if info.frame.dep_kind == DepKind::representability
98 if info.frame.dep_kind == DepKind::check_representability
9999 && let Some(field_id) = info.frame.def_id
100100 && let Some(field_id) = field_id.as_local()
101101 && let Some(DefKind::Field) = info.frame.info.def_kind
......@@ -109,7 +109,7 @@ impl<'tcx> FromCycleError<'tcx> for Representability {
109109 }
110110 }
111111 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
113113 && let Some(def_id) = info.frame.def_id_for_ty_in_cycle
114114 && let Some(def_id) = def_id.as_local()
115115 && !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
......@@ -117,8 +117,10 @@ impl<'tcx> FromCycleError<'tcx> for Representability {
117117 representable_ids.insert(def_id);
118118 }
119119 }
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`.
120122 let guar = recursive_type_error(tcx, item_and_field_ids, &representable_ids);
121 Representability::Infinite(guar)
123 guar.raise_fatal();
122124 }
123125}
124126
compiler/rustc_resolve/src/errors.rs+1-1
......@@ -1366,7 +1366,7 @@ impl Subdiagnostic for FoundItemConfigureOut {
13661366 ItemWas::BehindFeature { feature, span } => {
13671367 let key = "feature".into();
13681368 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(
13701370 msg!("the item is gated behind the `{$feature}` feature"),
13711371 [(&key, &value)].into_iter(),
13721372 );
compiler/rustc_session/src/session.rs+6
......@@ -166,6 +166,11 @@ pub struct Session {
166166 /// Used by `-Zmir-opt-bisect-limit` to assign an index to each
167167 /// optimization-pass execution candidate during this compilation.
168168 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>>,
169174}
170175
171176#[derive(Clone, Copy)]
......@@ -1096,6 +1101,7 @@ pub fn build_session(
10961101 replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler`
10971102 thin_lto_supported: true, // filled by `run_compiler`
10981103 mir_opt_bisect_eval_count: AtomicUsize::new(0),
1104 used_features: Lock::default(),
10991105 };
11001106
11011107 validate_commandline_args_with_session_available(&sess);
compiler/rustc_span/src/symbol.rs+4-4
......@@ -1708,9 +1708,13 @@ symbols! {
17081708 rustc_driver,
17091709 rustc_dummy,
17101710 rustc_dump_def_parents,
1711 rustc_dump_inferred_outlives,
17111712 rustc_dump_item_bounds,
1713 rustc_dump_object_lifetime_defaults,
17121714 rustc_dump_predicates,
17131715 rustc_dump_user_args,
1716 rustc_dump_variances,
1717 rustc_dump_variances_of_opaques,
17141718 rustc_dump_vtable,
17151719 rustc_dyn_incompatible_trait,
17161720 rustc_effective_visibility,
......@@ -1747,10 +1751,8 @@ symbols! {
17471751 rustc_nounwind,
17481752 rustc_objc_class,
17491753 rustc_objc_selector,
1750 rustc_object_lifetime_default,
17511754 rustc_offload_kernel,
17521755 rustc_on_unimplemented,
1753 rustc_outlives,
17541756 rustc_paren_sugar,
17551757 rustc_partition_codegened,
17561758 rustc_partition_reused,
......@@ -1780,8 +1782,6 @@ symbols! {
17801782 rustc_then_this_would_need,
17811783 rustc_trivial_field_reads,
17821784 rustc_unsafe_specialization_marker,
1783 rustc_variance,
1784 rustc_variance_of_opaques,
17851785 rustdoc,
17861786 rustdoc_internals,
17871787 rustdoc_missing_doc_code_examples,
compiler/rustc_trait_selection/src/errors.rs+8-10
......@@ -456,7 +456,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
456456 // See https://github.com/rust-lang/rust/issues/143872 for details.
457457 diag.store_args();
458458 diag.arg("requirement", requirement);
459 let msg = diag.eagerly_translate(msg!(
459 let msg = diag.eagerly_format(msg!(
460460 "...so that the {$requirement ->
461461 [method_compat] method type is compatible with trait
462462 [type_compat] associated type is compatible with trait
......@@ -482,7 +482,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
482482 // *terrible*.
483483 diag.store_args();
484484 diag.arg("requirement", requirement);
485 let msg = diag.eagerly_translate(msg!(
485 let msg = diag.eagerly_format(msg!(
486486 "...so that {$requirement ->
487487 [method_compat] method type is compatible with trait
488488 [type_compat] associated type is compatible with trait
......@@ -1174,7 +1174,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp {
11741174 type_param_span
11751175 .push_span_label(span, msg!("consider borrowing this type parameter in the trait"));
11761176 }
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`"));
11781178 diag.span_help(type_param_span, msg);
11791179 }
11801180}
......@@ -1218,10 +1218,9 @@ impl Subdiagnostic for DynTraitConstraintSuggestion {
12181218 self.ident.span,
12191219 msg!("calling this method introduces the `impl`'s `'static` requirement"),
12201220 );
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"));
12221222 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"));
12251224 diag.span_suggestion_verbose(
12261225 self.span.shrink_to_hi(),
12271226 msg,
......@@ -1284,9 +1283,8 @@ impl Subdiagnostic for ReqIntroducedLocations {
12841283 );
12851284 }
12861285 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"));
12901288 diag.span_note(self.span, msg);
12911289 }
12921290}
......@@ -1727,7 +1725,7 @@ impl Subdiagnostic for SuggestTuplePatternMany {
17271725 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
17281726 diag.arg("path", self.path);
17291727 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}`"));
17311729 diag.multipart_suggestions(
17321730 message,
17331731 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<'_> {
169169 diag.arg("desc_kind", self.desc.kind);
170170 diag.arg("desc_arg", self.desc.arg);
171171
172 let msg = diag.eagerly_translate(msg!(
172 let msg = diag.eagerly_format(msg!(
173173 "{$pref_kind ->
174174 *[should_not_happen] [{$pref_kind}]
175175 [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};
66use rustc_span::def_id::LocalDefId;
77
88pub(crate) fn provide(providers: &mut Providers) {
9 *providers =
10 Providers { representability, representability_adt_ty, params_in_repr, ..*providers };
11}
12
13macro_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
1914 };
2015}
2116
22fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
17fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
2318 match tcx.def_kind(def_id) {
2419 DefKind::Struct | DefKind::Union | DefKind::Enum => {
2520 for variant in tcx.adt_def(def_id).variants() {
2621 for field in variant.fields.iter() {
27 rtry!(tcx.representability(field.did.expect_local()));
22 let _ = tcx.check_representability(field.did.expect_local());
2823 }
2924 }
30 Representability::Representable
3125 }
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 }
3329 def_kind => bug!("unexpected {def_kind:?}"),
3430 }
31 Representability
3532}
3633
37fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
34fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) {
3835 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 }
4041 // 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 }
4245 ty::Tuple(tys) => {
4346 for ty in tys {
44 rtry!(representability_ty(tcx, ty));
47 check_representability_ty(tcx, ty);
4548 }
46 Representability::Representable
4749 }
48 _ => Representability::Representable,
50 _ => {}
4951 }
5052}
5153
52/*
53The reason for this being a separate query is very subtle:
54Consider this infinitely sized struct: `struct Foo(Box<Foo>, Bar<Foo>)`:
55When calling representability(Foo), a query cycle will occur:
56 representability(Foo)
57 -> representability_adt_ty(Bar<Foo>)
58 -> representability(Foo)
59For the diagnostic output (in `Value::from_cycle_error`), we want to detect that
60the `Foo` in the *second* field of the struct is culpable. This requires
61traversing the HIR of the struct and calling `params_in_repr(Bar)`. But we can't
62call params_in_repr for a given type unless it is known to be representable.
63params_in_repr will cycle/panic on infinitely sized types. Looking at the query
64cycle above, we know that `Bar` is representable because
65representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is
66*not* in the cycle.
67*/
68fn 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.
70fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
6971 let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") };
7072 if let Some(def_id) = adt.did().as_local() {
71 rtry!(tcx.representability(def_id));
73 let _ = tcx.check_representability(def_id);
7274 }
7375 // At this point, we know that the item of the ADT type is representable;
7476 // 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
7678 for (i, arg) in args.iter().enumerate() {
7779 if let ty::GenericArgKind::Type(ty) = arg.kind() {
7880 if params_in_repr.contains(i as u32) {
79 rtry!(representability_ty(tcx, ty));
81 check_representability_ty(tcx, ty);
8082 }
8183 }
8284 }
83 Representability::Representable
85 Representability
8486}
8587
8688fn 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>(
116116 tcx: TyCtxt<'tcx>,
117117 (def_id, sizedness): (DefId, SizedTraitKind),
118118) -> 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);
123121 }
122
124123 let def = tcx.adt_def(def_id);
125124
126125 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> {
693693 /// map.insert(1, "a");
694694 /// ```
695695 #[unstable(feature = "btreemap_alloc", issue = "32838")]
696 #[must_use]
696697 pub const fn new_in(alloc: A) -> BTreeMap<K, V, A> {
697698 BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(alloc), _marker: PhantomData }
698699 }
library/alloc/src/collections/btree/set.rs+1
......@@ -361,6 +361,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
361361 /// let mut set: BTreeSet<i32> = BTreeSet::new_in(Global);
362362 /// ```
363363 #[unstable(feature = "btreemap_alloc", issue = "32838")]
364 #[must_use]
364365 pub const fn new_in(alloc: A) -> BTreeSet<T, A> {
365366 BTreeSet { map: BTreeMap::new_in(alloc) }
366367 }
library/alloctests/tests/lib.rs-1
......@@ -1,6 +1,5 @@
11#![feature(allocator_api)]
22#![feature(binary_heap_pop_if)]
3#![feature(btree_merge)]
43#![feature(const_heap)]
54#![feature(deque_extend_front)]
65#![feature(iter_array_chunks)]
library/core/src/num/f16.rs+5-1
......@@ -1521,7 +1521,11 @@ impl f16 {
15211521// Functions in this module fall into `core_float_math`
15221522// #[unstable(feature = "core_float_math", issue = "137578")]
15231523#[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)))]
15251529impl f16 {
15261530 /// Returns the largest integer less than or equal to `self`.
15271531 ///
library/core/src/num/f32.rs+1
......@@ -393,6 +393,7 @@ pub mod consts {
393393 pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
394394}
395395
396#[doc(test(attr(allow(unused_features))))]
396397impl f32 {
397398 /// The radix or base of the internal representation of `f32`.
398399 #[stable(feature = "assoc_int_consts", since = "1.43.0")]
library/core/src/num/f64.rs+1
......@@ -393,6 +393,7 @@ pub mod consts {
393393 pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
394394}
395395
396#[doc(test(attr(allow(unused_features))))]
396397impl f64 {
397398 /// The radix or base of the internal representation of `f64`.
398399 #[stable(feature = "assoc_int_consts", since = "1.43.0")]
library/coretests/tests/lib.rs-1
......@@ -50,7 +50,6 @@
5050#![feature(f16)]
5151#![feature(f128)]
5252#![feature(float_algebraic)]
53#![feature(float_bits_const)]
5453#![feature(float_exact_integer_constants)]
5554#![feature(float_gamma)]
5655#![feature(float_minimum_maximum)]
library/std/src/collections/hash/map.rs+4
......@@ -357,6 +357,7 @@ impl<K, V, S> HashMap<K, V, S> {
357357 /// map.insert(1, 2);
358358 /// ```
359359 #[inline]
360 #[must_use]
360361 #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
361362 #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")]
362363 pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
......@@ -389,6 +390,7 @@ impl<K, V, S> HashMap<K, V, S> {
389390 /// map.insert(1, 2);
390391 /// ```
391392 #[inline]
393 #[must_use]
392394 #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
393395 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashMap<K, V, S> {
394396 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> {
409411 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
410412 /// the `HashMap` to be useful, see its documentation for details.
411413 #[inline]
414 #[must_use]
412415 #[unstable(feature = "allocator_api", issue = "32838")]
413416 pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self {
414417 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> {
430433 /// the `HashMap` to be useful, see its documentation for details.
431434 ///
432435 #[inline]
436 #[must_use]
433437 #[unstable(feature = "allocator_api", issue = "32838")]
434438 pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self {
435439 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> {
229229 /// set.insert(2);
230230 /// ```
231231 #[inline]
232 #[must_use]
232233 #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
233234 #[rustc_const_stable(feature = "const_collections_with_hasher", since = "1.85.0")]
234235 pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
......@@ -261,6 +262,7 @@ impl<T, S> HashSet<T, S> {
261262 /// set.insert(1);
262263 /// ```
263264 #[inline]
265 #[must_use]
264266 #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
265267 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S> {
266268 HashSet { base: base::HashSet::with_capacity_and_hasher(capacity, hasher) }
......@@ -281,6 +283,7 @@ impl<T, S, A: Allocator> HashSet<T, S, A> {
281283 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
282284 /// the `HashSet` to be useful, see its documentation for details.
283285 #[inline]
286 #[must_use]
284287 #[unstable(feature = "allocator_api", issue = "32838")]
285288 pub fn with_hasher_in(hasher: S, alloc: A) -> HashSet<T, S, A> {
286289 HashSet { base: base::HashSet::with_hasher_in(hasher, alloc) }
......@@ -301,6 +304,7 @@ impl<T, S, A: Allocator> HashSet<T, S, A> {
301304 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
302305 /// the `HashSet` to be useful, see its documentation for details.
303306 #[inline]
307 #[must_use]
304308 #[unstable(feature = "allocator_api", issue = "32838")]
305309 pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> HashSet<T, S, A> {
306310 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;
1616use crate::sys::cmath;
1717
1818#[cfg(not(test))]
19#[doc(test(attr(allow(unused_features))))]
1920impl f16 {
2021 /// Raises a number to a floating point power.
2122 ///
library/std/src/path.rs+24-13
......@@ -93,7 +93,7 @@ use crate::ops::{self, Deref};
9393use crate::rc::Rc;
9494use crate::str::FromStr;
9595use crate::sync::Arc;
96use crate::sys::path::{HAS_PREFIXES, MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix};
96use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix};
9797use crate::{cmp, fmt, fs, io, sys};
9898
9999////////////////////////////////////////////////////////////////////////////////
......@@ -266,22 +266,33 @@ impl<'a> Prefix<'a> {
266266/// ```
267267#[must_use]
268268#[stable(feature = "rust1", since = "1.0.0")]
269pub fn is_separator(c: char) -> bool {
269#[rustc_const_unstable(feature = "const_path_separators", issue = "153106")]
270pub const fn is_separator(c: char) -> bool {
270271 c.is_ascii() && is_sep_byte(c as u8)
271272}
272273
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")]
278pub 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")]
284pub 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.
276288#[stable(feature = "rust1", since = "1.0.0")]
277289#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]
278pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
290pub const MAIN_SEPARATOR: char = SEPARATORS[0];
279291
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.
283294#[stable(feature = "main_separator_str", since = "1.68.0")]
284pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
295pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0];
285296
286297////////////////////////////////////////////////////////////////////////////////
287298// Misc helpers
......@@ -562,7 +573,7 @@ impl<'a> Component<'a> {
562573 pub fn as_os_str(self) -> &'a OsStr {
563574 match self {
564575 Component::Prefix(p) => p.as_os_str(),
565 Component::RootDir => OsStr::new(MAIN_SEP_STR),
576 Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR),
566577 Component::CurDir => OsStr::new("."),
567578 Component::ParentDir => OsStr::new(".."),
568579 Component::Normal(path) => path,
......@@ -1379,7 +1390,7 @@ impl PathBuf {
13791390
13801391 for c in buf {
13811392 if need_sep && c != Component::RootDir {
1382 res.push(MAIN_SEP_STR);
1393 res.push(MAIN_SEPARATOR_STR);
13831394 }
13841395 res.push(c.as_os_str());
13851396
......@@ -1402,7 +1413,7 @@ impl PathBuf {
14021413
14031414 // `path` is a pure relative path
14041415 } else if need_sep {
1405 self.inner.push(MAIN_SEP_STR);
1416 self.inner.push(MAIN_SEPARATOR_STR);
14061417 }
14071418
14081419 self.inner.push(path);
library/std/src/process.rs+2
......@@ -1381,6 +1381,7 @@ impl Output {
13811381 /// # Examples
13821382 ///
13831383 /// ```
1384 /// # #![allow(unused_features)]
13841385 /// #![feature(exit_status_error)]
13851386 /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
13861387 /// use std::process::Command;
......@@ -1960,6 +1961,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
19601961pub struct ExitStatusError(imp::ExitStatusError);
19611962
19621963#[unstable(feature = "exit_status_error", issue = "84908")]
1964#[doc(test(attr(allow(unused_features))))]
19631965impl ExitStatusError {
19641966 /// Reports the exit code, if applicable, from an `ExitStatusError`.
19651967 ///
library/std/src/sys/path/cygwin.rs+3-8
......@@ -5,25 +5,20 @@ use crate::sys::cvt;
55use crate::sys::helpers::run_path_with_cstr;
66use crate::{io, ptr};
77
8#[inline]
9pub fn is_sep_byte(b: u8) -> bool {
10 b == b'/' || b == b'\\'
11}
8path_separator_bytes!(b'/', b'\\');
129
1310/// Cygwin always prefers `/` over `\`, and it always converts all `/` to `\`
1411/// internally when calling Win32 APIs. Therefore, the server component of path
1512/// `\\?\UNC\localhost/share` is `localhost/share` on Win32, but `localhost`
1613/// on Cygwin.
1714#[inline]
18pub fn is_verbatim_sep(b: u8) -> bool {
19 b == b'/' || b == b'\\'
15pub const fn is_verbatim_sep(b: u8) -> bool {
16 is_sep_byte(b)
2017}
2118
2219pub use super::windows_prefix::parse_prefix;
2320
2421pub const HAS_PREFIXES: bool = true;
25pub const MAIN_SEP_STR: &str = "/";
26pub const MAIN_SEP: char = '/';
2722
2823unsafe extern "C" {
2924 // 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.
3macro_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
120cfg_select! {
221 target_os = "windows" => {
322 mod windows;
library/std/src/sys/path/sgx.rs+3-8
......@@ -3,14 +3,11 @@ use crate::io;
33use crate::path::{Path, PathBuf, Prefix};
44use crate::sys::unsupported;
55
6#[inline]
7pub fn is_sep_byte(b: u8) -> bool {
8 b == b'/'
9}
6path_separator_bytes!(b'/');
107
118#[inline]
12pub fn is_verbatim_sep(b: u8) -> bool {
13 b == b'/'
9pub const fn is_verbatim_sep(b: u8) -> bool {
10 is_sep_byte(b)
1411}
1512
1613pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
......@@ -18,8 +15,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1815}
1916
2017pub const HAS_PREFIXES: bool = false;
21pub const MAIN_SEP_STR: &str = "/";
22pub const MAIN_SEP: char = '/';
2318
2419pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
2520 unsupported()
library/std/src/sys/path/uefi.rs+4-9
......@@ -5,17 +5,14 @@ use crate::path::{Path, PathBuf, Prefix};
55use crate::sys::pal::helpers;
66use crate::sys::unsupported_err;
77
8path_separator_bytes!(b'\\');
9
810const FORWARD_SLASH: u8 = b'/';
911const COLON: u8 = b':';
1012
1113#[inline]
12pub fn is_sep_byte(b: u8) -> bool {
13 b == b'\\'
14}
15
16#[inline]
17pub fn is_verbatim_sep(b: u8) -> bool {
18 b == b'\\'
14pub const fn is_verbatim_sep(b: u8) -> bool {
15 is_sep_byte(b)
1916}
2017
2118pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
......@@ -23,8 +20,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
2320}
2421
2522pub const HAS_PREFIXES: bool = true;
26pub const MAIN_SEP_STR: &str = "\\";
27pub const MAIN_SEP: char = '\\';
2823
2924/// UEFI paths can be of 4 types:
3025///
library/std/src/sys/path/unix.rs+3-8
......@@ -2,14 +2,11 @@ use crate::ffi::OsStr;
22use crate::path::{Path, PathBuf, Prefix};
33use crate::{env, io};
44
5#[inline]
6pub fn is_sep_byte(b: u8) -> bool {
7 b == b'/'
8}
5path_separator_bytes!(b'/');
96
107#[inline]
11pub fn is_verbatim_sep(b: u8) -> bool {
12 b == b'/'
8pub const fn is_verbatim_sep(b: u8) -> bool {
9 is_sep_byte(b)
1310}
1411
1512#[inline]
......@@ -18,8 +15,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1815}
1916
2017pub const HAS_PREFIXES: bool = false;
21pub const MAIN_SEP_STR: &str = "/";
22pub const MAIN_SEP: char = '/';
2318
2419/// Make a POSIX path absolute without changing its semantics.
2520pub(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;
44use crate::path::{Path, PathBuf, Prefix};
55use crate::sys::unsupported;
66
7#[inline]
8pub fn is_sep_byte(b: u8) -> bool {
9 b == b'\\'
10}
7path_separator_bytes!(b'\\');
118
129#[inline]
13pub fn is_verbatim_sep(b: u8) -> bool {
14 b == b'\\'
10pub const fn is_verbatim_sep(b: u8) -> bool {
11 is_sep_byte(b)
1512}
1613
1714pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
......@@ -19,8 +16,6 @@ pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
1916}
2017
2118pub const HAS_PREFIXES: bool = true;
22pub const MAIN_SEP_STR: &str = "\\";
23pub const MAIN_SEP: char = '\\';
2419
2520pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> {
2621 unsupported()
library/std/src/sys/path/windows.rs+3-8
......@@ -9,9 +9,9 @@ mod tests;
99
1010pub use super::windows_prefix::parse_prefix;
1111
12path_separator_bytes!(b'\\', b'/');
13
1214pub const HAS_PREFIXES: bool = true;
13pub const MAIN_SEP_STR: &str = "\\";
14pub const MAIN_SEP: char = '\\';
1515
1616/// A null terminated wide string.
1717#[repr(transparent)]
......@@ -48,12 +48,7 @@ pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&WCStr) -> io::Result<T>) ->
4848}
4949
5050#[inline]
51pub fn is_sep_byte(b: u8) -> bool {
52 b == b'/' || b == b'\\'
53}
54
55#[inline]
56pub fn is_verbatim_sep(b: u8) -> bool {
51pub const fn is_verbatim_sep(b: u8) -> bool {
5752 b == b'\\'
5853}
5954
src/doc/rustc-dev-guide/src/compiler-debugging.md+3-3
......@@ -275,16 +275,16 @@ Here are some notable ones:
275275|----------------|-------------|
276276| `rustc_def_path` | Dumps the [`def_path_str`] of an item. |
277277| `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. |
278279| `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. |
279281| `rustc_dump_predicates` | Dumps the [`predicates_of`] an item. |
282| `rustc_dump_variances` | Dumps the [variances] of an item. |
280283| `rustc_dump_vtable` | Dumps the vtable layout of an impl, or a type alias of a dyn type. |
281284| `rustc_hidden_type_of_opaques` | Dumps the [hidden type of each opaque types][opaq] in the crate. |
282285| `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. |
285286| `rustc_regions` | Dumps NLL closure region requirements. |
286287| `rustc_symbol_name` | Dumps the mangled & demangled [`symbol_name`] of an item. |
287| `rustc_variances` | Dumps the [variances] of an item. |
288288
289289Right below you can find elaborate explainers on a selected few.
290290
src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md+6-7
......@@ -1,6 +1,6 @@
11# Diagnostic and subdiagnostic structs
2rustc has three diagnostic traits that can be used to create diagnostics:
3`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`.
2rustc has two diagnostic traits that can be used to create diagnostics:
3`Diagnostic` and `Subdiagnostic`.
44
55For simple diagnostics,
66derived 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
88
99In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics,
1010customizing the rendering logic, or selecting messages at runtime, you will need to manually implement
11the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`).
11the corresponding trait (`Diagnostic` or `Subdiagnostic`).
1212This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.
1313
1414Diagnostic can be translated into different languages.
1515
16## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
16## `#[derive(Diagnostic)]`
1717
1818Consider the [definition][defn] of the "field already declared" diagnostic shown below:
1919
......@@ -123,8 +123,8 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
123123});
124124```
125125
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:
128128
129129- `#[diag("message", code = "...")]`
130130 - _Applied to struct or enum variant._
......@@ -171,7 +171,6 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
171171 - Adds the subdiagnostic represented by the subdiagnostic struct.
172172- `#[primary_span]` (_Optional_)
173173 - _Applied to `Span` fields on `Subdiagnostic`s.
174 Not used for `LintDiagnostic`s._
175174 - Indicates the primary span of the diagnostic.
176175- `#[skip_arg]` (_Optional_)
177176 - _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:
3232 deciding to emit subdiagnostics and can therefore be represented as diagnostic structs).
3333 See [the diagnostic and subdiagnostic structs documentation](./diagnostic-structs.md).
34342. Using typed identifiers with `Diag` APIs (in
35 `Diagnostic` or `Subdiagnostic` or `LintDiagnostic` implementations).
35 `Diagnostic` or `Subdiagnostic` implementations).
3636
3737When adding or changing a translatable diagnostic,
3838you 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;
55
66use rustc_data_structures::sync::Lock;
77use rustc_errors::emitter::Emitter;
8use rustc_errors::translation::format_diag_message;
8use rustc_errors::formatting::format_diag_message;
99use rustc_errors::{Applicability, DiagCtxt, DiagInner};
1010use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
1111use 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:
189189MIRI_TRACING=1 ./miri run --features=tracing tests/pass/hello.rs
190190```
191191
192See [doc/tracing.md](./doc/tracing.md) for more information.
193
192194### UI testing
193195
194196We 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 @@
22
33Miri 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.
44
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
58## Obtaining a trace file
69
710### From the Miri codebase
......@@ -240,7 +243,7 @@ let _trace = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_p
240243
241244### `tracing_separate_thread` parameter
242245
243Miri 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:
246Miri 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:
244247```rust
245248let _trace = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty);
246249```
......@@ -277,9 +280,12 @@ So the solution was to copy-paste [the only file](https://github.com/thoren-d/tr
277280
278281### Time measurements
279282
280tracing-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.
283tracing-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
285On 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.
281286
282Therefore, 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!
283289
284290## Other useful stuff
285291
src/tools/miri/rust-version+1-1
......@@ -1 +1 @@
17bee525095c0872e87c038c412c781b9bbb3f5dc
1d933cf483edf1605142ac6899ff32536c0ad8b22
src/tools/miri/src/alloc_addresses/mod.rs+5-1
......@@ -168,7 +168,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
168168 if let Some(GlobalAlloc::Function { instance, .. }) =
169169 this.tcx.try_get_global_alloc(alloc_id)
170170 {
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 );
172176 let fn_ptr = crate::shims::native_lib::build_libffi_closure(this, fn_sig)?;
173177
174178 #[expect(
src/tools/miri/src/bin/log/mod.rs-1
......@@ -1,3 +1,2 @@
11pub mod setup;
22mod tracing_chrome;
3mod tracing_chrome_instant;
src/tools/miri/src/bin/log/tracing_chrome.rs+39-22
......@@ -50,9 +50,8 @@ use std::{
5050 thread::JoinHandle,
5151};
5252
53use crate::log::tracing_chrome_instant::TracingChromeInstant;
54
5553/// Contains thread-local data for threads that send tracing spans or events.
54#[derive(Clone)]
5655struct ThreadData {
5756 /// A unique ID for this thread, will populate "tid" field in the output trace file.
5857 tid: usize,
......@@ -61,7 +60,7 @@ struct ThreadData {
6160 out: Sender<Message>,
6261 /// The instant in time this thread was started. All events happening on this thread will be
6362 /// saved to the trace file with a timestamp (the "ts" field) measured relative to this instant.
64 start: TracingChromeInstant,
63 start: std::time::Instant,
6564}
6665
6766thread_local! {
......@@ -562,28 +561,46 @@ where
562561 #[inline(always)]
563562 fn with_elapsed_micros_subtracting_tracing(&self, f: impl Fn(f64, usize, &Sender<Message>)) {
564563 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 }
574578 }
575579 };
576580
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;
587604 });
588605 }
589606}
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).
23pub 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
41impl 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")))]
112mod 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
193193
194194impl rustc_driver::Callbacks for MiriCompilerCalls {
195195 fn config(&mut self, config: &mut rustc_interface::interface::Config) {
196 // We never reach codegen anyway.
196197 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();
197201 }
198202
199203 fn after_analysis<'tcx>(
......@@ -354,6 +358,9 @@ impl rustc_driver::Callbacks for MiriDepCompilerCalls {
354358 )
355359 }
356360 });
361
362 // Register our custom extra symbols.
363 config.extra_symbols = miri::sym::EXTRA_SYMBOLS.into();
357364 }
358365
359366 fn after_analysis<'tcx>(
src/tools/miri/src/concurrency/genmc/scheduling.rs+5-4
......@@ -5,7 +5,8 @@ use rustc_middle::ty::{self, Ty};
55
66use super::GenmcCtx;
77use 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,
910};
1011
1112enum NextInstrKind {
......@@ -76,11 +77,11 @@ fn get_function_kind<'tcx>(
7677 // NOTE: Functions intercepted by Miri in `concurrency/genmc/intercep.rs` must also be added here.
7778 // Such intercepted functions, like `sys::Mutex::lock`, should be treated as atomics to ensure we call the scheduler when we encounter one of them.
7879 // 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)
8182 {
8283 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) {
8485 return interp_ok(MaybeAtomic(ActionKind::NonLoad));
8586 }
8687 // 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 {
2424 }
2525}
2626
27/// Small helper to get the arguments of an intercepted function call.
28fn 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
2739// Handling of code intercepted by Miri in GenMC mode, such as assume statement or `std::sync::Mutex`.
2840
2941impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
3042trait 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
4543 /**** Blocking functionality ****/
4644
4745 /// 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> {
200198 );
201199
202200 // 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;
204201 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)?;
206203 let mutex = this.deref_pointer(&mutex)?;
207204 this.intercept_mutex_lock(mutex)?;
208205 } 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)?;
210207 let mutex = this.deref_pointer(&mutex)?;
211208 this.intercept_mutex_try_lock(mutex, dest)?;
212209 } 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)?;
214211 let mutex = this.deref_pointer(&mutex)?;
215212 this.intercept_mutex_unlock(mutex)?;
216213 } else {
src/tools/miri/src/diagnostics.rs+3
......@@ -149,6 +149,7 @@ pub enum NonHaltingDiagnostic {
149149 failure_ordering: AtomicReadOrd,
150150 effective_failure_ordering: AtomicReadOrd,
151151 },
152 FileInProcOpened,
152153}
153154
154155/// Level of Miri specific diagnostics
......@@ -655,6 +656,7 @@ impl<'tcx> MiriMachine<'tcx> {
655656 | ProgressReport { .. }
656657 | WeakMemoryOutdatedLoad { .. } =>
657658 ("tracking was triggered here".to_string(), DiagLevel::Note),
659 FileInProcOpened => ("open a file in `/proc`".to_string(), DiagLevel::Warning),
658660 };
659661
660662 let title = match &e {
......@@ -702,6 +704,7 @@ impl<'tcx> MiriMachine<'tcx> {
702704 };
703705 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.")
704706 }
707 FileInProcOpened => format!("files in `/proc` can bypass the Abstract Machine and might not work properly in Miri")
705708 };
706709
707710 let notes = match &e {
src/tools/miri/src/intrinsics/mod.rs+1-1
......@@ -10,7 +10,7 @@ pub use self::atomic::AtomicRmwOp;
1010use rand::Rng;
1111use rustc_abi::Size;
1212use rustc_middle::{mir, ty};
13use rustc_span::{Symbol, sym};
13use rustc_span::Symbol;
1414
1515use self::atomic::EvalContextExt as _;
1616use self::math::EvalContextExt as _;
src/tools/miri/src/lib.rs+6-1
......@@ -1,4 +1,5 @@
11#![cfg_attr(bootstrap, feature(if_let_guard))]
2#![cfg_attr(bootstrap, feature(cfg_select))]
23#![feature(abort_unwind)]
34#![feature(rustc_private)]
45#![feature(float_gamma)]
......@@ -16,7 +17,7 @@
1617#![feature(derive_coerce_pointee)]
1718#![feature(arbitrary_self_types)]
1819#![feature(iter_advance_by)]
19#![cfg_attr(bootstrap, feature(cfg_select))]
20#![feature(macro_metavar_expr)]
2021// Configure clippy and other lints
2122#![allow(
2223 clippy::collapsible_else_if,
......@@ -39,8 +40,11 @@
3940 clippy::needless_lifetimes,
4041 clippy::too_long_first_doc_paragraph,
4142 clippy::len_zero,
43 clippy::collapsible_match,
4244 // We are not implementing queries here so it's fine
4345 rustc::potential_query_instability,
46 // FIXME: Unused features should be removed in the future
47 unused_features,
4448)]
4549#![warn(
4650 rust_2018_idioms,
......@@ -87,6 +91,7 @@ mod math;
8791mod operator;
8892mod provenance_gc;
8993mod shims;
94pub mod sym;
9095
9196// Establish a "crate-wide prelude": we often import `crate::*`.
9297// 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 {
300300
301301#[cfg(target_pointer_width = "64")]
302302static_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).
304305// #[cfg(target_pointer_width = "64")]
305306//static_assert_size!(Pointer, 24);
306307#[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> {
196196 let [flag] = check_min_vararg_count("fcntl(fd, F_SETFL, ...)", varargs)?;
197197 let flag = this.read_scalar(flag)?.to_i32()?;
198198
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)
200212 }
201213 cmd if this.tcx.sess.target.os == Os::MacOs
202214 && 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> {
539539 this.write_scalar(result, dest)?;
540540 }
541541
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
542554 // Time
543555 "gettimeofday" => {
544556 let [tv, tz] = this.check_shim_sig(
src/tools/miri/src/shims/unix/fs.rs+9-2
......@@ -7,7 +7,7 @@ use std::fs::{
77 rename,
88};
99use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write};
10use std::path::{Path, PathBuf};
10use std::path::{self, Path, PathBuf};
1111use std::time::SystemTime;
1212
1313use rustc_abi::Size;
......@@ -354,9 +354,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
354354 let this = self.eval_context_mut();
355355
356356 let path_raw = this.read_pointer(path_raw)?;
357 let path = this.read_path_from_c_str(path_raw)?;
358357 let flag = this.read_scalar(flag)?.to_i32()?;
359358
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
360367 let mut options = OpenOptions::new();
361368
362369 let o_rdonly = this.eval_libc_i32("O_RDONLY");
src/tools/miri/src/shims/unix/mod.rs+2
......@@ -4,6 +4,7 @@ mod env;
44mod fd;
55mod fs;
66mod mem;
7mod socket;
78mod sync;
89mod thread;
910mod unnamed_socket;
......@@ -21,6 +22,7 @@ pub use self::fd::{EvalContextExt as _, UnixFileDescription};
2122pub use self::fs::{DirTable, EvalContextExt as _};
2223pub use self::linux_like::epoll::EpollInterestTable;
2324pub use self::mem::EvalContextExt as _;
25pub use self::socket::EvalContextExt as _;
2426pub use self::sync::EvalContextExt as _;
2527pub use self::thread::{EvalContextExt as _, ThreadNameResult};
2628pub use self::unnamed_socket::EvalContextExt as _;
src/tools/miri/src/shims/unix/socket.rs created+157
......@@ -0,0 +1,157 @@
1use std::cell::Cell;
2use std::net::{TcpListener, TcpStream};
3
4use rustc_const_eval::interpret::{InterpResult, interp_ok};
5use rustc_middle::throw_unsup_format;
6use rustc_target::spec::Os;
7
8use crate::shims::files::{FdId, FileDescription};
9use crate::{OpTy, Scalar, *};
10
11#[derive(Debug, PartialEq)]
12enum SocketFamily {
13 // IPv4 internet protocols
14 IPv4,
15 // IPv6 internet protocols
16 IPv6,
17}
18
19#[derive(Debug)]
20enum SocketType {
21 /// Reliable full-duplex communication, based on connections.
22 Stream,
23}
24
25#[allow(unused)]
26#[derive(Debug)]
27enum SocketKind {
28 TcpListener(TcpListener),
29 TcpStream(TcpStream),
30}
31
32#[allow(unused)]
33#[derive(Debug)]
34struct 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
45impl 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
81impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
82pub 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 {
170170 mut flag: i32,
171171 ecx: &mut MiriInterpCx<'tcx>,
172172 ) -> InterpResult<'tcx, Scalar> {
173 // FIXME: File creation flags should be ignored.
174
175173 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");
179174
180175 // O_NONBLOCK flag can be set / unset by user.
181176 if flag & o_nonblock == o_nonblock {
......@@ -185,9 +180,6 @@ impl FileDescription for AnonSocket {
185180 self.is_nonblock.set(false);
186181 }
187182
188 // Ignore all file access mode flags.
189 flag &= !(o_rdonly | o_wronly | o_rdwr);
190
191183 // Throw error if there is any unsupported flag.
192184 if flag != 0 {
193185 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)]
4pub use rustc_span::sym::*;
5
6macro_rules! val {
7 ($name:ident) => {
8 stringify!($name)
9 };
10 ($name:ident $value:literal) => {
11 $value
12 };
13}
14
15macro_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.
32generate! {
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
4use std::alloc;
5use std::cell::Cell;
6
7type T = (Cell<i32>, i32);
8
9// Deallocating `x` is UB because not all bytes are in an `UnsafeCell`.
10fn 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
15fn 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 @@
1error: 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 |
4LL | 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
9help: <TAG> was created by a SharedReadOnly retag at offsets [0x4..0xc]
10 --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC
11 |
12LL | 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
20note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
21
22error: 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 @@
1error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x4] is forbidden
2 --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC
3 |
4LL | 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)
10help: the accessed tag <TAG> was created here, in the initial state Cell
11 --> tests/fail/both_borrows/mixed_cell_deallocate.rs:LL:CC
12 |
13LL | 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
21note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
22
23error: 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC
3 |
4LL | 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
17error: unsupported operation: calling a function pointer through the FFI boundary
18 --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC
19 |
20LL | 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
30note: 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
6fn main() {
7 pass_fn_ptr()
8}
9
10fn 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC
3 |
4LL | 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
18error: unsupported operation: calling a function pointer through the FFI boundary
19 --> tests/native-lib/fail/call_fn_ptr.rs:LL:CC
20 |
21LL | 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
31note: 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC
3 |
4LL | 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
17error: unsupported operation: calling a function pointer through the FFI boundary
18 --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC
19 |
20LL | 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
30note: 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
6fn main() {
7 pass_fn_ptr()
8}
9
10fn 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC
3 |
4LL | 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
18error: unsupported operation: calling a function pointer through the FFI boundary
19 --> tests/native-lib/fail/call_fn_ptr_with_generic.rs:LL:CC
20 |
21LL | 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
31note: 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_function_ptr.rs:LL:CC
3 |
4LL | 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
17error: unsupported operation: calling a function pointer through the FFI boundary
18 --> tests/native-lib/fail/call_function_ptr.rs:LL:CC
19 |
20LL | 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
30note: 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
6fn main() {
7 pass_fn_ptr()
8}
9
10fn 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 @@
1warning: sharing memory with a native function called via FFI
2 --> tests/native-lib/fail/call_function_ptr.rs:LL:CC
3 |
4LL | 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
18error: unsupported operation: calling a function pointer through the FFI boundary
19 --> tests/native-lib/fail/call_function_ptr.rs:LL:CC
20 |
21LL | 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
31note: 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
7EXPORT void call_fn_ptr(void f(void)) {
8 if (f != NULL) {
9 f();
10 }
11}
12
13EXPORT 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() {
1010 test_access_simple();
1111 test_access_nested();
1212 test_access_static();
13 pass_fn_ptr();
1413}
1514
1615/// Test function that dereferences an int pointer and prints its contents from C.
......@@ -82,16 +81,3 @@ fn test_access_static() {
8281
8382 assert_eq!(unsafe { access_static(&STATIC) }, 9001);
8483}
85
86fn 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) {
6262EXPORT uintptr_t do_one_deref(const int32_t ***ptr) {
6363 return (uintptr_t)*ptr;
6464}
65
66/* Test: pass_fn_ptr */
67
68EXPORT void pass_fn_ptr(void f(void)) {
69 (void)f; // suppress unused warning
70}
71
72/* Test: function_ptrs */
73EXPORT 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() {
148148 errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(),
149149 libc::O_RDONLY
150150 );
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 );
151169}
152170
153171/// 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
6use std::io::ErrorKind;
7
8#[path = "../../utils/libc.rs"]
9mod libc_utils;
10use libc_utils::*;
11
12fn 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 @@
1warning: `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"]
7mod libc_utils;
8use libc_utils::*;
9
10fn main() {
11 test_socket_close();
12}
13
14fn 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
5fn 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 @@
1warning: 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 |
4LL | 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 {
4242 std::fs::create_dir_all(&so_target_dir)
4343 .expect("Failed to create directory for shared object file");
4444 // 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");
4646 let cc_output = Command::new(cc)
4747 .args([
4848 "-shared",
......@@ -58,6 +58,7 @@ fn build_native_lib(target: &str) -> PathBuf {
5858 "tests/native-lib/aggregate_arguments.c",
5959 "tests/native-lib/ptr_read_access.c",
6060 "tests/native-lib/ptr_write_access.c",
61 "tests/native-lib/fn_ptr.c",
6162 // Ensure we notice serious problems in the C code.
6263 "-Wall",
6364 "-Wextra",
src/tools/run-make-support/src/external_deps/rustc.rs+32-1
......@@ -4,7 +4,7 @@ use std::str::FromStr as _;
44
55use crate::command::Command;
66use crate::env::env_var;
7use crate::path_helpers::cwd;
7use crate::path_helpers::{cwd, source_root};
88use crate::util::set_host_compiler_dylib_path;
99use crate::{is_aix, is_darwin, is_windows, is_windows_msvc, target, uname};
1010
......@@ -22,6 +22,37 @@ pub fn bare_rustc() -> Rustc {
2222 Rustc::bare()
2323}
2424
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]
47pub 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
2556/// A `rustc` invocation builder.
2657#[derive(Debug)]
2758#[must_use]
src/tools/run-make-support/src/lib.rs+1-1
......@@ -72,7 +72,7 @@ pub use crate::external_deps::llvm::{
7272 llvm_readobj,
7373};
7474pub use crate::external_deps::python::python_command;
75pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_path};
75pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path};
7676pub use crate::external_deps::rustdoc::{Rustdoc, bare_rustdoc, rustdoc};
7777// Path-related helpers.
7878pub use crate::path_helpers::{
src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs+1-1
......@@ -10,7 +10,7 @@
1010 feature = "sysroot-abi",
1111 feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)
1212)]
13#![allow(internal_features)]
13#![allow(internal_features, unused_features)]
1414#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
1515
1616#[cfg(feature = "in-rust-tree")]
src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs+2-1
......@@ -18,7 +18,8 @@
1818 internal_features,
1919 clippy::disallowed_types,
2020 clippy::print_stderr,
21 unused_crate_dependencies
21 unused_crate_dependencies,
22 unused_features
2223)]
2324#![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)]
2425
src/tools/test-float-parse/src/lib.rs+1-1
......@@ -1,5 +1,5 @@
1#![feature(f16)]
21#![feature(cfg_target_has_reliable_f16_f128)]
2#![cfg_attr(target_has_reliable_f16, feature(f16))]
33#![expect(internal_features)] // reliable_f16_f128
44
55mod traits;
tests/auxiliary/minicore.rs+11
......@@ -288,6 +288,17 @@ pub mod mem {
288288 pub const fn align_of<T>() -> usize;
289289}
290290
291pub 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
291302#[lang = "c_void"]
292303#[repr(u8)]
293304pub enum c_void {
tests/incremental/add_private_fn_at_krate_root_cc/struct_point.rs-1
......@@ -9,7 +9,6 @@
99//@ ignore-backends: gcc
1010
1111#![feature(rustc_attrs)]
12#![feature(stmt_expr_attributes)]
1312#![allow(dead_code)]
1413#![crate_type = "rlib"]
1514
tests/incremental/change_add_field/struct_point.rs-1
......@@ -9,7 +9,6 @@
99//@ ignore-backends: gcc
1010
1111#![feature(rustc_attrs)]
12#![feature(stmt_expr_attributes)]
1312#![allow(dead_code)]
1413#![crate_type = "rlib"]
1514
tests/incremental/change_crate_dep_kind.rs+1-1
......@@ -8,7 +8,7 @@
88//@ build-pass (FIXME(62277): could be check-pass?)
99//@ ignore-backends: gcc
1010
11#![feature(panic_unwind)]
11#![cfg_attr(cfail1, feature(panic_unwind))]
1212
1313// Turn the panic_unwind crate from an explicit into an implicit query:
1414#[cfg(cfail1)]
tests/incremental/change_private_fn/struct_point.rs-1
......@@ -7,7 +7,6 @@
77//@ ignore-backends: gcc
88
99#![feature(rustc_attrs)]
10#![feature(stmt_expr_attributes)]
1110#![allow(dead_code)]
1211#![crate_type = "rlib"]
1312
tests/incremental/change_private_fn_cc/struct_point.rs-1
......@@ -9,7 +9,6 @@
99
1010#![crate_type = "rlib"]
1111#![feature(rustc_attrs)]
12#![feature(stmt_expr_attributes)]
1312#![allow(dead_code)]
1413
1514#![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 @@
77//@ ignore-backends: gcc
88
99#![feature(rustc_attrs)]
10#![feature(stmt_expr_attributes)]
1110#![allow(dead_code)]
1211#![crate_type = "rlib"]
1312
tests/incremental/change_private_impl_method_cc/struct_point.rs-1
......@@ -9,7 +9,6 @@
99
1010#![crate_type = "rlib"]
1111#![feature(rustc_attrs)]
12#![feature(stmt_expr_attributes)]
1312#![allow(dead_code)]
1413
1514#![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 @@
77
88#![crate_type = "rlib"]
99#![feature(rustc_attrs)]
10#![feature(stmt_expr_attributes)]
1110#![allow(dead_code)]
1211
1312#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
tests/incremental/change_pub_inherent_method_sig/struct_point.rs-1
......@@ -7,7 +7,6 @@
77
88#![crate_type = "rlib"]
99#![feature(rustc_attrs)]
10#![feature(stmt_expr_attributes)]
1110#![allow(dead_code)]
1211
1312// 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
17pub fn use_box_patterns(b: Box<i32>) -> i32 {
18 let box x = b;
19 x
20}
21
22macro m() {}
23pub fn use_decl_macro() {
24 m!();
25}
26
27#[rustc_dummy]
28pub fn use_rustc_attrs() {}
29
30#[cfg(rpass)]
31pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) {
32 for _ in e.sources() {}
33}
34
35#[cfg(rpass)]
36pub fn use_allocator_api() {
37 use std::alloc::Global;
38 let _ = Vec::<i32>::new_in(Global);
39}
40
41fn main() {}
tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs+2-30
......@@ -7,7 +7,8 @@
77#![no_main]
88#![allow(internal_features)]
99
10use minicore::ptr;
10extern crate minicore;
11use minicore::*;
1112
1213#[no_mangle]
1314pub fn main() -> ! {
......@@ -21,32 +22,3 @@ pub fn main() -> ! {
2122 unsafe { ptr::write_volatile(port_b, 2) };
2223 }
2324}
24
25// FIXME: replace with proper minicore once available (#130693)
26mod 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 @@
1515// crashes... so I'm going to disable this test for windows for now.
1616//@ ignore-windows-gnu
1717
18use run_make_support::{llvm_objdump, rustc};
18use run_make_support::{llvm_objdump, path, rustc, rustc_minicore};
1919
2020fn main() {
21 rustc_minicore().target("avr-none").target_cpu("avr").output("libminicore.rlib").run();
22
2123 rustc()
2224 .input("avr-rjmp-offsets.rs")
2325 .opt_level("s")
......@@ -36,6 +38,7 @@ fn main() {
3638 .linker("rust-lld")
3739 .link_arg("--entry=main")
3840 .output("compiled")
41 .extern_("minicore", path("libminicore.rlib"))
3942 .run();
4043
4144 let disassembly = llvm_objdump().disassemble().input("compiled").run().stdout_utf8();
tests/run-make/thumb-interworking/rmake.rs+5-11
......@@ -1,6 +1,8 @@
11//@ needs-llvm-components: arm
22//@ needs-rust-lld
3use run_make_support::{llvm_filecheck, llvm_objdump, path, rfs, run, rustc, source_root};
3use run_make_support::{
4 llvm_filecheck, llvm_objdump, path, rfs, run, rustc, rustc_minicore, source_root,
5};
46
57// Test a thumb target calling arm functions. Doing so requires switching from thumb mode to arm
68// mode, calling the arm code, then switching back to thumb mode. Depending on the thumb version,
......@@ -25,21 +27,13 @@ fn main() {
2527}
2628
2729fn 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();
3631
3732 rustc()
3833 .input("main.rs")
3934 .panic("abort")
4035 .link_arg("-Tlink.ld")
41 .arg("--extern")
42 .arg(format!("minicore={}", minicore.display()))
36 .extern_("minicore", path("libminicore.rlib"))
4337 .target(target)
4438 .output(prefix)
4539 .run();
tests/run-make/wasm-unexpected-features/foo.rs+3-18
......@@ -4,6 +4,9 @@
44#![needs_allocator]
55#![allow(internal_features)]
66
7extern crate minicore;
8use minicore::*;
9
710#[rustc_std_internal_symbol]
811unsafe fn __rust_alloc(_size: usize, _align: usize) -> *mut u8 {
912 0 as *mut u8
......@@ -23,21 +26,3 @@ extern "C" fn init() {
2326 __rust_alloc_error_handler(0, 0);
2427 }
2528}
26
27mod 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
32use std::path::Path;
43
5use run_make_support::{rfs, rustc, wasmparser};
4use run_make_support::{path, rfs, rustc, rustc_minicore, wasmparser};
65
76fn main() {
7 rustc_minicore().target("wasm32-wasip1").target_cpu("mvp").output("libminicore.rlib").run();
8
89 rustc()
910 .input("foo.rs")
1011 .target("wasm32-wasip1")
......@@ -13,6 +14,7 @@ fn main() {
1314 .lto("fat")
1415 .linker_plugin_lto("on")
1516 .link_arg("--import-memory")
17 .extern_("minicore", path("libminicore.rlib"))
1618 .run();
1719 verify_features(Path::new("foo.wasm"));
1820}
tests/ui-fulldeps/rustc_public/check_abi.rs-1
......@@ -6,7 +6,6 @@
66//@ ignore-remote
77
88#![feature(rustc_private)]
9#![feature(ascii_char, ascii_char_variants)]
109
1110extern crate rustc_driver;
1211extern crate rustc_hir;
tests/ui-fulldeps/rustc_public/check_transform.rs-1
......@@ -6,7 +6,6 @@
66//@ ignore-remote
77
88#![feature(rustc_private)]
9#![feature(ascii_char, ascii_char_variants)]
109
1110extern crate rustc_hir;
1211extern crate rustc_middle;
tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs+1-28
......@@ -20,7 +20,7 @@ use rustc_span::symbol::Ident;
2020use rustc_span::Span;
2121
2222extern crate rustc_macros;
23use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
23use rustc_macros::{Diagnostic, Subdiagnostic};
2424
2525extern crate rustc_middle;
2626use rustc_middle::ty::Ty;
......@@ -495,18 +495,6 @@ struct LabelWithTrailingList {
495495 span: Span,
496496}
497497
498#[derive(LintDiagnostic)]
499#[diag("this is an example message")]
500struct LintsGood {}
501
502#[derive(LintDiagnostic)]
503#[diag("this is an example message")]
504struct PrimarySpanOnLint {
505 #[primary_span]
506 //~^ ERROR `#[primary_span]` is not a valid attribute
507 span: Span,
508}
509
510498#[derive(Diagnostic)]
511499#[diag("this is an example message", code = E0123)]
512500struct ErrorWithMultiSpan {
......@@ -542,13 +530,6 @@ struct WarnAttribute {}
542530//~| ERROR cannot find attribute `lint` in this scope
543531struct LintAttributeOnSessionDiag {}
544532
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
550struct LintAttributeOnLintDiag {}
551
552533#[derive(Diagnostic)]
553534#[diag("this is an example message", code = E0123)]
554535struct DuplicatedSuggestionCode {
......@@ -670,14 +651,6 @@ struct SubdiagnosticBadLitStr {
670651 note: Note,
671652}
672653
673#[derive(LintDiagnostic)]
674#[diag("this is an example message")]
675struct SubdiagnosticEagerLint {
676 #[subdiagnostic(eager)]
677 //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
678 note: Note,
679}
680
681654#[derive(Diagnostic)]
682655#[diag("this is an example message")]
683656struct SubdiagnosticEagerFormerlyCorrect {
tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr+35-75
......@@ -300,22 +300,14 @@ error: derive(Diagnostic): no nested attribute expected here
300300LL | #[label("with a label", foo("..."))]
301301 | ^^^
302302
303error: derive(Diagnostic): `#[primary_span]` is not a valid attribute
304 --> $DIR/diagnostic-derive-inline.rs:505:5
305 |
306LL | #[primary_span]
307 | ^
308 |
309 = help: the `primary_span` field attribute is not valid for lint diagnostics
310
311303error: derive(Diagnostic): `#[error(...)]` is not a valid attribute
312 --> $DIR/diagnostic-derive-inline.rs:525:1
304 --> $DIR/diagnostic-derive-inline.rs:513:1
313305 |
314306LL | #[error("this is an example message", code = E0123)]
315307 | ^
316308
317309error: derive(Diagnostic): diagnostic message not specified
318 --> $DIR/diagnostic-derive-inline.rs:525:1
310 --> $DIR/diagnostic-derive-inline.rs:513:1
319311 |
320312LL | #[error("this is an example message", code = E0123)]
321313 | ^
......@@ -323,13 +315,13 @@ LL | #[error("this is an example message", code = E0123)]
323315 = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
324316
325317error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute
326 --> $DIR/diagnostic-derive-inline.rs:532:1
318 --> $DIR/diagnostic-derive-inline.rs:520:1
327319 |
328320LL | #[warn_("this is an example message", code = E0123)]
329321 | ^
330322
331323error: derive(Diagnostic): diagnostic message not specified
332 --> $DIR/diagnostic-derive-inline.rs:532:1
324 --> $DIR/diagnostic-derive-inline.rs:520:1
333325 |
334326LL | #[warn_("this is an example message", code = E0123)]
335327 | ^
......@@ -337,27 +329,13 @@ LL | #[warn_("this is an example message", code = E0123)]
337329 = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
338330
339331error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute
340 --> $DIR/diagnostic-derive-inline.rs:539:1
341 |
342LL | #[lint("this is an example message", code = E0123)]
343 | ^
344
345error: derive(Diagnostic): diagnostic message not specified
346 --> $DIR/diagnostic-derive-inline.rs:539:1
347 |
348LL | #[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
353error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute
354 --> $DIR/diagnostic-derive-inline.rs:546:1
332 --> $DIR/diagnostic-derive-inline.rs:527:1
355333 |
356334LL | #[lint("this is an example message", code = E0123)]
357335 | ^
358336
359337error: derive(Diagnostic): diagnostic message not specified
360 --> $DIR/diagnostic-derive-inline.rs:546:1
338 --> $DIR/diagnostic-derive-inline.rs:527:1
361339 |
362340LL | #[lint("this is an example message", code = E0123)]
363341 | ^
......@@ -365,19 +343,19 @@ LL | #[lint("this is an example message", code = E0123)]
365343 = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]`
366344
367345error: derive(Diagnostic): attribute specified multiple times
368 --> $DIR/diagnostic-derive-inline.rs:555:53
346 --> $DIR/diagnostic-derive-inline.rs:536:53
369347 |
370348LL | #[suggestion("with a suggestion", code = "...", code = ",,,")]
371349 | ^^^^
372350 |
373351note: previously specified here
374 --> $DIR/diagnostic-derive-inline.rs:555:39
352 --> $DIR/diagnostic-derive-inline.rs:536:39
375353 |
376354LL | #[suggestion("with a suggestion", code = "...", code = ",,,")]
377355 | ^^^^
378356
379357error: derive(Diagnostic): wrong types for suggestion
380 --> $DIR/diagnostic-derive-inline.rs:564:24
358 --> $DIR/diagnostic-derive-inline.rs:545:24
381359 |
382360LL | suggestion: (Span, usize),
383361 | ^^^^^
......@@ -385,7 +363,7 @@ LL | suggestion: (Span, usize),
385363 = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
386364
387365error: derive(Diagnostic): wrong types for suggestion
388 --> $DIR/diagnostic-derive-inline.rs:572:17
366 --> $DIR/diagnostic-derive-inline.rs:553:17
389367 |
390368LL | suggestion: (Span,),
391369 | ^^^^^^^
......@@ -393,13 +371,13 @@ LL | suggestion: (Span,),
393371 = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
394372
395373error: derive(Diagnostic): suggestion without `code = "..."`
396 --> $DIR/diagnostic-derive-inline.rs:579:5
374 --> $DIR/diagnostic-derive-inline.rs:560:5
397375 |
398376LL | #[suggestion("with a suggestion")]
399377 | ^
400378
401379error: 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
403381 |
404382LL | #[multipart_suggestion("with a suggestion")]
405383 | ^
......@@ -407,7 +385,7 @@ LL | #[multipart_suggestion("with a suggestion")]
407385 = help: consider creating a `Subdiagnostic` instead
408386
409387error: 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
411389 |
412390LL | #[multipart_suggestion()]
413391 | ^
......@@ -415,7 +393,7 @@ LL | #[multipart_suggestion()]
415393 = help: consider creating a `Subdiagnostic` instead
416394
417395error: 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
419397 |
420398LL | #[multipart_suggestion("with a suggestion")]
421399 | ^
......@@ -423,7 +401,7 @@ LL | #[multipart_suggestion("with a suggestion")]
423401 = help: consider creating a `Subdiagnostic` instead
424402
425403error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute
426 --> $DIR/diagnostic-derive-inline.rs:601:1
404 --> $DIR/diagnostic-derive-inline.rs:582:1
427405 |
428406LL | #[suggestion("with a suggestion", code = "...")]
429407 | ^
......@@ -431,7 +409,7 @@ LL | #[suggestion("with a suggestion", code = "...")]
431409 = help: `#[label]` and `#[suggestion]` can only be applied to fields
432410
433411error: derive(Diagnostic): `#[label]` is not a valid attribute
434 --> $DIR/diagnostic-derive-inline.rs:610:1
412 --> $DIR/diagnostic-derive-inline.rs:591:1
435413 |
436414LL | #[label]
437415 | ^
......@@ -439,73 +417,67 @@ LL | #[label]
439417 = help: subdiagnostic message is missing
440418
441419error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
442 --> $DIR/diagnostic-derive-inline.rs:644:5
420 --> $DIR/diagnostic-derive-inline.rs:625:5
443421 |
444422LL | #[subdiagnostic(bad)]
445423 | ^
446424
447425error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute
448 --> $DIR/diagnostic-derive-inline.rs:652:5
426 --> $DIR/diagnostic-derive-inline.rs:633:5
449427 |
450428LL | #[subdiagnostic = "bad"]
451429 | ^
452430
453431error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
454 --> $DIR/diagnostic-derive-inline.rs:660:5
432 --> $DIR/diagnostic-derive-inline.rs:641:5
455433 |
456434LL | #[subdiagnostic(bad, bad)]
457435 | ^
458436
459437error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
460 --> $DIR/diagnostic-derive-inline.rs:668:5
438 --> $DIR/diagnostic-derive-inline.rs:649:5
461439 |
462440LL | #[subdiagnostic("bad")]
463441 | ^
464442
465443error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
466 --> $DIR/diagnostic-derive-inline.rs:676:5
444 --> $DIR/diagnostic-derive-inline.rs:657:5
467445 |
468446LL | #[subdiagnostic(eager)]
469447 | ^
470448
471449error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
472 --> $DIR/diagnostic-derive-inline.rs:684:5
473 |
474LL | #[subdiagnostic(eager)]
475 | ^
476
477error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute
478 --> $DIR/diagnostic-derive-inline.rs:705:5
450 --> $DIR/diagnostic-derive-inline.rs:678:5
479451 |
480452LL | #[subdiagnostic(eager)]
481453 | ^
482454
483455error: 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
485457 |
486458LL | #[suggestion("with a suggestion", code())]
487459 | ^
488460
489461error: derive(Diagnostic): `code(...)` must contain only string literals
490 --> $DIR/diagnostic-derive-inline.rs:744:44
462 --> $DIR/diagnostic-derive-inline.rs:717:44
491463 |
492464LL | #[suggestion("with a suggestion", code(foo))]
493465 | ^^^
494466
495467error: unexpected token, expected `)`
496 --> $DIR/diagnostic-derive-inline.rs:744:44
468 --> $DIR/diagnostic-derive-inline.rs:717:44
497469 |
498470LL | #[suggestion("with a suggestion", code(foo))]
499471 | ^^^
500472
501473error: expected string literal
502 --> $DIR/diagnostic-derive-inline.rs:753:46
474 --> $DIR/diagnostic-derive-inline.rs:726:46
503475 |
504476LL | #[suggestion("with a suggestion", code = 3)]
505477 | ^
506478
507479error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute
508 --> $DIR/diagnostic-derive-inline.rs:768:5
480 --> $DIR/diagnostic-derive-inline.rs:741:5
509481 |
510482LL | #[suggestion("with a suggestion", code = "")]
511483 | ^
......@@ -515,7 +487,7 @@ LL | #[suggestion("with a suggestion", code = "")]
515487 = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
516488
517489error: derive(Diagnostic): Variable `nosub` not found in diagnostic
518 --> $DIR/diagnostic-derive-inline.rs:780:8
490 --> $DIR/diagnostic-derive-inline.rs:753:8
519491 |
520492LL | #[diag("does not exist: {$nosub}")]
521493 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
......@@ -535,7 +507,7 @@ LL | #[nonsense]
535507 | ^^^^^^^^
536508
537509error: cannot find attribute `error` in this scope
538 --> $DIR/diagnostic-derive-inline.rs:525:3
510 --> $DIR/diagnostic-derive-inline.rs:513:3
539511 |
540512LL | #[error("this is an example message", code = E0123)]
541513 | ^^^^^
......@@ -547,7 +519,7 @@ LL | struct ErrorAttribute {}
547519 |
548520
549521error: cannot find attribute `warn_` in this scope
550 --> $DIR/diagnostic-derive-inline.rs:532:3
522 --> $DIR/diagnostic-derive-inline.rs:520:3
551523 |
552524LL | #[warn_("this is an example message", code = E0123)]
553525 | ^^^^^
......@@ -559,19 +531,7 @@ LL + #[warn("this is an example message", code = E0123)]
559531 |
560532
561533error: cannot find attribute `lint` in this scope
562 --> $DIR/diagnostic-derive-inline.rs:539:3
563 |
564LL | #[lint("this is an example message", code = E0123)]
565 | ^^^^
566 |
567help: a built-in attribute with a similar name exists
568 |
569LL - #[lint("this is an example message", code = E0123)]
570LL + #[link("this is an example message", code = E0123)]
571 |
572
573error: cannot find attribute `lint` in this scope
574 --> $DIR/diagnostic-derive-inline.rs:546:3
534 --> $DIR/diagnostic-derive-inline.rs:527:3
575535 |
576536LL | #[lint("this is an example message", code = E0123)]
577537 | ^^^^
......@@ -583,7 +543,7 @@ LL + #[link("this is an example message", code = E0123)]
583543 |
584544
585545error: cannot find attribute `multipart_suggestion` in this scope
586 --> $DIR/diagnostic-derive-inline.rs:586:3
546 --> $DIR/diagnostic-derive-inline.rs:567:3
587547 |
588548LL | #[multipart_suggestion("with a suggestion")]
589549 | ^^^^^^^^^^^^^^^^^^^^
......@@ -595,7 +555,7 @@ LL | struct MultipartSuggestion {
595555 |
596556
597557error: cannot find attribute `multipart_suggestion` in this scope
598 --> $DIR/diagnostic-derive-inline.rs:589:3
558 --> $DIR/diagnostic-derive-inline.rs:570:3
599559 |
600560LL | #[multipart_suggestion()]
601561 | ^^^^^^^^^^^^^^^^^^^^
......@@ -607,7 +567,7 @@ LL | struct MultipartSuggestion {
607567 |
608568
609569error: cannot find attribute `multipart_suggestion` in this scope
610 --> $DIR/diagnostic-derive-inline.rs:593:7
570 --> $DIR/diagnostic-derive-inline.rs:574:7
611571 |
612572LL | #[multipart_suggestion("with a suggestion")]
613573 | ^^^^^^^^^^^^^^^^^^^^
......@@ -636,6 +596,6 @@ note: required by a bound in `Diag::<'a, G>::arg`
636596 = note: in this macro invocation
637597 = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
638598
639error: aborting due to 81 previous errors
599error: aborting due to 76 previous errors
640600
641601For more information about this error, try `rustc --explain E0277`.
tests/ui/allocator/xcrate-use2.rs-1
......@@ -5,7 +5,6 @@
55//@ aux-build:helper.rs
66//@ no-prefer-dynamic
77
8#![feature(allocator_api)]
98
109extern crate custom;
1110extern crate custom_as_global;
tests/ui/associated-types/associated-types-impl-redirect.rs-1
......@@ -9,7 +9,6 @@
99// for `ByRef`. The right answer was to consider the result ambiguous
1010// until more type information was available.
1111
12#![feature(lang_items)]
1312#![no_implicit_prelude]
1413
1514use std::marker::Sized;
tests/ui/associated-types/associated-types-where-clause-impl-ambiguity.rs-1
......@@ -8,7 +8,6 @@
88// for `ByRef`. The right answer was to consider the result ambiguous
99// until more type information was available.
1010
11#![feature(lang_items)]
1211#![no_implicit_prelude]
1312
1413use std::marker::Sized;
tests/ui/async-await/async-drop/async-drop-initial.rs+1-1
......@@ -5,7 +5,7 @@
55// please consider modifying miri's async drop test at
66// `src/tools/miri/tests/pass/async-drop.rs`.
77
8#![feature(async_drop, impl_trait_in_assoc_type)]
8#![feature(async_drop)]
99#![allow(incomplete_features, dead_code)]
1010
1111//@ edition: 2021
tests/ui/backtrace/line-tables-only.rs-1
......@@ -18,7 +18,6 @@
1818//@ needs-unwind
1919//@ aux-build: line-tables-only-helper.rs
2020
21#![feature(backtrace_frames)]
2221
2322extern crate line_tables_only_helper;
2423
tests/ui/borrowck/super-let-lifetime-and-drop.rs+1-1
......@@ -7,7 +7,7 @@
77//@ [borrowck] check-fail
88
99#![allow(dropping_references)]
10#![feature(super_let, stmt_expr_attributes)]
10#![feature(super_let)]
1111
1212use std::convert::identity;
1313
tests/ui/cfg/cfg_stmt_expr.rs-1
......@@ -3,7 +3,6 @@
33#![allow(unused_mut)]
44#![allow(unused_variables)]
55#![deny(non_snake_case)]
6#![feature(stmt_expr_attributes)]
76
87fn main() {
98 let a = 413;
tests/ui/const-generics/transmute.rs-1
......@@ -1,6 +1,5 @@
11//@ run-pass
22#![feature(generic_const_exprs)]
3#![feature(transmute_generic_consts)]
43#![allow(incomplete_features)]
54
65fn 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 @@
11//@ run-pass
22
33#![feature(core_intrinsics)]
4#![feature(const_type_name)]
54#![allow(dead_code)]
65
76const fn type_name_wrapper<T>(_: &T) -> &'static str {
tests/ui/consts/const-ptr-nonnull-rpass.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-pass
22
3#![feature(ptr_internals, test)]
3#![feature(test)]
44
55extern crate test;
66use 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 @@
11//@ ignore-backends: gcc
22//@ run-pass
33
4#![feature(try_trait_v2)]
54#![feature(const_trait_impl)]
65#![feature(const_try)]
76
tests/ui/contracts/internal_machinery/lowering/basics.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-pass
22#![expect(incomplete_features)]
3#![feature(contracts, cfg_contract_checks, contracts_internals, core_intrinsics)]
3#![feature(contracts, contracts_internals, core_intrinsics)]
44
55extern crate core;
66
tests/ui/coroutine/control-flow.rs+1-1
......@@ -3,7 +3,7 @@
33//@ revisions: default nomiropt
44//@[nomiropt]compile-flags: -Z mir-opt-level=0
55
6#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
6#![feature(coroutines, coroutine_trait)]
77
88use std::ops::{CoroutineState, Coroutine};
99use std::pin::Pin;
tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed+1-1
......@@ -1,6 +1,6 @@
11//@ run-rustfix
22
3#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
3#![feature(coroutines, stmt_expr_attributes)]
44
55fn main() {
66 let _ = #[coroutine] || yield;
tests/ui/coroutine/missing_coroutine_attr_suggestion.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-rustfix
22
3#![feature(coroutines, gen_blocks, stmt_expr_attributes)]
3#![feature(coroutines, stmt_expr_attributes)]
44
55fn main() {
66 let _ = || yield;
tests/ui/coroutine/non-static-is-unpin.rs+1-1
......@@ -3,7 +3,7 @@
33//@[next] compile-flags: -Znext-solver
44//@ run-pass
55
6#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
6#![feature(coroutines)]
77#![allow(dropping_copy_types)]
88
99use std::marker::PhantomPinned;
tests/ui/coroutine/other-attribute-on-gen.rs-1
......@@ -2,7 +2,6 @@
22//@ run-pass
33#![feature(gen_blocks)]
44#![feature(optimize_attribute)]
5#![feature(stmt_expr_attributes)]
65#![feature(async_iterator)]
76#![allow(dead_code)]
87
tests/ui/coroutine/pin-box-coroutine.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-pass
22
3#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
3#![feature(coroutines, coroutine_trait)]
44
55use std::ops::Coroutine;
66
tests/ui/coroutine/xcrate.rs+1-1
......@@ -2,7 +2,7 @@
22
33//@ aux-build:xcrate.rs
44
5#![feature(coroutines, coroutine_trait)]
5#![feature(coroutine_trait)]
66
77extern crate xcrate;
88
tests/ui/eii/default/call_default.rs-1
......@@ -7,7 +7,6 @@
77//@ ignore-windows
88// Tests EIIs with default implementations.
99// When there's no explicit declaration, the default should be called from the declaring crate.
10#![feature(extern_item_impls)]
1110
1211extern crate decl_with_default;
1312
tests/ui/eii/default/call_default_panics.rs-1
......@@ -23,7 +23,6 @@
2323// ```
2424// This is a simple test to make sure that we can unwind through these,
2525// and that this wrapper function effectively doesn't show up in the trace.
26#![feature(extern_item_impls)]
2726
2827extern crate decl_with_default_panics;
2928
tests/ui/eii/default/call_impl.rs-1
......@@ -9,7 +9,6 @@
99// Tests EIIs with default implementations.
1010// When an explicit implementation is given in one dependency, and the declaration is in another,
1111// the explicit implementation is preferred.
12#![feature(extern_item_impls)]
1312
1413extern crate decl_with_default;
1514extern crate impl1;
tests/ui/eii/linking/codegen_cross_crate.rs-1
......@@ -6,7 +6,6 @@
66// FIXME: linking on windows (speciifcally mingw) not yet supported, see tracking issue #125418
77//@ ignore-windows
88// Tests whether calling EIIs works with the declaration in another crate.
9#![feature(extern_item_impls)]
109
1110extern crate codegen_cross_crate_other_crate as codegen;
1211
tests/ui/eii/privacy1.rs-1
......@@ -5,7 +5,6 @@
55// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
66//@ ignore-windows
77// Tests whether re-exports work.
8#![feature(extern_item_impls)]
98
109extern crate other_crate_privacy1 as codegen;
1110
tests/ui/enum-discriminant/issue-72554.rs-1
......@@ -3,7 +3,6 @@ use std::collections::BTreeSet;
33#[derive(Hash)]
44pub enum ElemDerived {
55 //~^ ERROR recursive type `ElemDerived` has infinite size
6 //~| ERROR cycle detected
76 A(ElemDerived)
87}
98
tests/ui/enum-discriminant/issue-72554.stderr+3-18
......@@ -3,7 +3,7 @@ error[E0072]: recursive type `ElemDerived` has infinite size
33 |
44LL | pub enum ElemDerived {
55 | ^^^^^^^^^^^^^^^^^^^^
6...
6LL |
77LL | A(ElemDerived)
88 | ----------- recursive without indirection
99 |
......@@ -12,21 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
1212LL | A(Box<ElemDerived>)
1313 | ++++ +
1414
15error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived`
16 --> $DIR/issue-72554.rs:4:1
17 |
18LL | pub enum ElemDerived {
19 | ^^^^^^^^^^^^^^^^^^^^
20 |
21 = note: ...which immediately requires computing drop-check constraints for `ElemDerived` again
22note: cycle used when computing drop-check constraints for `Elem`
23 --> $DIR/issue-72554.rs:11:1
24 |
25LL | 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
29error: aborting due to 2 previous errors
15error: aborting due to 1 previous error
3016
31Some errors have detailed explanations: E0072, E0391.
32For more information about an error, try `rustc --explain E0072`.
17For 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]
4struct Foo<'a, T> { //~ ERROR ['a: +, T: o]
5 t: &'a mut T,
6}
7
8fn main() {}
tests/ui/error-codes/E0208.stderr deleted-8
......@@ -1,8 +0,0 @@
1error: ['a: +, T: o]
2 --> $DIR/E0208.rs:4:1
3 |
4LL | struct Foo<'a, T> {
5 | ^^^^^^^^^^^^^^^^^
6
7error: aborting due to 1 previous error
8
tests/ui/extern/extern-prelude-core.rs-1
......@@ -1,5 +1,4 @@
11//@ run-pass
2#![feature(lang_items)]
32#![no_std]
43
54extern crate std as other;
tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed-1
......@@ -22,7 +22,6 @@
2222//@ [future_feature] compile-flags: -Z unstable-options
2323
2424#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25#![cfg_attr(current_feature, feature(explicit_extern_abis))]
2625
2726extern "C" fn _foo() {}
2827//[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 @@
11warning: `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
33 |
44LL | extern fn _foo() {}
55 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
......@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
77 = note: `#[warn(missing_abi)]` on by default
88
99warning: `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
1111 |
1212LL | unsafe extern fn _bar() {}
1313 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
1414
1515warning: `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
1717 |
1818LL | unsafe extern {}
1919 | ^^^^^^ 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 @@
2222//@ [future_feature] compile-flags: -Z unstable-options
2323
2424#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25#![cfg_attr(current_feature, feature(explicit_extern_abis))]
2625
2726extern "C" fn _foo() {}
2827//[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 @@
11warning: `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
33 |
44LL | extern fn _foo() {}
55 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
......@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
77 = note: `#[warn(missing_abi)]` on by default
88
99warning: `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
1111 |
1212LL | unsafe extern fn _bar() {}
1313 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
1414
1515warning: `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
1717 |
1818LL | unsafe extern {}
1919 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed-1
......@@ -22,7 +22,6 @@
2222//@ [future_feature] compile-flags: -Z unstable-options
2323
2424#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25#![cfg_attr(current_feature, feature(explicit_extern_abis))]
2625
2726extern "C" fn _foo() {}
2827//[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 @@
11warning: `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
33 |
44LL | extern fn _foo() {}
55 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
......@@ -7,13 +7,13 @@ LL | extern fn _foo() {}
77 = note: `#[warn(missing_abi)]` on by default
88
99warning: `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
1111 |
1212LL | unsafe extern fn _bar() {}
1313 | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"`
1414
1515warning: `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
1717 |
1818LL | unsafe extern {}
1919 | ^^^^^^ 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 @@
11error: `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
33 |
44LL | extern fn _foo() {}
55 | ^^^^^^ help: specify an ABI: `extern "<abi>"`
......@@ -7,7 +7,7 @@ LL | extern fn _foo() {}
77 = help: prior to Rust 2024, a default ABI was inferred
88
99error: `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
1111 |
1212LL | unsafe extern fn _bar() {}
1313 | ^^^^^^ help: specify an ABI: `extern "<abi>"`
......@@ -15,7 +15,7 @@ LL | unsafe extern fn _bar() {}
1515 = help: prior to Rust 2024, a default ABI was inferred
1616
1717error: `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
1919 |
2020LL | unsafe extern {}
2121 | ^^^^^^ help: specify an ABI: `extern "<abi>"`
tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs-1
......@@ -22,7 +22,6 @@
2222//@ [future_feature] compile-flags: -Z unstable-options
2323
2424#![cfg_attr(future_feature, feature(explicit_extern_abis))]
25#![cfg_attr(current_feature, feature(explicit_extern_abis))]
2625
2726extern fn _foo() {}
2827//[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 @@
77//~| 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
88struct Foo {}
99
10#[rustc_variance]
10#[rustc_dump_variances]
1111//~^ 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
1414enum E {}
1515
1616fn main() {}
tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr+4-4
......@@ -12,12 +12,12 @@ LL | #[rustc_nonnull_optimization_guaranteed]
1212error[E0658]: use of an internal attribute
1313 --> $DIR/feature-gate-rustc-attrs-1.rs:10:1
1414 |
15LL | #[rustc_variance]
16 | ^^^^^^^^^^^^^^^^^
15LL | #[rustc_dump_variances]
16 | ^^^^^^^^^^^^^^^^^^^^^^^
1717 |
1818 = 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
2121
2222error: aborting due to 2 previous errors
2323
tests/ui/float/classify-runtime-const.rs-2
......@@ -6,8 +6,6 @@
66
77// This tests the float classification functions, for regular runtime code and for const evaluation.
88
9#![feature(f16)]
10#![feature(f128)]
119
1210use std::num::FpCategory::*;
1311
tests/ui/float/conv-bits-runtime-const.rs+3-2
......@@ -3,9 +3,10 @@
33
44// This tests the float classification functions, for regular runtime code and for const evaluation.
55
6#![feature(f16)]
7#![feature(f128)]
86#![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
910#![allow(unused_macro_rules)]
1011// expect the unexpected (`target_has_reliable_*` are not "known" configs since they are unstable)
1112#![expect(unexpected_cfgs)]
tests/ui/fmt/format-macro-no-std.rs-1
......@@ -4,7 +4,6 @@
44//@ ignore-emscripten no no_std executables
55//@ ignore-wasm different `main` convention
66
7#![feature(lang_items)]
87#![no_std]
98#![no_main]
109
tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs+2-2
......@@ -6,8 +6,8 @@
66
77#![allow(unreachable_patterns)]
88#![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))]
1111
1212macro_rules! yes {
1313 ($scrutinee:expr, $($t:tt)+) => {
tests/ui/hygiene/xcrate.rs-1
......@@ -3,7 +3,6 @@
33
44//@ aux-build:xcrate.rs
55
6#![feature(decl_macro)]
76
87extern crate xcrate;
98
tests/ui/impl-trait/capture-lifetime-not-in-hir.rs+1-1
......@@ -1,5 +1,5 @@
11#![feature(rustc_attrs)]
2#![rustc_variance_of_opaques]
2#![rustc_dump_variances_of_opaques]
33
44trait Bar<'a> {
55 type Assoc: From<()>;
tests/ui/impl-trait/example-calendar.rs+1-2
......@@ -1,7 +1,6 @@
11//@ run-pass
22
3#![feature(fn_traits,
4 step_trait,
3#![feature(step_trait,
54 unboxed_closures,
65)]
76
tests/ui/impl-trait/implicit-capture-late.rs+1-1
......@@ -2,7 +2,7 @@
22
33#![feature(rustc_attrs)]
44#![allow(internal_features)]
5#![rustc_variance_of_opaques]
5#![rustc_dump_variances_of_opaques]
66
77use std::ops::Deref;
88
tests/ui/impl-trait/in-trait/variance.rs+1-1
......@@ -1,6 +1,6 @@
11#![feature(rustc_attrs)]
22#![allow(internal_features)]
3#![rustc_variance_of_opaques]
3#![rustc_dump_variances_of_opaques]
44
55trait Foo<'i> {
66 fn implicit_capture_early<'a: 'a>() -> impl Sized {}
tests/ui/impl-trait/precise-capturing/capturing-implicit.rs+1-1
......@@ -2,7 +2,7 @@
22
33#![feature(rustc_attrs)]
44#![feature(type_alias_impl_trait)]
5#![rustc_variance_of_opaques]
5#![rustc_dump_variances_of_opaques]
66
77fn foo(x: &()) -> impl IntoIterator<Item = impl Sized> + use<> {
88 //~^ ERROR ['_: o]
tests/ui/impl-trait/variance.rs+1-1
......@@ -3,7 +3,7 @@
33
44#![feature(rustc_attrs)]
55#![allow(internal_features)]
6#![rustc_variance_of_opaques]
6#![rustc_dump_variances_of_opaques]
77
88trait Captures<'a> {}
99impl<T> Captures<'_> for T {}
tests/ui/infinite/infinite-struct.rs-2
......@@ -1,7 +1,5 @@
11struct Take(Take);
22//~^ ERROR has infinite size
3//~| ERROR cycle
4//~| ERROR reached the recursion limit finding the struct tail for `Take`
53
64// check that we don't hang trying to find the tail of a recursive struct (#79437)
75fn foo() -> Take {
tests/ui/infinite/infinite-struct.stderr+3-22
......@@ -10,7 +10,7 @@ LL | struct Take(Box<Take>);
1010 | ++++ +
1111
1212error[E0072]: recursive type `Foo` has infinite size
13 --> $DIR/infinite-struct.rs:12:1
13 --> $DIR/infinite-struct.rs:10:1
1414 |
1515LL | struct Foo {
1616 | ^^^^^^^^^^
......@@ -22,25 +22,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
2222LL | x: Bar<Box<Foo>>,
2323 | ++++ +
2424
25error: reached the recursion limit finding the struct tail for `Take`
26 --> $DIR/infinite-struct.rs:1:1
27 |
28LL | struct Take(Take);
29 | ^^^^^^^^^^^
30 |
31 = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
32
33error[E0391]: cycle detected when computing when `Take` needs drop
34 --> $DIR/infinite-struct.rs:1:1
35 |
36LL | 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
43error: aborting due to 4 previous errors
25error: aborting due to 2 previous errors
4426
45Some errors have detailed explanations: E0072, E0391.
46For more information about an error, try `rustc --explain E0072`.
27For more information about this error, try `rustc --explain E0072`.
tests/ui/infinite/infinite-tag-type-recursion.rs-1
......@@ -1,5 +1,4 @@
11enum MList { Cons(isize, MList), Nil }
22//~^ ERROR recursive type `MList` has infinite size
3//~| ERROR cycle
43
54fn 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
99LL | enum MList { Cons(isize, Box<MList>), Nil }
1010 | ++++ +
1111
12error[E0391]: cycle detected when computing when `MList` needs drop
13 --> $DIR/infinite-tag-type-recursion.rs:1:1
14 |
15LL | 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
22error: aborting due to 2 previous errors
12error: aborting due to 1 previous error
2313
24Some errors have detailed explanations: E0072, E0391.
25For more information about an error, try `rustc --explain E0072`.
14For more information about this error, try `rustc --explain E0072`.
tests/ui/intrinsics/intrinsic-alignment.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-pass
22
3#![feature(core_intrinsics, rustc_attrs)]
3#![feature(rustc_attrs)]
44
55#[cfg(any(
66 target_os = "aix",
tests/ui/io-checks/write-macro-error.rs-1
......@@ -4,7 +4,6 @@
44//@ run-pass
55//@ needs-unwind
66
7#![feature(io_error_uncategorized)]
87
98use std::fmt;
109use std::io::{self, Error, Write};
tests/ui/linkage-attr/raw-dylib/elf/as_needed.rs+1-1
......@@ -15,7 +15,7 @@
1515
1616#![allow(incomplete_features)]
1717#![feature(raw_dylib_elf)]
18#![feature(native_link_modifiers_as_needed)]
18#![cfg_attr(not(no_modifier), feature(native_link_modifiers_as_needed))]
1919
2020#[cfg_attr(
2121 as_needed,
tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs+5-6
......@@ -3,17 +3,16 @@
33// Previously, this test ICEs when the `unused_must_use` lint is suppressed via the combination of
44// `-A warnings` and `--cap-lints=warn`, because:
55//
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
77// `def_path_str` was called (which calls `trimmed_def_path`, which will produce a
88// `must_produce_diag` ICE if a trimmed def path is constructed but never emitted in a diagnostic
99// 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.
1413// - If a lint's corresponding diagnostic is suppressed (to be effectively allow at the final
1514// 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 --
1716// but the diagnostic is never eventually emitted, triggering the aforementioned
1817// `must_produce_diag` ICE due to use of `trimmed_def_path`.
1918//
tests/ui/lint/lint-expr-stmt-attrs-for-early-lints.rs-1
......@@ -1,6 +1,5 @@
11//@ run-pass
22
3#![feature(stmt_expr_attributes)]
43#![deny(unused_parens)]
54
65// Tests that lint attributes on statements/expressions are
tests/ui/lint/lint-unknown-feature.rs-1
......@@ -4,6 +4,5 @@
44
55#![allow(stable_features)]
66// FIXME(#44232) we should warn that this isn't used.
7#![feature(rust1)]
87
98fn main() {}
tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed+1-1
......@@ -2,7 +2,7 @@
22//@ edition:2021
33#![deny(unused_qualifications)]
44#![deny(unused_imports)]
5#![feature(coroutines, coroutine_trait)]
5#![feature(coroutine_trait)]
66
77use std::ops::{
88 Coroutine,
tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs+1-1
......@@ -2,7 +2,7 @@
22//@ edition:2021
33#![deny(unused_qualifications)]
44#![deny(unused_imports)]
5#![feature(coroutines, coroutine_trait)]
5#![feature(coroutine_trait)]
66
77use std::ops::{
88 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
21macro_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 @@
1error: feature `coroutines` is declared but not used
2 --> $DIR/unused-language-features.rs:5:12
3 |
4LL | #![feature(coroutines)]
5 | ^^^^^^^^^^
6 |
7note: the lint level is defined here
8 --> $DIR/unused-language-features.rs:2:9
9 |
10LL | #![deny(unused_features)]
11 | ^^^^^^^^^^^^^^^
12
13error: feature `coroutine_clone` is declared but not used
14 --> $DIR/unused-language-features.rs:7:12
15 |
16LL | #![feature(coroutine_clone)]
17 | ^^^^^^^^^^^^^^^
18
19error: feature `stmt_expr_attributes` is declared but not used
20 --> $DIR/unused-language-features.rs:9:12
21 |
22LL | #![feature(stmt_expr_attributes)]
23 | ^^^^^^^^^^^^^^^^^^^^
24
25error: feature `asm_unwind` is declared but not used
26 --> $DIR/unused-language-features.rs:11:12
27 |
28LL | #![feature(asm_unwind)]
29 | ^^^^^^^^^^
30
31error: feature `negative_impls` is declared but not used
32 --> $DIR/unused-language-features.rs:15:28
33 |
34LL | #![cfg_attr(all(), feature(negative_impls))]
35 | ^^^^^^^^^^^^^^
36
37error: 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 @@
1warning: 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 |
4LL | #![feature(is_sorted)]
5 | ^^^^^^^^^
6 |
7 = note: `#[warn(stable_features)]` on by default
8
9error: feature `step_trait` is declared but not used
10 --> $DIR/unused-library-features.rs:5:12
11 |
12LL | #![feature(step_trait)]
13 | ^^^^^^^^^^
14 |
15note: the lint level is defined here
16 --> $DIR/unused-library-features.rs:2:9
17 |
18LL | #![deny(unused_features)]
19 | ^^^^^^^^^^^^^^^
20
21error: feature `is_sorted` is declared but not used
22 --> $DIR/unused-library-features.rs:7:12
23 |
24LL | #![feature(is_sorted)]
25 | ^^^^^^^^^
26
27error: feature `slice_ptr_get` is declared but not used
28 --> $DIR/unused-library-features.rs:12:28
29 |
30LL | #![cfg_attr(all(), feature(slice_ptr_get))]
31 | ^^^^^^^^^^^^^
32
33error: 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
11pub fn use_box_patterns(b: Box<i32>) -> i32 {
12 let box x = b;
13 x
14}
15
16macro m() {}
17pub fn use_decl_macro() {
18 m!();
19}
20
21#[rustc_dummy]
22pub 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
10pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) {
11 for _ in e.sources() {}
12}
13
14pub 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 @@
11//@ run-rustfix
22
3#![allow(dead_code, path_statements)]
3#![allow(dead_code, path_statements, unused_features)]
44#![deny(unused_attributes, unused_must_use)]
55#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
66
tests/ui/lint/unused/unused_attributes-must_use.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-rustfix
22
3#![allow(dead_code, path_statements)]
3#![allow(dead_code, path_statements, unused_features)]
44#![deny(unused_attributes, unused_must_use)]
55#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
66
tests/ui/lowering/issue-96847.rs-1
......@@ -3,7 +3,6 @@
33// Test that this doesn't abort during AST lowering. In #96847 it did abort
44// because the attribute was being lowered twice.
55
6#![feature(stmt_expr_attributes)]
76#![feature(lang_items)]
87
98fn main() {
tests/ui/lowering/issue-96847.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0522]: definition of an unknown lang item: `foo`
2 --> $DIR/issue-96847.rs:11:9
2 --> $DIR/issue-96847.rs:10:9
33 |
44LL | #![lang="foo"]
55 | ^^^^^^^^^^^^^^ definition of unknown lang item `foo`
tests/ui/macros/metavar_cross_edition_recursive_macros.rs-1
......@@ -6,7 +6,6 @@
66// This test captures the behavior of macro-generating-macros with fragment
77// specifiers across edition boundaries.
88
9#![feature(macro_metavar_expr)]
109#![allow(incomplete_features)]
1110
1211extern crate metavar_2018;
tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs+1-1
......@@ -5,7 +5,7 @@
55//@ needs-unwind Asserting on contents of error message
66
77#![allow(path_statements, unused_allocation)]
8#![feature(core_intrinsics, generic_assert)]
8#![feature(generic_assert)]
99
1010macro_rules! test {
1111 (
tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs+1-1
......@@ -4,7 +4,7 @@
44//@ run-pass
55//@ needs-unwind Asserting on contents of error message
66
7#![feature(core_intrinsics, generic_assert)]
7#![feature(generic_assert)]
88
99extern crate common;
1010
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs-1
......@@ -3,7 +3,6 @@
33//@ compile-flags: --test -Zpanic_abort_tests
44//@ run-pass
55
6#![feature(core_intrinsics, generic_assert)]
76
87#[should_panic(expected = "Custom user message")]
98#[test]
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs+1-1
......@@ -3,7 +3,7 @@
33//@ run-pass
44//@ needs-unwind Asserting on contents of error message
55
6#![feature(core_intrinsics, generic_assert)]
6#![feature(generic_assert)]
77
88extern crate common;
99
tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs+1-1
......@@ -4,7 +4,7 @@
44// ignore-tidy-linelength
55//@ run-pass
66
7#![feature(core_intrinsics, generic_assert)]
7#![feature(generic_assert)]
88
99use std::fmt::{Debug, Formatter};
1010
tests/ui/macros/stringify.rs-2
......@@ -9,12 +9,10 @@
99#![feature(const_trait_impl)]
1010#![feature(coroutines)]
1111#![feature(decl_macro)]
12#![feature(explicit_tail_calls)]
1312#![feature(more_qualified_paths)]
1413#![feature(never_patterns)]
1514#![feature(trait_alias)]
1615#![feature(try_blocks)]
17#![feature(type_ascription)]
1816#![feature(yeet_expr)]
1917#![deny(unused_macros)]
2018
tests/ui/match/match-float.rs+2-2
......@@ -3,8 +3,8 @@
33// Makes sure we use `==` (not bitwise) semantics for float comparison.
44
55#![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))]
88
99#[cfg(target_has_reliable_f16)]
1010fn check_f16() {
tests/ui/methods/supertrait-shadowing/out-of-scope.rs-1
......@@ -1,7 +1,6 @@
11//@ run-pass
22//@ check-run-results
33
4#![feature(supertrait_item_shadowing)]
54#![allow(dead_code)]
65
76mod out_of_scope {
tests/ui/nll/issue-48623-coroutine.rs+1-1
......@@ -2,7 +2,7 @@
22#![allow(path_statements)]
33#![allow(dead_code)]
44
5#![feature(coroutines, coroutine_trait)]
5#![feature(coroutines)]
66
77struct WithDrop;
88
tests/ui/object-lifetime/object-lifetime-default.rs+7-7
......@@ -1,37 +1,37 @@
11#![feature(rustc_attrs)]
22
3#[rustc_object_lifetime_default]
3#[rustc_dump_object_lifetime_defaults]
44struct A<
55 T, //~ ERROR BaseDefault
66>(T);
77
8#[rustc_object_lifetime_default]
8#[rustc_dump_object_lifetime_defaults]
99struct B<
1010 'a,
1111 T, //~ ERROR BaseDefault
1212>(&'a (), T);
1313
14#[rustc_object_lifetime_default]
14#[rustc_dump_object_lifetime_defaults]
1515struct C<
1616 'a,
1717 T: 'a, //~ ERROR 'a
1818>(&'a T);
1919
20#[rustc_object_lifetime_default]
20#[rustc_dump_object_lifetime_defaults]
2121struct D<
2222 'a,
2323 'b,
2424 T: 'a + 'b, //~ ERROR Ambiguous
2525>(&'a T, &'b T);
2626
27#[rustc_object_lifetime_default]
27#[rustc_dump_object_lifetime_defaults]
2828struct E<
2929 'a,
3030 'b: 'a,
3131 T: 'b, //~ ERROR 'b
3232>(&'a T, &'b T);
3333
34#[rustc_object_lifetime_default]
34#[rustc_dump_object_lifetime_defaults]
3535struct F<
3636 'a,
3737 'b,
......@@ -39,7 +39,7 @@ struct F<
3939 U: 'b, //~ ERROR 'b
4040>(&'a T, &'b U);
4141
42#[rustc_object_lifetime_default]
42#[rustc_dump_object_lifetime_defaults]
4343struct G<
4444 'a,
4545 'b,
tests/ui/overloaded/overloaded-calls-simple.rs+1-1
......@@ -1,6 +1,6 @@
11//@ run-pass
22
3#![feature(lang_items, unboxed_closures, fn_traits)]
3#![feature(unboxed_closures, fn_traits)]
44
55struct S1 {
66 x: i32,
tests/ui/query-system/query-cycle-printing-issue-151226.rs-2
......@@ -1,8 +1,6 @@
11struct A<T>(std::sync::OnceLock<Self>);
22//~^ ERROR recursive type `A` has infinite size
3//~| ERROR cycle detected when computing layout of `A<()>`
43
54static B: A<()> = todo!();
6//~^ ERROR cycle occurred during layout computation
75
86fn 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
99LL | struct A<T>(Box<std::sync::OnceLock<Self>>);
1010 | ++++ +
1111
12error[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
20note: cycle used when checking that `B` is well-formed
21 --> $DIR/query-cycle-printing-issue-151226.rs:5:1
22 |
23LL | 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
27error[E0080]: a cycle occurred during layout computation
28 --> $DIR/query-cycle-printing-issue-151226.rs:5:1
29 |
30LL | static B: A<()> = todo!();
31 | ^^^^^^^^^^^^^^^ evaluation of `B` failed here
32
33error: aborting due to 3 previous errors
12error: aborting due to 1 previous error
3413
35Some errors have detailed explanations: E0072, E0080, E0391.
36For more information about an error, try `rustc --explain E0072`.
14For 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 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives
55 bar: std::slice::IterMut<'a, T>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/cross-crate.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/cross-crate.rs:4:1
33 |
44LL | struct Foo<'a, T> {
tests/ui/rfcs/rfc-2093-infer-outlives/enum.rs+6-6
......@@ -3,20 +3,20 @@
33// Needs an explicit where clause stating outlives condition. (RFC 2093)
44
55// Type T needs to outlive lifetime 'a.
6#[rustc_outlives]
7enum Foo<'a, T> { //~ ERROR rustc_outlives
6#[rustc_dump_inferred_outlives]
7enum Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives
88 One(Bar<'a, T>)
99}
1010
1111// Type U needs to outlive lifetime 'b
12#[rustc_outlives]
13struct Bar<'b, U> { //~ ERROR rustc_outlives
12#[rustc_dump_inferred_outlives]
13struct Bar<'b, U> { //~ ERROR rustc_dump_inferred_outlives
1414 field2: &'b U
1515}
1616
1717// Type K needs to outlive lifetime 'c.
18#[rustc_outlives]
19enum Ying<'c, K> { //~ ERROR rustc_outlives
18#[rustc_dump_inferred_outlives]
19enum Ying<'c, K> { //~ ERROR rustc_dump_inferred_outlives
2020 One(&'c Yang<K>)
2121}
2222
tests/ui/rfcs/rfc-2093-infer-outlives/enum.stderr+3-3
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/enum.rs:7:1
33 |
44LL | enum Foo<'a, T> {
......@@ -6,7 +6,7 @@ LL | enum Foo<'a, T> {
66 |
77 = note: T: 'a
88
9error: rustc_outlives
9error: rustc_dump_inferred_outlives
1010 --> $DIR/enum.rs:13:1
1111 |
1212LL | struct Bar<'b, U> {
......@@ -14,7 +14,7 @@ LL | struct Bar<'b, U> {
1414 |
1515 = note: U: 'b
1616
17error: rustc_outlives
17error: rustc_dump_inferred_outlives
1818 --> $DIR/enum.rs:19:1
1919 |
2020LL | enum Ying<'c, K> {
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.rs+2-2
......@@ -3,8 +3,8 @@
33trait Trait<'x, T> where T: 'x {
44}
55
6#[rustc_outlives]
7struct Foo<'a, A> //~ ERROR rustc_outlives
6#[rustc_dump_inferred_outlives]
7struct Foo<'a, A> //~ ERROR rustc_dump_inferred_outlives
88{
99 foo: Box<dyn Trait<'a, A>>
1010}
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-dyn.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/explicit-dyn.rs:7:1
33 |
44LL | struct Foo<'a, A>
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4enum Foo<'a, U> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4enum Foo<'a, U> { //~ ERROR rustc_dump_inferred_outlives
55 One(Bar<'a, U>)
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-enum.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/explicit-enum.rs:4:1
33 |
44LL | 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 {
44 type Type;
55}
66
7#[rustc_outlives]
8struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives
7#[rustc_dump_inferred_outlives]
8struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_dump_inferred_outlives
99{
1010 foo: <A as Trait<'a, B>>::Type
1111}
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-projection.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/explicit-projection.rs:8:1
33 |
44LL | 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 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'b, U> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'b, U> { //~ ERROR rustc_dump_inferred_outlives
55 bar: Bar<'b, U>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-struct.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/explicit-struct.rs:4:1
33 |
44LL | struct Foo<'b, U> {
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4union Foo<'b, U: Copy> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4union Foo<'b, U: Copy> { //~ ERROR rustc_dump_inferred_outlives
55 bar: Bar<'b, U>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/explicit-union.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/explicit-union.rs:4:1
33 |
44LL | union Foo<'b, U: Copy> {
tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4enum Foo<'a, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4enum Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives
55
66 One(Bar<'a, T>)
77}
tests/ui/rfcs/rfc-2093-infer-outlives/nested-enum.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/nested-enum.rs:4:1
33 |
44LL | enum Foo<'a, T> {
tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, 'b, T> { //~ ERROR rustc_dump_inferred_outlives
55 x: &'a &'b T
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/nested-regions.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/nested-regions.rs:4:1
33 |
44LL | struct Foo<'a, 'b, T> {
tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives
55 field1: Bar<'a, T>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/nested-structs.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/nested-structs.rs:4:1
33 |
44LL | struct Foo<'a, T> {
tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4union Foo<'a, T: Copy> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4union Foo<'a, T: Copy> { //~ ERROR rustc_dump_inferred_outlives
55 field1: Bar<'a, T>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/nested-union.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/nested-union.rs:4:1
33 |
44LL | union Foo<'a, T: Copy> {
tests/ui/rfcs/rfc-2093-infer-outlives/projection.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, T: Iterator> { //~ ERROR rustc_dump_inferred_outlives
55 bar: &'a T::Item
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/projection.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/projection.rs:4:1
33 |
44LL | struct Foo<'a, T: Iterator> {
tests/ui/rfcs/rfc-2093-infer-outlives/reference.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, T> { //~ ERROR rustc_dump_inferred_outlives
55 bar: &'a T,
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/reference.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/reference.rs:4:1
33 |
44LL | 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,
44 's: {
55}
66
7#[rustc_outlives]
8struct Foo<'a, 'b, A> //~ ERROR rustc_outlives
7#[rustc_dump_inferred_outlives]
8struct Foo<'a, 'b, A> //~ ERROR rustc_dump_inferred_outlives
99{
1010 foo: Box<dyn Trait<'a, 'b, A>>
1111}
tests/ui/rfcs/rfc-2093-infer-outlives/self-dyn.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/self-dyn.rs:8:1
33 |
44LL | struct Foo<'a, 'b, A>
tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.rs+2-2
......@@ -1,7 +1,7 @@
11#![feature(rustc_attrs)]
22
3#[rustc_outlives]
4struct Foo<'a, 'b, T> { //~ ERROR rustc_outlives
3#[rustc_dump_inferred_outlives]
4struct Foo<'a, 'b, T> { //~ ERROR rustc_dump_inferred_outlives
55 field1: dyn Bar<'a, 'b, T>
66}
77
tests/ui/rfcs/rfc-2093-infer-outlives/self-structs.stderr+1-1
......@@ -1,4 +1,4 @@
1error: rustc_outlives
1error: rustc_dump_inferred_outlives
22 --> $DIR/self-structs.rs:4:1
33 |
44LL | struct Foo<'a, 'b, T> {
tests/ui/sanitizer/memory-passing.rs-1
......@@ -13,7 +13,6 @@
1313// This test case intentionally limits the usage of the std,
1414// since it will be linked with an uninstrumented version of it.
1515
16#![feature(core_intrinsics)]
1716#![allow(invalid_value)]
1817#![no_main]
1918
tests/ui/simd/monomorphize-shuffle-index.rs+1-1
......@@ -4,12 +4,12 @@
44//@ ignore-backends: gcc
55#![feature(
66 repr_simd,
7 core_intrinsics,
87 intrinsics,
98 adt_const_params,
109 unsized_const_params,
1110 generic_const_exprs
1211)]
12#![cfg_attr(old, feature(core_intrinsics))]
1313#![allow(incomplete_features)]
1414
1515#[path = "../../auxiliary/minisimd.rs"]
tests/ui/structs-enums/enum-rec/issue-17431-6.rs-1
......@@ -2,7 +2,6 @@ use std::cell::UnsafeCell;
22
33enum Foo { X(UnsafeCell<Option<Foo>>) }
44//~^ ERROR recursive type `Foo` has infinite size
5//~| ERROR cycle detected
65
76impl Foo { fn bar(self) {} }
87
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
99LL | enum Foo { X(UnsafeCell<Option<Box<Foo>>>) }
1010 | ++++ +
1111
12error[E0391]: cycle detected when computing when `Foo` needs drop
13 --> $DIR/issue-17431-6.rs:3:1
14 |
15LL | 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
22error: aborting due to 2 previous errors
12error: aborting due to 1 previous error
2313
24Some errors have detailed explanations: E0072, E0391.
25For more information about an error, try `rustc --explain E0072`.
14For more information about this error, try `rustc --explain E0072`.
tests/ui/structs-enums/rec-align-u32.rs+1-1
......@@ -3,7 +3,7 @@
33#![allow(unused_unsafe)]
44// Issue #2303
55
6#![feature(core_intrinsics, rustc_attrs)]
6#![feature(rustc_attrs)]
77
88use std::mem;
99
tests/ui/structs-enums/rec-align-u64.rs+1-1
......@@ -4,7 +4,7 @@
44
55// Issue #2303
66
7#![feature(core_intrinsics, rustc_attrs)]
7#![feature(rustc_attrs)]
88
99use std::mem;
1010
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))]
23#![crate_type = "lib"]
34
45#[cfg(target_thread_local)]
tests/ui/threads-sendsync/thread-local-extern-static.rs+2-1
......@@ -2,7 +2,8 @@
22//@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows
33//@ aux-build:thread-local-extern-static.rs
44
5#![feature(cfg_target_thread_local, thread_local)]
5#![feature(cfg_target_thread_local)]
6#![cfg_attr(target_thread_local, feature(thread_local))]
67
78#[cfg(target_thread_local)]
89extern crate thread_local_extern_static;
tests/ui/traits/alias/import-cross-crate.rs-1
......@@ -1,7 +1,6 @@
11//@ run-pass
22//@ aux-build:greeter.rs
33
4#![feature(trait_alias)]
54
65extern crate greeter;
76
tests/ui/traits/const-traits/variance.rs+1-1
......@@ -1,6 +1,6 @@
11#![feature(rustc_attrs, const_trait_impl)]
22#![allow(internal_features)]
3#![rustc_variance_of_opaques]
3#![rustc_dump_variances_of_opaques]
44
55const trait Foo {}
66
tests/ui/traits/issue-105231.rs-1
......@@ -6,5 +6,4 @@ struct B<T>(A<A<T>>);
66trait Foo {}
77impl<T> Foo for T where T: Send {}
88impl Foo for B<u8> {}
9//~^ ERROR conflicting implementations of trait `Foo` for type `B<u8>`
109fn main() {}
tests/ui/traits/issue-105231.stderr+2-14
......@@ -37,18 +37,6 @@ LL | struct B<T>(A<A<T>>);
3737 = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
3838 = note: all type parameters must be used in a non-recursive way in order to constrain their variance
3939
40error[E0119]: conflicting implementations of trait `Foo` for type `B<u8>`
41 --> $DIR/issue-105231.rs:8:1
42 |
43LL | impl<T> Foo for T where T: Send {}
44 | ------------------------------- first implementation here
45LL | 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
51error: aborting due to 4 previous errors
40error: aborting due to 3 previous errors
5241
53Some errors have detailed explanations: E0072, E0119.
54For more information about an error, try `rustc --explain E0072`.
42For more information about this error, try `rustc --explain E0072`.
tests/ui/traits/overlap-permitted-for-marker-traits.rs-1
......@@ -4,7 +4,6 @@
44// `MyMarker` if it is either `Debug` or `Display`.
55
66#![feature(marker_trait_attr)]
7#![feature(negative_impls)]
87
98use std::fmt::{Debug, Display};
109
tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs-1
......@@ -1,4 +1,3 @@
1//~ ERROR: cycle detected
21//! Safe transmute did not handle cycle errors that could occur during
32//! layout computation. This test checks that we do not ICE in such
43//! situations (see #117491).
tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr+3-10
......@@ -1,5 +1,5 @@
11error[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
33 |
44LL | struct ExplicitlyPadded(ExplicitlyPadded);
55 | ^^^^^^^^^^^^^^^^^^^^^^^ ---------------- recursive without indirection
......@@ -9,13 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
99LL | struct ExplicitlyPadded(Box<ExplicitlyPadded>);
1010 | ++++ +
1111
12error[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
18error: aborting due to 2 previous errors
12error: aborting due to 1 previous error
1913
20Some errors have detailed explanations: E0072, E0391.
21For more information about an error, try `rustc --explain E0072`.
14For more information about this error, try `rustc --explain E0072`.
tests/ui/type-alias-impl-trait/variance.rs+1-1
......@@ -1,6 +1,6 @@
11#![feature(rustc_attrs, type_alias_impl_trait, impl_trait_in_assoc_type)]
22#![allow(internal_features)]
3#![rustc_variance_of_opaques]
3#![rustc_dump_variances_of_opaques]
44
55trait Captures<'a> {}
66impl<T> Captures<'_> for T {}
tests/ui/type/typeid-consistency.rs-1
......@@ -3,7 +3,6 @@
33//@ run-pass
44
55#![allow(deprecated)]
6#![feature(core_intrinsics)]
76
87//@ aux-build:typeid-consistency-aux1.rs
98//@ aux-build:typeid-consistency-aux2.rs
tests/ui/typeck/type-name-intrinsic-usage-61894.rs-1
......@@ -1,7 +1,6 @@
11// https://github.com/rust-lang/rust/issues/61894
22//@ run-pass
33
4#![feature(core_intrinsics)]
54
65use std::any::type_name;
76
tests/ui/variance/variance-associated-consts.rs+1-1
......@@ -9,7 +9,7 @@ trait Trait {
99 const Const: usize;
1010}
1111
12#[rustc_variance]
12#[rustc_dump_variances]
1313struct Foo<T: Trait> { //~ ERROR [T: o]
1414 field: [u8; <T as Trait>::Const]
1515 //~^ ERROR: unconstrained generic constant
tests/ui/variance/variance-associated-types.rs+2-2
......@@ -9,12 +9,12 @@ trait Trait<'a> {
99 fn method(&'a self) { }
1010}
1111
12#[rustc_variance]
12#[rustc_dump_variances]
1313struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +]
1414 field: (T, &'a ())
1515}
1616
17#[rustc_variance]
17#[rustc_dump_variances]
1818struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o]
1919 field: <T as Trait<'a>>::Type
2020}
tests/ui/variance/variance-object-types.rs+1-1
......@@ -3,7 +3,7 @@
33
44// For better or worse, associated types are invariant, and hence we
55// get an invariant result for `'a`.
6#[rustc_variance]
6#[rustc_dump_variances]
77struct Foo<'a> { //~ ERROR ['a: o]
88 x: Box<dyn Fn(i32) -> &'a i32 + 'static>
99}
tests/ui/variance/variance-regions-direct.rs+7-7
......@@ -5,7 +5,7 @@
55
66// Regions that just appear in normal spots are contravariant:
77
8#[rustc_variance]
8#[rustc_dump_variances]
99struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +]
1010 x: &'a isize,
1111 y: &'b [isize],
......@@ -14,7 +14,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR ['a: +, 'b: +, 'c: +]
1414
1515// Those same annotations in function arguments become covariant:
1616
17#[rustc_variance]
17#[rustc_dump_variances]
1818struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -]
1919 x: extern "Rust" fn(&'a isize),
2020 y: extern "Rust" fn(&'b [isize]),
......@@ -23,7 +23,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR ['a: -, 'b: -, 'c: -]
2323
2424// Mutability induces invariance:
2525
26#[rustc_variance]
26#[rustc_dump_variances]
2727struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o]
2828 x: &'a mut &'b isize,
2929}
......@@ -31,7 +31,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o]
3131// Mutability induces invariance, even when in a
3232// contravariant context:
3333
34#[rustc_variance]
34#[rustc_dump_variances]
3535struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o]
3636 x: extern "Rust" fn(&'a mut &'b isize),
3737}
......@@ -41,14 +41,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR ['a: -, 'b: o]
4141// an argument list (which is contravariant), that
4242// argument list occurs in an invariant context.
4343
44#[rustc_variance]
44#[rustc_dump_variances]
4545struct Test6<'a, 'b:'a> { //~ ERROR ['a: +, 'b: o]
4646 x: &'a mut extern "Rust" fn(&'b isize),
4747}
4848
4949// No uses at all is bivariant:
5050
51#[rustc_variance]
51#[rustc_dump_variances]
5252struct Test7<'a> { //~ ERROR ['a: *]
5353 //~^ ERROR: `'a` is never used
5454 x: isize
......@@ -56,7 +56,7 @@ struct Test7<'a> { //~ ERROR ['a: *]
5656
5757// Try enums too.
5858
59#[rustc_variance]
59#[rustc_dump_variances]
6060enum Test8<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o]
6161 Test8A(extern "Rust" fn(&'a isize)),
6262 Test8B(&'b [isize]),
tests/ui/variance/variance-regions-indirect.rs+5-5
......@@ -4,7 +4,7 @@
44
55#![feature(rustc_attrs)]
66
7#[rustc_variance]
7#[rustc_dump_variances]
88enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *]
99 //~^ ERROR: `'d` is never used
1010 Test8A(extern "Rust" fn(&'a isize)),
......@@ -12,25 +12,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR ['a: -, 'b: +, 'c: o, 'd: *]
1212 Test8C(&'b mut &'c str),
1313}
1414
15#[rustc_variance]
15#[rustc_dump_variances]
1616struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR ['w: *, 'x: o, 'y: +, 'z: -]
1717 //~^ ERROR: `'w` is never used
1818 f: Base<'z, 'y, 'x, 'w>
1919}
2020
21#[rustc_variance] // Combine - and + to yield o
21#[rustc_dump_variances] // Combine - and + to yield o
2222struct Derived2<'a, 'b:'a, 'c> { //~ ERROR ['a: o, 'b: o, 'c: *]
2323 //~^ ERROR: `'c` is never used
2424 f: Base<'a, 'a, 'b, 'c>
2525}
2626
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)
2828struct Derived3<'a:'b, 'b, 'c> { //~ ERROR ['a: o, 'b: +, 'c: *]
2929 //~^ ERROR: `'c` is never used
3030 f: Base<'a, 'b, 'a, 'c>
3131}
3232
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)
3434struct Derived4<'a, 'b, 'c:'b> { //~ ERROR ['a: -, 'b: +, 'c: o]
3535 f: Base<'a, 'b, 'c, 'a>
3636}
tests/ui/variance/variance-trait-bounds.rs+4-4
......@@ -12,24 +12,24 @@ trait Setter<T> {
1212 fn get(&self, _: T);
1313}
1414
15#[rustc_variance]
15#[rustc_dump_variances]
1616struct TestStruct<U,T:Setter<U>> { //~ ERROR [U: +, T: +]
1717 t: T, u: U
1818}
1919
20#[rustc_variance]
20#[rustc_dump_variances]
2121enum TestEnum<U,T:Setter<U>> { //~ ERROR [U: *, T: +]
2222 //~^ ERROR: `U` is never used
2323 Foo(T)
2424}
2525
26#[rustc_variance]
26#[rustc_dump_variances]
2727struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [U: *, T: +]
2828 //~^ ERROR: `U` is never used
2929 t: T
3030}
3131
32#[rustc_variance]
32#[rustc_dump_variances]
3333struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [U: *, T: +]
3434 //~^ ERROR: `U` is never used
3535 t: T
tests/ui/variance/variance-trait-object-bound.rs+1-1
......@@ -10,7 +10,7 @@ use std::mem;
1010
1111trait T { fn foo(&self); }
1212
13#[rustc_variance]
13#[rustc_dump_variances]
1414struct TOption<'a> { //~ ERROR ['a: +]
1515 v: Option<Box<dyn T + 'a>>,
1616}
tests/ui/variance/variance-types-bounds.rs+5-5
......@@ -3,24 +3,24 @@
33
44#![feature(rustc_attrs)]
55
6#[rustc_variance]
6#[rustc_dump_variances]
77struct TestImm<A, B> { //~ ERROR [A: +, B: +]
88 x: A,
99 y: B,
1010}
1111
12#[rustc_variance]
12#[rustc_dump_variances]
1313struct TestMut<A, B:'static> { //~ ERROR [A: +, B: o]
1414 x: A,
1515 y: &'static mut B,
1616}
1717
18#[rustc_variance]
18#[rustc_dump_variances]
1919struct TestIndirect<A:'static, B:'static> { //~ ERROR [A: +, B: o]
2020 m: TestMut<A, B>
2121}
2222
23#[rustc_variance]
23#[rustc_dump_variances]
2424struct TestIndirect2<A:'static, B:'static> { //~ ERROR [A: o, B: o]
2525 n: TestMut<A, B>,
2626 m: TestMut<B, A>
......@@ -34,7 +34,7 @@ trait Setter<A> {
3434 fn set(&mut self, a: A);
3535}
3636
37#[rustc_variance]
37#[rustc_dump_variances]
3838struct TestObject<A, R> { //~ ERROR [A: o, R: o]
3939 n: Box<dyn Setter<A>+Send>,
4040 m: Box<dyn Getter<R>+Send>,
tests/ui/variance/variance-types.rs+6-6
......@@ -6,32 +6,32 @@ use std::cell::Cell;
66// Check that a type parameter which is only used in a trait bound is
77// not considered bivariant.
88
9#[rustc_variance]
9#[rustc_dump_variances]
1010struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o]
1111 t: &'a mut (A,B)
1212}
1313
14#[rustc_variance]
14#[rustc_dump_variances]
1515struct InvariantCell<A> { //~ ERROR [A: o]
1616 t: Cell<A>
1717}
1818
19#[rustc_variance]
19#[rustc_dump_variances]
2020struct InvariantIndirect<A> { //~ ERROR [A: o]
2121 t: InvariantCell<A>
2222}
2323
24#[rustc_variance]
24#[rustc_dump_variances]
2525struct Covariant<A> { //~ ERROR [A: +]
2626 t: A, u: fn() -> A
2727}
2828
29#[rustc_variance]
29#[rustc_dump_variances]
3030struct Contravariant<A> { //~ ERROR [A: -]
3131 t: fn(A)
3232}
3333
34#[rustc_variance]
34#[rustc_dump_variances]
3535enum Enum<A,B,C> { //~ ERROR [A: +, B: -, C: o]
3636 Foo(Covariant<A>),
3737 Bar(Contravariant<B>),
triagebot.toml+4-4
......@@ -534,7 +534,7 @@ trigger_files = [
534534[autolabel."A-translation"]
535535trigger_files = [
536536 "compiler/rustc_error_messages",
537 "compiler/rustc_errors/src/translation.rs",
537 "compiler/rustc_errors/src/formatting.rs",
538538 "compiler/rustc_macros/src/diagnostics"
539539]
540540
......@@ -1180,8 +1180,8 @@ cc = ["@Muscraft"]
11801180message = "`rustc_errors::emitter` was changed"
11811181cc = ["@Muscraft"]
11821182
1183[mentions."compiler/rustc_errors/src/translation.rs"]
1184message = "`rustc_errors::translation` was changed"
1183[mentions."compiler/rustc_errors/src/formatting.rs"]
1184message = "`rustc_errors::formatting` was changed"
11851185cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"]
11861186
11871187[mentions."compiler/rustc_macros/src/diagnostics"]
......@@ -1371,7 +1371,7 @@ cc = ["@ehuss"]
13711371
13721372[mentions."src/doc/rustc-dev-guide"]
13731373message = "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."
1374cc = ["@BoxyUwU", "@jieyouxu", "@tshepang"]
1374cc = ["@BoxyUwU", "@tshepang"]
13751375
13761376[mentions."compiler/rustc_passes/src/check_attr.rs"]
13771377cc = ["@jdonszelmann", "@JonathanBrouwer"]