|
| 1 | +use hir::{BlockCheckMode, ExprKind, Node}; |
1 | 2 | use rustc_data_structures::fx::FxHashSet;
|
2 | 3 | use rustc_errors::struct_span_err;
|
3 | 4 | use rustc_hir as hir;
|
@@ -517,24 +518,49 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
517 | 518 | for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
|
518 | 519 | let (description, note) = details.description_and_note();
|
519 | 520 |
|
520 |
| - // Report an error. |
521 |
| - let unsafe_fn_msg = |
522 |
| - if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" }; |
523 |
| - |
524 | 521 | match kind {
|
525 | 522 | UnsafetyViolationKind::General => {
|
526 | 523 | // once
|
527 |
| - struct_span_err!( |
| 524 | + // Mutable statics always require an unsafe block |
| 525 | + let unsafe_fn_msg = if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) |
| 526 | + && details != UnsafetyViolationDetails::UseOfMutableStatic |
| 527 | + { |
| 528 | + " function or" |
| 529 | + } else { |
| 530 | + "" |
| 531 | + }; |
| 532 | + |
| 533 | + let mut err = struct_span_err!( |
528 | 534 | tcx.sess,
|
529 | 535 | source_info.span,
|
530 | 536 | E0133,
|
531 | 537 | "{} is unsafe and requires unsafe{} block",
|
532 | 538 | description,
|
533 | 539 | unsafe_fn_msg,
|
534 |
| - ) |
535 |
| - .span_label(source_info.span, description) |
536 |
| - .note(note) |
537 |
| - .emit(); |
| 540 | + ); |
| 541 | + err.span_label(source_info.span, description).note(note); |
| 542 | + let note_non_inherited = tcx.hir().parent_iter(lint_root).find(|(id, node)| { |
| 543 | + if let Node::Expr(block) = node |
| 544 | + && let ExprKind::Block(block, _) = block.kind |
| 545 | + && let BlockCheckMode::UnsafeBlock(_) = block.rules { |
| 546 | + true |
| 547 | + } |
| 548 | + else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) |
| 549 | + && sig.header.is_unsafe() { |
| 550 | + true |
| 551 | + } else { |
| 552 | + false |
| 553 | + } |
| 554 | + }); |
| 555 | + if let Some((id, _)) = note_non_inherited { |
| 556 | + let span = tcx.hir().span(id); |
| 557 | + err.span_label( |
| 558 | + tcx.sess.source_map().guess_head_span(span), |
| 559 | + "items do not inherit unsafety from separate enclosing items", |
| 560 | + ); |
| 561 | + } |
| 562 | + |
| 563 | + err.emit(); |
538 | 564 | }
|
539 | 565 | UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir(
|
540 | 566 | UNSAFE_OP_IN_UNSAFE_FN,
|
|
0 commit comments