-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invert control in struct_lint_level
#67927
Comments
I'd like to give this a go. @rustbot claim |
Regarding the original suggestion of having pub struct DiagnosticBuilder {
// Keep DiagnosticBuilder the way it currently is ...
}
// But introduce a new proxy type which stores just enough information that methods like
// struct_lint_level can set up things like level and span.
pub struct PendingDiagnosticBuilder<'a> {
handler: &'a Handler,
level: Level,
}
impl PendingDiagnosticBuilder<'_> {
// Only accessible internally to rustc_errors.
crate fn new(
handler: &'a Handler,
level: Level,
span: Option<MultiSpan>,
) -> PendingDiagnosticBuilder<'a> {
PendingDiagnosticBuilder { handler, level }
}
// Only method publicly accessible -- forces the user of the API to explicitly provide a
// message the same way the API currently does.
pub fn into_diagnostic_builder(self, msg: &str) -> DiagnosticBuilder {
DiagnosticBuilder::new(handler, level, msg)
}
}
// struct_lint_level & co get their signature changed to something like this:
pub fn struct_lint_level<'a>(
sess: &'a Session,
lint: &'static Lint,
level: Level,
src: LintSource,
span: Option<MultiSpan>,
set_message: impl Fn(PendingDiagnosticBuilder<'_>) -> DiagnosticBuilder<'_>,
) -> DiagnosticBuilder<'a> {
// ...
}
// then, when calling struct_lint_level in another crate:
rustc::lint::struct_lint_level(session, lint, src, span, |pending_diagnostic| {
pending_diagnostic.into_diagnostic_builder(format!(
"Some diagnostic message which does string formatting: {}",
something_expensive_to_display
))
});
// the API enforces that the caller provides a message. Because `PendingDiagnosticBuilder::new` and
// `DiagnosticBuilder::new` can't be called outside the crate, users of the API can't create their
// own, erroneous DiagnosticBuilder to return, either. I feel like this is worth it, because it achieves the original goal of preventing formatting of lint diagnostics that don't end up emitted, but makes it so the public API stops you from forgetting to add a diagnostic message, which I feel like would be too easy to do with defaulting to Also, I know |
The point of the // defined where `struct_lint_level` is:
struct LintDiagnosticBuilder<'a, 'b>(&'a mut DiagnosticBuilder<'b>);
impl<'a, 'b> LintDiagnosticBuilder<'a, 'b> {
fn build(self, msg: &str) -> &'a mut DiagnosticBuilder<'b> {
let LintDiagnosticBuilder(diag) = self);
diag.set_message(msg);
diag
}
} Also, note that pub fn struct_lint_level<'a>(
sess: &'a Session,
lint: &'static Lint,
level: Level,
src: LintSource,
span: Option<MultiSpan>,
decorate: impl Fn(LintDiagnosticBuilder<'_>),
) {
// ...
} |
It might be a good idea to avoid using |
I don't think this is necessary today. |
I see. Originally, when I posted that, I thought the only way to set the message was on construction, which I thought was a deliberate design decision to ensure a diagnostic's message couldn't accidentally overwritten. I realised later that Diagnostic already has a set_primary_message, which DiagnosticBuilder can already access via DerefMut to Diagnostic. I was having some lifetime issues earlier, trying to have I have a long weekend now, so I'm aiming to get a PR up to close this issue by tonight or tomorrow night. edit: The |
…=<try> Invert control in struct_lint_level. Closes #67927 Changes the `struct_lint*` methods to take a `decorate` function instead of a message string. This decorate function is also responsible for eventually stashing, emitting or cancelling the diagnostic. If the lint was allowed after all, the decorate function is not run at all, saving us from spending time formatting messages (and potentially other expensive work) for lints don't end up being emitted. r? @Centril
…=<try> Invert control in struct_lint_level. Closes #67927 Changes the `struct_lint*` methods to take a `decorate` function instead of a message string. This decorate function is also responsible for eventually stashing, emitting or cancelling the diagnostic. If the lint was allowed after all, the decorate function is not run at all, saving us from spending time formatting messages (and potentially other expensive work) for lints don't end up being emitted. r? @Centril
…=Centril Invert control in struct_lint_level. Closes #67927 Changes the `struct_lint*` methods to take a `decorate` function instead of a message string. This decorate function is also responsible for eventually stashing, emitting or cancelling the diagnostic. If the lint was allowed after all, the decorate function is not run at all, saving us from spending time formatting messages (and potentially other expensive work) for lints don't end up being emitted. r? @Centril
See #67755 (comment).
cc @rust-lang/wg-diagnostics
This issue has been assigned to @jumbatm via this comment.
The text was updated successfully, but these errors were encountered: