diff --git a/Cargo.lock b/Cargo.lock index d83bdf767e5c1..d2dba92b7d8fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3767,6 +3767,7 @@ dependencies = [ name = "rustc_driver_impl" version = "0.0.0" dependencies = [ + "anstyle", "ctrlc", "jiff", "libc", @@ -3792,6 +3793,7 @@ dependencies = [ "rustc_index", "rustc_infer", "rustc_interface", + "rustc_lexer", "rustc_lint", "rustc_log", "rustc_macros", diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 453e7443d3247..f82513094aa1f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -625,12 +625,12 @@ impl TokenKind { } impl Token { - pub fn new(kind: TokenKind, span: Span) -> Self { + pub const fn new(kind: TokenKind, span: Span) -> Self { Token { kind, span } } /// Some token that will be thrown away later. - pub fn dummy() -> Self { + pub const fn dummy() -> Self { Token::new(TokenKind::Question, DUMMY_SP) } diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index 6752218fa0d4b..9acdd672178a1 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -29,7 +29,6 @@ pub(crate) fn extern_abi_enabled( }) } -#[allow(rustc::untranslatable_diagnostic)] pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) { match extern_abi_enabled(features, span, abi) { Ok(_) => (), diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 028a5048d5438..dd0e27948bec6 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -13,15 +13,11 @@ use crate::errors; macro_rules! gate { ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit(); } }}; ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{ if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) { - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit(); } }}; @@ -31,13 +27,11 @@ macro_rules! gate { macro_rules! gate_alt { ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{ if !$has_feature && !$span.allows_unstable($name) { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(&$visitor.sess, $name, $span, $explain).emit(); } }}; ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr, $notes: expr) => {{ if !$has_feature && !$span.allows_unstable($name) { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable let mut diag = feature_err(&$visitor.sess, $name, $span, $explain); for note in $notes { diag.note(*note); @@ -491,7 +485,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) { - #[allow(rustc::untranslatable_diagnostic)] // Emit yield_expr as the error, since that will be sufficient. You can think of it // as coroutines and gen_blocks imply yield_expr. feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental") @@ -523,7 +516,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { if !visitor.features.min_generic_const_args() && !span.allows_unstable(sym::min_generic_const_args) { - #[allow(rustc::untranslatable_diagnostic)] feature_err( &visitor.sess, sym::min_generic_const_args, @@ -559,7 +551,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { if let Ok(snippet) = sm.span_to_snippet(span) && snippet == "!" { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") .emit(); } else { diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 89c2d621e0793..a9b2a4c96c334 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -412,7 +412,6 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Feat } } -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) { let (cfg, feature, has_feature) = gated_cfg; if !has_feature(features) && !cfg_span.allows_unstable(*feature) { diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 2a04b55f469e4..ce3d116dce3ba 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -141,8 +141,6 @@ impl CombineAttributeParser for LinkParser { macro report_unstable_modifier($feature: ident) { if !features.$feature() { - // FIXME: make this translatable - #[expect(rustc::untranslatable_diagnostic)] feature_err( sess, sym::$feature, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 51792b7aff72c..365cd55bdc38b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -164,21 +164,6 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { } } -pub(crate) struct RustcLintDiagnosticsParser; - -impl NoArgsAttributeParser for RustcLintDiagnosticsParser { - const PATH: &[Symbol] = &[sym::rustc_lint_diagnostics]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ - Allow(Target::Fn), - Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Method(MethodKind::Trait { body: false })), - Allow(Target::Method(MethodKind::Trait { body: true })), - Allow(Target::Method(MethodKind::TraitImpl)), - ]); - const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintDiagnostics; -} - pub(crate) struct RustcLintOptDenyFieldAccessParser; impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 7db84f8f2d957..5b8b3cd151eb9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -4,9 +4,6 @@ use super::prelude::*; pub(crate) struct TransparencyParser; -// FIXME(jdonszelmann): make these proper diagnostics -#[allow(rustc::untranslatable_diagnostic)] -#[allow(rustc::diagnostic_outside_of_impl)] impl SingleAttributeParser for TransparencyParser { const PATH: &[Symbol] = &[sym::rustc_macro_transparency]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0c882fee01c8a..6aae2b90a5045 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -75,11 +75,11 @@ use crate::attributes::rustc_dump::{ use crate::attributes::rustc_internal::{ RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, - RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, - RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, - RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser, - RustcNoImplicitAutorefsParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser, - RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, + RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, + RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser, + RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser, + RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, + RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ @@ -289,7 +289,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 303fa469332e0..4644c210137fe 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -253,19 +253,52 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { } let region = region.as_var(); - - let borrow = BorrowData { + let borrow = |activation_location| BorrowData { kind, region, reserve_location: location, - activation_location: TwoPhaseActivation::NotTwoPhase, + activation_location, borrowed_place, assigned_place: *assigned_place, }; - let (idx, _) = self.location_map.insert_full(location, borrow); - let idx = BorrowIndex::from(idx); - self.insert_as_pending_if_two_phase(location, assigned_place, kind, idx); + let idx = if !kind.is_two_phase_borrow() { + debug!(" -> {:?}", location); + let (idx, _) = self + .location_map + .insert_full(location, borrow(TwoPhaseActivation::NotTwoPhase)); + BorrowIndex::from(idx) + } else { + // When we encounter a 2-phase borrow statement, it will always + // be assigning into a temporary TEMP: + // + // TEMP = &foo + // + // so extract `temp`. + let Some(temp) = assigned_place.as_local() else { + span_bug!( + self.body.source_info(location).span, + "expected 2-phase borrow to assign to a local, not `{:?}`", + assigned_place, + ); + }; + + // Consider the borrow not activated to start. When we find an activation, we'll update + // this field. + let (idx, _) = self + .location_map + .insert_full(location, borrow(TwoPhaseActivation::NotActivated)); + let idx = BorrowIndex::from(idx); + + // Insert `temp` into the list of pending activations. From + // now on, we'll be on the lookout for a use of it. Note that + // we are guaranteed that this use will come after the + // assignment. + let prev = self.pending_activations.insert(temp, idx); + assert_eq!(prev, None, "temporary associated with multiple two phase borrows"); + + idx + }; self.local_map.entry(borrowed_place.local).or_default().insert(idx); } @@ -334,62 +367,3 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> { self.super_rvalue(rvalue, location) } } - -impl<'a, 'tcx> GatherBorrows<'a, 'tcx> { - /// If this is a two-phase borrow, then we will record it - /// as "pending" until we find the activating use. - fn insert_as_pending_if_two_phase( - &mut self, - start_location: Location, - assigned_place: &mir::Place<'tcx>, - kind: mir::BorrowKind, - borrow_index: BorrowIndex, - ) { - debug!( - "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?})", - start_location, assigned_place, borrow_index, - ); - - if !kind.allows_two_phase_borrow() { - debug!(" -> {:?}", start_location); - return; - } - - // When we encounter a 2-phase borrow statement, it will always - // be assigning into a temporary TEMP: - // - // TEMP = &foo - // - // so extract `temp`. - let Some(temp) = assigned_place.as_local() else { - span_bug!( - self.body.source_info(start_location).span, - "expected 2-phase borrow to assign to a local, not `{:?}`", - assigned_place, - ); - }; - - // Consider the borrow not activated to start. When we find an activation, we'll update - // this field. - { - let borrow_data = &mut self.location_map[borrow_index.as_usize()]; - borrow_data.activation_location = TwoPhaseActivation::NotActivated; - } - - // Insert `temp` into the list of pending activations. From - // now on, we'll be on the lookout for a use of it. Note that - // we are guaranteed that this use will come after the - // assignment. - let old_value = self.pending_activations.insert(temp, borrow_index); - if let Some(old_index) = old_value { - span_bug!( - self.body.source_info(start_location).span, - "found already pending activation for temp: {:?} \ - at borrow_index: {:?} with associated data {:?}", - temp, - old_index, - self.location_map[old_index.as_usize()] - ); - } - } -} diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 7c9011505d64c..0d3c554e41765 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, struct_span_code_err}; use rustc_hir as hir; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5cfe9db009bff..caf6a86af098a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,8 +1,5 @@ // ignore-tidy-filelength -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::iter; use std::ops::ControlFlow; diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 8f643d8f460f2..bbd0a8ae07108 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -1,8 +1,5 @@ //! Print diagnostics to explain why values are borrowed. -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use rustc_data_structures::assert_matches; use rustc_errors::{Applicability, Diag, EmissionGuarantee}; use rustc_hir as hir; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index e725b13434a1f..c15e7041c94d3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -162,8 +162,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } for (_, (mut diag, count)) in std::mem::take(&mut self.diags_buffer.buffered_mut_errors) { if count > 10 { - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } self.buffer_error(diag); @@ -236,7 +234,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// LL | for (key, value) in dict { /// | ^^^^ /// ``` - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME pub(super) fn add_moved_or_invoked_closure_note( &self, location: Location, @@ -820,7 +817,6 @@ impl UseSpans<'_> { } /// Add a span label to the arguments of the closure, if it exists. - #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn args_subdiag(self, err: &mut Diag<'_>, f: impl FnOnce(Span) -> CaptureArgLabel) { if let UseSpans::ClosureUse { args_span, .. } = self { err.subdiagnostic(f(args_span)); @@ -829,7 +825,6 @@ impl UseSpans<'_> { /// Add a span label to the use of the captured variable, if it exists. /// only adds label to the `path_span` - #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn var_path_only_subdiag( self, err: &mut Diag<'_>, @@ -861,7 +856,6 @@ impl UseSpans<'_> { } /// Add a subdiagnostic to the use of the captured variable, if it exists. - #[allow(rustc::diagnostic_outside_of_impl)] pub(super) fn var_subdiag( self, err: &mut Diag<'_>, @@ -1225,8 +1219,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.borrow_spans(span, borrow.reserve_location) } - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn explain_captures( &mut self, err: &mut Diag<'infcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3322c590a6cee..f83931d375996 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index e9039d4311b66..4fb739403cede 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use core::ops::ControlFlow; use either::Either; diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs index 9991362641847..62ba4d172a3f4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::ops::ControlFlow; use either::Either; diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index bd0cf3578c2bb..b1e16717466b5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -1,9 +1,6 @@ //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::collections::BTreeMap; use rustc_data_structures::fx::FxIndexSet; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 9c2b9139367a9..17f1988a17c40 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -196,7 +196,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // For generic associated types (GATs) which implied 'static requirement // from higher-ranked trait bounds (HRTB). Try to locate span of the trait // and the span which bounded to the trait for adding 'static lifetime suggestion - #[allow(rustc::diagnostic_outside_of_impl)] fn suggest_static_lifetime_for_gat_from_hrtb( &self, diag: &mut Diag<'_>, @@ -421,9 +420,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`. - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] pub(crate) fn report_region_error( &mut self, fr: RegionVid, @@ -577,7 +573,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// executing... /// = note: ...therefore, returned references to captured variables will escape the closure /// ``` - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME fn report_fnmut_error( &self, errci: &ErrorConstraintInfo<'tcx>, @@ -686,18 +681,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from); if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span { - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] diag.span_label( outlived_fr_span, format!("`{outlived_fr_name}` declared here, outside of the {escapes_from} body",), ); } - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] if let Some((Some(fr_name), fr_span)) = fr_name_and_span { diag.span_label( fr_span, @@ -732,9 +721,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); outlived_fr_region_name.highlight_region_name(&mut diag); - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] diag.span_label( *span, format!( @@ -766,7 +752,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it /// | is returning data with lifetime `'b` /// ``` - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> { let ErrorConstraintInfo { fr, outlived_fr, span, category, .. } = errci; @@ -824,8 +809,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// LL | fn iter_values_anon(&self) -> impl Iterator + 'a { /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// ``` - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn add_static_impl_trait_suggestion( &self, diag: &mut Diag<'_>, @@ -966,7 +949,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty); } - #[allow(rustc::diagnostic_outside_of_impl)] #[instrument(skip(self, err), level = "debug")] fn suggest_constrain_dyn_trait_in_impl( &self, @@ -1032,7 +1014,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); } - #[allow(rustc::diagnostic_outside_of_impl)] /// When encountering a lifetime error caused by the return type of a closure, check the /// corresponding trait bound and see if dereferencing the closure return value would satisfy /// them. If so, we produce a structured suggestion. @@ -1160,7 +1141,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - #[allow(rustc::diagnostic_outside_of_impl)] fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) { let body = self.infcx.tcx.hir_body_owned_by(self.mir_def_id()); let expr = &body.value.peel_blocks(); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 517f9e88cd9bd..fba0879e81337 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,6 +1,3 @@ -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::fmt::{self, Display}; use std::iter; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 91defbad0a0e0..4a059481c326b 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1301,7 +1301,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. if !is_active(this.dominators(), borrow, location) { - assert!(borrow.kind.allows_two_phase_borrow()); + assert!(borrow.kind.is_two_phase_borrow()); return ControlFlow::Continue(()); } @@ -1464,7 +1464,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { } BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); - if bk.allows_two_phase_borrow() { + if bk.is_two_phase_borrow() { (Deep, Reservation(wk)) } else { (Deep, Write(wk)) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5537d90e297aa..64e3b59acfff9 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -287,8 +287,6 @@ pub(crate) fn emit_nll_mir<'tcx>( Ok(()) } -#[allow(rustc::diagnostic_outside_of_impl)] -#[allow(rustc::untranslatable_diagnostic)] pub(super) fn dump_annotation<'tcx, 'infcx>( infcx: &'infcx BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index d2eae2c7e65a6..99567da92ffe7 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { } BorrowKind::Mut { .. } => { let wk = WriteKind::MutableBorrow(bk); - if bk.allows_two_phase_borrow() { + if bk.is_two_phase_borrow() { (Deep, Reservation(wk)) } else { (Deep, Write(wk)) @@ -384,7 +384,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { // Reading from mere reservations of mutable-borrows is OK. if !is_active(this.dominators, borrow, location) { // If the borrow isn't active yet, reads don't invalidate it - assert!(borrow.kind.allows_two_phase_borrow()); + assert!(borrow.kind.is_two_phase_borrow()); return ControlFlow::Continue(()); } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 279625cb87c9c..c4d964441b1d2 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -229,8 +229,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // not ready to process them yet. // - Then compute the implied bounds. This will adjust // the `region_bound_pairs` and so forth. - // - After this is done, we'll process the constraints, once - // the `relations` is built. + // - After this is done, we'll register the constraints in + // the `BorrowckInferCtxt`. Checking these constraints is + // handled later by actual borrow checking. let mut normalized_inputs_and_output = Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1); for ty in unnormalized_input_output_tys { @@ -254,6 +255,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { constraints.push(c) } + // Currently `implied_outlives_bounds` will normalize the provided + // `Ty`, despite this it's still important to normalize the ty ourselves + // as normalization may introduce new region variables (#136547). + // + // If we do not add implied bounds for the type involving these new + // region variables then we'll wind up with the normalized form of + // the signature having not-wf types due to unsatisfied region + // constraints. + // // Note: we need this in examples like // ``` // trait Foo { @@ -262,7 +272,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // } // impl Foo for () { // type Bar = (); - // fn foo(&self) ->&() {} + // fn foo(&self) -> &() {} // } // ``` // Both &Self::Bar and &() are WF @@ -277,6 +287,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } // Add implied bounds from impl header. + // + // We don't use `assumed_wf_types` to source the entire set of implied bounds for + // a few reasons: + // - `DefiningTy` for closure has the `&'env Self` type while `assumed_wf_types` doesn't + // - We compute implied bounds from the unnormalized types in the `DefiningTy` but do not + // do so for types in impl headers + // - We must compute the normalized signature and then compute implied bounds from that + // in order to connect any unconstrained region vars created during normalization to + // the types of the locals corresponding to the inputs and outputs of the item. (#136547) if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) { for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) { let result: Result<_, ErrorGuaranteed> = param_env @@ -352,10 +371,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { known_type_outlives_obligations.push(outlives); } - /// Update the type of a single local, which should represent - /// either the return type of the MIR or one of its arguments. At - /// the same time, compute and add any implied bounds that come - /// from this local. + /// Compute and add any implied bounds that come from a given type. #[instrument(level = "debug", skip(self))] fn add_implied_bounds( &mut self, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fda4719fc3f5e..aeba5ee70cf17 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -11,9 +11,6 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] - use std::cell::Cell; use std::iter; @@ -207,10 +204,10 @@ struct UniversalRegionIndices<'tcx> { /// `ty::Region` to the internal `RegionVid` we are using. This is /// used because trait matching and type-checking will feed us /// region constraints that reference those regions and we need to - /// be able to map them to our internal `RegionVid`. This is - /// basically equivalent to an `GenericArgs`, except that it also - /// contains an entry for `ReStatic` -- it might be nice to just - /// use an args, and then handle `ReStatic` another way. + /// be able to map them to our internal `RegionVid`. + /// + /// This is similar to just using `GenericArgs`, except that it contains + /// an entry for `'static`, and also late bound parameters in scope. indices: FxIndexMap, RegionVid>, /// The vid assigned to `'static`. Used only for diagnostics. diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index df64d8f314dba..e2109caf2e59d 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -19,8 +19,6 @@ pub(crate) fn expand_compile_error<'cx>( Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; - #[expect(rustc::diagnostic_outside_of_impl, reason = "diagnostic message is specified by user")] - #[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")] let guar = cx.dcx().span_err(sp, var.to_string()); cx.resolver.mark_scope_with_compile_error(cx.current_expansion.lint_node_id); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index a9ce41c9be76e..0aaa8cf558c43 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -503,10 +503,6 @@ pub(crate) struct EnvNotDefinedWithUserMessage { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - #[expect( - rustc::untranslatable_diagnostic, - reason = "cannot translate user-provided messages" - )] let mut diag = Diag::new(dcx, level, self.msg_from_user.to_string()); diag.span(self.span); diag diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index e1c5a4f85c1ba..120e3f849ff63 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -3,8 +3,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index e26f31dce67bd..9ac3d0e7eac12 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -78,8 +78,6 @@ type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), Err /// The returned bool indicates whether an applicable suggestion has already been /// added to the diagnostic to avoid emitting multiple suggestions. `Err(Err(ErrorGuaranteed))` /// indicates that an ast error was encountered. -// FIXME(Nilstrieb) Make this function setup translatable -#[allow(rustc::untranslatable_diagnostic)] pub(crate) fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: Box, diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 5fdecd014ac05..7361a6af41784 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -1,6 +1,4 @@ // tidy-alphabetical-start -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] // Note: please avoid adding other feature gates where possible #![feature(rustc_private)] // Only used to define intrinsics in `compiler_builtins.rs`. diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 8c39d04ef21dd..3ffc16d49ac15 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -1,6 +1,4 @@ // tidy-alphabetical-start -#![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(file_buffered)] diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index f606158e40180..a9366bf29fbef 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -125,9 +125,6 @@ pub(crate) struct FnCallNonConst<'tcx> { } impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { - // FIXME: make this translatable - #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { let tcx = ccx.tcx; let caller = ccx.def_id(); diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index b68c73a46425e..e6092fc3787c6 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -1,7 +1,6 @@ use rustc_abi::FieldIdx; use rustc_ast::Mutability; use rustc_hir::LangItem; -use rustc_middle::mir::interpret::{CtfeProvenance, Scalar}; use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Const, ScalarInt, Ty}; @@ -9,7 +8,8 @@ use rustc_span::{Symbol, sym}; use crate::const_eval::CompileTimeMachine; use crate::interpret::{ - Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Writeable, interp_ok, + CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable, + interp_ok, }; impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { @@ -112,11 +112,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } + ty::RawPtr(ty, mutability) => { + let (variant, variant_place) = downcast(sym::Pointer)?; + let pointer_place = + self.project_field(&variant_place, FieldIdx::ZERO)?; + + self.write_pointer_type_info(pointer_place, *ty, *mutability)?; + + variant + } ty::Adt(_, _) | ty::Foreign(_) | ty::Pat(_, _) | ty::Slice(_) - | ty::RawPtr(..) | ty::FnDef(..) | ty::FnPtr(..) | ty::UnsafeBinder(..) @@ -312,4 +320,30 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { } interp_ok(()) } + + pub(crate) fn write_pointer_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + ty: Ty<'tcx>, + mutability: Mutability, + ) -> InterpResult<'tcx> { + // Iterate over all fields of `type_info::Pointer`. + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + // Write the `TypeId` of the pointer's inner type to the `ty` field. + sym::pointee => self.write_type_id(ty, &field_place)?, + // Write the boolean representing the pointer's mutability to the `mutable` field. + sym::mutable => { + self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index aeadf0257ea8a..b72a50a0bfce6 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -232,7 +232,6 @@ pub fn format_interp_error<'tcx>(dcx: DiagCtxtHandle<'_>, e: InterpErrorInfo<'tc backtrace.print_backtrace(); // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the // label and arguments from the InterpError. - #[allow(rustc::untranslatable_diagnostic)] let mut diag = dcx.struct_allow(""); let msg = e.diagnostic_message(); e.add_args(&mut diag); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 051c6c3445063..4aa9030cfe61c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -218,7 +218,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // A fresh reference was created, make sure it gets retagged. let val = M::retag_ptr_value( self, - if borrow_kind.allows_two_phase_borrow() { + if borrow_kind.is_two_phase_borrow() { mir::RetagKind::TwoPhase } else { mir::RetagKind::Default diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 9b1d4652212b6..1266e15c682fd 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![allow(rustc::diagnostic_outside_of_impl)] #![feature(array_try_map)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 531b9e0c8ff72..c160240a18a77 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +anstyle = "1.0.13" jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } @@ -28,6 +29,7 @@ rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_interface = { path = "../rustc_interface" } +rustc_lexer = { path = "../rustc_lexer" } rustc_lint = { path = "../rustc_lint" } rustc_log = { path = "../rustc_log" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index b0970144c421e..d8d55ce141257 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -97,7 +97,6 @@ impl Expander { /// **Note:** This function doesn't interpret argument 0 in any special way. /// If this function is intended to be used with command line arguments, /// `argv[0]` must be removed prior to calling it manually. -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec { let mut expander = Expander::default(); let mut result = Ok(()); diff --git a/compiler/rustc_driver_impl/src/highlighter.rs b/compiler/rustc_driver_impl/src/highlighter.rs new file mode 100644 index 0000000000000..70b73cc29b723 --- /dev/null +++ b/compiler/rustc_driver_impl/src/highlighter.rs @@ -0,0 +1,159 @@ +//! This module provides a syntax highlighter for Rust code. +//! It is used by the `rustc --explain` command. +//! +//! The syntax highlighter uses `rustc_lexer`'s `tokenize` +//! function to parse the Rust code into a `Vec` of tokens. +//! The highlighter then highlights the tokens in the `Vec`, +//! and writes the highlighted output to the buffer. +use std::io::{self, Write}; + +use anstyle::{AnsiColor, Color, Effects, Style}; +use rustc_lexer::{LiteralKind, strip_shebang, tokenize}; + +const PRIMITIVE_TYPES: &'static [&str] = &[ + "i8", "i16", "i32", "i64", "i128", "isize", // signed integers + "u8", "u16", "u32", "u64", "u128", "usize", // unsigned integers + "f32", "f64", // floating point + "char", "bool", // others +]; + +const KEYWORDS: &'static [&str] = &[ + "static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while", "as", + "async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern", + "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", + "ref", +]; + +const STR_LITERAL_COLOR: AnsiColor = AnsiColor::Green; +const OTHER_LITERAL_COLOR: AnsiColor = AnsiColor::BrightRed; +const DERIVE_COLOR: AnsiColor = AnsiColor::BrightRed; +const KEYWORD_COLOR: AnsiColor = AnsiColor::BrightMagenta; +const TYPE_COLOR: AnsiColor = AnsiColor::Yellow; +const FUNCTION_COLOR: AnsiColor = AnsiColor::Blue; +const USE_COLOR: AnsiColor = AnsiColor::BrightMagenta; +const PRIMITIVE_TYPE_COLOR: AnsiColor = AnsiColor::Cyan; + +/// Highlight a Rust code string and write the highlighted +/// output to the buffer. It serves as a wrapper around +/// `Highlighter::highlight_rustc_lexer`. It is passed to +/// `write_anstream_buf` in the `lib.rs` file. +pub fn highlight(code: &str, buf: &mut Vec) -> io::Result<()> { + let mut highlighter = Highlighter::default(); + highlighter.highlight_rustc_lexer(code, buf) +} + +/// A syntax highlighter for Rust code +/// It is used by the `rustc --explain` command. +#[derive(Default)] +pub struct Highlighter { + /// Used to track if the previous token was a token + /// that warrants the next token to be colored differently + /// + /// For example, the keyword `fn` requires the next token + /// (the function name) to be colored differently. + prev_was_special: bool, + /// Used to track the length of tokens that have been + /// written so far. This is used to find the original + /// lexeme for a token from the code string. + len_accum: usize, +} + +impl Highlighter { + /// Create a new highlighter + pub fn new() -> Self { + Self::default() + } + + /// Highlight a Rust code string and write the highlighted + /// output to the buffer. + pub fn highlight_rustc_lexer(&mut self, code: &str, buf: &mut Vec) -> io::Result<()> { + use rustc_lexer::TokenKind; + + // Remove shebang from code string + let stripped_idx = strip_shebang(code).unwrap_or(0); + let stripped_code = &code[stripped_idx..]; + self.len_accum = stripped_idx; + let len_accum = &mut self.len_accum; + let tokens = tokenize(stripped_code, rustc_lexer::FrontmatterAllowed::No); + for token in tokens { + let len = token.len as usize; + // If the previous token was a special token, and this token is + // not a whitespace token, then it should be colored differently + let token_str = &code[*len_accum..*len_accum + len]; + if self.prev_was_special { + if token_str != " " { + self.prev_was_special = false; + } + let style = Style::new().fg_color(Some(Color::Ansi(AnsiColor::Blue))); + write!(buf, "{style}{token_str}{style:#}")?; + *len_accum += len; + continue; + } + match token.kind { + TokenKind::Ident => { + let mut style = Style::new(); + // Match if an identifier is a (well-known) keyword + if KEYWORDS.contains(&token_str) { + if token_str == "fn" { + self.prev_was_special = true; + } + style = style.fg_color(Some(Color::Ansi(KEYWORD_COLOR))); + } + // The `use` keyword is colored differently + if matches!(token_str, "use") { + style = style.fg_color(Some(Color::Ansi(USE_COLOR))); + } + // This heuristic test is to detect if the identifier is + // a function call. If it is, then the function identifier is + // colored differently. + if code[*len_accum..*len_accum + len + 1].ends_with('(') { + style = style.fg_color(Some(Color::Ansi(FUNCTION_COLOR))); + } + // The `derive` keyword is colored differently. + if token_str == "derive" { + style = style.fg_color(Some(Color::Ansi(DERIVE_COLOR))); + } + // This heuristic test is to detect if the identifier is + // a type. If it is, then the identifier is colored differently. + if matches!(token_str.chars().next().map(|c| c.is_uppercase()), Some(true)) { + style = style.fg_color(Some(Color::Ansi(TYPE_COLOR))); + } + // This if statement is to detect if the identifier is a primitive type. + if PRIMITIVE_TYPES.contains(&token_str) { + style = style.fg_color(Some(Color::Ansi(PRIMITIVE_TYPE_COLOR))); + } + write!(buf, "{style}{token_str}{style:#}")?; + } + + // Color literals + TokenKind::Literal { kind, suffix_start: _ } => { + // Strings -> Green + // Chars -> Green + // Raw strings -> Green + // C strings -> Green + // Byte Strings -> Green + // Other literals -> Bright Red (Orage-esque) + let style = match kind { + LiteralKind::Str { terminated: _ } + | LiteralKind::Char { terminated: _ } + | LiteralKind::RawStr { n_hashes: _ } + | LiteralKind::CStr { terminated: _ } => { + Style::new().fg_color(Some(Color::Ansi(STR_LITERAL_COLOR))) + } + _ => Style::new().fg_color(Some(Color::Ansi(OTHER_LITERAL_COLOR))), + }; + write!(buf, "{style}{token_str}{style:#}")?; + } + _ => { + // All other tokens are dimmed + let style = Style::new() + .fg_color(Some(Color::Ansi(AnsiColor::BrightWhite))) + .effects(Effects::DIMMED); + write!(buf, "{style}{token_str}{style:#}")?; + } + } + *len_accum += len; + } + Ok(()) + } +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 021802040d3b9..f425c26ba706f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #![feature(decl_macro)] #![feature(panic_backtrace_config)] #![feature(panic_update_hook)] @@ -86,6 +85,7 @@ pub mod args; pub mod pretty; #[macro_use] mod print; +pub mod highlighter; mod session_diagnostics; // Keep the OS parts of this `cfg` in sync with the `cfg` on the `libc` @@ -303,7 +303,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) } if !has_input { - #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("no input filename given"); // this is fatal } @@ -528,7 +527,11 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { let mdstream = markdown::MdStream::parse_str(content); let bufwtr = markdown::create_stdout_bufwtr(); let mut mdbuf = Vec::new(); - if mdstream.write_anstream_buf(&mut mdbuf).is_ok() { Some((bufwtr, mdbuf)) } else { None } + if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() { + Some((bufwtr, mdbuf)) + } else { + None + } }; // Try to print via the pager, pretty output if possible. @@ -615,7 +618,6 @@ fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) { safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { - #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("cannot list metadata for stdin"); } } @@ -842,7 +844,6 @@ fn print_crate_info( sess.apple_deployment_target().fmt_pretty(), ) } else { - #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info") } } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 085403c8ef36b..c0737edd7d65f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -244,13 +244,6 @@ type FluentId = Cow<'static, str>; pub enum SubdiagMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), - /// Translatable message which has already been translated eagerly. - /// - /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would - /// be instantiated multiple times with different values. These subdiagnostics' messages - /// are translated when they are added to the parent diagnostic, producing this variant of - /// `DiagMessage`. - Translated(Cow<'static, str>), /// Identifier of a Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. FluentIdentifier(FluentId), @@ -285,15 +278,13 @@ impl From> for SubdiagMessage { #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] #[rustc_diagnostic_item = "DiagMessage"] pub enum DiagMessage { - /// Non-translatable diagnostic message. - Str(Cow<'static, str>), - /// Translatable message which has been already translated. + /// Non-translatable diagnostic message or a message that has been translated eagerly. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would /// be instantiated multiple times with different values. These subdiagnostics' messages - /// are translated when they are added to the parent diagnostic, producing this variant of - /// `DiagMessage`. - Translated(Cow<'static, str>), + /// are translated when they are added to the parent diagnostic. This is one of the ways + /// this variant of `DiagMessage` is produced. + Str(Cow<'static, str>), /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic /// message. Yet to be translated. /// @@ -311,7 +302,6 @@ impl DiagMessage { pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self { let attr = match sub { SubdiagMessage::Str(s) => return DiagMessage::Str(s), - SubdiagMessage::Translated(s) => return DiagMessage::Translated(s), SubdiagMessage::FluentIdentifier(id) => { return DiagMessage::FluentIdentifier(id, None); } @@ -320,7 +310,6 @@ impl DiagMessage { match self { DiagMessage::Str(s) => DiagMessage::Str(s.clone()), - DiagMessage::Translated(s) => DiagMessage::Translated(s.clone()), DiagMessage::FluentIdentifier(id, _) => { DiagMessage::FluentIdentifier(id.clone(), Some(attr)) } @@ -329,7 +318,7 @@ impl DiagMessage { pub fn as_str(&self) -> Option<&str> { match self { - DiagMessage::Translated(s) | DiagMessage::Str(s) => Some(s), + DiagMessage::Str(s) => Some(s), DiagMessage::FluentIdentifier(_, _) => None, } } @@ -360,7 +349,6 @@ impl From for SubdiagMessage { fn from(val: DiagMessage) -> Self { match val { DiagMessage::Str(s) => SubdiagMessage::Str(s), - DiagMessage::Translated(s) => SubdiagMessage::Translated(s), DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id), // There isn't really a sensible behaviour for this because it loses information but // this is the most sensible of the behaviours. diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 96a4ed3218fbf..4365ceaff22d4 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -538,7 +538,6 @@ macro_rules! with_fn { } impl<'a, G: EmissionGuarantee> Diag<'a, G> { - #[rustc_lint_diagnostics] #[track_caller] pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into) -> Self { Self::new_diagnostic(dcx, DiagInner::new(level, message)) @@ -566,7 +565,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. - #[rustc_lint_diagnostics] #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( @@ -584,7 +582,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// This function still gives an emission guarantee, the guarantee is now just that it exits fatally. /// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another /// might now be ignored. - #[rustc_lint_diagnostics] #[track_caller] pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> { assert!( @@ -613,7 +610,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// the diagnostic was constructed. However, the label span is *not* considered a /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. - #[rustc_lint_diagnostics] pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { let msg = self.subdiagnostic_message_to_diagnostic_message(label); self.span.push_span_label(span, msg); @@ -623,7 +619,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_labels, /// Labels all the given spans with the provided label. /// See [`Self::span_label()`] for more information. - #[rustc_lint_diagnostics] pub fn span_labels(&mut self, spans: impl IntoIterator, label: &str) -> &mut Self { for span in spans { self.span_label(span, label.to_string()); @@ -631,7 +626,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } - #[rustc_lint_diagnostics] pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); self.span(after); @@ -647,7 +641,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } - #[rustc_lint_diagnostics] pub fn note_expected_found( &mut self, expected_label: &str, @@ -665,7 +658,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { ) } - #[rustc_lint_diagnostics] pub fn note_expected_found_extra( &mut self, expected_label: &str, @@ -711,7 +703,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } - #[rustc_lint_diagnostics] pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ StringPart::normal(format!("`{name}` from trait: `")), @@ -723,19 +714,16 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_note, /// Add a note attached to this diagnostic. - #[rustc_lint_diagnostics] pub fn note(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self } } - #[rustc_lint_diagnostics] pub fn highlighted_note(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } - #[rustc_lint_diagnostics] pub fn highlighted_span_note( &mut self, span: impl Into, @@ -746,7 +734,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// This is like [`Diag::note()`], but it's only printed once. - #[rustc_lint_diagnostics] pub fn note_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self @@ -755,7 +742,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_note, /// Prints the span with a note above it. /// This is like [`Diag::note()`], but it gets its own span. - #[rustc_lint_diagnostics] pub fn span_note( &mut self, sp: impl Into, @@ -767,7 +753,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints the span with a note above it. /// This is like [`Diag::note_once()`], but it gets its own span. - #[rustc_lint_diagnostics] pub fn span_note_once>( &mut self, sp: S, @@ -779,7 +764,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_warn, /// Add a warning attached to this diagnostic. - #[rustc_lint_diagnostics] pub fn warn(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new()); self @@ -787,7 +771,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints the span with a warning above it. /// This is like [`Diag::warn()`], but it gets its own span. - #[rustc_lint_diagnostics] pub fn span_warn>( &mut self, sp: S, @@ -799,28 +782,24 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_help, /// Add a help message attached to this diagnostic. - #[rustc_lint_diagnostics] pub fn help(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new()); self } } /// This is like [`Diag::help()`], but it's only printed once. - #[rustc_lint_diagnostics] pub fn help_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. - #[rustc_lint_diagnostics] pub fn highlighted_help(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self } /// Add a help message attached to this diagnostic with a customizable highlighted message. - #[rustc_lint_diagnostics] pub fn highlighted_span_help( &mut self, span: impl Into, @@ -833,7 +812,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_help, /// Prints the span with some help above it. /// This is like [`Diag::help()`], but it gets its own span. - #[rustc_lint_diagnostics] pub fn span_help( &mut self, sp: impl Into, @@ -846,7 +824,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Disallow attaching suggestions to this diagnostic. /// Any suggestions attached e.g. with the `span_suggestion_*` methods /// (before and after the call to `disable_suggestions`) will be ignored. - #[rustc_lint_diagnostics] pub fn disable_suggestions(&mut self) -> &mut Self { self.suggestions = Suggestions::Disabled; self @@ -856,7 +833,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// Suggestions added before the call to `.seal_suggestions()` will be preserved /// and new suggestions will be ignored. - #[rustc_lint_diagnostics] pub fn seal_suggestions(&mut self) -> &mut Self { if let Suggestions::Enabled(suggestions) = &mut self.suggestions { let suggestions_slice = std::mem::take(suggestions).into_boxed_slice(); @@ -869,7 +845,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// A new suggestion is added if suggestions are enabled for this diagnostic. /// Otherwise, they are ignored. - #[rustc_lint_diagnostics] fn push_suggestion(&mut self, suggestion: CodeSuggestion) { for subst in &suggestion.substitutions { for part in &subst.parts { @@ -890,7 +865,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_multipart_suggestion, /// Show a suggestion that has multiple parts to it. /// In other words, multiple changes need to be applied as part of this suggestion. - #[rustc_lint_diagnostics] pub fn multipart_suggestion( &mut self, msg: impl Into, @@ -907,7 +881,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Show a suggestion that has multiple parts to it, always as its own subdiagnostic. /// In other words, multiple changes need to be applied as part of this suggestion. - #[rustc_lint_diagnostics] pub fn multipart_suggestion_verbose( &mut self, msg: impl Into, @@ -923,7 +896,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. - #[rustc_lint_diagnostics] pub fn multipart_suggestion_with_style( &mut self, msg: impl Into, @@ -966,7 +938,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. - #[rustc_lint_diagnostics] pub fn tool_only_multipart_suggestion( &mut self, msg: impl Into, @@ -999,7 +970,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See [`CodeSuggestion`] for more information. - #[rustc_lint_diagnostics] pub fn span_suggestion( &mut self, sp: Span, @@ -1018,7 +988,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } } /// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`]. - #[rustc_lint_diagnostics] pub fn span_suggestion_with_style( &mut self, sp: Span, @@ -1044,7 +1013,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestion_verbose, /// Always show the suggested change. - #[rustc_lint_diagnostics] pub fn span_suggestion_verbose( &mut self, sp: Span, @@ -1065,7 +1033,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span_suggestions, /// Prints out a message with multiple suggested edits of the code. /// See also [`Diag::span_suggestion()`]. - #[rustc_lint_diagnostics] pub fn span_suggestions( &mut self, sp: Span, @@ -1082,7 +1049,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { ) } } - #[rustc_lint_diagnostics] pub fn span_suggestions_with_style( &mut self, sp: Span, @@ -1113,7 +1079,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// Prints out a message with multiple suggested edits of the code, where each edit consists of /// multiple parts. /// See also [`Diag::multipart_suggestion()`]. - #[rustc_lint_diagnostics] pub fn multipart_suggestions( &mut self, msg: impl Into, @@ -1160,7 +1125,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// inline, it will only show the message and not the suggestion. /// /// See [`CodeSuggestion`] for more information. - #[rustc_lint_diagnostics] pub fn span_suggestion_short( &mut self, sp: Span, @@ -1184,7 +1148,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// be from the message, showing the span label inline would be visually unpleasant /// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't /// improve understandability. - #[rustc_lint_diagnostics] pub fn span_suggestion_hidden( &mut self, sp: Span, @@ -1207,7 +1170,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// /// This is intended to be used for suggestions that are *very* obvious in what the changes /// need to be from the message, but we still want other tools to be able to apply them. - #[rustc_lint_diagnostics] pub fn tool_only_span_suggestion( &mut self, sp: Span, @@ -1229,7 +1191,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of /// interpolated variables). - #[rustc_lint_diagnostics] pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self { subdiagnostic.add_to_diag(self); self @@ -1248,7 +1209,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_span, /// Add a span. - #[rustc_lint_diagnostics] pub fn span(&mut self, sp: impl Into) -> &mut Self { self.span = sp.into(); if let Some(span) = self.span.primary_span() { @@ -1257,7 +1217,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } - #[rustc_lint_diagnostics] pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self { self.is_lint = Some(IsLint { name, has_future_breakage }); self @@ -1265,7 +1224,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_code, /// Add an error code. - #[rustc_lint_diagnostics] pub fn code(&mut self, code: ErrCode) -> &mut Self { self.code = Some(code); self @@ -1273,7 +1231,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_lint_id, /// Add an argument. - #[rustc_lint_diagnostics] pub fn lint_id( &mut self, id: LintExpectationId, @@ -1284,7 +1241,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_primary_message, /// Add a primary message. - #[rustc_lint_diagnostics] pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self @@ -1292,7 +1248,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_arg, /// Add an argument. - #[rustc_lint_diagnostics] pub fn arg( &mut self, name: impl Into, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ce40f3ae8bf87..ead7af9b39eb9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -4,9 +4,7 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![allow(rustc::untranslatable_diagnostic)] #![cfg_attr(bootstrap, feature(array_windows))] #![feature(assert_matches)] #![feature(associated_type_defaults)] @@ -1216,22 +1214,16 @@ impl<'a> DiagCtxtHandle<'a> { // Functions beginning with `struct_`/`create_` create a diagnostic. Other // functions create and emit a diagnostic all in one go. impl<'a> DiagCtxtHandle<'a> { - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn struct_bug(self, msg: impl Into>) -> Diag<'a, BugAbort> { Diag::new(self, Bug, msg.into()) } - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn bug(self, msg: impl Into>) -> ! { self.struct_bug(msg).emit() } - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn struct_span_bug( self, @@ -1241,8 +1233,6 @@ impl<'a> DiagCtxtHandle<'a> { self.struct_bug(msg).with_span(span) } - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn span_bug(self, span: impl Into, msg: impl Into>) -> ! { self.struct_span_bug(span, msg.into()).emit() @@ -1258,19 +1248,16 @@ impl<'a> DiagCtxtHandle<'a> { self.create_bug(bug).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_fatal(self, msg: impl Into) -> Diag<'a, FatalAbort> { Diag::new(self, Fatal, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn fatal(self, msg: impl Into) -> ! { self.struct_fatal(msg).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_fatal( self, @@ -1280,7 +1267,6 @@ impl<'a> DiagCtxtHandle<'a> { self.struct_fatal(msg).with_span(span) } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_fatal(self, span: impl Into, msg: impl Into) -> ! { self.struct_span_fatal(span, msg).emit() @@ -1310,19 +1296,16 @@ impl<'a> DiagCtxtHandle<'a> { } // FIXME: This method should be removed (every error should have an associated error code). - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_err(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Error, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn err(self, msg: impl Into) -> ErrorGuaranteed { self.struct_err(msg).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_err( self, @@ -1332,7 +1315,6 @@ impl<'a> DiagCtxtHandle<'a> { self.struct_err(msg).with_span(span) } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_err( self, @@ -1353,9 +1335,6 @@ impl<'a> DiagCtxtHandle<'a> { } /// Ensures that an error is printed. See [`Level::DelayedBug`]. - // - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn delayed_bug(self, msg: impl Into>) -> ErrorGuaranteed { Diag::::new(self, DelayedBug, msg.into()).emit() @@ -1365,9 +1344,6 @@ impl<'a> DiagCtxtHandle<'a> { /// /// Note: this function used to be called `delay_span_bug`. It was renamed /// to match similar functions like `span_err`, `span_warn`, etc. - // - // No `#[rustc_lint_diagnostics]` and no `impl Into` because bug messages aren't - // user-facing. #[track_caller] pub fn span_delayed_bug( self, @@ -1377,19 +1353,16 @@ impl<'a> DiagCtxtHandle<'a> { Diag::::new(self, DelayedBug, msg.into()).with_span(sp).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_warn(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, Warning, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn warn(self, msg: impl Into) { self.struct_warn(msg).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_warn( self, @@ -1399,7 +1372,6 @@ impl<'a> DiagCtxtHandle<'a> { self.struct_warn(msg).with_span(span) } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_warn(self, span: impl Into, msg: impl Into) { self.struct_span_warn(span, msg).emit() @@ -1415,19 +1387,16 @@ impl<'a> DiagCtxtHandle<'a> { self.create_warn(warning).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_note(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, Note, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn note(&self, msg: impl Into) { self.struct_note(msg).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_note( self, @@ -1437,7 +1406,6 @@ impl<'a> DiagCtxtHandle<'a> { self.struct_note(msg).with_span(span) } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_note(self, span: impl Into, msg: impl Into) { self.struct_span_note(span, msg).emit() @@ -1453,25 +1421,21 @@ impl<'a> DiagCtxtHandle<'a> { self.create_note(note).emit() } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_help(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, Help, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_failure_note(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, FailureNote, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_allow(self, msg: impl Into) -> Diag<'a, ()> { Diag::new(self, Allow, msg) } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a, ()> { Diag::new(self, Expect, msg).with_lint_id(id) @@ -1744,7 +1708,7 @@ impl DiagCtxtInner { message: DiagMessage, args: impl Iterator>, ) -> SubdiagMessage { - SubdiagMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args))) + SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) } /// Translate `message` eagerly with `args` to `String`. diff --git a/compiler/rustc_errors/src/markdown/mod.rs b/compiler/rustc_errors/src/markdown/mod.rs index 4f5e2328234d8..9993407b05c0e 100644 --- a/compiler/rustc_errors/src/markdown/mod.rs +++ b/compiler/rustc_errors/src/markdown/mod.rs @@ -18,9 +18,14 @@ impl<'a> MdStream<'a> { parse::entrypoint(s) } - /// Write formatted output to an anstream buffer - pub fn write_anstream_buf(&self, buf: &mut Vec) -> io::Result<()> { - term::entrypoint(self, buf) + /// Write formatted output to a stdout buffer, optionally with + /// a formatter for code blocks + pub fn write_anstream_buf( + &self, + buf: &mut Vec, + formatter: Option<&(dyn Fn(&str, &mut Vec) -> io::Result<()> + 'static)>, + ) -> io::Result<()> { + term::entrypoint(self, buf, formatter) } } diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index b0ce01548f00f..b94cd06b30ef0 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -12,29 +12,33 @@ thread_local! { static CURSOR: Cell = const { Cell::new(0) }; /// Width of the terminal static WIDTH: Cell = const { Cell::new(DEFAULT_COLUMN_WIDTH) }; + } -/// Print to terminal output to a buffer -pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Vec) -> io::Result<()> { - #[cfg(not(test))] - if let Some((w, _)) = termize::dimensions() { - WIDTH.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH)); - } - write_stream(stream, buf, None, 0)?; +/// Print to the terminal output to a buffer +/// optionally with a formatter for code blocks +pub(crate) fn entrypoint( + stream: &MdStream<'_>, + buf: &mut Vec, + formatter: Option<&(dyn Fn(&str, &mut Vec) -> io::Result<()> + 'static)>, +) -> io::Result<()> { + write_stream(stream, buf, None, 0, formatter)?; buf.write_all(b"\n") } -/// Write the buffer, reset to the default style after each + +/// Write the buffer, reset to the default style after each, +/// optionally with a formatter for code blocks fn write_stream( MdStream(stream): &MdStream<'_>, buf: &mut Vec, + default: Option