authorbors <bors@rust-lang.org> 2025-06-18 21:19:39 UTC
committerbors <bors@rust-lang.org> 2025-06-18 21:19:39 UTC
log044514eb26511d2d8aa999fdf27e85df6beb6576
treefb5c0b63b1bbee2e9a2615a9c985d4dc62e2b8f0
parentc68340350c78eea402c4a85f8d9c1b7d3d607635
parent663939dfb0d20a4de47d755b8f8fd1af44aac80f

Auto merge of #142689 - Urgau:rollup-4ho6835, r=Urgau

Rollup of 6 pull requests Successful merges: - rust-lang/rust#135656 (Add `-Z hint-mostly-unused` to tell rustc that most of a crate will go unused) - rust-lang/rust#138237 (Get rid of `EscapeDebugInner`.) - rust-lang/rust#141614 (lint direct use of rustc_type_ir ) - rust-lang/rust#142123 (Implement initial support for timing sections (`--json=timings`)) - rust-lang/rust#142377 (Try unremapping compiler sources) - rust-lang/rust#142674 (remove duplicate crash test) r? `@ghost` `@rustbot` modify labels: rollup

35 files changed, 772 insertions(+), 181 deletions(-)

compiler/rustc_errors/src/emitter.rs+11-1
......@@ -34,6 +34,7 @@ use crate::snippet::{
3434 Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
3535};
3636use crate::styled_buffer::StyledBuffer;
37use crate::timings::TimingRecord;
3738use crate::translation::{Translate, to_fluent_args};
3839use crate::{
3940 CodeSuggestion, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, Level,
......@@ -164,11 +165,16 @@ impl Margin {
164165 }
165166}
166167
168pub enum TimingEvent {
169 Start,
170 End,
171}
172
167173const ANONYMIZED_LINE_NUM: &str = "LL";
168174
169175pub type DynEmitter = dyn Emitter + DynSend;
170176
171/// Emitter trait for emitting errors.
177/// Emitter trait for emitting errors and other structured information.
172178pub trait Emitter: Translate {
173179 /// Emit a structured diagnostic.
174180 fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry);
......@@ -177,6 +183,10 @@ pub trait Emitter: Translate {
177183 /// Currently only supported for the JSON format.
178184 fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
179185
186 /// Emit a timestamp with start/end of a timing section.
187 /// Currently only supported for the JSON format.
188 fn emit_timing_section(&mut self, _record: TimingRecord, _event: TimingEvent) {}
189
180190 /// Emit a report about future breakage.
181191 /// Currently only supported for the JSON format.
182192 fn emit_future_breakage_report(&mut self, _diags: Vec<DiagInner>, _registry: &Registry) {}
compiler/rustc_errors/src/json.rs+28-1
......@@ -28,9 +28,10 @@ use termcolor::{ColorSpec, WriteColor};
2828use crate::diagnostic::IsLint;
2929use crate::emitter::{
3030 ColorConfig, Destination, Emitter, HumanEmitter, HumanReadableErrorType, OutputTheme,
31 should_show_source_code,
31 TimingEvent, should_show_source_code,
3232};
3333use crate::registry::Registry;
34use crate::timings::{TimingRecord, TimingSection};
3435use crate::translation::{Translate, to_fluent_args};
3536use crate::{
3637 CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, Suggestions,
......@@ -104,6 +105,7 @@ impl JsonEmitter {
104105enum EmitTyped<'a> {
105106 Diagnostic(Diagnostic),
106107 Artifact(ArtifactNotification<'a>),
108 SectionTiming(SectionTimestamp<'a>),
107109 FutureIncompat(FutureIncompatReport<'a>),
108110 UnusedExtern(UnusedExterns<'a>),
109111}
......@@ -135,6 +137,21 @@ impl Emitter for JsonEmitter {
135137 }
136138 }
137139
140 fn emit_timing_section(&mut self, record: TimingRecord, event: TimingEvent) {
141 let event = match event {
142 TimingEvent::Start => "start",
143 TimingEvent::End => "end",
144 };
145 let name = match record.section {
146 TimingSection::Linking => "link",
147 };
148 let data = SectionTimestamp { name, event, timestamp: record.timestamp };
149 let result = self.emit(EmitTyped::SectionTiming(data));
150 if let Err(e) = result {
151 panic!("failed to print timing section: {e:?}");
152 }
153 }
154
138155 fn emit_future_breakage_report(&mut self, diags: Vec<crate::DiagInner>, registry: &Registry) {
139156 let data: Vec<FutureBreakageItem<'_>> = diags
140157 .into_iter()
......@@ -263,6 +280,16 @@ struct ArtifactNotification<'a> {
263280 emit: &'a str,
264281}
265282
283#[derive(Serialize)]
284struct SectionTimestamp<'a> {
285 /// Name of the section
286 name: &'a str,
287 /// Start/end of the section
288 event: &'a str,
289 /// Opaque timestamp.
290 timestamp: u128,
291}
292
266293#[derive(Serialize)]
267294struct FutureBreakageItem<'a> {
268295 // Always EmitTyped::Diagnostic, but we want to make sure it gets serialized
compiler/rustc_errors/src/lib.rs+12
......@@ -7,6 +7,7 @@
77#![allow(internal_features)]
88#![allow(rustc::diagnostic_outside_of_impl)]
99#![allow(rustc::untranslatable_diagnostic)]
10#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
1011#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
1112#![doc(rust_logo)]
1213#![feature(array_windows)]
......@@ -74,7 +75,9 @@ pub use snippet::Style;
7475pub use termcolor::{Color, ColorSpec, WriteColor};
7576use tracing::debug;
7677
78use crate::emitter::TimingEvent;
7779use crate::registry::Registry;
80use crate::timings::TimingRecord;
7881
7982pub mod annotate_snippet_emitter_writer;
8083pub mod codes;
......@@ -90,6 +93,7 @@ mod snippet;
9093mod styled_buffer;
9194#[cfg(test)]
9295mod tests;
96pub mod timings;
9397pub mod translation;
9498
9599pub type PResult<'a, T> = Result<T, Diag<'a>>;
......@@ -1156,6 +1160,14 @@ impl<'a> DiagCtxtHandle<'a> {
11561160 self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type);
11571161 }
11581162
1163 pub fn emit_timing_section_start(&self, record: TimingRecord) {
1164 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::Start);
1165 }
1166
1167 pub fn emit_timing_section_end(&self, record: TimingRecord) {
1168 self.inner.borrow_mut().emitter.emit_timing_section(record, TimingEvent::End);
1169 }
1170
11591171 pub fn emit_future_breakage_report(&self) {
11601172 let inner = &mut *self.inner.borrow_mut();
11611173 let diags = std::mem::take(&mut inner.future_breakage_diagnostics);
compiler/rustc_errors/src/timings.rs created+80
......@@ -0,0 +1,80 @@
1use std::time::Instant;
2
3use crate::DiagCtxtHandle;
4
5/// A high-level section of the compilation process.
6#[derive(Copy, Clone, Debug)]
7pub enum TimingSection {
8 /// Time spent linking.
9 Linking,
10}
11
12/// Section with attached timestamp
13#[derive(Copy, Clone, Debug)]
14pub struct TimingRecord {
15 pub section: TimingSection,
16 /// Microseconds elapsed since some predetermined point in time (~start of the rustc process).
17 pub timestamp: u128,
18}
19
20impl TimingRecord {
21 fn from_origin(origin: Instant, section: TimingSection) -> Self {
22 Self { section, timestamp: Instant::now().duration_since(origin).as_micros() }
23 }
24
25 pub fn section(&self) -> TimingSection {
26 self.section
27 }
28
29 pub fn timestamp(&self) -> u128 {
30 self.timestamp
31 }
32}
33
34/// Manages emission of start/end section timings, enabled through `--json=timings`.
35pub struct TimingSectionHandler {
36 /// Time when the compilation session started.
37 /// If `None`, timing is disabled.
38 origin: Option<Instant>,
39}
40
41impl TimingSectionHandler {
42 pub fn new(enabled: bool) -> Self {
43 let origin = if enabled { Some(Instant::now()) } else { None };
44 Self { origin }
45 }
46
47 /// Returns a RAII guard that will immediately emit a start the provided section, and then emit
48 /// its end when it is dropped.
49 pub fn start_section<'a>(
50 &self,
51 diag_ctxt: DiagCtxtHandle<'a>,
52 section: TimingSection,
53 ) -> TimingSectionGuard<'a> {
54 TimingSectionGuard::create(diag_ctxt, section, self.origin)
55 }
56}
57
58/// RAII wrapper for starting and ending section timings.
59pub struct TimingSectionGuard<'a> {
60 dcx: DiagCtxtHandle<'a>,
61 section: TimingSection,
62 origin: Option<Instant>,
63}
64
65impl<'a> TimingSectionGuard<'a> {
66 fn create(dcx: DiagCtxtHandle<'a>, section: TimingSection, origin: Option<Instant>) -> Self {
67 if let Some(origin) = origin {
68 dcx.emit_timing_section_start(TimingRecord::from_origin(origin, section));
69 }
70 Self { dcx, section, origin }
71 }
72}
73
74impl<'a> Drop for TimingSectionGuard<'a> {
75 fn drop(&mut self) {
76 if let Some(origin) = self.origin {
77 self.dcx.emit_timing_section_end(TimingRecord::from_origin(origin, self.section));
78 }
79 }
80}
compiler/rustc_infer/src/lib.rs+1
......@@ -16,6 +16,7 @@
1616#![allow(internal_features)]
1717#![allow(rustc::diagnostic_outside_of_impl)]
1818#![allow(rustc::untranslatable_diagnostic)]
19#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
1920#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
2021#![doc(rust_logo)]
2122#![feature(assert_matches)]
compiler/rustc_interface/src/queries.rs+2
......@@ -4,6 +4,7 @@ use std::sync::Arc;
44use rustc_codegen_ssa::CodegenResults;
55use rustc_codegen_ssa::traits::CodegenBackend;
66use rustc_data_structures::svh::Svh;
7use rustc_errors::timings::TimingSection;
78use rustc_hir::def_id::LOCAL_CRATE;
89use rustc_metadata::EncodedMetadata;
910use rustc_middle::dep_graph::DepGraph;
......@@ -88,6 +89,7 @@ impl Linker {
8889 }
8990
9091 let _timer = sess.prof.verbose_generic_activity("link_crate");
92 let _timing = sess.timings.start_section(sess.dcx(), TimingSection::Linking);
9193 codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames)
9294 }
9395}
compiler/rustc_interface/src/tests.rs+1
......@@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() {
802802 tracked!(force_unstable_if_unmarked, true);
803803 tracked!(function_return, FunctionReturn::ThunkExtern);
804804 tracked!(function_sections, Some(false));
805 tracked!(hint_mostly_unused, true);
805806 tracked!(human_readable_cgu_names, true);
806807 tracked!(incremental_ignore_spans, true);
807808 tracked!(inline_mir, Some(true));
compiler/rustc_lint/messages.ftl+3
......@@ -812,6 +812,9 @@ lint_tykind = usage of `ty::TyKind`
812812lint_tykind_kind = usage of `ty::TyKind::<kind>`
813813 .suggestion = try using `ty::<kind>` directly
814814
815lint_type_ir_direct_use = do not use `rustc_type_ir` unless you are implementing type system internals
816 .note = use `rustc_middle::ty` instead
817
815818lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver
816819 .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler
817820
compiler/rustc_lint/src/internal.rs+28-3
......@@ -14,8 +14,8 @@ use {rustc_ast as ast, rustc_hir as hir};
1414use crate::lints::{
1515 BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
1616 NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
17 SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
18 TypeIrTraitUsage, UntranslatableDiag,
17 SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrDirectUse,
18 TypeIrInherentUsage, TypeIrTraitUsage, UntranslatableDiag,
1919};
2020use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
2121
......@@ -301,8 +301,18 @@ declare_tool_lint! {
301301 "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
302302 report_in_external_macro: true
303303}
304declare_tool_lint! {
305 /// The `direct_use_of_rustc_type_ir` lint detects usage of `rustc_type_ir`.
306 ///
307 /// This module should only be used within the trait solver and some desirable
308 /// crates like rustc_middle.
309 pub rustc::DIRECT_USE_OF_RUSTC_TYPE_IR,
310 Allow,
311 "usage `rustc_type_ir` abstraction outside of trait system",
312 report_in_external_macro: true
313}
304314
305declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
315declare_lint_pass!(TypeIr => [DIRECT_USE_OF_RUSTC_TYPE_IR, NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
306316
307317impl<'tcx> LateLintPass<'tcx> for TypeIr {
308318 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
......@@ -372,6 +382,21 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr {
372382 NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet },
373383 );
374384 }
385
386 fn check_path(
387 &mut self,
388 cx: &LateContext<'tcx>,
389 path: &rustc_hir::Path<'tcx>,
390 _: rustc_hir::HirId,
391 ) {
392 if let Some(seg) = path.segments.iter().find(|seg| {
393 seg.res
394 .opt_def_id()
395 .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir, def_id))
396 }) {
397 cx.emit_span_lint(DIRECT_USE_OF_RUSTC_TYPE_IR, seg.ident.span, TypeIrDirectUse);
398 }
399 }
375400}
376401
377402declare_tool_lint! {
compiler/rustc_lint/src/lib.rs+1
......@@ -668,6 +668,7 @@ fn register_internals(store: &mut LintStore) {
668668 LintId::of(USAGE_OF_TYPE_IR_TRAITS),
669669 LintId::of(BAD_OPT_ACCESS),
670670 LintId::of(SPAN_USE_EQ_CTXT),
671 LintId::of(DIRECT_USE_OF_RUSTC_TYPE_IR),
671672 ],
672673 );
673674}
compiler/rustc_lint/src/lints.rs+5
......@@ -969,6 +969,11 @@ pub(crate) struct TypeIrInherentUsage;
969969#[note]
970970pub(crate) struct TypeIrTraitUsage;
971971
972#[derive(LintDiagnostic)]
973#[diag(lint_type_ir_direct_use)]
974#[note]
975pub(crate) struct TypeIrDirectUse;
976
972977#[derive(LintDiagnostic)]
973978#[diag(lint_non_glob_import_type_ir_inherent)]
974979pub(crate) struct NonGlobImportTypeIrInherent {
compiler/rustc_metadata/src/rmeta/decoder.rs+123-75
......@@ -1,7 +1,7 @@
11// Decoding metadata from a single crate's metadata
22
33use std::iter::TrustedLen;
4use std::path::Path;
4use std::path::{Path, PathBuf};
55use std::sync::{Arc, OnceLock};
66use std::{io, iter, mem};
77
......@@ -1610,10 +1610,14 @@ impl<'a> CrateMetadataRef<'a> {
16101610 /// Proc macro crates don't currently export spans, so this function does not have
16111611 /// to work for them.
16121612 fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1613 fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1613 fn filter<'a>(
1614 sess: &Session,
1615 real_source_base_dir: &Option<PathBuf>,
1616 path: Option<&'a Path>,
1617 ) -> Option<&'a Path> {
16141618 path.filter(|_| {
16151619 // Only spend time on further checks if we have what to translate *to*.
1616 sess.opts.real_rust_source_base_dir.is_some()
1620 real_source_base_dir.is_some()
16171621 // Some tests need the translation to be always skipped.
16181622 && sess.opts.unstable_opts.translate_remapped_path_to_local_path
16191623 })
......@@ -1625,57 +1629,92 @@ impl<'a> CrateMetadataRef<'a> {
16251629 })
16261630 }
16271631
1628 let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
1629 // Translate the virtual `/rustc/$hash` prefix back to a real directory
1630 // that should hold actual sources, where possible.
1631 //
1632 // NOTE: if you update this, you might need to also update bootstrap's code for generating
1633 // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1634 let virtual_rust_source_base_dir = [
1635 filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1636 filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1637 ];
1632 let try_to_translate_virtual_to_real =
1633 |virtual_source_base_dir: Option<&str>,
1634 real_source_base_dir: &Option<PathBuf>,
1635 name: &mut rustc_span::FileName| {
1636 let virtual_source_base_dir = [
1637 filter(sess, real_source_base_dir, virtual_source_base_dir.map(Path::new)),
1638 filter(
1639 sess,
1640 real_source_base_dir,
1641 sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
1642 ),
1643 ];
16381644
1639 debug!(
1640 "try_to_translate_virtual_to_real(name={:?}): \
1641 virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1642 name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1643 );
1645 debug!(
1646 "try_to_translate_virtual_to_real(name={:?}): \
1647 virtual_source_base_dir={:?}, real_source_base_dir={:?}",
1648 name, virtual_source_base_dir, real_source_base_dir,
1649 );
16441650
1645 for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1646 if let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1651 for virtual_dir in virtual_source_base_dir.iter().flatten() {
1652 if let Some(real_dir) = &real_source_base_dir
1653 && let rustc_span::FileName::Real(old_name) = name
1654 && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1655 old_name
1656 && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
1657 {
1658 let new_path = real_dir.join(rest);
1659
1660 debug!(
1661 "try_to_translate_virtual_to_real: `{}` -> `{}`",
1662 virtual_name.display(),
1663 new_path.display(),
1664 );
1665
1666 // Check if the translated real path is affected by any user-requested
1667 // remaps via --remap-path-prefix. Apply them if so.
1668 // Note that this is a special case for imported rust-src paths specified by
1669 // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1670 // Other imported paths are not currently remapped (see #66251).
1671 let (user_remapped, applied) =
1672 sess.source_map().path_mapping().map_prefix(&new_path);
1673 let new_name = if applied {
1674 rustc_span::RealFileName::Remapped {
1675 local_path: Some(new_path.clone()),
1676 virtual_name: user_remapped.to_path_buf(),
1677 }
1678 } else {
1679 rustc_span::RealFileName::LocalPath(new_path)
1680 };
1681 *old_name = new_name;
1682 }
1683 }
1684 };
1685
1686 let try_to_translate_real_to_virtual =
1687 |virtual_source_base_dir: Option<&str>,
1688 real_source_base_dir: &Option<PathBuf>,
1689 subdir: &str,
1690 name: &mut rustc_span::FileName| {
1691 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1692 && let Some(real_dir) = real_source_base_dir
16471693 && let rustc_span::FileName::Real(old_name) = name
1648 && let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
1649 old_name
1650 && let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
16511694 {
1652 let new_path = real_dir.join(rest);
1653
1654 debug!(
1655 "try_to_translate_virtual_to_real: `{}` -> `{}`",
1656 virtual_name.display(),
1657 new_path.display(),
1658 );
1659
1660 // Check if the translated real path is affected by any user-requested
1661 // remaps via --remap-path-prefix. Apply them if so.
1662 // Note that this is a special case for imported rust-src paths specified by
1663 // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1664 // Other imported paths are not currently remapped (see #66251).
1665 let (user_remapped, applied) =
1666 sess.source_map().path_mapping().map_prefix(&new_path);
1667 let new_name = if applied {
1668 rustc_span::RealFileName::Remapped {
1669 local_path: Some(new_path.clone()),
1670 virtual_name: user_remapped.to_path_buf(),
1695 let relative_path = match old_name {
1696 rustc_span::RealFileName::LocalPath(local) => {
1697 local.strip_prefix(real_dir).ok()
1698 }
1699 rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1700 virtual_source_base_dir
1701 .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
16711702 }
1672 } else {
1673 rustc_span::RealFileName::LocalPath(new_path)
16741703 };
1675 *old_name = new_name;
1704 debug!(
1705 ?relative_path,
1706 ?virtual_dir,
1707 ?subdir,
1708 "simulate_remapped_rust_src_base"
1709 );
1710 if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
1711 *old_name = rustc_span::RealFileName::Remapped {
1712 local_path: None,
1713 virtual_name: virtual_dir.join(subdir).join(rest),
1714 };
1715 }
16761716 }
1677 }
1678 };
1717 };
16791718
16801719 let mut import_info = self.cdata.source_map_import_info.lock();
16811720 for _ in import_info.len()..=(source_file_index as usize) {
......@@ -1713,36 +1752,45 @@ impl<'a> CrateMetadataRef<'a> {
17131752 // This is useful for testing so that tests about the effects of
17141753 // `try_to_translate_virtual_to_real` don't have to worry about how the
17151754 // compiler is bootstrapped.
1716 if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1717 && let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1718 && let rustc_span::FileName::Real(ref mut old_name) = name
1719 {
1720 let relative_path = match old_name {
1721 rustc_span::RealFileName::LocalPath(local) => {
1722 local.strip_prefix(real_dir).ok()
1723 }
1724 rustc_span::RealFileName::Remapped { virtual_name, .. } => {
1725 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR")
1726 .and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
1727 }
1728 };
1729 debug!(?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base");
1730 for subdir in ["library", "compiler"] {
1731 if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok())
1732 {
1733 *old_name = rustc_span::RealFileName::Remapped {
1734 local_path: None, // FIXME: maybe we should preserve this?
1735 virtual_name: virtual_dir.join(subdir).join(rest),
1736 };
1737 break;
1738 }
1739 }
1740 }
1755 try_to_translate_real_to_virtual(
1756 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1757 &sess.opts.real_rust_source_base_dir,
1758 "library",
1759 &mut name,
1760 );
1761
1762 // If this file is under $sysroot/lib/rustlib/rustc-src/
1763 // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
1764 // then we change `name` to a similar state as if the rust was bootstrapped
1765 // with `remap-debuginfo = true`.
1766 try_to_translate_real_to_virtual(
1767 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1768 &sess.opts.real_rustc_dev_source_base_dir,
1769 "compiler",
1770 &mut name,
1771 );
17411772
17421773 // If this file's path has been remapped to `/rustc/$hash`,
1743 // we might be able to reverse that (also see comments above,
1744 // on `try_to_translate_virtual_to_real`).
1745 try_to_translate_virtual_to_real(&mut name);
1774 // we might be able to reverse that.
1775 //
1776 // NOTE: if you update this, you might need to also update bootstrap's code for generating
1777 // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1778 try_to_translate_virtual_to_real(
1779 option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR"),
1780 &sess.opts.real_rust_source_base_dir,
1781 &mut name,
1782 );
1783
1784 // If this file's path has been remapped to `/rustc-dev/$hash`,
1785 // we might be able to reverse that.
1786 //
1787 // NOTE: if you update this, you might need to also update bootstrap's code for generating
1788 // the `rustc-dev` component in `Src::run` in `src/bootstrap/dist.rs`.
1789 try_to_translate_virtual_to_real(
1790 option_env!("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR"),
1791 &sess.opts.real_rustc_dev_source_base_dir,
1792 &mut name,
1793 );
17461794
17471795 let local_version = sess.source_map().new_imported_source_file(
17481796 name,
compiler/rustc_middle/src/lib.rs+1
......@@ -28,6 +28,7 @@
2828#![allow(internal_features)]
2929#![allow(rustc::diagnostic_outside_of_impl)]
3030#![allow(rustc::untranslatable_diagnostic)]
31#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
3132#![cfg_attr(not(bootstrap), feature(sized_hierarchy))]
3233#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
3334#![doc(rust_logo)]
compiler/rustc_mir_transform/src/cross_crate_inline.rs+7
......@@ -50,6 +50,13 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
5050 _ => {}
5151 }
5252
53 // If the crate is likely to be mostly unused, use cross-crate inlining to defer codegen until
54 // the function is referenced, in order to skip codegen for unused functions. This is
55 // intentionally after the check for `inline(never)`, so that `inline(never)` wins.
56 if tcx.sess.opts.unstable_opts.hint_mostly_unused {
57 return true;
58 }
59
5360 let sig = tcx.fn_sig(def_id).instantiate_identity();
5461 for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder()))
5562 {
compiler/rustc_next_trait_solver/src/lib.rs+1
......@@ -7,6 +7,7 @@
77// tidy-alphabetical-start
88#![allow(rustc::usage_of_type_ir_inherent)]
99#![allow(rustc::usage_of_type_ir_traits)]
10#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
1011// tidy-alphabetical-end
1112
1213pub mod canonicalizer;
compiler/rustc_passes/src/diagnostic_items.rs+2-2
......@@ -10,7 +10,7 @@
1010//! * Compiler internal types like `Ty` and `TyCtxt`
1111
1212use rustc_hir::diagnostic_items::DiagnosticItems;
13use rustc_hir::{Attribute, OwnerId};
13use rustc_hir::{Attribute, CRATE_OWNER_ID, OwnerId};
1414use rustc_middle::query::{LocalCrate, Providers};
1515use rustc_middle::ty::TyCtxt;
1616use rustc_span::def_id::{DefId, LOCAL_CRATE};
......@@ -67,7 +67,7 @@ fn diagnostic_items(tcx: TyCtxt<'_>, _: LocalCrate) -> DiagnosticItems {
6767
6868 // Collect diagnostic items in this crate.
6969 let crate_items = tcx.hir_crate_items(());
70 for id in crate_items.owners() {
70 for id in crate_items.owners().chain(std::iter::once(CRATE_OWNER_ID)) {
7171 observe_item(tcx, &mut diagnostic_items, id);
7272 }
7373
compiler/rustc_session/src/config.rs+26-4
......@@ -1364,8 +1364,10 @@ impl Default for Options {
13641364 cli_forced_local_thinlto_off: false,
13651365 remap_path_prefix: Vec::new(),
13661366 real_rust_source_base_dir: None,
1367 real_rustc_dev_source_base_dir: None,
13671368 edition: DEFAULT_EDITION,
13681369 json_artifact_notifications: false,
1370 json_timings: false,
13691371 json_unused_externs: JsonUnusedExterns::No,
13701372 json_future_incompat: false,
13711373 pretty: None,
......@@ -1880,6 +1882,9 @@ pub struct JsonConfig {
18801882 pub json_rendered: HumanReadableErrorType,
18811883 pub json_color: ColorConfig,
18821884 json_artifact_notifications: bool,
1885 /// Output start and end timestamps of several high-level compilation sections
1886 /// (frontend, backend, linker).
1887 json_timings: bool,
18831888 pub json_unused_externs: JsonUnusedExterns,
18841889 json_future_incompat: bool,
18851890}
......@@ -1921,6 +1926,7 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json
19211926 let mut json_artifact_notifications = false;
19221927 let mut json_unused_externs = JsonUnusedExterns::No;
19231928 let mut json_future_incompat = false;
1929 let mut json_timings = false;
19241930 for option in matches.opt_strs("json") {
19251931 // For now conservatively forbid `--color` with `--json` since `--json`
19261932 // won't actually be emitting any colors and anything colorized is
......@@ -1937,6 +1943,7 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json
19371943 }
19381944 "diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
19391945 "artifacts" => json_artifact_notifications = true,
1946 "timings" => json_timings = true,
19401947 "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
19411948 "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
19421949 "future-incompat" => json_future_incompat = true,
......@@ -1949,6 +1956,7 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json
19491956 json_rendered,
19501957 json_color,
19511958 json_artifact_notifications,
1959 json_timings,
19521960 json_unused_externs,
19531961 json_future_incompat,
19541962 }
......@@ -2476,6 +2484,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
24762484 json_rendered,
24772485 json_color,
24782486 json_artifact_notifications,
2487 json_timings,
24792488 json_unused_externs,
24802489 json_future_incompat,
24812490 } = parse_json(early_dcx, matches);
......@@ -2497,6 +2506,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
24972506 let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers);
24982507 let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
24992508
2509 if !unstable_opts.unstable_options && json_timings {
2510 early_dcx.early_fatal("--json=timings is unstable and requires using `-Zunstable-options`");
2511 }
2512
25002513 check_error_format_stability(early_dcx, &unstable_opts, error_format);
25012514
25022515 let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
......@@ -2701,9 +2714,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27012714
27022715 let sysroot = filesearch::materialize_sysroot(sysroot_opt);
27032716
2704 let real_rust_source_base_dir = {
2705 // This is the location used by the `rust-src` `rustup` component.
2706 let mut candidate = sysroot.join("lib/rustlib/src/rust");
2717 let real_source_base_dir = |suffix: &str, confirm: &str| {
2718 let mut candidate = sysroot.join(suffix);
27072719 if let Ok(metadata) = candidate.symlink_metadata() {
27082720 // Replace the symlink bootstrap creates, with its destination.
27092721 // We could try to use `fs::canonicalize` instead, but that might
......@@ -2716,9 +2728,17 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27162728 }
27172729
27182730 // Only use this directory if it has a file we can expect to always find.
2719 candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
2731 candidate.join(confirm).is_file().then_some(candidate)
27202732 };
27212733
2734 let real_rust_source_base_dir =
2735 // This is the location used by the `rust-src` `rustup` component.
2736 real_source_base_dir("lib/rustlib/src/rust", "library/std/src/lib.rs");
2737
2738 let real_rustc_dev_source_base_dir =
2739 // This is the location used by the `rustc-dev` `rustup` component.
2740 real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs");
2741
27222742 let mut search_paths = vec![];
27232743 for s in &matches.opt_strs("L") {
27242744 search_paths.push(SearchPath::from_cli_opt(
......@@ -2772,8 +2792,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27722792 cli_forced_local_thinlto_off: disable_local_thinlto,
27732793 remap_path_prefix,
27742794 real_rust_source_base_dir,
2795 real_rustc_dev_source_base_dir,
27752796 edition,
27762797 json_artifact_notifications,
2798 json_timings,
27772799 json_unused_externs,
27782800 json_future_incompat,
27792801 pretty,
compiler/rustc_session/src/options.rs+19-3
......@@ -395,21 +395,35 @@ top_level_options!(
395395
396396 /// Remap source path prefixes in all output (messages, object files, debug, etc.).
397397 remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
398 /// Base directory containing the `src/` for the Rust standard library, and
399 /// potentially `rustc` as well, if we can find it. Right now it's always
400 /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
398
399 /// Base directory containing the `library/` directory for the Rust standard library.
400 /// Right now it's always `$sysroot/lib/rustlib/src/rust`
401 /// (i.e. the `rustup` `rust-src` component).
401402 ///
402403 /// This directory is what the virtual `/rustc/$hash` is translated back to,
403404 /// if Rust was built with path remapping to `/rustc/$hash` enabled
404405 /// (the `rust.remap-debuginfo` option in `bootstrap.toml`).
405406 real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
406407
408 /// Base directory containing the `compiler/` directory for the rustc sources.
409 /// Right now it's always `$sysroot/lib/rustlib/rustc-src/rust`
410 /// (i.e. the `rustup` `rustc-dev` component).
411 ///
412 /// This directory is what the virtual `/rustc-dev/$hash` is translated back to,
413 /// if Rust was built with path remapping to `/rustc/$hash` enabled
414 /// (the `rust.remap-debuginfo` option in `bootstrap.toml`).
415 real_rustc_dev_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
416
407417 edition: Edition [TRACKED],
408418
409419 /// `true` if we're emitting JSON blobs about each artifact produced
410420 /// by the compiler.
411421 json_artifact_notifications: bool [TRACKED],
412422
423 /// `true` if we're emitting JSON timings with the start and end of
424 /// high-level compilation sections
425 json_timings: bool [UNTRACKED],
426
413427 /// `true` if we're emitting a JSON blob containing the unused externs
414428 json_unused_externs: JsonUnusedExterns [UNTRACKED],
415429
......@@ -2235,6 +2249,8 @@ options! {
22352249 environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
22362250 has_thread_local: Option<bool> = (None, parse_opt_bool, [TRACKED],
22372251 "explicitly enable the `cfg(target_thread_local)` directive"),
2252 hint_mostly_unused: bool = (false, parse_bool, [TRACKED],
2253 "hint that most of this crate will go unused, to minimize work for uncalled functions"),
22382254 human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
22392255 "generate human-readable, predictable names for codegen units (default: no)"),
22402256 identify_regions: bool = (false, parse_bool, [UNTRACKED],
compiler/rustc_session/src/session.rs+7
......@@ -18,6 +18,7 @@ use rustc_errors::emitter::{
1818 DynEmitter, HumanEmitter, HumanReadableErrorType, OutputTheme, stderr_destination,
1919};
2020use rustc_errors::json::JsonEmitter;
21use rustc_errors::timings::TimingSectionHandler;
2122use rustc_errors::{
2223 Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
2324 FluentBundle, LazyFallbackBundle, TerminalUrl, fallback_fluent_bundle,
......@@ -156,6 +157,9 @@ pub struct Session {
156157 /// Used by `-Z self-profile`.
157158 pub prof: SelfProfilerRef,
158159
160 /// Used to emit section timings events (enabled by `--json=timings`).
161 pub timings: TimingSectionHandler,
162
159163 /// Data about code being compiled, gathered during compilation.
160164 pub code_stats: CodeStats,
161165
......@@ -1126,6 +1130,8 @@ pub fn build_session(
11261130 .as_ref()
11271131 .map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string());
11281132
1133 let timings = TimingSectionHandler::new(sopts.json_timings);
1134
11291135 let sess = Session {
11301136 target,
11311137 host,
......@@ -1136,6 +1142,7 @@ pub fn build_session(
11361142 io,
11371143 incr_comp_session: RwLock::new(IncrCompSession::NotInitialized),
11381144 prof,
1145 timings,
11391146 code_stats: Default::default(),
11401147 lint_store: None,
11411148 driver_lint_caps,
compiler/rustc_span/src/symbol.rs+1
......@@ -2183,6 +2183,7 @@ symbols! {
21832183 type_changing_struct_update,
21842184 type_const,
21852185 type_id,
2186 type_ir,
21862187 type_ir_infer_ctxt_like,
21872188 type_ir_inherent,
21882189 type_ir_interner,
compiler/rustc_type_ir/src/lib.rs+2
......@@ -1,3 +1,4 @@
1#![cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir")]
12// tidy-alphabetical-start
23#![allow(rustc::usage_of_ty_tykind)]
34#![allow(rustc::usage_of_type_ir_inherent)]
......@@ -7,6 +8,7 @@
78 feature(associated_type_defaults, never_type, rustc_attrs, negative_impls)
89)]
910#![cfg_attr(feature = "nightly", allow(internal_features))]
11#![cfg_attr(not(bootstrap), allow(rustc::direct_use_of_rustc_type_ir))]
1012// tidy-alphabetical-end
1113
1214extern crate self as rustc_type_ir;
library/core/src/ascii.rs+6-10
......@@ -9,9 +9,10 @@
99
1010#![stable(feature = "core_ascii", since = "1.26.0")]
1111
12use crate::escape::{AlwaysEscaped, EscapeIterInner};
13use crate::fmt;
1214use crate::iter::FusedIterator;
1315use crate::num::NonZero;
14use crate::{escape, fmt};
1516
1617mod ascii_char;
1718#[unstable(feature = "ascii_char", issue = "110998")]
......@@ -24,7 +25,7 @@ pub use ascii_char::AsciiChar as Char;
2425#[must_use = "iterators are lazy and do nothing unless consumed"]
2526#[stable(feature = "rust1", since = "1.0.0")]
2627#[derive(Clone)]
27pub struct EscapeDefault(escape::EscapeIterInner<4>);
28pub struct EscapeDefault(EscapeIterInner<4, AlwaysEscaped>);
2829
2930/// Returns an iterator that produces an escaped version of a `u8`.
3031///
......@@ -96,17 +97,12 @@ pub fn escape_default(c: u8) -> EscapeDefault {
9697impl EscapeDefault {
9798 #[inline]
9899 pub(crate) const fn new(c: u8) -> Self {
99 Self(escape::EscapeIterInner::ascii(c))
100 Self(EscapeIterInner::ascii(c))
100101 }
101102
102103 #[inline]
103104 pub(crate) fn empty() -> Self {
104 Self(escape::EscapeIterInner::empty())
105 }
106
107 #[inline]
108 pub(crate) fn as_str(&self) -> &str {
109 self.0.as_str()
105 Self(EscapeIterInner::empty())
110106 }
111107}
112108
......@@ -168,7 +164,7 @@ impl FusedIterator for EscapeDefault {}
168164#[stable(feature = "ascii_escape_display", since = "1.39.0")]
169165impl fmt::Display for EscapeDefault {
170166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 f.write_str(self.0.as_str())
167 fmt::Display::fmt(&self.0, f)
172168 }
173169}
174170
library/core/src/char/mod.rs+19-43
......@@ -44,7 +44,7 @@ pub use self::methods::{encode_utf8_raw, encode_utf8_raw_unchecked}; // perma-un
4444use crate::ascii;
4545pub(crate) use self::methods::EscapeDebugExtArgs;
4646use crate::error::Error;
47use crate::escape;
47use crate::escape::{AlwaysEscaped, EscapeIterInner, MaybeEscaped};
4848use crate::fmt::{self, Write};
4949use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
5050use crate::num::NonZero;
......@@ -161,12 +161,12 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
161161/// [`escape_unicode`]: char::escape_unicode
162162#[derive(Clone, Debug)]
163163#[stable(feature = "rust1", since = "1.0.0")]
164pub struct EscapeUnicode(escape::EscapeIterInner<10>);
164pub struct EscapeUnicode(EscapeIterInner<10, AlwaysEscaped>);
165165
166166impl EscapeUnicode {
167167 #[inline]
168168 const fn new(c: char) -> Self {
169 Self(escape::EscapeIterInner::unicode(c))
169 Self(EscapeIterInner::unicode(c))
170170 }
171171}
172172
......@@ -215,7 +215,7 @@ impl FusedIterator for EscapeUnicode {}
215215#[stable(feature = "char_struct_display", since = "1.16.0")]
216216impl fmt::Display for EscapeUnicode {
217217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 f.write_str(self.0.as_str())
218 fmt::Display::fmt(&self.0, f)
219219 }
220220}
221221
......@@ -227,22 +227,22 @@ impl fmt::Display for EscapeUnicode {
227227/// [`escape_default`]: char::escape_default
228228#[derive(Clone, Debug)]
229229#[stable(feature = "rust1", since = "1.0.0")]
230pub struct EscapeDefault(escape::EscapeIterInner<10>);
230pub struct EscapeDefault(EscapeIterInner<10, AlwaysEscaped>);
231231
232232impl EscapeDefault {
233233 #[inline]
234234 const fn printable(c: ascii::Char) -> Self {
235 Self(escape::EscapeIterInner::ascii(c.to_u8()))
235 Self(EscapeIterInner::ascii(c.to_u8()))
236236 }
237237
238238 #[inline]
239239 const fn backslash(c: ascii::Char) -> Self {
240 Self(escape::EscapeIterInner::backslash(c))
240 Self(EscapeIterInner::backslash(c))
241241 }
242242
243243 #[inline]
244244 const fn unicode(c: char) -> Self {
245 Self(escape::EscapeIterInner::unicode(c))
245 Self(EscapeIterInner::unicode(c))
246246 }
247247}
248248
......@@ -290,8 +290,9 @@ impl FusedIterator for EscapeDefault {}
290290
291291#[stable(feature = "char_struct_display", since = "1.16.0")]
292292impl fmt::Display for EscapeDefault {
293 #[inline]
293294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294 f.write_str(self.0.as_str())
295 fmt::Display::fmt(&self.0, f)
295296 }
296297}
297298
......@@ -303,37 +304,22 @@ impl fmt::Display for EscapeDefault {
303304/// [`escape_debug`]: char::escape_debug
304305#[stable(feature = "char_escape_debug", since = "1.20.0")]
305306#[derive(Clone, Debug)]
306pub struct EscapeDebug(EscapeDebugInner);
307
308#[derive(Clone, Debug)]
309// Note: It’s possible to manually encode the EscapeDebugInner inside of
310// EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] holds
311// a char) which would likely result in a more optimised code. For now we use
312// the option easier to implement.
313enum EscapeDebugInner {
314 Bytes(escape::EscapeIterInner<10>),
315 Char(char),
316}
307pub struct EscapeDebug(EscapeIterInner<10, MaybeEscaped>);
317308
318309impl EscapeDebug {
319310 #[inline]
320311 const fn printable(chr: char) -> Self {
321 Self(EscapeDebugInner::Char(chr))
312 Self(EscapeIterInner::printable(chr))
322313 }
323314
324315 #[inline]
325316 const fn backslash(c: ascii::Char) -> Self {
326 Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::backslash(c)))
317 Self(EscapeIterInner::backslash(c))
327318 }
328319
329320 #[inline]
330321 const fn unicode(c: char) -> Self {
331 Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::unicode(c)))
332 }
333
334 #[inline]
335 fn clear(&mut self) {
336 self.0 = EscapeDebugInner::Bytes(escape::EscapeIterInner::empty());
322 Self(EscapeIterInner::unicode(c))
337323 }
338324}
339325
......@@ -343,13 +329,7 @@ impl Iterator for EscapeDebug {
343329
344330 #[inline]
345331 fn next(&mut self) -> Option<char> {
346 match self.0 {
347 EscapeDebugInner::Bytes(ref mut bytes) => bytes.next().map(char::from),
348 EscapeDebugInner::Char(chr) => {
349 self.clear();
350 Some(chr)
351 }
352 }
332 self.0.next()
353333 }
354334
355335 #[inline]
......@@ -367,10 +347,7 @@ impl Iterator for EscapeDebug {
367347#[stable(feature = "char_escape_debug", since = "1.20.0")]
368348impl ExactSizeIterator for EscapeDebug {
369349 fn len(&self) -> usize {
370 match &self.0 {
371 EscapeDebugInner::Bytes(bytes) => bytes.len(),
372 EscapeDebugInner::Char(_) => 1,
373 }
350 self.0.len()
374351 }
375352}
376353
......@@ -379,11 +356,9 @@ impl FusedIterator for EscapeDebug {}
379356
380357#[stable(feature = "char_escape_debug", since = "1.20.0")]
381358impl fmt::Display for EscapeDebug {
359 #[inline]
382360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 match &self.0 {
384 EscapeDebugInner::Bytes(bytes) => f.write_str(bytes.as_str()),
385 EscapeDebugInner::Char(chr) => f.write_char(*chr),
386 }
361 fmt::Display::fmt(&self.0, f)
387362 }
388363}
389364
......@@ -480,6 +455,7 @@ macro_rules! casemappingiter_impls {
480455
481456 #[stable(feature = "char_struct_display", since = "1.16.0")]
482457 impl fmt::Display for $ITER_NAME {
458 #[inline]
483459 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484460 fmt::Display::fmt(&self.0, f)
485461 }
library/core/src/escape.rs+184-38
......@@ -1,11 +1,16 @@
11//! Helper code for character escaping.
22
33use crate::ascii;
4use crate::fmt::{self, Write};
5use crate::marker::PhantomData;
46use crate::num::NonZero;
57use crate::ops::Range;
68
79const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
810
11/// Escapes a character with `\x` representation.
12///
13/// Returns a buffer with the escaped representation and its corresponding range.
914#[inline]
1015const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) {
1116 const { assert!(N >= 2) };
......@@ -18,6 +23,9 @@ const fn backslash<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u
1823 (output, 0..2)
1924}
2025
26/// Escapes a character with `\xNN` representation.
27///
28/// Returns a buffer with the escaped representation and its corresponding range.
2129#[inline]
2230const fn hex_escape<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) {
2331 const { assert!(N >= 4) };
......@@ -35,6 +43,7 @@ const fn hex_escape<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) {
3543 (output, 0..4)
3644}
3745
46/// Returns a buffer with the verbatim character and its corresponding range.
3847#[inline]
3948const fn verbatim<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8>) {
4049 const { assert!(N >= 1) };
......@@ -48,7 +57,7 @@ const fn verbatim<const N: usize>(a: ascii::Char) -> ([ascii::Char; N], Range<u8
4857
4958/// Escapes an ASCII character.
5059///
51/// Returns a buffer and the length of the escaped representation.
60/// Returns a buffer with the escaped representation and its corresponding range.
5261const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>) {
5362 const { assert!(N >= 4) };
5463
......@@ -122,9 +131,9 @@ const fn escape_ascii<const N: usize>(byte: u8) -> ([ascii::Char; N], Range<u8>)
122131 }
123132}
124133
125/// Escapes a character `\u{NNNN}` representation.
134/// Escapes a character with `\u{NNNN}` representation.
126135///
127/// Returns a buffer and the length of the escaped representation.
136/// Returns a buffer with the escaped representation and its corresponding range.
128137const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], Range<u8>) {
129138 const { assert!(N >= 10 && N < u8::MAX as usize) };
130139
......@@ -149,77 +158,214 @@ const fn escape_unicode<const N: usize>(c: char) -> ([ascii::Char; N], Range<u8>
149158 (output, (start as u8)..(N as u8))
150159}
151160
152/// An iterator over an fixed-size array.
153///
154/// This is essentially equivalent to array’s IntoIter except that indexes are
155/// limited to u8 to reduce size of the structure.
156#[derive(Clone, Debug)]
157pub(crate) struct EscapeIterInner<const N: usize> {
158 // The element type ensures this is always ASCII, and thus also valid UTF-8.
159 data: [ascii::Char; N],
160
161 // Invariant: `alive.start <= alive.end <= N`
161#[derive(Clone, Copy)]
162union MaybeEscapedCharacter<const N: usize> {
163 pub escape_seq: [ascii::Char; N],
164 pub literal: char,
165}
166
167/// Marker type to indicate that the character is always escaped,
168/// used to optimize the iterator implementation.
169#[derive(Clone, Copy)]
170#[non_exhaustive]
171pub(crate) struct AlwaysEscaped;
172
173/// Marker type to indicate that the character may be escaped,
174/// used to optimize the iterator implementation.
175#[derive(Clone, Copy)]
176#[non_exhaustive]
177pub(crate) struct MaybeEscaped;
178
179/// An iterator over a possibly escaped character.
180#[derive(Clone)]
181pub(crate) struct EscapeIterInner<const N: usize, ESCAPING> {
182 // Invariant:
183 //
184 // If `alive.end <= Self::LITERAL_ESCAPE_START`, `data` must contain
185 // printable ASCII characters in the `alive` range of its `escape_seq` variant.
186 //
187 // If `alive.end > Self::LITERAL_ESCAPE_START`, `data` must contain a
188 // `char` in its `literal` variant, and the `alive` range must have a
189 // length of at most `1`.
190 data: MaybeEscapedCharacter<N>,
162191 alive: Range<u8>,
192 escaping: PhantomData<ESCAPING>,
163193}
164194
165impl<const N: usize> EscapeIterInner<N> {
195impl<const N: usize, ESCAPING> EscapeIterInner<N, ESCAPING> {
196 const LITERAL_ESCAPE_START: u8 = 128;
197
198 /// # Safety
199 ///
200 /// `data.escape_seq` must contain an escape sequence in the range given by `alive`.
201 #[inline]
202 const unsafe fn new(data: MaybeEscapedCharacter<N>, alive: Range<u8>) -> Self {
203 // Longer escape sequences are not useful given `alive.end` is at most
204 // `Self::LITERAL_ESCAPE_START`.
205 const { assert!(N < Self::LITERAL_ESCAPE_START as usize) };
206
207 // Check bounds, which implicitly also checks the invariant
208 // `alive.end <= Self::LITERAL_ESCAPE_START`.
209 debug_assert!(alive.end <= (N + 1) as u8);
210
211 Self { data, alive, escaping: PhantomData }
212 }
213
166214 pub(crate) const fn backslash(c: ascii::Char) -> Self {
167 let (data, range) = backslash(c);
168 Self { data, alive: range }
215 let (escape_seq, alive) = backslash(c);
216 // SAFETY: `escape_seq` contains an escape sequence in the range given by `alive`.
217 unsafe { Self::new(MaybeEscapedCharacter { escape_seq }, alive) }
169218 }
170219
171220 pub(crate) const fn ascii(c: u8) -> Self {
172 let (data, range) = escape_ascii(c);
173 Self { data, alive: range }
221 let (escape_seq, alive) = escape_ascii(c);
222 // SAFETY: `escape_seq` contains an escape sequence in the range given by `alive`.
223 unsafe { Self::new(MaybeEscapedCharacter { escape_seq }, alive) }
174224 }
175225
176226 pub(crate) const fn unicode(c: char) -> Self {
177 let (data, range) = escape_unicode(c);
178 Self { data, alive: range }
227 let (escape_seq, alive) = escape_unicode(c);
228 // SAFETY: `escape_seq` contains an escape sequence in the range given by `alive`.
229 unsafe { Self::new(MaybeEscapedCharacter { escape_seq }, alive) }
179230 }
180231
181232 #[inline]
182233 pub(crate) const fn empty() -> Self {
183 Self { data: [ascii::Char::Null; N], alive: 0..0 }
234 // SAFETY: `0..0` ensures an empty escape sequence.
235 unsafe { Self::new(MaybeEscapedCharacter { escape_seq: [ascii::Char::Null; N] }, 0..0) }
184236 }
185237
186238 #[inline]
187 pub(crate) fn as_ascii(&self) -> &[ascii::Char] {
188 // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`.
189 unsafe {
190 self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end))
191 }
239 pub(crate) fn len(&self) -> usize {
240 usize::from(self.alive.end - self.alive.start)
192241 }
193242
194243 #[inline]
195 pub(crate) fn as_str(&self) -> &str {
196 self.as_ascii().as_str()
244 pub(crate) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
245 self.alive.advance_by(n)
197246 }
198247
199248 #[inline]
200 pub(crate) fn len(&self) -> usize {
201 usize::from(self.alive.end - self.alive.start)
249 pub(crate) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
250 self.alive.advance_back_by(n)
251 }
252
253 /// Returns a `char` if `self.data` contains one in its `literal` variant.
254 #[inline]
255 const fn to_char(&self) -> Option<char> {
256 if self.alive.end > Self::LITERAL_ESCAPE_START {
257 // SAFETY: We just checked that `self.data` contains a `char` in
258 // its `literal` variant.
259 return Some(unsafe { self.data.literal });
260 }
261
262 None
202263 }
203264
265 /// Returns the printable ASCII characters in the `escape_seq` variant of `self.data`
266 /// as a string.
267 ///
268 /// # Safety
269 ///
270 /// - `self.data` must contain printable ASCII characters in its `escape_seq` variant.
271 /// - `self.alive` must be a valid range for `self.data.escape_seq`.
272 #[inline]
273 unsafe fn to_str_unchecked(&self) -> &str {
274 debug_assert!(self.alive.end <= Self::LITERAL_ESCAPE_START);
275
276 // SAFETY: The caller guarantees `self.data` contains printable ASCII
277 // characters in its `escape_seq` variant, and `self.alive` is
278 // a valid range for `self.data.escape_seq`.
279 unsafe {
280 self.data
281 .escape_seq
282 .get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end))
283 .as_str()
284 }
285 }
286}
287
288impl<const N: usize> EscapeIterInner<N, AlwaysEscaped> {
204289 pub(crate) fn next(&mut self) -> Option<u8> {
205290 let i = self.alive.next()?;
206291
207 // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
208 unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
292 // SAFETY: The `AlwaysEscaped` marker guarantees that `self.data`
293 // contains printable ASCII characters in its `escape_seq`
294 // variant, and `i` is guaranteed to be a valid index for
295 // `self.data.escape_seq`.
296 unsafe { Some(self.data.escape_seq.get_unchecked(usize::from(i)).to_u8()) }
209297 }
210298
211299 pub(crate) fn next_back(&mut self) -> Option<u8> {
212300 let i = self.alive.next_back()?;
213301
214 // SAFETY: `i` is guaranteed to be a valid index for `self.data`.
215 unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) }
302 // SAFETY: The `AlwaysEscaped` marker guarantees that `self.data`
303 // contains printable ASCII characters in its `escape_seq`
304 // variant, and `i` is guaranteed to be a valid index for
305 // `self.data.escape_seq`.
306 unsafe { Some(self.data.escape_seq.get_unchecked(usize::from(i)).to_u8()) }
216307 }
308}
217309
218 pub(crate) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
219 self.alive.advance_by(n)
310impl<const N: usize> EscapeIterInner<N, MaybeEscaped> {
311 // This is the only way to create any `EscapeIterInner` containing a `char` in
312 // the `literal` variant of its `self.data`, meaning the `AlwaysEscaped` marker
313 // guarantees that `self.data` contains printable ASCII characters in its
314 // `escape_seq` variant.
315 pub(crate) const fn printable(c: char) -> Self {
316 Self {
317 data: MaybeEscapedCharacter { literal: c },
318 // Uphold the invariant `alive.end > Self::LITERAL_ESCAPE_START`, and ensure
319 // `len` behaves correctly for iterating through one character literal.
320 alive: Self::LITERAL_ESCAPE_START..(Self::LITERAL_ESCAPE_START + 1),
321 escaping: PhantomData,
322 }
220323 }
221324
222 pub(crate) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
223 self.alive.advance_back_by(n)
325 pub(crate) fn next(&mut self) -> Option<char> {
326 let i = self.alive.next()?;
327
328 if let Some(c) = self.to_char() {
329 return Some(c);
330 }
331
332 // SAFETY: At this point, `self.data` must contain printable ASCII
333 // characters in its `escape_seq` variant, and `i` is
334 // guaranteed to be a valid index for `self.data.escape_seq`.
335 Some(char::from(unsafe { self.data.escape_seq.get_unchecked(usize::from(i)).to_u8() }))
336 }
337}
338
339impl<const N: usize> fmt::Display for EscapeIterInner<N, AlwaysEscaped> {
340 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
341 // SAFETY: The `AlwaysEscaped` marker guarantees that `self.data`
342 // contains printable ASCII chars, and `self.alive` is
343 // guaranteed to be a valid range for `self.data`.
344 f.write_str(unsafe { self.to_str_unchecked() })
345 }
346}
347
348impl<const N: usize> fmt::Display for EscapeIterInner<N, MaybeEscaped> {
349 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350 if let Some(c) = self.to_char() {
351 return f.write_char(c);
352 }
353
354 // SAFETY: At this point, `self.data` must contain printable ASCII
355 // characters in its `escape_seq` variant, and `self.alive`
356 // is guaranteed to be a valid range for `self.data`.
357 f.write_str(unsafe { self.to_str_unchecked() })
358 }
359}
360
361impl<const N: usize> fmt::Debug for EscapeIterInner<N, AlwaysEscaped> {
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 f.debug_tuple("EscapeIterInner").field(&format_args!("'{}'", self)).finish()
364 }
365}
366
367impl<const N: usize> fmt::Debug for EscapeIterInner<N, MaybeEscaped> {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 f.debug_tuple("EscapeIterInner").field(&format_args!("'{}'", self)).finish()
224370 }
225371}
library/core/src/slice/ascii.rs+1-1
......@@ -308,7 +308,7 @@ impl<'a> fmt::Display for EscapeAscii<'a> {
308308
309309 if let Some(&b) = bytes.first() {
310310 // guaranteed to be non-empty, better to write it as a str
311 f.write_str(ascii::escape_default(b).as_str())?;
311 fmt::Display::fmt(&ascii::escape_default(b), f)?;
312312 bytes = &bytes[1..];
313313 }
314314 }
src/doc/rustc-dev-guide/src/tests/ui.md+2
......@@ -113,6 +113,8 @@ Compiletest makes the following replacements on the compiler output:
113113- The base directory where the test's output goes is replaced with
114114 `$TEST_BUILD_DIR`. This only comes up in a few rare circumstances. Example:
115115 `/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui`
116- The real directory to the standard library source is replaced with `$SRC_DIR_REAL`.
117- The real directory to the compiler source is replaced with `$COMPILER_DIR_REAL`.
116118- Tabs are replaced with `\t`.
117119- Backslashes (`\`) are converted to forward slashes (`/`) within paths (using a
118120 heuristic). This helps normalize differences with Windows-style paths.
src/doc/rustc/src/command-line-arguments.md+3
......@@ -471,6 +471,9 @@ to customize the output:
471471- `future-incompat` - includes a JSON message that contains a report if the
472472 crate contains any code that may fail to compile in the future.
473473
474- `timings` - output a JSON message when a certain compilation "section"
475 (such as frontend analysis, code generation, linking) begins or ends.
476
474477Note that it is invalid to combine the `--json` argument with the
475478[`--color`](#option-color) argument, and it is required to combine `--json`
476479with `--error-format=json`.
src/doc/rustc/src/json.md+29
......@@ -298,6 +298,35 @@ appropriately. (This is needed by Cargo which shares the same dependencies
298298across multiple build targets, so it should only report an unused dependency if
299299its not used by any of the targets.)
300300
301## Timings
302
303**This setting is currently unstable and requires usage of `-Zunstable-options`.**
304
305The `--timings` option will tell `rustc` to emit messages when a certain compilation
306section (such as code generation or linking) begins or ends. The messages currently have
307the following format:
308
309```json
310{
311 "$message_type": "section_timing", /* Type of this message */
312 "event": "start", /* Marks the "start" or "end" of the compilation section */
313 "name": "link", /* The name of the compilation section */
314 // Opaque timestamp when the message was emitted, in microseconds
315 // The timestamp is currently relative to the beginning of the compilation session
316 "time": 12345
317}
318```
319
320Note that the JSON format of the `timings` messages is unstable and subject to change.
321
322Compilation sections can be nested; for example, if you encounter the start of "foo",
323then the start of "bar", then the end of "bar" and then the end of "bar", it means that the
324"bar" section happened as a part of the "foo" section.
325
326The timestamp should only be used for computing the duration of each section.
327
328We currently do not guarantee any specific section names to be emitted.
329
301330[option-emit]: command-line-arguments.md#option-emit
302331[option-error-format]: command-line-arguments.md#option-error-format
303332[option-json]: command-line-arguments.md#option-json
src/doc/unstable-book/src/compiler-flags/hint-mostly-unused.md created+33
......@@ -0,0 +1,33 @@
1# `hint-mostly-unused`
2
3This flag hints to the compiler that most of the crate will probably go unused.
4The compiler can optimize its operation based on this assumption, in order to
5compile faster. This is a hint, and does not guarantee any particular behavior.
6
7This option can substantially speed up compilation if applied to a large
8dependency where the majority of the dependency does not get used. This flag
9may slow down compilation in other cases.
10
11Currently, this option makes the compiler defer as much code generation as
12possible from functions in the crate, until later crates invoke those
13functions. Functions that never get invoked will never have code generated for
14them. For instance, if a crate provides thousands of functions, but only a few
15of them will get called, this flag will result in the compiler only doing code
16generation for the called functions. (This uses the same mechanisms as
17cross-crate inlining of functions.) This does not affect `extern` functions, or
18functions marked as `#[inline(never)]`.
19
20To try applying this flag to one dependency out of a dependency tree, use the
21[`profile-rustflags`](https://doc.rust-lang.org/cargo/reference/unstable.html#profile-rustflags-option)
22feature of nightly cargo:
23
24```toml
25cargo-features = ["profile-rustflags"]
26
27# ...
28[dependencies]
29mostly-unused-dependency = "1.2.3"
30
31[profile.release.package.mostly-unused-dependency]
32rustflags = ["-Zhint-mostly-unused"]
33```
src/tools/compiletest/src/runtest.rs+6
......@@ -2372,6 +2372,12 @@ impl<'test> TestCx<'test> {
23722372 rust_src_dir.read_link_utf8().unwrap_or_else(|_| rust_src_dir.to_path_buf());
23732373 normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");
23742374
2375 // Real paths into the compiler
2376 let rustc_src_dir = &self.config.sysroot_base.join("lib/rustlib/rustc-src/rust");
2377 rustc_src_dir.try_exists().expect(&*format!("{} should exists", rustc_src_dir));
2378 let rustc_src_dir = rustc_src_dir.read_link_utf8().unwrap_or(rustc_src_dir.to_path_buf());
2379 normalize_path(&rustc_src_dir.join("compiler"), "$COMPILER_DIR_REAL");
2380
23752381 // eg.
23762382 // /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui/<test_dir>/$name.$revision.$mode/
23772383 normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR");
tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.rs created+26
......@@ -0,0 +1,26 @@
1//@ compile-flags: -Z unstable-options
2//@ ignore-stage1
3
4#![feature(rustc_private)]
5#![deny(rustc::direct_use_of_rustc_type_ir)]
6
7extern crate rustc_middle;
8extern crate rustc_type_ir;
9
10use rustc_middle::ty::*; // OK, we have to accept rustc_middle::ty::*
11
12// We have to deny direct import of type_ir
13use rustc_type_ir::*;
14//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals
15
16// We have to deny direct types usages which resolves to type_ir
17fn foo<I: rustc_type_ir::Interner>(cx: I, did: I::DefId) {
18//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals
19}
20
21fn main() {
22 let _ = rustc_type_ir::InferConst::Fresh(42);
23//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals
24 let _: rustc_type_ir::InferConst;
25//~^ ERROR: do not use `rustc_type_ir` unless you are implementing type system internals
26}
tests/ui-fulldeps/internal-lints/direct-use-of-rustc-type-ir.stderr created+39
......@@ -0,0 +1,39 @@
1error: do not use `rustc_type_ir` unless you are implementing type system internals
2 --> $DIR/direct-use-of-rustc-type-ir.rs:13:5
3 |
4LL | use rustc_type_ir::*;
5 | ^^^^^^^^^^^^^
6 |
7 = note: use `rustc_middle::ty` instead
8note: the lint level is defined here
9 --> $DIR/direct-use-of-rustc-type-ir.rs:5:9
10 |
11LL | #![deny(rustc::direct_use_of_rustc_type_ir)]
12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13
14error: do not use `rustc_type_ir` unless you are implementing type system internals
15 --> $DIR/direct-use-of-rustc-type-ir.rs:17:11
16 |
17LL | fn foo<I: rustc_type_ir::Interner>(cx: I, did: I::DefId) {
18 | ^^^^^^^^^^^^^
19 |
20 = note: use `rustc_middle::ty` instead
21
22error: do not use `rustc_type_ir` unless you are implementing type system internals
23 --> $DIR/direct-use-of-rustc-type-ir.rs:22:13
24 |
25LL | let _ = rustc_type_ir::InferConst::Fresh(42);
26 | ^^^^^^^^^^^^^
27 |
28 = note: use `rustc_middle::ty` instead
29
30error: do not use `rustc_type_ir` unless you are implementing type system internals
31 --> $DIR/direct-use-of-rustc-type-ir.rs:24:12
32 |
33LL | let _: rustc_type_ir::InferConst;
34 | ^^^^^^^^^^^^^
35 |
36 = note: use `rustc_middle::ty` instead
37
38error: aborting due to 4 previous errors
39
tests/ui-fulldeps/rustc-dev-remap.only-remap.stderr created+15
......@@ -0,0 +1,15 @@
1error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisfied
2 --> $DIR/rustc-dev-remap.rs:LL:COL
3 |
4LL | type Result = NotAValidResultType;
5 | ^^^^^^^^^^^^^^^^^^^ the trait `VisitorResult` is not implemented for `NotAValidResultType`
6 |
7 = help: the following other types implement trait `VisitorResult`:
8 ()
9 ControlFlow<T>
10note: required by a bound in `rustc_ast::visit::Visitor::Result`
11 --> /rustc-dev/xyz/compiler/rustc_ast/src/visit.rs:LL:COL
12
13error: aborting due to 1 previous error
14
15For more information about this error, try `rustc --explain E0277`.
tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr created+18
......@@ -0,0 +1,18 @@
1error[E0277]: the trait bound `NotAValidResultType: VisitorResult` is not satisfied
2 --> $DIR/rustc-dev-remap.rs:LL:COL
3 |
4LL | type Result = NotAValidResultType;
5 | ^^^^^^^^^^^^^^^^^^^ the trait `VisitorResult` is not implemented for `NotAValidResultType`
6 |
7 = help: the following other types implement trait `VisitorResult`:
8 ()
9 ControlFlow<T>
10note: required by a bound in `rustc_ast::visit::Visitor::Result`
11 --> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL
12 |
13LL | type Result: VisitorResult = ();
14 | ^^^^^^^^^^^^^ required by this bound in `Visitor::Result`
15
16error: aborting due to 1 previous error
17
18For more information about this error, try `rustc --explain E0277`.
tests/ui-fulldeps/rustc-dev-remap.rs created+30
......@@ -0,0 +1,30 @@
1//@ check-fail
2//
3//@ ignore-stage1
4//@ ignore-cross-compile
5//@ ignore-remote
6//
7//@ revisions: only-remap remap-unremap
8//@ compile-flags: -Z simulate-remapped-rust-src-base=/rustc-dev/xyz
9//@ [remap-unremap]compile-flags: -Ztranslate-remapped-path-to-local-path=yes
10
11// The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically
12// as the remapped revision will begin with $COMPILER_DIR_REAL,
13// so we have to do it ourselves.
14//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:COL"
15
16#![feature(rustc_private)]
17
18extern crate rustc_ast;
19
20use rustc_ast::visit::Visitor;
21
22struct MyStruct;
23struct NotAValidResultType;
24
25impl Visitor<'_> for MyStruct {
26 type Result = NotAValidResultType;
27 //~^ ERROR the trait bound `NotAValidResultType: VisitorResult` is not satisfied
28}
29
30fn main() {}