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``
This commit is contained in:
Dylan DPC 2022-06-28 15:30:04 +05:30 committed by GitHub
commit 400f435c2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 189 additions and 48 deletions

View File

@ -4280,6 +4280,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",

View File

@ -1,4 +1,6 @@
use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed, MultiSpan};
use rustc_errors::{
struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
@ -476,10 +478,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
msg: &str,
msg: impl Into<DiagnosticMessage>,
code: DiagnosticId,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)

View File

@ -6,6 +6,7 @@
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![feature(try_blocks)]

View File

@ -0,0 +1,12 @@
privacy-field-is-private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private
privacy-field-is-private-is-update-syntax-label = field `{$field_name}` is private
privacy-field-is-private-label = private field
privacy-item-is-private = {$kind} `{$descr}` is private
.label = private {$kind}
privacy-unnamed-item-is-private = {$kind} is private
.label = private {$kind}
privacy-in-public-interface = {$vis_descr} {$kind} `{$descr}` in public interface
.label = can't leak {$vis_descr} {$kind}
.visibility-label = `{$descr}` declared as {$vis_descr}

View File

@ -32,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
fluent_messages! {
parser => "../locales/en-US/parser.ftl",
privacy => "../locales/en-US/privacy.ftl",
typeck => "../locales/en-US/typeck.ftl",
builtin_macros => "../locales/en-US/builtin_macros.ftl",
}

View File

@ -1077,6 +1077,7 @@ impl<'a> ExtCtxt<'a> {
self.current_expansion.id.expansion_cause()
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -1101,9 +1102,11 @@ impl<'a> ExtCtxt<'a> {
///
/// Compilation will be stopped in the near future (at the end of
/// the macro expansion phase).
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
}

View File

@ -9,6 +9,7 @@
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]
#![feature(rustc_attrs)]
#![feature(try_blocks)]
#![recursion_limit = "256"]

View File

@ -406,9 +406,12 @@ impl LateLintPass<'_> for Diagnostics {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
let Some((span, def_id, substs)) = typeck_results_of_method_fn(cx, expr) else { return };
debug!(?span, ?def_id, ?substs);
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) &&
!cx.tcx.has_attr(instance.def_id(), sym::rustc_lint_diagnostics)
{
let has_attr = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs)
.ok()
.and_then(|inst| inst)
.map(|inst| cx.tcx.has_attr(inst.def_id(), sym::rustc_lint_diagnostics))
.unwrap_or(false);
if !has_attr {
return;
}

View File

@ -6,6 +6,7 @@
#![feature(let_chains)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -357,6 +357,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
}
impl<'a> Parser<'a> {
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub(super) fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -365,6 +366,7 @@ impl<'a> Parser<'a> {
err.span_err(sp, self.diagnostic())
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,

View File

@ -4,14 +4,15 @@ version = "0.0.0"
edition = "2021"
[dependencies]
rustc_middle = { path = "../rustc_middle" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
rustc_typeck = { path = "../rustc_typeck" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_typeck = { path = "../rustc_typeck" }
tracing = "0.1"

View File

@ -0,0 +1,75 @@
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
use rustc_span::{Span, Symbol};
#[derive(SessionDiagnostic)]
#[error(privacy::field_is_private, code = "E0451")]
pub struct FieldIsPrivate {
#[primary_span]
pub span: Span,
pub field_name: Symbol,
pub variant_descr: &'static str,
pub def_path_str: String,
#[subdiagnostic]
pub label: FieldIsPrivateLabel,
}
#[derive(SessionSubdiagnostic)]
pub enum FieldIsPrivateLabel {
#[label(privacy::field_is_private_is_update_syntax_label)]
IsUpdateSyntax {
#[primary_span]
span: Span,
field_name: Symbol,
},
#[label(privacy::field_is_private_label)]
Other {
#[primary_span]
span: Span,
},
}
#[derive(SessionDiagnostic)]
#[error(privacy::item_is_private)]
pub struct ItemIsPrivate<'a> {
#[primary_span]
#[label]
pub span: Span,
pub kind: &'a str,
pub descr: String,
}
#[derive(SessionDiagnostic)]
#[error(privacy::unnamed_item_is_private)]
pub struct UnnamedItemIsPrivate {
#[primary_span]
pub span: Span,
pub kind: &'static str,
}
// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
#[derive(SessionDiagnostic)]
#[error(privacy::in_public_interface, code = "E0445")]
pub struct InPublicInterfaceTraits<'a> {
#[primary_span]
#[label]
pub span: Span,
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: String,
#[label(privacy::visibility_label)]
pub vis_span: Span,
}
// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
#[derive(SessionDiagnostic)]
#[error(privacy::in_public_interface, code = "E0446")]
pub struct InPublicInterface<'a> {
#[primary_span]
#[label]
pub span: Span,
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: String,
#[label(privacy::visibility_label)]
pub vis_span: Span,
}

View File

@ -1,15 +1,19 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(control_flow_enum)]
#![feature(try_blocks)]
#![feature(associated_type_defaults)]
#![feature(control_flow_enum)]
#![feature(rustc_private)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![cfg_attr(not(bootstrap), deny(rustc::untranslatable_diagnostic))]
#![cfg_attr(not(bootstrap), deny(rustc::diagnostic_outside_of_impl))]
mod errors;
use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
@ -34,6 +38,11 @@ use std::marker::PhantomData;
use std::ops::ControlFlow;
use std::{cmp, fmt, mem};
use errors::{
FieldIsPrivate, FieldIsPrivateLabel, InPublicInterface, InPublicInterfaceTraits, ItemIsPrivate,
UnnamedItemIsPrivate,
};
////////////////////////////////////////////////////////////////////////////////
/// Generic infrastructure used to implement specific visitors below.
////////////////////////////////////////////////////////////////////////////////
@ -935,23 +944,17 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.current_item);
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
if !field.vis.is_accessible_from(def_id, self.tcx) {
let label = if in_update_syntax {
format!("field `{}` is private", field.name)
} else {
"private field".to_string()
};
struct_span_err!(
self.tcx.sess,
self.tcx.sess.emit_err(FieldIsPrivate {
span,
E0451,
"field `{}` of {} `{}` is private",
field.name,
def.variant_descr(),
self.tcx.def_path_str(def.did())
)
.span_label(span, label)
.emit();
field_name: field.name,
variant_descr: def.variant_descr(),
def_path_str: self.tcx.def_path_str(def.did()),
label: if in_update_syntax {
FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name }
} else {
FieldIsPrivateLabel::Other { span }
},
});
}
}
}
@ -1075,11 +1078,11 @@ impl<'tcx> TypePrivacyVisitor<'tcx> {
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
let is_error = !self.item_is_accessible(def_id);
if is_error {
self.tcx
.sess
.struct_span_err(self.span, &format!("{} `{}` is private", kind, descr))
.span_label(self.span, &format!("private {}", kind))
.emit();
self.tcx.sess.emit_err(ItemIsPrivate {
span: self.span,
kind,
descr: descr.to_string(),
});
}
is_error
}
@ -1250,13 +1253,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
};
let kind = kind.descr(def_id);
let msg = match name {
Some(name) => format!("{} `{}` is private", kind, name),
None => format!("{} is private", kind),
let _ = match name {
Some(name) => sess.emit_err(ItemIsPrivate { span, kind, descr: name }),
None => sess.emit_err(UnnamedItemIsPrivate { span, kind }),
};
sess.struct_span_err(span, &msg)
.span_label(span, &format!("private {}", kind))
.emit();
return;
}
}
@ -1753,22 +1753,31 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
}
}
};
let make_msg = || format!("{} {} `{}` in public interface", vis_descr, kind, descr);
let span = self.tcx.def_span(self.item_def_id.to_def_id());
if self.has_old_errors
|| self.in_assoc_ty
|| self.tcx.resolutions(()).has_pub_restricted
{
let mut err = if kind == "trait" {
struct_span_err!(self.tcx.sess, span, E0445, "{}", make_msg())
} else {
struct_span_err!(self.tcx.sess, span, E0446, "{}", make_msg())
};
let descr = descr.to_string();
let vis_span =
self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id));
err.span_label(span, format!("can't leak {} {}", vis_descr, kind));
err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr));
err.emit();
if kind == "trait" {
self.tcx.sess.emit_err(InPublicInterfaceTraits {
span,
vis_descr,
kind,
descr,
vis_span,
});
} else {
self.tcx.sess.emit_err(InPublicInterface {
span,
vis_descr,
kind,
descr,
vis_span,
});
}
} else {
let err_code = if kind == "trait" { "E0445" } else { "E0446" };
self.tcx.struct_span_lint_hir(
@ -1776,7 +1785,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
hir_id,
span,
|lint| {
lint.build(&format!("{} (error {})", make_msg(), err_code)).emit();
lint.build(&format!(
"{} (error {})",
format!("{} {} `{}` in public interface", vis_descr, kind, descr),
err_code
))
.emit();
},
);
}

View File

@ -280,6 +280,7 @@ impl Session {
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
@ -287,6 +288,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
@ -295,6 +297,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -303,9 +306,11 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
@ -313,6 +318,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
@ -320,9 +326,11 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_span_allow(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
@ -330,6 +338,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_expect(msg, id)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -337,6 +346,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.diagnostic().struct_span_err(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -346,12 +356,14 @@ impl Session {
self.diagnostic().struct_span_err_with_code(sp, msg, code)
}
// FIXME: This method should be removed (every error should have an associated error code).
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.parse_sess.struct_err(msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@ -359,6 +371,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.diagnostic().struct_err_with_code(msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@ -366,6 +379,7 @@ impl Session {
) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn_with_code(msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
@ -373,6 +387,7 @@ impl Session {
) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_span_fatal(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -381,13 +396,16 @@ impl Session {
) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_fatal(msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -396,9 +414,11 @@ impl Session {
) -> ! {
self.diagnostic().span_fatal_with_code(sp, msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().fatal(msg).raise()
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
@ -411,6 +431,7 @@ impl Session {
self.span_err(sp, msg);
}
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@ -418,6 +439,7 @@ impl Session {
) -> ErrorGuaranteed {
self.diagnostic().span_err(sp, msg)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@ -426,6 +448,7 @@ impl Session {
) {
self.diagnostic().span_err_with_code(sp, msg, code)
}
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}