Skip to content

Commit ceb0f32

Browse files
committed
Invert control in struct_lint_level.
Caller now passes in a `decorate` function, which is only run if the lint is allowed.
1 parent 0d34a87 commit ceb0f32

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1278
-1110
lines changed

src/librustc/infer/error_reporting/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16701670
sub: Region<'tcx>,
16711671
) {
16721672
self.construct_generic_bound_failure(region_scope_tree, span, origin, bound_kind, sub)
1673-
.emit()
1673+
.emit();
16741674
}
16751675

16761676
pub fn construct_generic_bound_failure(

src/librustc/lint.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_span::hygiene::MacroKind;
1111
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
1212
use rustc_span::{Span, Symbol};
1313

14+
1415
/// How a lint level was set.
1516
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
1617
pub enum LintSource {
@@ -174,20 +175,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
174175
}
175176
}
176177

177-
pub fn struct_lint_level<'a>(
178-
sess: &'a Session,
178+
179+
pub struct LintDiagnosticBuilder<'a>(DiagnosticBuilder<'a>);
180+
181+
impl<'a> LintDiagnosticBuilder<'a> {
182+
/// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
183+
pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
184+
self.0.set_primary_message(msg);
185+
self.0
186+
}
187+
188+
/// Create a LintDiagnosticBuilder from some existing DiagnosticBuilder.
189+
pub fn new(err: DiagnosticBuilder<'a>) -> LintDiagnosticBuilder<'a>{
190+
LintDiagnosticBuilder(err)
191+
}
192+
}
193+
194+
pub fn struct_lint_level<'s>(
195+
sess: &'s Session,
179196
lint: &'static Lint,
180197
level: Level,
181198
src: LintSource,
182199
span: Option<MultiSpan>,
183-
msg: &str,
184-
) -> DiagnosticBuilder<'a> {
200+
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>)) {
201+
202+
// FIXME: Move the guts of this function into a fn which takes dyn Fn to reduce code bloat.
185203
let mut err = match (level, span) {
186-
(Level::Allow, _) => return sess.diagnostic().struct_dummy(),
187-
(Level::Warn, Some(span)) => sess.struct_span_warn(span, msg),
188-
(Level::Warn, None) => sess.struct_warn(msg),
189-
(Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg),
190-
(Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg),
204+
(Level::Allow, _) => { return; },
205+
(Level::Warn, Some(span)) => sess.struct_span_warn(span, ""),
206+
(Level::Warn, None) => sess.struct_warn(""),
207+
(Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, ""),
208+
(Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(""),
191209
};
192210

193211
// Check for future incompatibility lints and issue a stronger warning.
@@ -209,7 +227,7 @@ pub fn struct_lint_level<'a>(
209227
err.cancel();
210228
// Don't continue further, since we don't want to have
211229
// `diag_span_note_once` called for a diagnostic that isn't emitted.
212-
return err;
230+
return;
213231
}
214232
}
215233

@@ -299,7 +317,8 @@ pub fn struct_lint_level<'a>(
299317
err.note(&citation);
300318
}
301319

302-
return err;
320+
// Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
321+
decorate(LintDiagnosticBuilder::new(err));
303322
}
304323

305324
/// Returns whether `span` originates in a foreign crate's external macro.

src/librustc/middle/stability.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,13 @@ fn late_report_deprecation(
222222
return;
223223
}
224224

225-
let mut diag = tcx.struct_span_lint_hir(lint, hir_id, span, message);
226-
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
227-
deprecation_suggestion(&mut diag, suggestion, span);
228-
}
229-
diag.emit();
225+
tcx.struct_span_lint_hir(lint, hir_id, span, |lint| {
226+
let mut diag = lint.build(message);
227+
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
228+
deprecation_suggestion(&mut diag, suggestion, span);
229+
}
230+
diag.emit()
231+
});
230232
if hir_id == hir::DUMMY_HIR_ID {
231233
span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id);
232234
}
@@ -387,8 +389,11 @@ impl<'tcx> TyCtxt<'tcx> {
387389
/// Additionally, this function will also check if the item is deprecated. If so, and `id` is
388390
/// not `None`, a deprecated lint attached to `id` will be emitted.
389391
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
390-
let soft_handler =
391-
|lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg);
392+
let soft_handler = |lint, span, msg: &_| {
393+
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
394+
lint.build(msg).emit()
395+
})
396+
};
392397
match self.eval_stability(def_id, id, span) {
393398
EvalResult::Allow => {}
394399
EvalResult::Deny { feature, reason, issue, is_soft } => {

src/librustc/mir/interpret/error.rs

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,15 @@ impl<'tcx> ConstEvalErr<'tcx> {
8383
&self,
8484
tcx: TyCtxtAt<'tcx>,
8585
message: &str,
86-
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
87-
self.struct_generic(tcx, message, None)
86+
emit: impl FnOnce(DiagnosticBuilder<'_>),
87+
) -> Result<(), ErrorHandled> {
88+
self.struct_generic(tcx, message, emit, None)
8889
}
8990

9091
pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
91-
let err = self.struct_error(tcx, message);
92-
match err {
93-
Ok(mut err) => {
94-
err.emit();
95-
ErrorHandled::Reported
96-
}
97-
Err(err) => err,
92+
match self.struct_error(tcx, message, |mut e| e.emit()) {
93+
Ok(_) => ErrorHandled::Reported,
94+
Err(x) => x,
9895
}
9996
}
10097

@@ -105,9 +102,11 @@ impl<'tcx> ConstEvalErr<'tcx> {
105102
lint_root: hir::HirId,
106103
span: Option<Span>,
107104
) -> ErrorHandled {
108-
let lint = self.struct_generic(tcx, message, Some(lint_root));
109-
match lint {
110-
Ok(mut lint) => {
105+
match self.struct_generic(
106+
tcx,
107+
message,
108+
|mut lint: DiagnosticBuilder<'_>| {
109+
// Apply the span.
111110
if let Some(span) = span {
112111
let primary_spans = lint.span.primary_spans().to_vec();
113112
// point at the actual error as the primary span
@@ -121,18 +120,26 @@ impl<'tcx> ConstEvalErr<'tcx> {
121120
}
122121
}
123122
lint.emit();
123+
}
124+
, Some(lint_root)) {
125+
Ok(_) => {
124126
ErrorHandled::Reported
125127
}
126128
Err(err) => err,
127129
}
128130
}
129131

132+
/// Sets the message passed in via `message`, then adds the span labels for you, before applying
133+
/// further modifications in `emit`. It's up to you to call emit(), stash(..), etc. within the
134+
/// `emit` method. If you don't need to do any additional processing, just use
135+
/// struct_generic.
130136
fn struct_generic(
131137
&self,
132138
tcx: TyCtxtAt<'tcx>,
133139
message: &str,
140+
emit: impl FnOnce(DiagnosticBuilder<'_>),
134141
lint_root: Option<hir::HirId>,
135-
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
142+
) -> Result<(), ErrorHandled> {
136143
let must_error = match self.error {
137144
InterpError::MachineStop(_) => bug!("CTFE does not stop"),
138145
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
@@ -143,7 +150,22 @@ impl<'tcx> ConstEvalErr<'tcx> {
143150
_ => false,
144151
};
145152
trace!("reporting const eval failure at {:?}", self.span);
146-
let mut err = if let (Some(lint_root), false) = (lint_root, must_error) {
153+
154+
let add_span_labels = |err: &mut DiagnosticBuilder<'_>| {
155+
if !must_error {
156+
err.span_label(self.span, self.error.to_string());
157+
}
158+
// Skip the last, which is just the environment of the constant. The stacktrace
159+
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
160+
// on constant values.
161+
if self.stacktrace.len() > 0 {
162+
for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] {
163+
err.span_label(frame_info.call_site, frame_info.to_string());
164+
}
165+
}
166+
};
167+
168+
if let (Some(lint_root), false) = (lint_root, must_error) {
147169
let hir_id = self
148170
.stacktrace
149171
.iter()
@@ -155,25 +177,22 @@ impl<'tcx> ConstEvalErr<'tcx> {
155177
rustc_session::lint::builtin::CONST_ERR,
156178
hir_id,
157179
tcx.span,
158-
message,
159-
)
160-
} else if must_error {
161-
struct_error(tcx, &self.error.to_string())
180+
|lint| {
181+
let mut err = lint.build(message);
182+
add_span_labels(&mut err);
183+
emit(err);
184+
},
185+
);
162186
} else {
163-
struct_error(tcx, message)
187+
let mut err = if must_error {
188+
struct_error(tcx, &self.error.to_string())
189+
} else {
190+
struct_error(tcx, message)
191+
};
192+
add_span_labels(&mut err);
193+
emit(err);
164194
};
165-
if !must_error {
166-
err.span_label(self.span, self.error.to_string());
167-
}
168-
// Skip the last, which is just the environment of the constant. The stacktrace
169-
// is sometimes empty because we create "fake" eval contexts in CTFE to do work
170-
// on constant values.
171-
if self.stacktrace.len() > 0 {
172-
for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] {
173-
err.span_label(frame_info.call_site, frame_info.to_string());
174-
}
175-
}
176-
Ok(err)
195+
Ok(())
177196
}
178197
}
179198

src/librustc/traits/object_safety.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,16 @@ fn object_safety_violations_for_trait(
183183
WHERE_CLAUSES_OBJECT_SAFETY,
184184
hir::CRATE_HIR_ID,
185185
*span,
186-
&format!(
187-
"the trait `{}` cannot be made into an object",
188-
tcx.def_path_str(trait_def_id)
189-
),
190-
)
191-
.note(&violation.error_msg())
192-
.emit();
186+
|lint| {
187+
lint.build(
188+
&format!(
189+
"the trait `{}` cannot be made into an object",
190+
tcx.def_path_str(trait_def_id)
191+
))
192+
.note(&violation.error_msg())
193+
.emit()
194+
},
195+
);
193196
false
194197
} else {
195198
true

0 commit comments

Comments
 (0)