@@ -9,7 +9,7 @@ use rustc_middle::mir::*;
99use rustc_middle:: ty:: cast:: CastTy ;
1010use rustc_middle:: ty:: query:: Providers ;
1111use rustc_middle:: ty:: { self , TyCtxt } ;
12- use rustc_session:: lint:: builtin:: { SAFE_PACKED_BORROWS , UNUSED_UNSAFE } ;
12+ use rustc_session:: lint:: builtin:: { SAFE_PACKED_BORROWS , UNSAFE_OP_IN_UNSAFE_FN , UNUSED_UNSAFE } ;
1313use rustc_span:: symbol:: { sym, Symbol } ;
1414
1515use std:: ops:: Bound ;
@@ -351,14 +351,35 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
351351 violation. kind = UnsafetyViolationKind :: General ;
352352 }
353353 }
354+ UnsafetyViolationKind :: UnsafeFn ( _) => {
355+ bug ! ( "`UnsafetyViolationKind::UnsafeFn` in an `Safe` context" )
356+ }
357+ }
358+ if !self . violations . contains ( & violation) {
359+ self . violations . push ( violation)
354360 }
361+ }
362+ false
363+ }
364+ // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
365+ Safety :: FnUnsafe if self . tcx . features ( ) . unsafe_block_in_unsafe_fn => {
366+ for violation in violations {
367+ let mut violation = * violation;
368+ let lint_root = self . body . source_scopes [ self . source_info . scope ]
369+ . local_data
370+ . as_ref ( )
371+ . assert_crate_local ( )
372+ . lint_root ;
373+
374+ // FIXME(LeSeulArtichaut): what to do with `UnsafetyViolationKind::BorrowPacked`?
375+ violation. kind = UnsafetyViolationKind :: UnsafeFn ( lint_root) ;
355376 if !self . violations . contains ( & violation) {
356377 self . violations . push ( violation)
357378 }
358379 }
359380 false
360381 }
361- // `unsafe` function bodies allow unsafe without additional unsafe blocks
382+ // `unsafe` function bodies allow unsafe without additional unsafe blocks (before RFC 2585)
362383 Safety :: BuiltinUnsafe | Safety :: FnUnsafe => true ,
363384 Safety :: ExplicitUnsafe ( hir_id) => {
364385 // mark unsafe block as used if there are any unsafe operations inside
@@ -383,6 +404,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
383404 self . violations . push ( violation)
384405 }
385406 }
407+ UnsafetyViolationKind :: UnsafeFn ( _) => bug ! (
408+ "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
409+ ) ,
386410 }
387411 }
388412 }
@@ -575,9 +599,12 @@ fn is_enclosed(
575599 kind : hir:: ItemKind :: Fn ( ref sig, _, _) , ..
576600 } ) ) = tcx. hir ( ) . find ( parent_id)
577601 {
578- match sig. header . unsafety {
579- hir:: Unsafety :: Unsafe => Some ( ( "fn" . to_string ( ) , parent_id) ) ,
580- hir:: Unsafety :: Normal => None ,
602+ if sig. header . unsafety == hir:: Unsafety :: Unsafe
603+ && !tcx. features ( ) . unsafe_block_in_unsafe_fn
604+ {
605+ Some ( ( "fn" . to_string ( ) , parent_id) )
606+ } else {
607+ None
581608 }
582609 } else {
583610 is_enclosed ( tcx, used_unsafe, parent_id)
@@ -630,16 +657,20 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
630657 let UnsafetyCheckResult { violations, unsafe_blocks } =
631658 tcx. unsafety_check_result ( def_id. expect_local ( ) ) ;
632659
660+ let or_block_msg = if tcx. features ( ) . unsafe_block_in_unsafe_fn { "" } else { " or block" } ;
661+
633662 for & UnsafetyViolation { source_info, description, details, kind } in violations. iter ( ) {
634663 // Report an error.
635664 match kind {
636665 UnsafetyViolationKind :: GeneralAndConstFn | UnsafetyViolationKind :: General => {
666+ // once
637667 struct_span_err ! (
638668 tcx. sess,
639669 source_info. span,
640670 E0133 ,
641- "{} is unsafe and requires unsafe function or block" ,
642- description
671+ "{} is unsafe and requires unsafe function{}" ,
672+ description,
673+ or_block_msg,
643674 )
644675 . span_label ( source_info. span , & * description. as_str ( ) )
645676 . note ( & details. as_str ( ) )
@@ -655,15 +686,29 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
655686 source_info. span ,
656687 |lint| {
657688 lint. build ( & format ! (
658- "{} is unsafe and requires unsafe function or block (error E0133)" ,
659- description
689+ "{} is unsafe and requires unsafe function{} (error E0133)" ,
690+ description, or_block_msg ,
660691 ) )
661692 . note ( & details. as_str ( ) )
662693 . emit ( )
663694 } ,
664695 )
665696 }
666697 }
698+ UnsafetyViolationKind :: UnsafeFn ( lint_hir_id) => tcx. struct_span_lint_hir (
699+ UNSAFE_OP_IN_UNSAFE_FN ,
700+ lint_hir_id,
701+ source_info. span ,
702+ |lint| {
703+ lint. build ( & format ! (
704+ "{} is unsafe and requires unsafe block (error E0133)" ,
705+ description
706+ ) )
707+ . span_label ( source_info. span , & * description. as_str ( ) )
708+ . note ( & details. as_str ( ) )
709+ . emit ( ) ;
710+ } ,
711+ ) ,
667712 }
668713 }
669714
0 commit comments