Skip to content

Commit

Permalink
Rollup merge of #98420 - davidtwco:translation-lint-fixes-and-more-mi…
Browse files Browse the repository at this point in the history
…gration, 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``
  • Loading branch information
Dylan-DPC authored Jun 28, 2022
2 parents 56b7786 + 15d61d7 commit 400f435
Show file tree
Hide file tree
Showing 14 changed files with 188 additions and 47 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4280,6 +4280,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/borrowck_errors.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/privacy.ftl
Original file line number Diff line number Diff line change
@@ -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}
1 change: 1 addition & 0 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_expand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![feature(let_chains)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_privacy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
75 changes: 75 additions & 0 deletions compiler/rustc_privacy/src/errors.rs
Original file line number Diff line number Diff line change
@@ -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,
}
92 changes: 53 additions & 39 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(associated_type_defaults)]
#![feature(control_flow_enum)]
#![feature(rustc_private)]
#![feature(try_blocks)]
#![feature(associated_type_defaults)]
#![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};
Expand All @@ -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.
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -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 }
},
});
}
}
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -1753,30 +1753,44 @@ 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(
lint::builtin::PRIVATE_IN_PUBLIC,
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();
},
);
}
Expand Down
Loading

0 comments on commit 400f435

Please sign in to comment.