Skip to content
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

Rollup of 9 pull requests #122483

Merged
merged 30 commits into from Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bf62d59
Give `TRACK_DIAGNOSTIC` a return value.
nnethercote Feb 9, 2024
ecd3718
Inline and remove `Level::get_diagnostic_id`.
nnethercote Feb 13, 2024
272e60b
Move `DelayedBug` handling into the `match`.
nnethercote Feb 13, 2024
c81767e
Reorder `has_future_breakage` handling.
nnethercote Feb 13, 2024
aec4bdb
Move `Expect`/`ForceWarning` handling into the `match`.
nnethercote Feb 13, 2024
a7d9262
Add comments about `TRACK_DIAGNOSTIC` use.
nnethercote Feb 13, 2024
7ef605b
Make the `match` in `emit_diagnostic` complete.
nnethercote Mar 1, 2024
71080dd
Document how removing a type's field can be bad and what to do instead
shepmaster Mar 2, 2024
15b71f4
Add CStr::bytes iterator
clarfonthey Nov 13, 2022
7f427f8
rustdoc-search: parse and search with ML-style HOF
notriddle Jan 6, 2024
d38527e
rustdoc: clean up search.js by removing empty sort case
notriddle Jan 6, 2024
23e931f
rustdoc: use `const` for the special type name ids
notriddle Jan 6, 2024
7b92655
rustdoc-search: add search query syntax `Fn(T) -> U`
notriddle Jan 6, 2024
c076509
Add methods to create constants
celinval Mar 1, 2024
893a910
Add a test to SMIR body transformation
celinval Mar 12, 2024
a38a556
Reduce unsafe code, use more NonNull APIs per @cuviper review
clarfonthey Mar 12, 2024
f2fcfe8
Various style improvements to `rustc_lint::levels`
Zalathar Mar 13, 2024
c527ec7
Improve Step docs
CAD97 Mar 13, 2024
514b274
const-eval: organize and extend tests for required-consts
RalfJung Mar 13, 2024
be33586
fix unsoundness in Step::forward_unchecked for signed integers
the8472 Mar 13, 2024
d3cab9f
update virtual clock in miri test since signed loops now execute more…
the8472 Mar 13, 2024
1ae69ae
Rollup merge of #104353 - clarfonthey:cstr-bytes-iter, r=cuviper
matthiaskrgr Mar 14, 2024
6694918
Rollup merge of #119676 - notriddle:notriddle/rustdoc-search-hof, r=G…
matthiaskrgr Mar 14, 2024
fce6e75
Rollup merge of #120699 - nnethercote:rm-useless-TRACK_DIAGNOSTIC-cal…
matthiaskrgr Mar 14, 2024
7a744af
Rollup merge of #121899 - shepmaster:dead-code-docs, r=wesleywiser
matthiaskrgr Mar 14, 2024
bd53d1e
Rollup merge of #122405 - celinval:smir-new-const, r=oli-obk
matthiaskrgr Mar 14, 2024
0286591
Rollup merge of #122416 - Zalathar:levels, r=petrochenkov
matthiaskrgr Mar 14, 2024
a0e50a4
Rollup merge of #122421 - CAD97:step-trait-docs, r=jhpratt
matthiaskrgr Mar 14, 2024
bdf84ea
Rollup merge of #122440 - RalfJung:required-consts, r=oli-obk
matthiaskrgr Mar 14, 2024
75dc99b
Rollup merge of #122461 - the8472:fix-step-forward-unchecked, r=Amanieu
matthiaskrgr Mar 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/emitter.rs
Expand Up @@ -2086,7 +2086,7 @@ impl HumanEmitter {
}
if !self.short_message {
for child in children {
assert!(child.level.can_be_top_or_sub().1);
assert!(child.level.can_be_subdiag());
let span = &child.span;
if let Err(err) = self.emit_messages_default_inner(
span,
Expand Down
162 changes: 92 additions & 70 deletions compiler/rustc_errors/src/lib.rs
Expand Up @@ -526,12 +526,15 @@ pub enum StashKey {
UndeterminedMacroResolution,
}

fn default_track_diagnostic(diag: DiagInner, f: &mut dyn FnMut(DiagInner)) {
fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
(*f)(diag)
}

pub static TRACK_DIAGNOSTIC: AtomicRef<fn(DiagInner, &mut dyn FnMut(DiagInner))> =
AtomicRef::new(&(default_track_diagnostic as _));
/// Diagnostics emitted by `DiagCtxtInner::emit_diagnostic` are passed through this function. Used
/// for tracking by incremental, to replay diagnostics as necessary.
pub static TRACK_DIAGNOSTIC: AtomicRef<
fn(DiagInner, &mut dyn FnMut(DiagInner) -> Option<ErrorGuaranteed>) -> Option<ErrorGuaranteed>,
> = AtomicRef::new(&(default_track_diagnostic as _));

#[derive(Copy, Clone, Default)]
pub struct DiagCtxtFlags {
Expand Down Expand Up @@ -1422,74 +1425,103 @@ impl DiagCtxtInner {

// Return value is only `Some` if the level is `Error` or `DelayedBug`.
fn emit_diagnostic(&mut self, mut diagnostic: DiagInner) -> Option<ErrorGuaranteed> {
assert!(diagnostic.level.can_be_top_or_sub().0);

if let Some(expectation_id) = diagnostic.level.get_expectation_id() {
// The `LintExpectationId` can be stable or unstable depending on when it was created.
// Diagnostics created before the definition of `HirId`s are unstable and can not yet
// be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
// a stable one by the `LintLevelsBuilder`.
if let LintExpectationId::Unstable { .. } = expectation_id {
self.unstable_expect_diagnostics.push(diagnostic);
return None;
}
self.suppressed_expected_diag = true;
self.fulfilled_expectations.insert(expectation_id.normalize());
}

if diagnostic.has_future_breakage() {
// Future breakages aren't emitted if they're `Level::Allow`,
// but they still need to be constructed and stashed below,
// so they'll trigger the must_produce_diag check.
self.suppressed_expected_diag = true;
assert!(matches!(diagnostic.level, Error | Warning | Allow));
self.future_breakage_diagnostics.push(diagnostic.clone());
}

// Note that because this comes before the `match` below,
// `-Zeagerly-emit-delayed-bugs` continues to work even after we've
// issued an error and stopped recording new delayed bugs.
if diagnostic.level == DelayedBug && self.flags.eagerly_emit_delayed_bugs {
diagnostic.level = Error;
}

// We call TRACK_DIAGNOSTIC with an empty closure for the cases that
// return early *and* have some kind of side-effect, except where
// noted.
match diagnostic.level {
// This must come after the possible promotion of `DelayedBug` to
// `Error` above.
Fatal | Error if self.treat_next_err_as_bug() => {
diagnostic.level = Bug;
Bug => {}
Fatal | Error => {
if self.treat_next_err_as_bug() {
// `Fatal` and `Error` can be promoted to `Bug`.
diagnostic.level = Bug;
}
}
DelayedBug => {
// If we have already emitted at least one error, we don't need
// to record the delayed bug, because it'll never be used.
return if let Some(guar) = self.has_errors() {
Some(guar)
// Note that because we check these conditions first,
// `-Zeagerly-emit-delayed-bugs` and `-Ztreat-err-as-bug`
// continue to work even after we've issued an error and
// stopped recording new delayed bugs.
if self.flags.eagerly_emit_delayed_bugs {
// `DelayedBug` can be promoted to `Error` or `Bug`.
if self.treat_next_err_as_bug() {
diagnostic.level = Bug;
} else {
diagnostic.level = Error;
}
} else {
let backtrace = std::backtrace::Backtrace::capture();
// This `unchecked_error_guaranteed` is valid. It is where the
// `ErrorGuaranteed` for delayed bugs originates. See
// `DiagCtxtInner::drop`.
#[allow(deprecated)]
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
self.delayed_bugs
.push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
Some(guar)
};
// If we have already emitted at least one error, we don't need
// to record the delayed bug, because it'll never be used.
return if let Some(guar) = self.has_errors() {
Some(guar)
} else {
// No `TRACK_DIAGNOSTIC` call is needed, because the
// incremental session is deleted if there is a delayed
// bug. This also saves us from cloning the diagnostic.
let backtrace = std::backtrace::Backtrace::capture();
// This `unchecked_error_guaranteed` is valid. It is where the
// `ErrorGuaranteed` for delayed bugs originates. See
// `DiagCtxtInner::drop`.
#[allow(deprecated)]
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
self.delayed_bugs
.push((DelayedDiagInner::with_backtrace(diagnostic, backtrace), guar));
Some(guar)
};
}
}
ForceWarning(None) => {} // `ForceWarning(Some(...))` is below, with `Expect`
Warning => {
if !self.flags.can_emit_warnings {
// We are not emitting warnings.
if diagnostic.has_future_breakage() {
// The side-effect is at the top of this method.
TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
}
return None;
}
}
Warning if !self.flags.can_emit_warnings => {
Note | Help | FailureNote => {}
OnceNote | OnceHelp => panic!("bad level: {:?}", diagnostic.level),
Allow => {
// Nothing emitted for allowed lints.
if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
// The side-effect is at the top of this method.
TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
self.suppressed_expected_diag = true;
}
return None;
}
Allow | Expect(_) => {
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
return None;
Expect(expect_id) | ForceWarning(Some(expect_id)) => {
// Diagnostics created before the definition of `HirId`s are
// unstable and can not yet be stored. Instead, they are
// buffered until the `LintExpectationId` is replaced by a
// stable one by the `LintLevelsBuilder`.
if let LintExpectationId::Unstable { .. } = expect_id {
// We don't call TRACK_DIAGNOSTIC because we wait for the
// unstable ID to be updated, whereupon the diagnostic will
// be passed into this method again.
self.unstable_expect_diagnostics.push(diagnostic);
return None;
}
self.fulfilled_expectations.insert(expect_id.normalize());
if let Expect(_) = diagnostic.level {
// Nothing emitted here for expected lints.
TRACK_DIAGNOSTIC(diagnostic, &mut |_| None);
self.suppressed_expected_diag = true;
return None;
}
}
_ => {}
}

let mut guaranteed = None;
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |mut diagnostic| {
TRACK_DIAGNOSTIC(diagnostic, &mut |mut diagnostic| {
if let Some(code) = diagnostic.code {
self.emitted_diagnostic_codes.insert(code);
}
Expand Down Expand Up @@ -1552,17 +1584,17 @@ impl DiagCtxtInner {
// `ErrorGuaranteed` for errors and lint errors originates.
#[allow(deprecated)]
let guar = ErrorGuaranteed::unchecked_error_guaranteed();
guaranteed = Some(guar);
if is_lint {
self.lint_err_guars.push(guar);
} else {
self.err_guars.push(guar);
}
self.panic_if_treat_err_as_bug();
Some(guar)
} else {
None
}
});

guaranteed
})
}

fn treat_err_as_bug(&self) -> bool {
Expand Down Expand Up @@ -1863,23 +1895,13 @@ impl Level {
matches!(*self, FailureNote)
}

pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
match self {
Expect(id) | ForceWarning(Some(id)) => Some(*id),
_ => None,
}
}

// Can this level be used in a top-level diagnostic message and/or a
// subdiagnostic message?
fn can_be_top_or_sub(&self) -> (bool, bool) {
// Can this level be used in a subdiagnostic message?
fn can_be_subdiag(&self) -> bool {
match self {
Bug | DelayedBug | Fatal | Error | ForceWarning(_) | FailureNote | Allow
| Expect(_) => (true, false),

Warning | Note | Help => (true, true),
| Expect(_) => false,

OnceNote | OnceHelp => (false, true),
Warning | Note | Help | OnceNote | OnceHelp => true,
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_interface/src/callbacks.rs
Expand Up @@ -29,7 +29,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
/// This is a callback from `rustc_errors` as it cannot access the implicit state
/// in `rustc_middle` otherwise. It is used when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
fn track_diagnostic(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner)) {
fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
tls::with_context_opt(|icx| {
if let Some(icx) = icx {
if let Some(diagnostics) = icx.diagnostics {
Expand All @@ -38,11 +38,11 @@ fn track_diagnostic(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner)) {

// Diagnostics are tracked, we can ignore the dependency.
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };
return tls::enter_context(&icx, move || (*f)(diagnostic));
tls::enter_context(&icx, move || (*f)(diagnostic))
} else {
// In any other case, invoke diagnostics anyway.
(*f)(diagnostic)
}

// In any other case, invoke diagnostics anyway.
(*f)(diagnostic);
})
}

Expand Down