Skip to content

Commit cb9b68f

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 55b512c commit cb9b68f

File tree

2 files changed

+352
-102
lines changed

2 files changed

+352
-102
lines changed

compiler/rustc_lint/src/lints.rs

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

1953+
pub(crate) struct ImproperCTypesLayer<'a> {
1954+
pub ty: Ty<'a>,
1955+
pub inner_ty: Option<Ty<'a>>,
1956+
pub note: DiagMessage,
1957+
pub span_note: Option<Span>,
1958+
pub help: Option<DiagMessage>,
1959+
}
1960+
1961+
impl<'a> Subdiagnostic for ImproperCTypesLayer<'a> {
1962+
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1963+
diag.arg("ty", self.ty);
1964+
if let Some(ty) = self.inner_ty {
1965+
diag.arg("inner_ty", ty);
1966+
}
1967+
1968+
if let Some(help) = self.help {
1969+
diag.help(diag.eagerly_translate(help));
1970+
}
1971+
1972+
diag.note(diag.eagerly_translate(self.note));
1973+
if let Some(note) = self.span_note {
1974+
diag.span_note(note, fluent::lint_note);
1975+
};
1976+
1977+
diag.remove_arg("ty");
1978+
if self.inner_ty.is_some() {
1979+
diag.remove_arg("inner_ty");
1980+
}
1981+
}
1982+
}
1983+
19531984
pub(crate) struct ImproperCTypes<'a> {
19541985
pub ty: Ty<'a>,
19551986
pub desc: &'a str,
19561987
pub label: Span,
1957-
pub help: Option<DiagMessage>,
1958-
pub note: DiagMessage,
1959-
pub span_note: Option<Span>,
1988+
pub reasons: Vec<ImproperCTypesLayer<'a>>,
19601989
}
19611990

19621991
// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
19631992
impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
19641993
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
19651994
diag.primary_message(fluent::lint_improper_ctypes);
1966-
diag.arg("ty", self.ty);
1967-
diag.arg("desc", self.desc);
19681995
diag.span_label(self.label, fluent::lint_label);
1969-
if let Some(help) = self.help {
1970-
diag.help(help);
1971-
}
1972-
diag.note(self.note);
1973-
if let Some(note) = self.span_note {
1974-
diag.span_note(note, fluent::lint_note);
1996+
for reason in self.reasons.into_iter() {
1997+
diag.subdiagnostic(reason);
19751998
}
1999+
// declare the arguments at the end to avoid them being clobbered in the subdiagnostics
2000+
diag.arg("ty", self.ty);
2001+
diag.arg("desc", self.desc);
19762002
}
19772003
}
19782004

0 commit comments

Comments
 (0)