Auto merge of #151381 - JonathanBrouwer:rollup-zvO3tIH, r=JonathanBrouwer

Rollup of 15 pull requests

Successful merges:

 - rust-lang/rust#148623 (Ignore `#[doc(hidden)]` items when computing trimmed paths for printing)
 - rust-lang/rust#150550 (Miscellaneous cleanups to borrowck related code)
 - rust-lang/rust#150879 (Remove the diagnostic lints)
 - rust-lang/rust#150895 (rustc_errors: Add (heuristic) Syntax Highlighting for `rustc --explain`)
 - rust-lang/rust#150987 (remote-test-server: Fix header in batch mode)
 - rust-lang/rust#151004 (std: implement `sleep_until` on Apple platforms)
 - rust-lang/rust#151045 (Simplify some literal-value negations with `u128::wrapping_neg`)
 - rust-lang/rust#151119 (Support pointers in type reflection)
 - rust-lang/rust#151171 (Do not recover from `Trait()` if generic list is unterminated)
 - rust-lang/rust#151231 (HIR typeck cleanup: clarify and re-style `check_expr_unop`)
 - rust-lang/rust#151249 (Parse ident with allowing recovery when trying to diagnose)
 - rust-lang/rust#151295 (THIR patterns: Use `ty::Value` in more places throughout `const_to_pat`)
 - rust-lang/rust#151326 (Remove `DiagMessage::Translated` in favour of `DiagMessage::Str`)
 - rust-lang/rust#151361 (add test for issue 61463)
 - rust-lang/rust#151371 (Add `S-blocked` to `labels_blocking_approval`)

r? @ghost
This commit is contained in:
bors 2026-01-19 23:08:48 +00:00
commit 63f4513795
236 changed files with 1243 additions and 1280 deletions

View file

@ -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",

View file

@ -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)
}

View file

@ -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(_) => (),

View file

@ -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 {

View file

@ -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) {

View file

@ -141,8 +141,6 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
macro report_unstable_modifier($feature: ident) {
if !features.$feature() {
// FIXME: make this translatable
#[expect(rustc::untranslatable_diagnostic)]
feature_err(
sess,
sym::$feature,

View file

@ -164,21 +164,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
}
}
pub(crate) struct RustcLintDiagnosticsParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcLintDiagnosticsParser {
const PATH: &[Symbol] = &[sym::rustc_lint_diagnostics];
const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {

View file

@ -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<S: Stage> SingleAttributeParser<S> for TransparencyParser {
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;

View file

@ -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<WithoutArgs<RustcDumpUserArgs>>,
Single<WithoutArgs<RustcDumpVtable>>,
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
Single<WithoutArgs<RustcLintDiagnosticsParser>>,
Single<WithoutArgs<RustcLintOptTyParser>>,
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
Single<WithoutArgs<RustcLintUntrackedQueryInformationParser>>,

View file

@ -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()]
);
}
}
}

View file

@ -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;

View file

@ -1,8 +1,5 @@
// ignore-tidy-filelength
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use std::iter;
use std::ops::ControlFlow;

View file

@ -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;

View file

@ -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>,

View file

@ -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;

View file

@ -1,6 +1,3 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use core::ops::ControlFlow;
use either::Either;

View file

@ -1,6 +1,3 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use std::ops::ControlFlow;
use either::Either;

View file

@ -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;

View file

@ -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<Item=u32> + '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();

View file

@ -1,6 +1,3 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
use std::fmt::{self, Display};
use std::iter;

View file

@ -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))

View file

@ -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>,

View file

@ -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(());
}

View file

@ -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,

View file

@ -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<ty::Region<'tcx>, RegionVid>,
/// The vid assigned to `'static`. Used only for diagnostics.

View file

@ -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);

View file

@ -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

View file

@ -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)]

View file

@ -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<ast::Expr>,

View file

@ -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`.

View file

@ -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)]

View file

@ -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();

View file

@ -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(())
}
}

View file

@ -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);

View file

@ -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

View file

@ -1,5 +1,4 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![feature(array_try_map)]
#![feature(assert_matches)]
#![feature(box_patterns)]

View file

@ -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" }

View file

@ -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<String> {
let mut expander = Expander::default();
let mut result = Ok(());

View file

@ -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<u8>) -> 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<u8>) -> 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(())
}
}

View file

@ -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")
}
}

View file

@ -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<Cow<'static, str>> 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<DiagMessage> 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.

View file

@ -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<DiagMessage>) -> 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<SubdiagMessage>) -> &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<Item = Span>, 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<SubdiagMessage>) -> &mut Self {
self.sub(Level::Note, msg, MultiSpan::new());
self
} }
#[rustc_lint_diagnostics]
pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &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<MultiSpan>,
@ -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<SubdiagMessage>) -> &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<MultiSpan>,
@ -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<S: Into<MultiSpan>>(
&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<SubdiagMessage>) -> &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<S: Into<MultiSpan>>(
&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<SubdiagMessage>) -> &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<SubdiagMessage>) -> &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<StringPart>) -> &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<MultiSpan>,
@ -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<MultiSpan>,
@ -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<SubdiagMessage>,
@ -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<SubdiagMessage>,
@ -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<SubdiagMessage>,
@ -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<SubdiagMessage>,
@ -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<SubdiagMessage>,
@ -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<MultiSpan>) -> &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<DiagMessage>) -> &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<DiagArgName>,

View file

@ -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<DiagMessage>` because bug messages aren't
// user-facing.
#[track_caller]
pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
Diag::new(self, Bug, msg.into())
}
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
// user-facing.
#[track_caller]
pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
self.struct_bug(msg).emit()
}
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` 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<DiagMessage>` because bug messages aren't
// user-facing.
#[track_caller]
pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
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<DiagMessage>) -> Diag<'a, FatalAbort> {
Diag::new(self, Fatal, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
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<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
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<DiagMessage>) -> Diag<'a> {
Diag::new(self, Error, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn err(self, msg: impl Into<DiagMessage>) -> 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<DiagMessage>` because bug messages aren't
// user-facing.
#[track_caller]
pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
Diag::<ErrorGuaranteed>::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<DiagMessage>` because bug messages aren't
// user-facing.
#[track_caller]
pub fn span_delayed_bug(
self,
@ -1377,19 +1353,16 @@ impl<'a> DiagCtxtHandle<'a> {
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
Diag::new(self, Warning, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn warn(self, msg: impl Into<DiagMessage>) {
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<MultiSpan>, msg: impl Into<DiagMessage>) {
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<DiagMessage>) -> Diag<'a, ()> {
Diag::new(self, Note, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn note(&self, msg: impl Into<DiagMessage>) {
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<MultiSpan>, msg: impl Into<DiagMessage>) {
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<DiagMessage>) -> Diag<'a, ()> {
Diag::new(self, Help, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
Diag::new(self, FailureNote, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
Diag::new(self, Allow, msg)
}
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
Diag::new(self, Expect, msg).with_lint_id(id)
@ -1744,7 +1708,7 @@ impl DiagCtxtInner {
message: DiagMessage,
args: impl Iterator<Item = DiagArg<'a>>,
) -> 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`.

View file

@ -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<u8>) -> 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<u8>,
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
) -> io::Result<()> {
term::entrypoint(self, buf, formatter)
}
}

View file

@ -12,29 +12,33 @@ thread_local! {
static CURSOR: Cell<usize> = const { Cell::new(0) };
/// Width of the terminal
static WIDTH: Cell<usize> = const { Cell::new(DEFAULT_COLUMN_WIDTH) };
}
/// Print to terminal output to a buffer
pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Vec<u8>) -> 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<u8>,
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> 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<u8>,
default: Option<Style>,
indent: usize,
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
) -> io::Result<()> {
for tt in stream {
write_tt(tt, buf, default, indent)?;
write_tt(tt, buf, default, indent, formatter)?;
}
reset_opt_style(buf, default)?;
Ok(())
}
@ -43,12 +47,17 @@ fn write_tt(
buf: &mut Vec<u8>,
default: Option<Style>,
indent: usize,
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
) -> io::Result<()> {
match tt {
MdTree::CodeBlock { txt, lang: _ } => {
reset_opt_style(buf, default)?;
let style = Style::new().effects(Effects::DIMMED);
write!(buf, "{style}{txt}{style:#}")?;
if let Some(formatter) = formatter {
formatter(txt, buf)?;
} else {
let style = Style::new().effects(Effects::DIMMED);
write!(buf, "{style}{txt}{style:#}")?;
}
render_opt_style(buf, default)?;
}
MdTree::CodeInline(txt) => {
@ -105,7 +114,7 @@ fn write_tt(
};
reset_opt_style(buf, default)?;
write!(buf, "{cs}")?;
write_stream(stream, buf, Some(cs), 0)?;
write_stream(stream, buf, Some(cs), 0, None)?;
write!(buf, "{cs:#}")?;
render_opt_style(buf, default)?;
buf.write_all(b"\n")?;
@ -113,12 +122,12 @@ fn write_tt(
MdTree::OrderedListItem(n, stream) => {
let base = format!("{n}. ");
write_wrapping(buf, &format!("{base:<4}"), indent, None, None)?;
write_stream(stream, buf, None, indent + 4)?;
write_stream(stream, buf, None, indent + 4, None)?;
}
MdTree::UnorderedListItem(stream) => {
let base = "* ";
write_wrapping(buf, &format!("{base:<4}"), indent, None, None)?;
write_stream(stream, buf, None, indent + 4)?;
write_stream(stream, buf, None, indent + 4, None)?;
}
// Patterns popped in previous step
MdTree::Comment(_) | MdTree::LinkDef { .. } | MdTree::RefLink { .. } => unreachable!(),

View file

@ -1,13 +1,13 @@
H1 Heading ]8;;http://docs.rs\with a link]8;;\
H1 Heading ]8;;http://docs.rs\with a link]8;;\
H1 content: some words in bold and so does inline code
H2 Heading
H2 Heading
H2 content: some words in italic
H3 Heading
H3 Heading
H3 content: strikethrough text
H4 Heading
H4 Heading
H4 content: A ]8;;https://docs.rs\simple link]8;;\ and a ]8;;http://docs.rs\remote-link]8;;\.
--------------------------------------------------------------------------------------------------------------------------------------------
A section break was above. We can also do paragraph breaks:
@ -24,7 +24,7 @@ Or ordered:
elit quam, pulvinar ac risus in, dictum vehicula turpis. Vestibulum neque est, accumsan in cursus sit amet, dictum a nunc. Suspendisse
aliquet, lorem eu eleifend accumsan, magna neque sodales nisi, a aliquet lectus leo eu sem.
--------------------------------------------------------------------------------------------------------------------------------------------
Code
Code
Both inline code and code blocks are supported:
/// A rust enum

View file

@ -65,7 +65,7 @@ fn test_output() {
let bless = std::env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
let ast = MdStream::parse_str(INPUT);
let mut buffer = Vec::new();
ast.write_anstream_buf(&mut buffer).unwrap();
ast.write_anstream_buf(&mut buffer, None).unwrap();
let mut blessed = PathBuf::new();
blessed.extend(OUTPUT_PATH);

View file

@ -76,7 +76,7 @@ impl Translator {
) -> Result<Cow<'a, str>, TranslateError<'a>> {
trace!(?message, ?args);
let (identifier, attr) = match message {
DiagMessage::Str(msg) | DiagMessage::Translated(msg) => {
DiagMessage::Str(msg) => {
return Ok(Cow::Borrowed(msg));
}
DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),

View file

@ -1355,8 +1355,6 @@ impl<'a> ExtCtxt<'a> {
for (span, notes) in self.expansions.iter() {
let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
for note in notes {
// FIXME: make this translatable
#[allow(rustc::untranslatable_diagnostic)]
db.note(note.clone());
}
db.emit();

View file

@ -999,7 +999,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
})
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
let kind = match item {
Annotatable::Item(_)

View file

@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![cfg_attr(bootstrap, feature(array_windows))]
#![feature(associated_type_defaults)]
#![feature(if_let_guard)]
@ -13,8 +12,6 @@
mod build;
mod errors;
// FIXME(Nilstrieb) Translate macro_rules diagnostics
#[allow(rustc::untranslatable_diagnostic)]
mod mbe;
mod placeholders;
mod proc_macro_server;
@ -25,8 +22,6 @@ pub mod base;
pub mod config;
pub mod expand;
pub mod module;
// FIXME(Nilstrieb) Translate proc_macro diagnostics
#[allow(rustc::untranslatable_diagnostic)]
pub mod proc_macro;
pub fn provide(providers: &mut rustc_middle::query::Providers) {

View file

@ -548,9 +548,6 @@ impl server::FreeFunctions for Rustc<'_, '_> {
Diag::new(self.psess().dcx(), diagnostic.level.to_internal(), message);
diag.span(MultiSpan::from_spans(diagnostic.spans));
for child in diagnostic.children {
// This message comes from another diagnostic, and we are just reconstructing the
// diagnostic, so there's no need for translation.
#[allow(rustc::untranslatable_diagnostic)]
diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
}
diag.emit();

View file

@ -1182,12 +1182,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
rustc_lint_untracked_query_information, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes,
),
// Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
// APIs. Any function with this attribute will be checked by that lint.
rustc_attr!(
rustc_lint_diagnostics, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes,
),
// Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
// types (as well as any others in future).
rustc_attr!(

View file

@ -954,9 +954,6 @@ pub enum AttributeKind {
/// Represents `#[rustc_legacy_const_generics]`
RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span },
/// Represents `#[rustc_lint_diagnostics]`
RustcLintDiagnostics,
/// Represents `#[rustc_lint_opt_deny_field_access]`
RustcLintOptDenyFieldAccess { lint_message: Symbol },

View file

@ -113,7 +113,6 @@ impl AttributeKind {
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcLegacyConstGenerics { .. } => Yes,
RustcLintDiagnostics => Yes,
RustcLintOptDenyFieldAccess { .. } => Yes,
RustcLintOptTy => Yes,
RustcLintQueryInstability => Yes,

View file

@ -56,8 +56,6 @@ This API is completely unstable and subject to change.
*/
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(assert_matches)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]

View file

@ -524,9 +524,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Unit testing: function items annotated with
// `#[rustc_evaluate_where_clauses]` trigger special output
// to let us test the trait evaluation system.
// Untranslatable diagnostics are okay for rustc internals
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
if self.has_rustc_attrs
&& self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses)
{

View file

@ -434,43 +434,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::UnOp::Not | hir::UnOp::Neg => expected,
hir::UnOp::Deref => NoExpectation,
};
let mut oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner);
let oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner);
if !oprnd_t.references_error() {
oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);
match unop {
hir::UnOp::Deref => {
if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) {
oprnd_t = ty;
} else {
let mut err =
self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t });
let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);
if let Some(sp) =
tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp)
{
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
oprnd_t = Ty::new_error(tcx, err.emit());
}
}
hir::UnOp::Not => {
let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
// If it's builtin, we can reuse the type, this helps inference.
if !(oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool) {
oprnd_t = result;
}
}
hir::UnOp::Neg => {
let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
// If it's builtin, we can reuse the type, this helps inference.
if !oprnd_t.is_numeric() {
oprnd_t = result;
}
if let Err(guar) = oprnd_t.error_reported() {
return Ty::new_error(tcx, guar);
}
let oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);
match unop {
hir::UnOp::Deref => self.lookup_derefing(expr, oprnd, oprnd_t).unwrap_or_else(|| {
let mut err =
self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t });
let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None);
if let Some(sp) = tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) {
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
Ty::new_error(tcx, err.emit())
}),
hir::UnOp::Not => {
let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
// If it's builtin, we can reuse the type, this helps inference.
if oprnd_t.is_integral() || *oprnd_t.kind() == ty::Bool { oprnd_t } else { result }
}
hir::UnOp::Neg => {
let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner);
// If it's builtin, we can reuse the type, this helps inference.
if oprnd_t.is_numeric() { oprnd_t } else { result }
}
}
oprnd_t
}
fn check_expr_addr_of(

View file

@ -66,8 +66,6 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
macro_rules! error {
($reason: expr) => {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
dcx.fatal(format!("invalid `--cfg` argument: `{s}` ({})", $reason));
};
}
@ -146,42 +144,30 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
"visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details";
macro_rules! error {
($reason:expr) => {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
{
let mut diag =
dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
diag.note($reason);
diag.note(VISIT);
diag.emit()
}
};
(in $arg:expr, $reason:expr) => {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
{
let mut diag =
dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
($reason:expr) => {{
let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
diag.note($reason);
diag.note(VISIT);
diag.emit()
}};
(in $arg:expr, $reason:expr) => {{
let mut diag = dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg);
if let Some(lit) = $arg.lit() {
let (lit_kind_article, lit_kind_descr) = {
let lit_kind = lit.as_token_lit().kind;
(lit_kind.article(), lit_kind.descr())
};
diag.note(format!(
"`{pparg}` is {lit_kind_article} {lit_kind_descr} literal"
));
} else {
diag.note(format!("`{pparg}` is invalid"));
}
diag.note($reason);
diag.note(VISIT);
diag.emit()
let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg);
if let Some(lit) = $arg.lit() {
let (lit_kind_article, lit_kind_descr) = {
let lit_kind = lit.as_token_lit().kind;
(lit_kind.article(), lit_kind.descr())
};
diag.note(format!("`{pparg}` is {lit_kind_article} {lit_kind_descr} literal"));
} else {
diag.note(format!("`{pparg}` is invalid"));
}
};
diag.note($reason);
diag.note(VISIT);
diag.emit()
}};
}
let expected_error = || -> ! {
@ -408,8 +394,6 @@ pub struct Config {
/// Initialize jobserver before getting `jobserver::client` and `build_session`.
pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
jobserver::initialize_checked(|err| {
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
early_dcx
.early_struct_warn(err)
.with_note("the build environment is likely misconfigured")
@ -476,11 +460,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
config.opts.unstable_opts.translate_directionality_markers,
) {
Ok(bundle) => bundle,
Err(e) => {
// We can't translate anything if we failed to load translations
#[allow(rustc::untranslatable_diagnostic)]
early_dcx.early_fatal(format!("failed to load fluent bundle: {e}"))
}
Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")),
};
let mut locale_resources = config.locale_resources;

View file

@ -119,8 +119,6 @@ fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize {
// FIXME: we could accept `RUST_MIN_STACK=64MB`, perhaps?
.map(|s| {
let s = s.trim();
// FIXME(workingjubilee): add proper diagnostics when we factor out "pre-run" setup
#[allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)]
s.parse::<usize>().unwrap_or_else(|_| {
let mut err = early_dcx.early_struct_fatal(format!(
r#"`RUST_MIN_STACK` should be a number of bytes, but was "{s}""#,
@ -301,7 +299,6 @@ pub(crate) fn run_in_thread_pool_with_globals<
})
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn {
match unsafe { load_symbol_from_dylib::<MakeBackendFn>(path, "__rustc_codegen_backend") } {
Ok(backend_sym) => backend_sym,
@ -434,8 +431,6 @@ impl CodegenBackend for DummyCodegenBackend {
.find(|&&crate_type| crate_type != CrateType::Rlib)
&& outputs.outputs.should_link()
{
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal(format!(
"crate type {crate_type} not supported by the dummy codegen backend"
));
@ -491,7 +486,6 @@ pub fn rustc_path<'a>(sysroot: &Sysroot) -> Option<&'a Path> {
.as_deref()
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn get_codegen_sysroot(
early_dcx: &EarlyDiagCtxt,
sysroot: &Sysroot,

View file

@ -237,9 +237,6 @@ lint_deprecated_where_clause_location = where clause not allowed here
.suggestion_move_to_end = move it to the end of the type declaration
.suggestion_remove_where = remove this `where`
lint_diag_out_of_impl =
diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
lint_doc_alias_duplicated = doc alias is duplicated
.label = first defined here
@ -992,8 +989,6 @@ lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
lint_untranslatable_diag = diagnostics should be created using translatable messages
lint_unused_allocation = unnecessary allocation, use `&` instead
lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead

View file

@ -509,7 +509,6 @@ pub trait LintContext {
/// Emit a lint at the appropriate level, with an optional associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
fn opt_span_lint<S: Into<MultiSpan>>(
&self,
@ -548,7 +547,6 @@ pub trait LintContext {
/// Emit a lint at the appropriate level, with an associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
fn span_lint<S: Into<MultiSpan>>(
&self,
@ -570,7 +568,6 @@ pub trait LintContext {
/// Emit a lint at the appropriate level, with no associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
fn lint(&self, lint: &'static Lint, decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>)) {
self.opt_span_lint(lint, None as Option<Span>, decorate);
}
@ -590,8 +587,6 @@ pub trait LintContext {
// and stored between compilation sessions. To not manually do these steps, we simply create
// a dummy diagnostic and emit it as usual, which will be suppressed and stored like a
// normal expected lint diagnostic.
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
self.sess()
.dcx()
.struct_expect(
@ -630,7 +625,6 @@ impl<'tcx> LintContext for LateContext<'tcx> {
self.tcx.sess
}
#[rustc_lint_diagnostics]
fn opt_span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
@ -656,7 +650,6 @@ impl LintContext for EarlyContext<'_> {
self.builder.sess()
}
#[rustc_lint_diagnostics]
fn opt_span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,

View file

@ -33,7 +33,6 @@ pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> {
}
impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> {
#[allow(rustc::diagnostic_outside_of_impl)]
fn check_id(&mut self, id: ast::NodeId) {
for early_lint in self.context.buffered.take(id) {
let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;

View file

@ -35,7 +35,6 @@ impl Subdiagnostic for OverruledAttributeSub {
OverruledAttributeSub::NodeSource { span, reason } => {
diag.span_label(span, fluent::lint_node_source);
if let Some(rationale) = reason {
#[allow(rustc::untranslatable_diagnostic)]
diag.note(rationale.to_string());
}
}

View file

@ -5,18 +5,17 @@ use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, HirId, find_attr};
use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity, Ty};
use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{Span, sym};
use tracing::debug;
use {rustc_ast as ast, rustc_hir as hir};
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, ImplicitSysrootCrateImportDiag,
LintPassByHand, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked,
SpanUseEqCtxtDiag, SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind,
TypeIrDirectUse, TypeIrInherentUsage, TypeIrTraitUsage, UntranslatableDiag,
BadOptAccessDiag, DefaultHashTypesDiag, ImplicitSysrootCrateImportDiag, LintPassByHand,
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrDirectUse,
TypeIrInherentUsage, TypeIrTraitUsage,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -492,162 +491,6 @@ impl EarlyLintPass for LintPassImpl {
}
}
declare_tool_lint! {
/// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl
/// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings.
///
/// More details on translatable diagnostics can be found
/// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html).
pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
Allow,
"prevent creation of diagnostics which cannot be translated",
report_in_external_macro: true,
@eval_always = true
}
declare_tool_lint! {
/// The `diagnostic_outside_of_impl` lint detects calls to functions annotated with
/// `#[rustc_lint_diagnostics]` that are outside an `Diagnostic`, `Subdiagnostic`, or
/// `LintDiagnostic` impl (either hand-written or derived).
///
/// More details on diagnostics implementations can be found
/// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html).
pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
Allow,
"prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
report_in_external_macro: true,
@eval_always = true
}
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
impl LateLintPass<'_> for Diagnostics {
fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
let collect_args_tys_and_spans = |args: &[hir::Expr<'_>], reserve_one_extra: bool| {
let mut result = Vec::with_capacity(args.len() + usize::from(reserve_one_extra));
result.extend(args.iter().map(|arg| (cx.typeck_results().expr_ty(arg), arg.span)));
result
};
// Only check function calls and method calls.
let Some((def_id, span, fn_gen_args, recv, args)) =
get_callee_span_generic_args_and_args(cx, expr)
else {
return;
};
let mut arg_tys_and_spans = collect_args_tys_and_spans(args, recv.is_some());
if let Some(recv) = recv {
arg_tys_and_spans.insert(0, (cx.tcx.types.self_param, recv.span)); // dummy inserted for `self`
}
Self::diagnostic_outside_of_impl(cx, span, expr.hir_id, def_id, fn_gen_args);
Self::untranslatable_diagnostic(cx, def_id, &arg_tys_and_spans);
}
}
impl Diagnostics {
// Is the type `{D,Subd}iagMessage`?
fn is_diag_message<'cx>(cx: &LateContext<'cx>, ty: Ty<'cx>) -> bool {
if let Some(adt_def) = ty.ty_adt_def()
&& let Some(name) = cx.tcx.get_diagnostic_name(adt_def.did())
&& matches!(name, sym::DiagMessage | sym::SubdiagMessage)
{
true
} else {
false
}
}
fn untranslatable_diagnostic<'cx>(
cx: &LateContext<'cx>,
def_id: DefId,
arg_tys_and_spans: &[(Ty<'cx>, Span)],
) {
let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
for (i, &param_ty) in fn_sig.inputs().iter().enumerate() {
if let ty::Param(sig_param) = param_ty.kind() {
// It is a type parameter. Check if it is `impl Into<{D,Subd}iagMessage>`.
for pred in predicates.iter() {
if let Some(trait_pred) = pred.as_trait_clause()
&& let trait_ref = trait_pred.skip_binder().trait_ref
&& trait_ref.self_ty() == param_ty // correct predicate for the param?
&& cx.tcx.is_diagnostic_item(sym::Into, trait_ref.def_id)
&& let ty1 = trait_ref.args.type_at(1)
&& Self::is_diag_message(cx, ty1)
{
// Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
// with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
// `UNTRANSLATABLE_DIAGNOSTIC` lint.
let (arg_ty, arg_span) = arg_tys_and_spans[i];
// Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
let is_translatable = Self::is_diag_message(cx, arg_ty)
|| matches!(arg_ty.kind(), ty::Param(arg_param) if arg_param.name == sig_param.name);
if !is_translatable {
cx.emit_span_lint(
UNTRANSLATABLE_DIAGNOSTIC,
arg_span,
UntranslatableDiag,
);
}
}
}
}
}
}
fn diagnostic_outside_of_impl<'cx>(
cx: &LateContext<'cx>,
span: Span,
current_id: HirId,
def_id: DefId,
fn_gen_args: GenericArgsRef<'cx>,
) {
// Is the callee marked with `#[rustc_lint_diagnostics]`?
let Some(inst) =
ty::Instance::try_resolve(cx.tcx, cx.typing_env(), def_id, fn_gen_args).ok().flatten()
else {
return;
};
if !find_attr!(cx.tcx.get_all_attrs(inst.def_id()), AttributeKind::RustcLintDiagnostics) {
return;
};
for (hir_id, _parent) in cx.tcx.hir_parent_iter(current_id) {
if let Some(owner_did) = hir_id.as_owner()
&& find_attr!(cx.tcx.get_all_attrs(owner_did), AttributeKind::RustcLintDiagnostics)
{
// The parent method is marked with `#[rustc_lint_diagnostics]`
return;
}
}
// Calls to `#[rustc_lint_diagnostics]`-marked functions should only occur:
// - inside an impl of `Diagnostic`, `Subdiagnostic`, or `LintDiagnostic`, or
// - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`.
//
// Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint.
let mut is_inside_appropriate_impl = false;
for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) {
debug!(?parent);
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent
&& let Some(of_trait) = impl_.of_trait
&& let Some(def_id) = of_trait.trait_ref.trait_def_id()
&& let Some(name) = cx.tcx.get_diagnostic_name(def_id)
&& matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
{
is_inside_appropriate_impl = true;
break;
}
}
debug!(?is_inside_appropriate_impl);
if !is_inside_appropriate_impl {
cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
}
}
}
declare_tool_lint! {
/// The `bad_opt_access` lint detects accessing options by field instead of
/// the wrapper function.

View file

@ -941,8 +941,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
if self.lint_added_lints {
let lint = builtin::UNKNOWN_LINTS;
let level = self.lint_level(builtin::UNKNOWN_LINTS);
// FIXME: make this translatable
#[allow(rustc::diagnostic_outside_of_impl)]
lint_level(self.sess, lint, level, Some(span.into()), |lint| {
lint.primary_message(fluent::lint_unknown_gated_lint);
lint.arg("name", lint_id.lint.name_lower());
@ -970,7 +968,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
/// this lint context.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
pub(crate) fn opt_span_lint(
&self,

View file

@ -655,8 +655,6 @@ fn register_internals(store: &mut LintStore) {
store.register_late_mod_pass(|_| Box::new(TyTyKind));
store.register_lints(&TypeIr::lint_vec());
store.register_late_mod_pass(|_| Box::new(TypeIr));
store.register_lints(&Diagnostics::lint_vec());
store.register_late_mod_pass(|_| Box::new(Diagnostics));
store.register_lints(&BadOptAccess::lint_vec());
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
store.register_lints(&PassByValue::lint_vec());
@ -667,10 +665,6 @@ fn register_internals(store: &mut LintStore) {
store.register_late_mod_pass(|_| Box::new(SymbolInternStringLiteral));
store.register_lints(&ImplicitSysrootCrateImport::lint_vec());
store.register_early_pass(|| Box::new(ImplicitSysrootCrateImport));
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
// these lints will trigger all of the time - change this once migration to diagnostic structs
// and translation is completed
store.register_group(
false,
"rustc::internal",

View file

@ -1,6 +1,5 @@
// ignore-tidy-filelength
#![allow(rustc::untranslatable_diagnostic)]
use std::num::NonZero;
use rustc_errors::codes::*;
@ -944,14 +943,6 @@ pub(crate) struct NonGlobImportTypeIrInherent {
#[help]
pub(crate) struct LintPassByHand;
#[derive(LintDiagnostic)]
#[diag(lint_diag_out_of_impl)]
pub(crate) struct DiagOutOfImpl;
#[derive(LintDiagnostic)]
#[diag(lint_untranslatable_diag)]
pub(crate) struct UntranslatableDiag;
#[derive(LintDiagnostic)]
#[diag(lint_bad_opt_access)]
pub(crate) struct BadOptAccessDiag<'a> {
@ -2869,7 +2860,6 @@ pub(crate) struct AmbiguousGlobReexports {
pub duplicate_reexport: Span,
pub name: String,
// FIXME: make this translatable
pub namespace: String,
}
@ -2882,7 +2872,6 @@ pub(crate) struct HiddenGlobReexports {
pub private_item: Span,
pub name: String,
// FIXME: make this translatable
pub namespace: String,
}

View file

@ -120,7 +120,6 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
arg_span = expn.call_site;
}
#[allow(rustc::diagnostic_outside_of_impl)]
cx.span_lint(NON_FMT_PANICS, arg_span, |lint| {
lint.primary_message(fluent::lint_non_fmt_panic);
lint.arg("name", symbol);

View file

@ -199,10 +199,6 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
let mut ms = MultiSpan::from_span(impl_span);
for path in &collector.paths {
// FIXME: While a translatable diagnostic message can have an argument
// we (currently) have no way to set different args per diag msg with
// `MultiSpan::push_span_label`.
#[allow(rustc::untranslatable_diagnostic)]
ms.push_span_label(
path_span_without_args(path),
format!("`{}` is not local", path_name_to_string(path)),

View file

@ -338,8 +338,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for MultipleCandidates {
diag.code(E0464);
diag.span(self.span);
for (i, candidate) in self.candidates.iter().enumerate() {
// FIXME: make this translatable
#[allow(rustc::untranslatable_diagnostic)]
diag.note(format!("candidate #{}: {}", i + 1, candidate.display()));
}
diag
@ -446,8 +444,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidMetadataFiles {
diag.code(E0786);
diag.span(self.span);
for crate_rejection in self.crate_rejections {
// FIXME: make this translatable
#[allow(rustc::untranslatable_diagnostic)]
diag.note(crate_rejection);
}
diag

View file

@ -26,9 +26,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(allocator_api)]
#![feature(assert_matches)]

View file

@ -119,7 +119,6 @@ pub struct DeprecationSuggestion {
pub struct Deprecated {
pub sub: Option<DeprecationSuggestion>,
// FIXME: make this translatable
pub kind: String,
pub path: String,
pub note: Option<Symbol>,

View file

@ -842,7 +842,7 @@ impl BorrowKind {
/// Returns whether borrows represented by this kind are allowed to be split into separate
/// Reservation and Activation phases.
pub fn allows_two_phase_borrow(&self) -> bool {
pub fn is_two_phase_borrow(&self) -> bool {
match *self {
BorrowKind::Shared
| BorrowKind::Fake(_)

View file

@ -3281,7 +3281,6 @@ impl<'tcx> TyCtxt<'tcx> {
/// Emit a lint at the appropriate level for a hir node, with an associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
pub fn node_span_lint(
self,
@ -3341,7 +3340,6 @@ impl<'tcx> TyCtxt<'tcx> {
/// Emit a lint at the appropriate level for a hir node.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
pub fn node_lint(
self,

View file

@ -3421,6 +3421,13 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
def::Res::Def(DefKind::AssocTy, _) => {}
def::Res::Def(DefKind::TyAlias, _) => {}
def::Res::Def(defkind, def_id) => {
// Ignore external `#[doc(hidden)]` items and their descendants.
// They shouldn't prevent other items from being considered
// unique, and should be printed with a full path if necessary.
if tcx.is_doc_hidden(def_id) {
continue;
}
if let Some(ns) = defkind.ns() {
collect_fn(&child.ident, ns, def_id);
}

View file

@ -157,7 +157,9 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
}
(ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()),
(ast::LitKind::Int(n, _), ty::Int(_)) => {
trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })
// Unsigned "negation" has the same bitwise effect as signed negation,
// which gets the result we want without additional casts.
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() })
}
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
parse_float_into_constval(n, *fty, neg).unwrap()

View file

@ -1,8 +1,6 @@
//! Construction of MIR from HIR.
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]

View file

@ -72,10 +72,10 @@ pub(crate) fn lit_to_const<'tcx>(
ty::ValTree::from_scalar_int(tcx, scalar_int)
}
(ast::LitKind::Int(n, _), ty::Int(i)) => {
let scalar_int = trunc(
if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() },
i.to_unsigned(),
);
// Unsigned "negation" has the same bitwise effect as signed negation,
// which gets the result we want without additional casts.
let scalar_int =
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
ty::ValTree::from_scalar_int(tcx, scalar_int)
}
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int(tcx, b.into()),

View file

@ -13,9 +13,7 @@ use rustc_infer::traits::Obligation;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::span_bug;
use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, ValTree,
};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor};
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, Span};
use rustc_trait_selection::traits::ObligationCause;
@ -48,7 +46,7 @@ impl<'tcx> PatCtxt<'tcx> {
match c.kind() {
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
ty::ConstKind::Value(cv) => convert.valtree_to_pat(cv.valtree, cv.ty),
ty::ConstKind::Value(value) => convert.valtree_to_pat(value),
_ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c),
}
}
@ -175,7 +173,7 @@ impl<'tcx> ConstToPat<'tcx> {
};
// Lower the valtree to a THIR pattern.
let mut thir_pat = self.valtree_to_pat(valtree, ty);
let mut thir_pat = self.valtree_to_pat(ty::Value { ty, valtree });
if !thir_pat.references_error() {
// Always check for `PartialEq` if we had no other errors yet.
@ -192,31 +190,32 @@ impl<'tcx> ConstToPat<'tcx> {
thir_pat
}
fn field_pats(
fn lower_field_values_to_fieldpats(
&self,
vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
values: impl Iterator<Item = ty::Value<'tcx>>,
) -> Vec<FieldPat<'tcx>> {
vals.enumerate()
.map(|(idx, (val, ty))| {
let field = FieldIdx::new(idx);
// Patterns can only use monomorphic types.
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
FieldPat { field, pattern: *self.valtree_to_pat(val, ty) }
values
.enumerate()
.map(|(index, value)| FieldPat {
field: FieldIdx::new(index),
pattern: *self.valtree_to_pat(value),
})
.collect()
}
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
// FIXME(valtrees): Accept `ty::Value` instead of `Ty` and `ty::ValTree` separately.
#[instrument(skip(self), level = "debug")]
fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
fn valtree_to_pat(&self, value: ty::Value<'tcx>) -> Box<Pat<'tcx>> {
let span = self.span;
let tcx = self.tcx;
let ty::Value { ty, valtree } = value;
let kind = match ty.kind() {
// Extremely important check for all ADTs!
// Make sure they are eligible to be used in patterns, and if not, emit an error.
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
// Extremely important check for all ADTs! Make sure they opted-in to be used in
// patterns.
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
// This ADT cannot be used as a constant in patterns.
debug!(?adt_def, ?value.ty, "ADT type in pattern is not `type_marked_structural`");
let PartialEqImplStatus {
is_derived, structural_partial_eq, non_blanket_impl, ..
} = type_has_partial_eq_impl(self.tcx, self.typing_env, ty);
@ -239,51 +238,43 @@ impl<'tcx> ConstToPat<'tcx> {
return self.mk_err(tcx.dcx().create_err(err), ty);
}
ty::Adt(adt_def, args) if adt_def.is_enum() => {
let (&variant_index, fields) = cv.to_branch().split_first().unwrap();
let (&variant_index, fields) = valtree.to_branch().split_first().unwrap();
let variant_index = VariantIdx::from_u32(variant_index.to_leaf().to_u32());
PatKind::Variant {
adt_def: *adt_def,
args,
variant_index,
subpatterns: self.field_pats(
fields.iter().map(|ct| ct.to_value().valtree).zip(
adt_def.variants()[variant_index]
.fields
.iter()
.map(|field| field.ty(tcx, args)),
),
),
subpatterns: self
.lower_field_values_to_fieldpats(fields.iter().map(|ct| ct.to_value())),
}
}
ty::Adt(def, args) => {
ty::Adt(def, _) => {
assert!(!def.is_union()); // Valtree construction would never succeed for unions.
PatKind::Leaf {
subpatterns: self.field_pats(
cv.to_branch().iter().map(|ct| ct.to_value().valtree).zip(
def.non_enum_variant().fields.iter().map(|field| field.ty(tcx, args)),
),
subpatterns: self.lower_field_values_to_fieldpats(
valtree.to_branch().iter().map(|ct| ct.to_value()),
),
}
}
ty::Tuple(fields) => PatKind::Leaf {
subpatterns: self.field_pats(
cv.to_branch().iter().map(|ct| ct.to_value().valtree).zip(fields.iter()),
ty::Tuple(_) => PatKind::Leaf {
subpatterns: self.lower_field_values_to_fieldpats(
valtree.to_branch().iter().map(|ct| ct.to_value()),
),
},
ty::Slice(elem_ty) => PatKind::Slice {
prefix: cv
ty::Slice(_) => PatKind::Slice {
prefix: valtree
.to_branch()
.iter()
.map(|val| *self.valtree_to_pat(val.to_value().valtree, *elem_ty))
.map(|val| *self.valtree_to_pat(val.to_value()))
.collect(),
slice: None,
suffix: Box::new([]),
},
ty::Array(elem_ty, _) => PatKind::Array {
prefix: cv
ty::Array(_, _) => PatKind::Array {
prefix: valtree
.to_branch()
.iter()
.map(|val| *self.valtree_to_pat(val.to_value().valtree, *elem_ty))
.map(|val| *self.valtree_to_pat(val.to_value()))
.collect(),
slice: None,
suffix: Box::new([]),
@ -296,7 +287,7 @@ impl<'tcx> ConstToPat<'tcx> {
// Under `feature(deref_patterns)`, string literal patterns can also
// have type `str` directly, without the `&`, in order to allow things
// like `deref!("...")` to work when the scrutinee is `String`.
PatKind::Constant { value: ty::Value { ty, valtree: cv } }
PatKind::Constant { value }
}
ty::Ref(_, pointee_ty, ..) => {
if pointee_ty.is_str()
@ -304,7 +295,9 @@ impl<'tcx> ConstToPat<'tcx> {
|| pointee_ty.is_sized(tcx, self.typing_env)
{
// References have the same valtree representation as their pointee.
PatKind::Deref { subpattern: self.valtree_to_pat(cv, *pointee_ty) }
PatKind::Deref {
subpattern: self.valtree_to_pat(ty::Value { ty: *pointee_ty, valtree }),
}
} else {
return self.mk_err(
tcx.dcx().create_err(UnsizedPattern { span, non_sm_ty: *pointee_ty }),
@ -313,7 +306,7 @@ impl<'tcx> ConstToPat<'tcx> {
}
}
ty::Float(flt) => {
let v = cv.to_leaf();
let v = valtree.to_leaf();
let is_nan = match flt {
ty::FloatTy::F16 => v.to_f16().is_nan(),
ty::FloatTy::F32 => v.to_f32().is_nan(),
@ -325,13 +318,13 @@ impl<'tcx> ConstToPat<'tcx> {
// Also see <https://github.com/rust-lang/rfcs/pull/3535>.
return self.mk_err(tcx.dcx().create_err(NaNPattern { span }), ty);
} else {
PatKind::Constant { value: ty::Value { ty, valtree: cv } }
PatKind::Constant { value }
}
}
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
// The raw pointers we see here have been "vetted" by valtree construction to be
// just integers, so we simply allow them.
PatKind::Constant { value: ty::Value { ty, valtree: cv } }
PatKind::Constant { value }
}
ty::FnPtr(..) => {
unreachable!(

View file

@ -258,8 +258,6 @@ fn run_passes_inner<'tcx>(
// Verify that no passes are missing from the `declare_passes` invocation
#[cfg(debug_assertions)]
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
{
let used_passes: FxIndexSet<_> = passes.iter().map(|p| p.name()).collect();

View file

@ -1,8 +1,6 @@
//! The main parser interface.
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(debug_closure_helpers)]

View file

@ -2264,7 +2264,7 @@ impl<'a> Parser<'a> {
&& self.look_ahead(1, |t| *t == token::Comma || *t == token::CloseParen)
{
// `fn foo(String s) {}`
let ident = self.parse_ident().unwrap();
let ident = self.parse_ident_common(true).unwrap();
let span = pat.span.with_hi(ident.span.hi());
err.span_suggestion(

View file

@ -204,9 +204,11 @@ impl<'a> Parser<'a> {
pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
let mut params = ThinVec::new();
let mut done = false;
let prev = self.parsing_generics;
self.parsing_generics = true;
while !done {
let attrs = self.parse_outer_attributes()?;
let param = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
let param = match self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
if this.eat_keyword_noexpect(kw::SelfUpper) {
// `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
// as if `Self` never existed.
@ -288,7 +290,13 @@ impl<'a> Parser<'a> {
}
// We just ate the comma, so no need to capture the trailing token.
Ok((param, Trailing::No, UsePreAttrPos::No))
})?;
}) {
Ok(param) => param,
Err(err) => {
self.parsing_generics = prev;
return Err(err);
}
};
if let Some(param) = param {
params.push(param);
@ -296,6 +304,7 @@ impl<'a> Parser<'a> {
break;
}
}
self.parsing_generics = prev;
Ok(params)
}

View file

@ -408,12 +408,11 @@ impl<'a> Parser<'a> {
let insert_span = ident_span.shrink_to_lo();
let ident = if self.token.is_ident()
&& self.token.is_non_reserved_ident()
&& (!is_const || self.look_ahead(1, |t| *t == token::OpenParen))
&& self.look_ahead(1, |t| {
matches!(t.kind, token::Lt | token::OpenBrace | token::OpenParen)
}) {
self.parse_ident().unwrap()
self.parse_ident_common(true).unwrap()
} else {
return Ok(());
};

View file

@ -175,17 +175,17 @@ pub enum Recovery {
pub struct Parser<'a> {
pub psess: &'a ParseSess,
/// The current token.
pub token: Token,
pub token: Token = Token::dummy(),
/// The spacing for the current token.
token_spacing: Spacing,
token_spacing: Spacing = Spacing::Alone,
/// The previous token.
pub prev_token: Token,
pub capture_cfg: bool,
restrictions: Restrictions,
expected_token_types: TokenTypeSet,
pub prev_token: Token = Token::dummy(),
pub capture_cfg: bool = false,
restrictions: Restrictions = Restrictions::empty(),
expected_token_types: TokenTypeSet = TokenTypeSet::new(),
token_cursor: TokenCursor,
// The number of calls to `bump`, i.e. the position in the token stream.
num_bump_calls: u32,
num_bump_calls: u32 = 0,
// During parsing we may sometimes need to "unglue" a glued token into two
// or three component tokens (e.g. `>>` into `>` and `>`, or `>>=` into `>`
// and `>` and `=`), so the parser can consume them one at a time. This
@ -204,25 +204,27 @@ pub struct Parser<'a> {
//
// This value is always 0, 1, or 2. It can only reach 2 when splitting
// `>>=` or `<<=`.
break_last_token: u32,
break_last_token: u32 = 0,
/// This field is used to keep track of how many left angle brackets we have seen. This is
/// required in order to detect extra leading left angle brackets (`<` characters) and error
/// appropriately.
///
/// See the comments in the `parse_path_segment` function for more details.
unmatched_angle_bracket_count: u16,
angle_bracket_nesting: u16,
unmatched_angle_bracket_count: u16 = 0,
angle_bracket_nesting: u16 = 0,
/// Keep track of when we're within `<...>` for proper error recovery.
parsing_generics: bool = false,
last_unexpected_token_span: Option<Span>,
last_unexpected_token_span: Option<Span> = None,
/// If present, this `Parser` is not parsing Rust code but rather a macro call.
subparser_name: Option<&'static str>,
capture_state: CaptureState,
/// This allows us to recover when the user forget to add braces around
/// multiple statements in the closure body.
current_closure: Option<ClosureSpans>,
current_closure: Option<ClosureSpans> = None,
/// Whether the parser is allowed to do recovery.
/// This is disabled when parsing macro arguments, see #103534
recovery: Recovery,
recovery: Recovery = Recovery::Allowed,
}
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with
@ -351,18 +353,7 @@ impl<'a> Parser<'a> {
) -> Self {
let mut parser = Parser {
psess,
token: Token::dummy(),
token_spacing: Spacing::Alone,
prev_token: Token::dummy(),
capture_cfg: false,
restrictions: Restrictions::empty(),
expected_token_types: TokenTypeSet::new(),
token_cursor: TokenCursor { curr: TokenTreeCursor::new(stream), stack: Vec::new() },
num_bump_calls: 0,
break_last_token: 0,
unmatched_angle_bracket_count: 0,
angle_bracket_nesting: 0,
last_unexpected_token_span: None,
subparser_name,
capture_state: CaptureState {
capturing: Capturing::No,
@ -370,8 +361,7 @@ impl<'a> Parser<'a> {
inner_attr_parser_ranges: Default::default(),
seen_attrs: IntervalSet::new(u32::MAX as usize),
},
current_closure: None,
recovery: Recovery::Allowed,
..
};
// Make parser point to the first token.
@ -469,7 +459,7 @@ impl<'a> Parser<'a> {
self.parse_ident_common(self.may_recover())
}
fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
pub(crate) fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err(recover)?;
if is_raw == IdentIsRaw::No && ident.is_reserved() {

View file

@ -1669,7 +1669,6 @@ impl<'a> Parser<'a> {
Ok((fields, etc))
}
#[deny(rustc::untranslatable_diagnostic)]
fn report_misplaced_at_in_struct_pat(&self, prev_field: Ident) -> Diag<'a> {
debug_assert_eq!(self.token, token::At);
let span = prev_field.span.to(self.token.span);

View file

@ -184,7 +184,6 @@ impl<T: Write> Write for Shared<T> {
}
}
#[allow(rustc::untranslatable_diagnostic)] // no translation needed for tests
fn test_harness(
file_text: &str,
span_labels: Vec<SpanLabel>,

View file

@ -585,7 +585,7 @@ macro_rules! exp {
pub(super) struct TokenTypeSet(u128);
impl TokenTypeSet {
pub(super) fn new() -> TokenTypeSet {
pub(super) const fn new() -> TokenTypeSet {
TokenTypeSet(0)
}

View file

@ -1488,14 +1488,44 @@ impl<'a> Parser<'a> {
return Ok(());
}
let snapshot = if self.parsing_generics {
// The snapshot is only relevant if we're parsing the generics of an `fn` to avoid
// incorrect recovery.
Some(self.create_snapshot_for_diagnostic())
} else {
None
};
// Parse `(T, U) -> R`.
let inputs_lo = self.token.span;
let mode =
FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
let inputs: ThinVec<_> =
self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect();
let params = match self.parse_fn_params(&mode) {
Ok(params) => params,
Err(err) => {
if let Some(snapshot) = snapshot {
self.restore_snapshot(snapshot);
err.cancel();
return Ok(());
} else {
return Err(err);
}
}
};
let inputs: ThinVec<_> = params.into_iter().map(|input| input.ty).collect();
let inputs_span = inputs_lo.to(self.prev_token.span);
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)
{
Ok(output) => output,
Err(err) => {
if let Some(snapshot) = snapshot {
self.restore_snapshot(snapshot);
err.cancel();
return Ok(());
} else {
return Err(err);
}
}
};
let args = ast::ParenthesizedArgs {
span: fn_path_segment.span().to(self.prev_token.span),
inputs,
@ -1503,6 +1533,17 @@ impl<'a> Parser<'a> {
output,
}
.into();
if let Some(snapshot) = snapshot
&& ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)
{
// We would expect another bound or the end of type params by now. Most likely we've
// encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s
// argument list where the generic param list wasn't properly closed.
self.restore_snapshot(snapshot);
return Ok(());
}
*fn_path_segment = ast::PathSegment {
ident: fn_path_segment.ident,
args: Some(args),

View file

@ -266,7 +266,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcNoImplicitAutorefs
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
| AttributeKind::RustcLintDiagnostics
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
| AttributeKind::RustcLintOptTy
| AttributeKind::RustcLintQueryInstability
@ -1692,7 +1691,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let hir_sig = tcx.hir_fn_sig_by_hir_id(hir_id);
if let Some(hir_sig) = hir_sig {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
match terr {
TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
if let Some(ty) = hir_sig.decl.inputs.get(idx) {

View file

@ -3,8 +3,6 @@
//! [`rustc`] module.
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![allow(unused_crate_dependencies)]
// tidy-alphabetical-end

View file

@ -612,9 +612,6 @@ pub fn print_query_stack<Qcx: QueryContext>(
};
if Some(count_printed) < limit_frames || limit_frames.is_none() {
// Only print to stderr as many stack frames as `num_frames` when present.
// FIXME: needs translation
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
dcx.struct_failure_note(format!(
"#{} [{:?}] {}",
count_printed, query_info.query.dep_kind, query_info.query.description

View file

@ -8,8 +8,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(arbitrary_self_types)]
#![feature(assert_matches)]
#![feature(box_patterns)]

View file

@ -1138,7 +1138,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
errors::OutOfScopeMacroCalls {
span: path.span,
path: pprust::path_to_string(path),
// FIXME: Make this translatable.
location,
},
);

View file

@ -1,8 +1,6 @@
//! Contains infrastructure for configuring the compiler, including parsing
//! command-line options.
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
};

View file

@ -49,7 +49,6 @@ pub(crate) fn split_extern_opt<'a>(
));
let adjusted_name = crate_name.replace('-', "_");
if is_ascii_ident(&adjusted_name) {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
error
.help(format!("consider replacing the dashes with underscores: `{adjusted_name}`"));
}

View file

@ -213,7 +213,6 @@ fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nigh
.join(", ");
let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
#[allow(rustc::diagnostic_outside_of_impl)]
diag.help(format!("valid print requests are: {prints}"));
if req == "lints" {

View file

@ -724,7 +724,6 @@ impl<O> OptionDesc<O> {
}
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn build_options<O: Default>(
early_dcx: &EarlyDiagCtxt,
matches: &getopts::Matches,

View file

@ -132,8 +132,6 @@ pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'stat
///
/// This variant allows you to control whether it is a library or language feature.
/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
#[track_caller]
pub fn feature_warn_issue(
sess: &Session,
@ -171,7 +169,6 @@ pub fn add_feature_diagnostics<G: EmissionGuarantee>(
/// This variant allows you to control whether it is a library or language feature.
/// Almost always, you want to use this for a language feature. If so, prefer
/// `add_feature_diagnostics`.
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
err: &mut Diag<'_, G>,
sess: &Session,

Some files were not shown because too many files have changed in this diff Show more