Skip to content

Commit 400f435

Browse files
authored
Rollup merge of #98420 - davidtwco:translation-lint-fixes-and-more-migration, r=compiler-errors
translation: lint fix + more migration - Unfortunately, the diagnostic lints are very broken and trigger much more often than they should. This PR corrects the conditional which checks if the function call being made is to a diagnostic function so that it returns in every intended case. - The `rustc_lint_diagnostics` attribute is used by the diagnostic translation/struct migration lints to identify calls where non-translatable diagnostics or diagnostics outwith impls are being created. Any function used in creating a diagnostic should be annotated with this attribute so this PR adds the attribute to many more functions. - Port the diagnostics from the `rustc_privacy` crate and enable the lints for that crate. r? ``@compiler-errors``
2 parents 56b7786 + 15d61d7 commit 400f435

File tree

14 files changed

+188
-47
lines changed

14 files changed

+188
-47
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4280,6 +4280,7 @@ dependencies = [
42804280
"rustc_data_structures",
42814281
"rustc_errors",
42824282
"rustc_hir",
4283+
"rustc_macros",
42834284
"rustc_middle",
42844285
"rustc_session",
42854286
"rustc_span",

compiler/rustc_borrowck/src/borrowck_errors.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan};
1+
use rustc_errors::{
2+
struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
3+
};
24
use rustc_middle::ty::{self, Ty, TyCtxt};
35
use rustc_span::Span;
46

@@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
476478
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
477479
}
478480

481+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
479482
fn struct_span_err_with_code<S: Into<MultiSpan>>(
480483
&self,
481484
sp: S,
482-
msg: &str,
485+
msg: impl Into<DiagnosticMessage>,
483486
code: DiagnosticId,
484487
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
485488
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)

compiler/rustc_borrowck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(let_else)]
77
#![feature(min_specialization)]
88
#![feature(never_type)]
9+
#![feature(rustc_attrs)]
910
#![feature(stmt_expr_attributes)]
1011
#![feature(trusted_step)]
1112
#![feature(try_blocks)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
2+
privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private
3+
privacy-field-is-private-label = private field
4+
5+
privacy-item-is-private = {$kind} `{$descr}` is private
6+
.label = private {$kind}
7+
privacy-unnamed-item-is-private = {$kind} is private
8+
.label = private {$kind}
9+
10+
privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface
11+
.label = can't leak {$vis_descr} {$kind}
12+
.visibility-label = `{$descr}` declared as {$vis_descr}

compiler/rustc_error_messages/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
3232
// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
3333
fluent_messages! {
3434
parser => "../locales/en-US/parser.ftl",
35+
privacy => "../locales/en-US/privacy.ftl",
3536
typeck => "../locales/en-US/typeck.ftl",
3637
builtin_macros => "../locales/en-US/builtin_macros.ftl",
3738
}

compiler/rustc_expand/src/base.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> {
10771077
self.current_expansion.id.expansion_cause()
10781078
}
10791079

1080+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
10801081
pub fn struct_span_err<S: Into<MultiSpan>>(
10811082
&self,
10821083
sp: S,
@@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> {
11011102
///
11021103
/// Compilation will be stopped in the near future (at the end of
11031104
/// the macro expansion phase).
1105+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
11041106
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
11051107
self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
11061108
}
1109+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
11071110
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
11081111
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
11091112
}

compiler/rustc_expand/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![feature(proc_macro_diagnostic)]
1010
#![feature(proc_macro_internals)]
1111
#![feature(proc_macro_span)]
12+
#![feature(rustc_attrs)]
1213
#![feature(try_blocks)]
1314
#![recursion_limit = "256"]
1415

compiler/rustc_lint/src/internal.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics {
406406
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
407407
let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
408408
debug!(?span, ?def_id, ?substs);
409-
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
410-
!cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
411-
{
409+
let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
410+
.ok()
411+
.and_then(|inst| inst)
412+
.map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
413+
.unwrap_or(false);
414+
if !has_attr {
412415
return;
413416
}
414417

compiler/rustc_parse/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(let_chains)]
77
#![feature(let_else)]
88
#![feature(never_type)]
9+
#![feature(rustc_attrs)]
910
#![recursion_limit = "256"]
1011

1112
#[macro_use]

compiler/rustc_parse/src/parser/diagnostics.rs

+2
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
357357
}
358358

359359
impl<'a> Parser<'a> {
360+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
360361
pub(super) fn span_err<S: Into<MultiSpan>>(
361362
&self,
362363
sp: S,
@@ -365,6 +366,7 @@ impl<'a> Parser<'a> {
365366
err.span_err(sp, self.diagnostic())
366367
}
367368

369+
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
368370
pub fn struct_span_err<S: Into<MultiSpan>>(
369371
&self,
370372
sp: S,

compiler/rustc_privacy/Cargo.toml

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ version = "0.0.0"
44
edition = "2021"
55

66
[dependencies]
7-
rustc_middle = { path = "../rustc_middle" }
87
rustc_ast = { path = "../rustc_ast" }
98
rustc_attr = { path = "../rustc_attr" }
9+
rustc_data_structures = { path = "../rustc_data_structures" }
1010
rustc_errors = { path = "../rustc_errors" }
1111
rustc_hir = { path = "../rustc_hir" }
12-
rustc_typeck = { path = "../rustc_typeck" }
12+
rustc_macros = { path = "../rustc_macros" }
13+
rustc_middle = { path = "../rustc_middle" }
1314
rustc_session = { path = "../rustc_session" }
1415
rustc_span = { path = "../rustc_span" }
15-
rustc_data_structures = { path = "../rustc_data_structures" }
1616
rustc_trait_selection = { path = "../rustc_trait_selection" }
17+
rustc_typeck = { path = "../rustc_typeck" }
1718
tracing = "0.1"

compiler/rustc_privacy/src/errors.rs

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
2+
use rustc_span::{Span, Symbol};
3+
4+
#[derive(SessionDiagnostic)]
5+
#[error(privacy::field_is_private, code = "E0451")]
6+
pub struct FieldIsPrivate {
7+
#[primary_span]
8+
pub span: Span,
9+
pub field_name: Symbol,
10+
pub variant_descr: &'static str,
11+
pub def_path_str: String,
12+
#[subdiagnostic]
13+
pub label: FieldIsPrivateLabel,
14+
}
15+
16+
#[derive(SessionSubdiagnostic)]
17+
pub enum FieldIsPrivateLabel {
18+
#[label(privacy::field_is_private_is_update_syntax_label)]
19+
IsUpdateSyntax {
20+
#[primary_span]
21+
span: Span,
22+
field_name: Symbol,
23+
},
24+
#[label(privacy::field_is_private_label)]
25+
Other {
26+
#[primary_span]
27+
span: Span,
28+
},
29+
}
30+
31+
#[derive(SessionDiagnostic)]
32+
#[error(privacy::item_is_private)]
33+
pub struct ItemIsPrivate<'a> {
34+
#[primary_span]
35+
#[label]
36+
pub span: Span,
37+
pub kind: &'a str,
38+
pub descr: String,
39+
}
40+
41+
#[derive(SessionDiagnostic)]
42+
#[error(privacy::unnamed_item_is_private)]
43+
pub struct UnnamedItemIsPrivate {
44+
#[primary_span]
45+
pub span: Span,
46+
pub kind: &'static str,
47+
}
48+
49+
// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
50+
#[derive(SessionDiagnostic)]
51+
#[error(privacy::in_public_interface, code = "E0445")]
52+
pub struct InPublicInterfaceTraits<'a> {
53+
#[primary_span]
54+
#[label]
55+
pub span: Span,
56+
pub vis_descr: &'static str,
57+
pub kind: &'a str,
58+
pub descr: String,
59+
#[label(privacy::visibility_label)]
60+
pub vis_span: Span,
61+
}
62+
63+
// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
64+
#[derive(SessionDiagnostic)]
65+
#[error(privacy::in_public_interface, code = "E0446")]
66+
pub struct InPublicInterface<'a> {
67+
#[primary_span]
68+
#[label]
69+
pub span: Span,
70+
pub vis_descr: &'static str,
71+
pub kind: &'a str,
72+
pub descr: String,
73+
#[label(privacy::visibility_label)]
74+
pub vis_span: Span,
75+
}

compiler/rustc_privacy/src/lib.rs

+53-39
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
2+
#![feature(associated_type_defaults)]
23
#![feature(control_flow_enum)]
4+
#![feature(rustc_private)]
35
#![feature(try_blocks)]
4-
#![feature(associated_type_defaults)]
56
#![recursion_limit = "256"]
67
#![allow(rustc::potential_query_instability)]
8+
#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))]
9+
#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))]
10+
11+
mod errors;
712

813
use rustc_ast::MacroDef;
914
use rustc_attr as attr;
1015
use rustc_data_structures::fx::FxHashSet;
1116
use rustc_data_structures::intern::Interned;
12-
use rustc_errors::struct_span_err;
1317
use rustc_hir as hir;
1418
use rustc_hir::def::{DefKind, Res};
1519
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
@@ -34,6 +38,11 @@ use std::marker::PhantomData;
3438
use std::ops::ControlFlow;
3539
use std::{cmp, fmt, mem};
3640

41+
use errors::{
42+
FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate,
43+
UnnamedItemIsPrivate,
44+
};
45+
3746
////////////////////////////////////////////////////////////////////////////////
3847
/// Generic infrastructure used to implement specific visitors below.
3948
////////////////////////////////////////////////////////////////////////////////
@@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
935944
let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
936945
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
937946
if !field.vis.is_accessible_from(def_id, self.tcx) {
938-
let label = if in_update_syntax {
939-
format!("field `{}` is private", field.name)
940-
} else {
941-
"private field".to_string()
942-
};
943-
944-
struct_span_err!(
945-
self.tcx.sess,
947+
self.tcx.sess.emit_err(FieldIsPrivate {
946948
span,
947-
E0451,
948-
"field `{}` of {} `{}` is private",
949-
field.name,
950-
def.variant_descr(),
951-
self.tcx.def_path_str(def.did())
952-
)
953-
.span_label(span, label)
954-
.emit();
949+
field_name: field.name,
950+
variant_descr: def.variant_descr(),
951+
def_path_str: self.tcx.def_path_str(def.did()),
952+
label: if in_update_syntax {
953+
FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name }
954+
} else {
955+
FieldIsPrivateLabel::Other { span }
956+
},
957+
});
955958
}
956959
}
957960
}
@@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
10751078
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
10761079
let is_error = !self.item_is_accessible(def_id);
10771080
if is_error {
1078-
self.tcx
1079-
.sess
1080-
.struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
1081-
.span_label(self.span, &format!("private {}", kind))
1082-
.emit();
1081+
self.tcx.sess.emit_err(ItemIsPrivate {
1082+
span: self.span,
1083+
kind,
1084+
descr: descr.to_string(),
1085+
});
10831086
}
10841087
is_error
10851088
}
@@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
12501253
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
12511254
};
12521255
let kind = kind.descr(def_id);
1253-
let msg = match name {
1254-
Some(name) => format!("{} `{}` is private", kind, name),
1255-
None => format!("{} is private", kind),
1256+
let _ = match name {
1257+
Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }),
1258+
None => sess.emit_err(UnnamedItemIsPrivate { span, kind }),
12561259
};
1257-
sess.struct_span_err(span, &msg)
1258-
.span_label(span, &format!("private {}", kind))
1259-
.emit();
12601260
return;
12611261
}
12621262
}
@@ -1753,30 +1753,44 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
17531753
}
17541754
}
17551755
};
1756-
let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
17571756
let span = self.tcx.def_span(self.item_def_id.to_def_id());
17581757
if self.has_old_errors
17591758
|| self.in_assoc_ty
17601759
|| self.tcx.resolutions(()).has_pub_restricted
17611760
{
1762-
let mut err = if kind == "trait" {
1763-
struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
1764-
} else {
1765-
struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
1766-
};
1761+
let descr = descr.to_string();
17671762
let vis_span =
17681763
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
1769-
err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
1770-
err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
1771-
err.emit();
1764+
if kind == "trait" {
1765+
self.tcx.sess.emit_err(InPublicInterfaceTraits {
1766+
span,
1767+
vis_descr,
1768+
kind,
1769+
descr,
1770+
vis_span,
1771+
});
1772+
} else {
1773+
self.tcx.sess.emit_err(InPublicInterface {
1774+
span,
1775+
vis_descr,
1776+
kind,
1777+
descr,
1778+
vis_span,
1779+
});
1780+
}
17721781
} else {
17731782
let err_code = if kind == "trait" { "E0445" } else { "E0446" };
17741783
self.tcx.struct_span_lint_hir(
17751784
lint::builtin::PRIVATE_IN_PUBLIC,
17761785
hir_id,
17771786
span,
17781787
|lint| {
1779-
lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
1788+
lint.build(&format!(
1789+
"{} (error {})",
1790+
format!("{} {} `{}` in public interface", vis_descr, kind, descr),
1791+
err_code
1792+
))
1793+
.emit();
17801794
},
17811795
);
17821796
}

0 commit comments

Comments
 (0)