Skip to content

Commit 5fd5882

Browse files
committed
ImproperCTypes: add architecture for layered reasoning in lints
Another change that only impacts rustc developers: Added the necessary changes so that lints are able to specify in detail "A in unsafe because of its B field, which in turn is unsafe because of C, etc", and possibly specify multiple help messages (multiple ways to reach FFI-safety)
1 parent 585945c commit 5fd5882

File tree

2 files changed

+332
-89
lines changed

2 files changed

+332
-89
lines changed

compiler/rustc_lint/src/lints.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,29 +1943,55 @@ pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> {
19431943
},
19441944
}
19451945

1946+
pub(crate) struct ImproperCTypesLayer<'a> {
1947+
pub ty: Ty<'a>,
1948+
pub inner_ty: Option<Ty<'a>>,
1949+
pub note: DiagMessage,
1950+
pub span_note: Option<Span>,
1951+
pub help: Option<DiagMessage>,
1952+
}
1953+
1954+
impl<'a> Subdiagnostic for ImproperCTypesLayer<'a> {
1955+
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1956+
diag.arg("ty", self.ty);
1957+
if let Some(ty) = self.inner_ty {
1958+
diag.arg("inner_ty", ty);
1959+
}
1960+
1961+
if let Some(help) = self.help {
1962+
diag.help(diag.eagerly_translate(help));
1963+
}
1964+
1965+
diag.note(diag.eagerly_translate(self.note));
1966+
if let Some(note) = self.span_note {
1967+
diag.span_note(note, fluent::lint_note);
1968+
};
1969+
1970+
diag.remove_arg("ty");
1971+
if self.inner_ty.is_some() {
1972+
diag.remove_arg("inner_ty");
1973+
}
1974+
}
1975+
}
1976+
19461977
pub(crate) struct ImproperCTypes<'a> {
19471978
pub ty: Ty<'a>,
19481979
pub desc: &'a str,
19491980
pub label: Span,
1950-
pub help: Option<DiagMessage>,
1951-
pub note: DiagMessage,
1952-
pub span_note: Option<Span>,
1981+
pub reasons: Vec<ImproperCTypesLayer<'a>>,
19531982
}
19541983

19551984
// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
19561985
impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
19571986
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
19581987
diag.primary_message(fluent::lint_improper_ctypes);
1959-
diag.arg("ty", self.ty);
1960-
diag.arg("desc", self.desc);
19611988
diag.span_label(self.label, fluent::lint_label);
1962-
if let Some(help) = self.help {
1963-
diag.help(help);
1964-
}
1965-
diag.note(self.note);
1966-
if let Some(note) = self.span_note {
1967-
diag.span_note(note, fluent::lint_note);
1989+
for reason in self.reasons.into_iter() {
1990+
diag.subdiagnostic(reason);
19681991
}
1992+
// declare the arguments at the end to avoid them being clobbered in the subdiagnostics
1993+
diag.arg("ty", self.ty);
1994+
diag.arg("desc", self.desc);
19691995
}
19701996
}
19711997

0 commit comments

Comments
 (0)