mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
Remove the everybody loops pass
It isn't used anymore by rustdoc
This commit is contained in:
parent
4566094913
commit
2f84484aac
@ -42,7 +42,7 @@ where
|
||||
F: FnOnce(&dyn PrinterSupport) -> A,
|
||||
{
|
||||
match *ppmode {
|
||||
Normal | EveryBodyLoops | Expanded => {
|
||||
Normal | Expanded => {
|
||||
let annotation = NoAnn { sess, tcx };
|
||||
f(&annotation)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ use crate::proc_macro_decls;
|
||||
use crate::util;
|
||||
|
||||
use ast::CRATE_NODE_ID;
|
||||
use rustc_ast::mut_visit::MutVisitor;
|
||||
use rustc_ast::{self as ast, visit};
|
||||
use rustc_borrowck as mir_borrowck;
|
||||
use rustc_codegen_ssa::back::link::emit_metadata;
|
||||
@ -29,7 +28,7 @@ use rustc_plugin_impl as plugin;
|
||||
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
|
||||
use rustc_resolve::{Resolver, ResolverArenas};
|
||||
use rustc_serialize::json;
|
||||
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
|
||||
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
|
||||
use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::output::{filename_for_input, filename_for_metadata};
|
||||
@ -384,11 +383,6 @@ pub fn configure_and_expand(
|
||||
rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate)
|
||||
});
|
||||
|
||||
if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty {
|
||||
tracing::debug!("replacing bodies with loop {{}}");
|
||||
util::ReplaceBodyWithLoop::new(resolver).visit_crate(&mut krate);
|
||||
}
|
||||
|
||||
let has_proc_macro_decls = sess.time("AST_validation", || {
|
||||
rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer())
|
||||
});
|
||||
@ -457,18 +451,12 @@ pub fn configure_and_expand(
|
||||
});
|
||||
|
||||
// Add all buffered lints from the `ParseSess` to the `Session`.
|
||||
// The ReplaceBodyWithLoop pass may have deleted some AST nodes, potentially
|
||||
// causing a delay_span_bug later if a buffered lint refers to such a deleted
|
||||
// AST node (issue #87308). Since everybody_loops is for pretty-printing only,
|
||||
// anyway, we simply skip all buffered lints here.
|
||||
if !matches!(sess.opts.pretty, Some(PpMode::Source(PpSourceMode::EveryBodyLoops))) {
|
||||
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
|
||||
info!("{} parse sess buffered_lints", buffered_lints.len());
|
||||
for early_lint in buffered_lints.drain(..) {
|
||||
resolver.lint_buffer().add_early_lint(early_lint);
|
||||
}
|
||||
});
|
||||
}
|
||||
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
|
||||
info!("{} parse sess buffered_lints", buffered_lints.len());
|
||||
for early_lint in buffered_lints.drain(..) {
|
||||
resolver.lint_buffer().add_early_lint(early_lint);
|
||||
}
|
||||
});
|
||||
|
||||
// Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
|
||||
sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| {
|
||||
|
@ -1,7 +1,5 @@
|
||||
use libloading::Library;
|
||||
use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Term};
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
#[cfg(parallel_compiler)]
|
||||
@ -13,7 +11,6 @@ use rustc_middle::ty::tls;
|
||||
use rustc_parse::validate_attr;
|
||||
#[cfg(parallel_compiler)]
|
||||
use rustc_query_impl::QueryCtxt;
|
||||
use rustc_resolve::{self, Resolver};
|
||||
use rustc_session as session;
|
||||
use rustc_session::config::CheckCfg;
|
||||
use rustc_session::config::{self, CrateType};
|
||||
@ -25,12 +22,10 @@ use rustc_span::edition::Edition;
|
||||
use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::FileLoader;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use smallvec::SmallVec;
|
||||
use std::env;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::lazy::SyncOnceCell;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
#[cfg(not(parallel_compiler))]
|
||||
use std::panic;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -664,214 +659,6 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||
std::fs::rename(src, dst)
|
||||
}
|
||||
|
||||
/// Replaces function bodies with `loop {}` (an infinite loop). This gets rid of
|
||||
/// all semantic errors in the body while still satisfying the return type,
|
||||
/// except in certain cases, see below for more.
|
||||
///
|
||||
/// This pass is known as `everybody_loops`. Very punny.
|
||||
///
|
||||
/// As of March 2021, `everybody_loops` is only used for the
|
||||
/// `-Z unpretty=everybody_loops` debugging option.
|
||||
///
|
||||
/// FIXME: Currently the `everybody_loops` transformation is not applied to:
|
||||
/// * `const fn`; support could be added, but hasn't. Originally `const fn`
|
||||
/// was skipped due to issue #43636 that `loop` was not supported for
|
||||
/// const evaluation.
|
||||
/// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
|
||||
/// Solving this may require `!` to implement every trait, which relies on the an even more
|
||||
/// ambitious form of the closed RFC #1637. See also [#34511].
|
||||
///
|
||||
/// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
|
||||
pub struct ReplaceBodyWithLoop<'a, 'b> {
|
||||
within_static_or_const: bool,
|
||||
nested_blocks: Option<Vec<ast::Block>>,
|
||||
resolver: &'a mut Resolver<'b>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
|
||||
pub fn new(resolver: &'a mut Resolver<'b>) -> ReplaceBodyWithLoop<'a, 'b> {
|
||||
ReplaceBodyWithLoop { within_static_or_const: false, nested_blocks: None, resolver }
|
||||
}
|
||||
|
||||
fn run<R, F: FnOnce(&mut Self) -> R>(&mut self, is_const: bool, action: F) -> R {
|
||||
let old_const = mem::replace(&mut self.within_static_or_const, is_const);
|
||||
let old_blocks = self.nested_blocks.take();
|
||||
let ret = action(self);
|
||||
self.within_static_or_const = old_const;
|
||||
self.nested_blocks = old_blocks;
|
||||
ret
|
||||
}
|
||||
|
||||
fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool {
|
||||
let ast::FnRetTy::Ty(ref ty) = ret_ty else {
|
||||
return false;
|
||||
};
|
||||
fn involves_impl_trait(ty: &ast::Ty) -> bool {
|
||||
match ty.kind {
|
||||
ast::TyKind::ImplTrait(..) => true,
|
||||
ast::TyKind::Slice(ref subty)
|
||||
| ast::TyKind::Array(ref subty, _)
|
||||
| ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. })
|
||||
| ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. })
|
||||
| ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
|
||||
ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
|
||||
ast::TyKind::Path(_, ref path) => {
|
||||
path.segments.iter().any(|seg| match seg.args.as_deref() {
|
||||
None => false,
|
||||
Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
|
||||
data.args.iter().any(|arg| match arg {
|
||||
ast::AngleBracketedArg::Arg(arg) => match arg {
|
||||
ast::GenericArg::Type(ty) => involves_impl_trait(ty),
|
||||
ast::GenericArg::Lifetime(_) | ast::GenericArg::Const(_) => {
|
||||
false
|
||||
}
|
||||
},
|
||||
ast::AngleBracketedArg::Constraint(c) => match c.kind {
|
||||
ast::AssocConstraintKind::Bound { .. } => true,
|
||||
ast::AssocConstraintKind::Equality { ref term } => {
|
||||
match term {
|
||||
Term::Ty(ty) => involves_impl_trait(ty),
|
||||
// FIXME(...): This should check if the constant
|
||||
// involves a trait impl, but for now ignore.
|
||||
Term::Const(_) => false,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
Some(&ast::GenericArgs::Parenthesized(ref data)) => {
|
||||
any_involves_impl_trait(data.inputs.iter())
|
||||
|| ReplaceBodyWithLoop::should_ignore_fn(&data.output)
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn any_involves_impl_trait<'a, I: Iterator<Item = &'a P<ast::Ty>>>(mut it: I) -> bool {
|
||||
it.any(|subty| involves_impl_trait(subty))
|
||||
}
|
||||
|
||||
involves_impl_trait(ty)
|
||||
}
|
||||
|
||||
fn is_sig_const(sig: &ast::FnSig) -> bool {
|
||||
matches!(sig.header.constness, ast::Const::Yes(_))
|
||||
|| ReplaceBodyWithLoop::should_ignore_fn(&sig.decl.output)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
|
||||
fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
|
||||
let is_const = match i {
|
||||
ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
|
||||
ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
|
||||
_ => false,
|
||||
};
|
||||
self.run(is_const, |s| noop_visit_item_kind(i, s))
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
let is_const = match i.kind {
|
||||
ast::AssocItemKind::Const(..) => true,
|
||||
ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
|
||||
_ => false,
|
||||
};
|
||||
self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
self.flat_map_trait_item(i)
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &mut ast::AnonConst) {
|
||||
self.run(true, |s| noop_visit_anon_const(c, s))
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, b: &mut P<ast::Block>) {
|
||||
fn stmt_to_block(
|
||||
rules: ast::BlockCheckMode,
|
||||
s: Option<ast::Stmt>,
|
||||
resolver: &mut Resolver<'_>,
|
||||
) -> ast::Block {
|
||||
ast::Block {
|
||||
stmts: s.into_iter().collect(),
|
||||
rules,
|
||||
id: resolver.next_node_id(),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
tokens: None,
|
||||
could_be_bare_literal: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt {
|
||||
let expr = P(ast::Expr {
|
||||
id: resolver.next_node_id(),
|
||||
kind: ast::ExprKind::Block(P(b), None),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
|
||||
ast::Stmt {
|
||||
id: resolver.next_node_id(),
|
||||
kind: ast::StmtKind::Expr(expr),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.resolver);
|
||||
let loop_expr = P(ast::Expr {
|
||||
kind: ast::ExprKind::Loop(P(empty_block), None),
|
||||
id: self.resolver.next_node_id(),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
});
|
||||
|
||||
let loop_stmt = ast::Stmt {
|
||||
id: self.resolver.next_node_id(),
|
||||
span: rustc_span::DUMMY_SP,
|
||||
kind: ast::StmtKind::Expr(loop_expr),
|
||||
};
|
||||
|
||||
if self.within_static_or_const {
|
||||
noop_visit_block(b, self)
|
||||
} else {
|
||||
visit_clobber(b.deref_mut(), |b| {
|
||||
let mut stmts = vec![];
|
||||
for s in b.stmts {
|
||||
let old_blocks = self.nested_blocks.replace(vec![]);
|
||||
|
||||
stmts.extend(self.flat_map_stmt(s).into_iter().filter(|s| s.is_item()));
|
||||
|
||||
// we put a Some in there earlier with that replace(), so this is valid
|
||||
let new_blocks = self.nested_blocks.take().unwrap();
|
||||
self.nested_blocks = old_blocks;
|
||||
stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, self.resolver)));
|
||||
}
|
||||
|
||||
let mut new_block = ast::Block { stmts, ..b };
|
||||
|
||||
if let Some(old_blocks) = self.nested_blocks.as_mut() {
|
||||
//push our fresh block onto the cache and yield an empty block with `loop {}`
|
||||
if !new_block.stmts.is_empty() {
|
||||
old_blocks.push(new_block);
|
||||
}
|
||||
|
||||
stmt_to_block(b.rules, Some(loop_stmt), &mut self.resolver)
|
||||
} else {
|
||||
//push `loop {}` onto the end of our fresh block and yield that
|
||||
new_block.stmts.push(loop_stmt);
|
||||
|
||||
new_block
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
|
||||
pub fn version_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VERSION")
|
||||
|
@ -2509,7 +2509,6 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt
|
||||
let first = match debugging_opts.unpretty.as_deref()? {
|
||||
"normal" => Source(PpSourceMode::Normal),
|
||||
"identified" => Source(PpSourceMode::Identified),
|
||||
"everybody_loops" => Source(PpSourceMode::EveryBodyLoops),
|
||||
"expanded" => Source(PpSourceMode::Expanded),
|
||||
"expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
|
||||
"expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
|
||||
@ -2645,8 +2644,6 @@ impl fmt::Display for CrateType {
|
||||
pub enum PpSourceMode {
|
||||
/// `-Zunpretty=normal`
|
||||
Normal,
|
||||
/// `-Zunpretty=everybody_loops`
|
||||
EveryBodyLoops,
|
||||
/// `-Zunpretty=expanded`
|
||||
Expanded,
|
||||
/// `-Zunpretty=identified`
|
||||
@ -2678,7 +2675,7 @@ pub enum PpHirMode {
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum PpMode {
|
||||
/// Options that print the source code, i.e.
|
||||
/// `-Zunpretty=normal` and `-Zunpretty=everybody_loops`
|
||||
/// `-Zunpretty=normal` and `-Zunpretty=expanded`
|
||||
Source(PpSourceMode),
|
||||
AstTree(PpAstTreeMode),
|
||||
/// Options that print the HIR, i.e. `-Zunpretty=hir`
|
||||
@ -2700,7 +2697,7 @@ impl PpMode {
|
||||
match *self {
|
||||
Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false,
|
||||
|
||||
Source(Expanded | EveryBodyLoops | ExpandedIdentified | ExpandedHygiene)
|
||||
Source(Expanded | ExpandedIdentified | ExpandedHygiene)
|
||||
| AstTree(PpAstTreeMode::Expanded)
|
||||
| Hir(_)
|
||||
| HirTree
|
||||
|
@ -1491,7 +1491,6 @@ options! {
|
||||
`normal`, `identified`,
|
||||
`expanded`, `expanded,identified`,
|
||||
`expanded,hygiene` (with internal representations),
|
||||
`everybody_loops` (all function bodies replaced with `loop {}`),
|
||||
`ast-tree` (raw AST before expansion),
|
||||
`ast-tree,expanded` (raw AST after expansion),
|
||||
`hir` (the HIR), `hir,identified`,
|
||||
|
@ -82,8 +82,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
|
||||
// The `def_id` here actually was calculated during resolution (at least
|
||||
// at the time of this writing) and is being shipped to us via a side
|
||||
// channel of the tcx. There may have been extra expansion phases,
|
||||
// however, which ended up removing the `def_id` *after* expansion such
|
||||
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
|
||||
// however, which ended up removing the `def_id` *after* expansion.
|
||||
//
|
||||
// As a result we need to verify that `def_id` is indeed still valid for
|
||||
// our AST and actually present in the HIR map. If it's not there then
|
||||
|
@ -1,12 +0,0 @@
|
||||
// Regression test for issue #87308.
|
||||
|
||||
// compile-flags: -Zunpretty=everybody_loops
|
||||
// check-pass
|
||||
|
||||
macro_rules! foo {
|
||||
() => { break 'x; }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
'x: loop { foo!() }
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
#![feature(prelude_import)]
|
||||
#![no_std]
|
||||
#[prelude_import]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
// Regression test for issue #87308.
|
||||
|
||||
// compile-flags: -Zunpretty=everybody_loops
|
||||
// check-pass
|
||||
|
||||
macro_rules! foo { () => { break 'x ; } }
|
||||
|
||||
pub fn main() { loop {} }
|
@ -1,9 +0,0 @@
|
||||
error[E0565]: meta item in `repr` must be an identifier
|
||||
--> $DIR/issue-83921-pretty.rs:10:8
|
||||
|
|
||||
LL | #[repr("C")]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0565`.
|
@ -1,18 +0,0 @@
|
||||
#![feature(prelude_import)]
|
||||
#![no_std]
|
||||
#[prelude_import]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
#[macro_use]
|
||||
extern crate std;
|
||||
// Regression test for #83921. A `delay_span_bug()` call was issued, but the
|
||||
// error was never reported because the pass responsible for detecting and
|
||||
// reporting the error does not run in certain modes of pretty-printing.
|
||||
|
||||
// Make sure the error is reported if we do not just pretty-print:
|
||||
// revisions: pretty normal
|
||||
// [pretty]compile-flags: -Zunpretty=everybody_loops
|
||||
// [pretty]check-pass
|
||||
#[repr("C")]
|
||||
struct A {}
|
||||
|
||||
fn main() { loop {} }
|
@ -1,14 +0,0 @@
|
||||
// Regression test for #83921. A `delay_span_bug()` call was issued, but the
|
||||
// error was never reported because the pass responsible for detecting and
|
||||
// reporting the error does not run in certain modes of pretty-printing.
|
||||
|
||||
// Make sure the error is reported if we do not just pretty-print:
|
||||
// revisions: pretty normal
|
||||
// [pretty]compile-flags: -Zunpretty=everybody_loops
|
||||
// [pretty]check-pass
|
||||
|
||||
#[repr("C")]
|
||||
//[normal]~^ ERROR: meta item in `repr` must be an identifier [E0565]
|
||||
struct A {}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user