11use 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;
53use rustc_codegen_ssa:: traits:: CodegenBackend ;
64use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
75#[ cfg( parallel_compiler) ]
@@ -13,7 +11,6 @@ use rustc_middle::ty::tls;
1311use rustc_parse:: validate_attr;
1412#[ cfg( parallel_compiler) ]
1513use rustc_query_impl:: QueryCtxt ;
16- use rustc_resolve:: { self , Resolver } ;
1714use rustc_session as session;
1815use rustc_session:: config:: CheckCfg ;
1916use rustc_session:: config:: { self , CrateType } ;
@@ -25,12 +22,10 @@ use rustc_span::edition::Edition;
2522use rustc_span:: lev_distance:: find_best_match_for_name;
2623use rustc_span:: source_map:: FileLoader ;
2724use rustc_span:: symbol:: { sym, Symbol } ;
28- use smallvec:: SmallVec ;
2925use std:: env;
3026use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
3127use std:: lazy:: SyncOnceCell ;
3228use std:: mem;
33- use std:: ops:: DerefMut ;
3429#[ cfg( not( parallel_compiler) ) ]
3530use std:: panic;
3631use std:: path:: { Path , PathBuf } ;
@@ -664,214 +659,6 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
664659 std:: fs:: rename ( src, dst)
665660}
666661
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-
875662/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
876663pub fn version_str ( ) -> Option < & ' static str > {
877664 option_env ! ( "CFG_VERSION" )
0 commit comments