1
1
use libloading:: Library ;
2
- use rustc_ast:: mut_visit:: { visit_clobber, MutVisitor , * } ;
3
- use rustc_ast:: ptr:: P ;
4
- use rustc_ast:: { self as ast, AttrVec , BlockCheckMode , Term } ;
2
+ use rustc_ast as ast;
5
3
use rustc_codegen_ssa:: traits:: CodegenBackend ;
6
4
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
7
5
#[ cfg( parallel_compiler) ]
@@ -13,7 +11,6 @@ use rustc_middle::ty::tls;
13
11
use rustc_parse:: validate_attr;
14
12
#[ cfg( parallel_compiler) ]
15
13
use rustc_query_impl:: QueryCtxt ;
16
- use rustc_resolve:: { self , Resolver } ;
17
14
use rustc_session as session;
18
15
use rustc_session:: config:: CheckCfg ;
19
16
use rustc_session:: config:: { self , CrateType } ;
@@ -25,12 +22,10 @@ use rustc_span::edition::Edition;
25
22
use rustc_span:: lev_distance:: find_best_match_for_name;
26
23
use rustc_span:: source_map:: FileLoader ;
27
24
use rustc_span:: symbol:: { sym, Symbol } ;
28
- use smallvec:: SmallVec ;
29
25
use std:: env;
30
26
use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
31
27
use std:: lazy:: SyncOnceCell ;
32
28
use std:: mem;
33
- use std:: ops:: DerefMut ;
34
29
#[ cfg( not( parallel_compiler) ) ]
35
30
use std:: panic;
36
31
use std:: path:: { Path , PathBuf } ;
@@ -664,214 +659,6 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
664
659
std:: fs:: rename ( src, dst)
665
660
}
666
661
667
- /// Replaces function bodies with `loop {}` (an infinite loop). This gets rid of
668
- /// all semantic errors in the body while still satisfying the return type,
669
- /// except in certain cases, see below for more.
670
- ///
671
- /// This pass is known as `everybody_loops`. Very punny.
672
- ///
673
- /// As of March 2021, `everybody_loops` is only used for the
674
- /// `-Z unpretty=everybody_loops` debugging option.
675
- ///
676
- /// FIXME: Currently the `everybody_loops` transformation is not applied to:
677
- /// * `const fn`; support could be added, but hasn't. Originally `const fn`
678
- /// was skipped due to issue #43636 that `loop` was not supported for
679
- /// const evaluation.
680
- /// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
681
- /// Solving this may require `!` to implement every trait, which relies on the an even more
682
- /// ambitious form of the closed RFC #1637. See also [#34511].
683
- ///
684
- /// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
685
- pub struct ReplaceBodyWithLoop < ' a , ' b > {
686
- within_static_or_const : bool ,
687
- nested_blocks : Option < Vec < ast:: Block > > ,
688
- resolver : & ' a mut Resolver < ' b > ,
689
- }
690
-
691
- impl < ' a , ' b > ReplaceBodyWithLoop < ' a , ' b > {
692
- pub fn new ( resolver : & ' a mut Resolver < ' b > ) -> ReplaceBodyWithLoop < ' a , ' b > {
693
- ReplaceBodyWithLoop { within_static_or_const : false , nested_blocks : None , resolver }
694
- }
695
-
696
- fn run < R , F : FnOnce ( & mut Self ) -> R > ( & mut self , is_const : bool , action : F ) -> R {
697
- let old_const = mem:: replace ( & mut self . within_static_or_const , is_const) ;
698
- let old_blocks = self . nested_blocks . take ( ) ;
699
- let ret = action ( self ) ;
700
- self . within_static_or_const = old_const;
701
- self . nested_blocks = old_blocks;
702
- ret
703
- }
704
-
705
- fn should_ignore_fn ( ret_ty : & ast:: FnRetTy ) -> bool {
706
- let ast:: FnRetTy :: Ty ( ref ty) = ret_ty else {
707
- return false ;
708
- } ;
709
- fn involves_impl_trait ( ty : & ast:: Ty ) -> bool {
710
- match ty. kind {
711
- ast:: TyKind :: ImplTrait ( ..) => true ,
712
- ast:: TyKind :: Slice ( ref subty)
713
- | ast:: TyKind :: Array ( ref subty, _)
714
- | ast:: TyKind :: Ptr ( ast:: MutTy { ty : ref subty, .. } )
715
- | ast:: TyKind :: Rptr ( _, ast:: MutTy { ty : ref subty, .. } )
716
- | ast:: TyKind :: Paren ( ref subty) => involves_impl_trait ( subty) ,
717
- ast:: TyKind :: Tup ( ref tys) => any_involves_impl_trait ( tys. iter ( ) ) ,
718
- ast:: TyKind :: Path ( _, ref path) => {
719
- path. segments . iter ( ) . any ( |seg| match seg. args . as_deref ( ) {
720
- None => false ,
721
- Some ( & ast:: GenericArgs :: AngleBracketed ( ref data) ) => {
722
- data. args . iter ( ) . any ( |arg| match arg {
723
- ast:: AngleBracketedArg :: Arg ( arg) => match arg {
724
- ast:: GenericArg :: Type ( ty) => involves_impl_trait ( ty) ,
725
- ast:: GenericArg :: Lifetime ( _) | ast:: GenericArg :: Const ( _) => {
726
- false
727
- }
728
- } ,
729
- ast:: AngleBracketedArg :: Constraint ( c) => match c. kind {
730
- ast:: AssocConstraintKind :: Bound { .. } => true ,
731
- ast:: AssocConstraintKind :: Equality { ref term } => {
732
- match term {
733
- Term :: Ty ( ty) => involves_impl_trait ( ty) ,
734
- // FIXME(...): This should check if the constant
735
- // involves a trait impl, but for now ignore.
736
- Term :: Const ( _) => false ,
737
- }
738
- }
739
- } ,
740
- } )
741
- }
742
- Some ( & ast:: GenericArgs :: Parenthesized ( ref data) ) => {
743
- any_involves_impl_trait ( data. inputs . iter ( ) )
744
- || ReplaceBodyWithLoop :: should_ignore_fn ( & data. output )
745
- }
746
- } )
747
- }
748
- _ => false ,
749
- }
750
- }
751
-
752
- fn any_involves_impl_trait < ' a , I : Iterator < Item = & ' a P < ast:: Ty > > > ( mut it : I ) -> bool {
753
- it. any ( |subty| involves_impl_trait ( subty) )
754
- }
755
-
756
- involves_impl_trait ( ty)
757
- }
758
-
759
- fn is_sig_const ( sig : & ast:: FnSig ) -> bool {
760
- matches ! ( sig. header. constness, ast:: Const :: Yes ( _) )
761
- || ReplaceBodyWithLoop :: should_ignore_fn ( & sig. decl . output )
762
- }
763
- }
764
-
765
- impl < ' a > MutVisitor for ReplaceBodyWithLoop < ' a , ' _ > {
766
- fn visit_item_kind ( & mut self , i : & mut ast:: ItemKind ) {
767
- let is_const = match i {
768
- ast:: ItemKind :: Static ( ..) | ast:: ItemKind :: Const ( ..) => true ,
769
- ast:: ItemKind :: Fn ( box ast:: Fn { ref sig, .. } ) => Self :: is_sig_const ( sig) ,
770
- _ => false ,
771
- } ;
772
- self . run ( is_const, |s| noop_visit_item_kind ( i, s) )
773
- }
774
-
775
- fn flat_map_trait_item ( & mut self , i : P < ast:: AssocItem > ) -> SmallVec < [ P < ast:: AssocItem > ; 1 ] > {
776
- let is_const = match i. kind {
777
- ast:: AssocItemKind :: Const ( ..) => true ,
778
- ast:: AssocItemKind :: Fn ( box ast:: Fn { ref sig, .. } ) => Self :: is_sig_const ( sig) ,
779
- _ => false ,
780
- } ;
781
- self . run ( is_const, |s| noop_flat_map_assoc_item ( i, s) )
782
- }
783
-
784
- fn flat_map_impl_item ( & mut self , i : P < ast:: AssocItem > ) -> SmallVec < [ P < ast:: AssocItem > ; 1 ] > {
785
- self . flat_map_trait_item ( i)
786
- }
787
-
788
- fn visit_anon_const ( & mut self , c : & mut ast:: AnonConst ) {
789
- self . run ( true , |s| noop_visit_anon_const ( c, s) )
790
- }
791
-
792
- fn visit_block ( & mut self , b : & mut P < ast:: Block > ) {
793
- fn stmt_to_block (
794
- rules : ast:: BlockCheckMode ,
795
- s : Option < ast:: Stmt > ,
796
- resolver : & mut Resolver < ' _ > ,
797
- ) -> ast:: Block {
798
- ast:: Block {
799
- stmts : s. into_iter ( ) . collect ( ) ,
800
- rules,
801
- id : resolver. next_node_id ( ) ,
802
- span : rustc_span:: DUMMY_SP ,
803
- tokens : None ,
804
- could_be_bare_literal : false ,
805
- }
806
- }
807
-
808
- fn block_to_stmt ( b : ast:: Block , resolver : & mut Resolver < ' _ > ) -> ast:: Stmt {
809
- let expr = P ( ast:: Expr {
810
- id : resolver. next_node_id ( ) ,
811
- kind : ast:: ExprKind :: Block ( P ( b) , None ) ,
812
- span : rustc_span:: DUMMY_SP ,
813
- attrs : AttrVec :: new ( ) ,
814
- tokens : None ,
815
- } ) ;
816
-
817
- ast:: Stmt {
818
- id : resolver. next_node_id ( ) ,
819
- kind : ast:: StmtKind :: Expr ( expr) ,
820
- span : rustc_span:: DUMMY_SP ,
821
- }
822
- }
823
-
824
- let empty_block = stmt_to_block ( BlockCheckMode :: Default , None , self . resolver ) ;
825
- let loop_expr = P ( ast:: Expr {
826
- kind : ast:: ExprKind :: Loop ( P ( empty_block) , None ) ,
827
- id : self . resolver . next_node_id ( ) ,
828
- span : rustc_span:: DUMMY_SP ,
829
- attrs : AttrVec :: new ( ) ,
830
- tokens : None ,
831
- } ) ;
832
-
833
- let loop_stmt = ast:: Stmt {
834
- id : self . resolver . next_node_id ( ) ,
835
- span : rustc_span:: DUMMY_SP ,
836
- kind : ast:: StmtKind :: Expr ( loop_expr) ,
837
- } ;
838
-
839
- if self . within_static_or_const {
840
- noop_visit_block ( b, self )
841
- } else {
842
- visit_clobber ( b. deref_mut ( ) , |b| {
843
- let mut stmts = vec ! [ ] ;
844
- for s in b. stmts {
845
- let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
846
-
847
- stmts. extend ( self . flat_map_stmt ( s) . into_iter ( ) . filter ( |s| s. is_item ( ) ) ) ;
848
-
849
- // we put a Some in there earlier with that replace(), so this is valid
850
- let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
851
- self . nested_blocks = old_blocks;
852
- stmts. extend ( new_blocks. into_iter ( ) . map ( |b| block_to_stmt ( b, self . resolver ) ) ) ;
853
- }
854
-
855
- let mut new_block = ast:: Block { stmts, ..b } ;
856
-
857
- if let Some ( old_blocks) = self . nested_blocks . as_mut ( ) {
858
- //push our fresh block onto the cache and yield an empty block with `loop {}`
859
- if !new_block. stmts . is_empty ( ) {
860
- old_blocks. push ( new_block) ;
861
- }
862
-
863
- stmt_to_block ( b. rules , Some ( loop_stmt) , & mut self . resolver )
864
- } else {
865
- //push `loop {}` onto the end of our fresh block and yield that
866
- new_block. stmts . push ( loop_stmt) ;
867
-
868
- new_block
869
- }
870
- } )
871
- }
872
- }
873
- }
874
-
875
662
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
876
663
pub fn version_str ( ) -> Option < & ' static str > {
877
664
option_env ! ( "CFG_VERSION" )
0 commit comments