Rollup merge of #65105 - Mark-Simulacrum:split-librustc, r=nikomatsakis

Split out some passes from librustc

This is just moving them out to librustc_passes -- I've not measured compile time or run time. I don't expect any significant impact, but this seems prudent regardless.
This commit is contained in:
Tyler Mandry 2019-10-05 21:55:00 -07:00 committed by GitHub
commit 2c8cbcca54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 238 additions and 228 deletions

View File

@ -3613,6 +3613,8 @@ dependencies = [
"rustc",
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_target",
"syntax",
"syntax_pos",
]

View File

@ -466,66 +466,6 @@ fn main() {
```
"##,
// This shouldn't really ever trigger since the repeated value error comes first
E0136: r##"
A binary can only have one entry point, and by default that entry point is the
function `main()`. If there are multiple such functions, please rename one.
"##,
E0137: r##"
More than one function was declared with the `#[main]` attribute.
Erroneous code example:
```compile_fail,E0137
#![feature(main)]
#[main]
fn foo() {}
#[main]
fn f() {} // error: multiple functions with a `#[main]` attribute
```
This error indicates that the compiler found multiple functions with the
`#[main]` attribute. This is an error because there must be a unique entry
point into a Rust program. Example:
```
#![feature(main)]
#[main]
fn f() {} // ok!
```
"##,
E0138: r##"
More than one function was declared with the `#[start]` attribute.
Erroneous code example:
```compile_fail,E0138
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize {}
#[start]
fn f(argc: isize, argv: *const *const u8) -> isize {}
// error: multiple 'start' functions
```
This error indicates that the compiler found multiple functions with the
`#[start]` attribute. This is an error because there must be a unique entry
point into a Rust program. Example:
```
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
```
"##,
E0139: r##"
#### Note: this error code is no longer emitted by the compiler.
@ -1626,33 +1566,6 @@ It is not possible to use stability attributes outside of the standard library.
Also, for now, it is not possible to write deprecation messages either.
"##,
E0512: r##"
Transmute with two differently sized types was attempted. Erroneous code
example:
```compile_fail,E0512
fn takes_u8(_: u8) {}
fn main() {
unsafe { takes_u8(::std::mem::transmute(0u16)); }
// error: cannot transmute between types of different sizes,
// or dependently-sized types
}
```
Please use types with same size or use the expected type directly. Example:
```
fn takes_u8(_: u8) {}
fn main() {
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
// or:
unsafe { takes_u8(0u8); } // ok!
}
```
"##,
E0517: r##"
This error indicates that a `#[repr(..)]` attribute was placed on an
unsupported item.
@ -1847,84 +1760,6 @@ See [RFC 1522] for more details.
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
"##,
E0591: r##"
Per [RFC 401][rfc401], if you have a function declaration `foo`:
```
// For the purposes of this explanation, all of these
// different kinds of `fn` declarations are equivalent:
struct S;
fn foo(x: S) { /* ... */ }
# #[cfg(for_demonstration_only)]
extern "C" { fn foo(x: S); }
# #[cfg(for_demonstration_only)]
impl S { fn foo(self) { /* ... */ } }
```
the type of `foo` is **not** `fn(S)`, as one might expect.
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
so you rarely notice this:
```
# struct S;
# fn foo(_: S) {}
let x: fn(S) = foo; // OK, coerces
```
The reason that this matter is that the type `fn(S)` is not specific to
any particular function: it's a function _pointer_. So calling `x()` results
in a virtual call, whereas `foo()` is statically dispatched, because the type
of `foo` tells us precisely what function is being called.
As noted above, coercions mean that most code doesn't have to be
concerned with this distinction. However, you can tell the difference
when using **transmute** to convert a fn item into a fn pointer.
This is sometimes done as part of an FFI:
```compile_fail,E0591
extern "C" fn foo(userdata: Box<i32>) {
/* ... */
}
# fn callback(_: extern "C" fn(*mut i32)) {}
# use std::mem::transmute;
# unsafe {
let f: extern "C" fn(*mut i32) = transmute(foo);
callback(f);
# }
```
Here, transmute is being used to convert the types of the fn arguments.
This pattern is incorrect because, because the type of `foo` is a function
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
is a function pointer, which is not zero-sized.
This pattern should be rewritten. There are a few possible ways to do this:
- change the original fn declaration to match the expected signature,
and do the cast in the fn body (the preferred option)
- cast the fn item fo a fn pointer before calling transmute, as shown here:
```
# extern "C" fn foo(_: Box<i32>) {}
# use std::mem::transmute;
# unsafe {
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
# }
```
The same applies to transmutes to `*mut fn()`, which were observed in practice.
Note though that use of this type is generally incorrect.
The intention is typically to describe a function pointer, but just `fn()`
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
(Since these values are typically just passed to C code, however, this rarely
makes a difference in practice.)
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
"##,
E0593: r##"
You tried to supply an `Fn`-based type with an incorrect number of arguments
than what was expected.
@ -1941,21 +1776,6 @@ fn main() {
```
"##,
E0601: r##"
No `main` function was found in a binary crate. To fix this error, add a
`main` function. For example:
```
fn main() {
// Your program will start here.
println!("Hello world!");
}
```
If you don't know the basics of Rust, you can go look to the Rust Book to get
started: https://doc.rust-lang.org/book/
"##,
E0602: r##"
An unknown lint was used on the command line.

View File

@ -101,16 +101,12 @@ pub mod lint;
pub mod middle {
pub mod expr_use_visitor;
pub mod cstore;
pub mod dead;
pub mod dependency_format;
pub mod diagnostic_items;
pub mod entry;
pub mod exported_symbols;
pub mod free_region;
pub mod intrinsicck;
pub mod lib_features;
pub mod lang_items;
pub mod liveness;
pub mod mem_categorization;
pub mod privacy;
pub mod reachable;

View File

@ -780,13 +780,10 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
ty::provide(providers);
traits::provide(providers);
stability::provide(providers);
middle::intrinsicck::provide(providers);
middle::liveness::provide(providers);
reachable::provide(providers);
rustc_passes::provide(providers);
rustc_traits::provide(providers);
middle::region::provide(providers);
middle::entry::provide(providers);
cstore::provide(providers);
lint::provide(providers);
rustc_lint::provide(providers);
@ -892,7 +889,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
time(sess, "misc checking 1", || {
parallel!({
entry_point = time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
rustc_passes::entry::find_entry_point(tcx)
});
time(sess, "looking for plugin registrar", || {
@ -973,7 +970,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
tcx.ensure().check_private_in_public(LOCAL_CRATE);
});
}, {
time(sess, "death checking", || middle::dead::check_crate(tcx));
time(sess, "death checking", || rustc_passes::dead::check_crate(tcx));
}, {
time(sess, "unused lib feature checking", || {
stability::check_unused_or_stable_features(tcx)

View File

@ -15,3 +15,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
rustc_target = { path = "../librustc_target" }
rustc_index = { path = "../librustc_index" }

View File

@ -2,18 +2,18 @@
// closely. The idea is that all reachable symbols are live, codes called
// from live codes are live, and everything else is dead.
use crate::hir::Node;
use crate::hir::{self, PatKind, TyKind};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::Node;
use rustc::hir::{self, PatKind, TyKind};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use crate::hir::def::{CtorOf, Res, DefKind};
use crate::hir::CodegenFnAttrFlags;
use crate::hir::def_id::{DefId, LOCAL_CRATE};
use crate::lint;
use crate::middle::privacy;
use crate::ty::{self, DefIdTree, TyCtxt};
use crate::util::nodemap::FxHashSet;
use rustc::hir::def::{CtorOf, Res, DefKind};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::lint;
use rustc::middle::privacy;
use rustc::ty::{self, DefIdTree, TyCtxt};
use rustc::util::nodemap::FxHashSet;
use rustc_data_structures::fx::FxHashMap;

View File

@ -1,15 +1,15 @@
use crate::hir::map as hir_map;
use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use crate::session::{config, Session};
use crate::session::config::EntryFnType;
use rustc::hir::map as hir_map;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use rustc::session::{config, Session};
use rustc::session::config::EntryFnType;
use syntax::attr;
use syntax::entry::EntryPointType;
use syntax::symbol::sym;
use syntax_pos::Span;
use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem};
use crate::hir::itemlikevisit::ItemLikeVisitor;
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
use rustc::hir::{HirId, Item, ItemKind, ImplItem, TraitItem};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
struct EntryContext<'a, 'tcx> {
session: &'a Session,

View File

@ -319,6 +319,188 @@ async fn foo() {}
Switch to the Rust 2018 edition to use `async fn`.
"##,
// This shouldn't really ever trigger since the repeated value error comes first
E0136: r##"
A binary can only have one entry point, and by default that entry point is the
function `main()`. If there are multiple such functions, please rename one.
"##,
E0137: r##"
More than one function was declared with the `#[main]` attribute.
Erroneous code example:
```compile_fail,E0137
#![feature(main)]
#[main]
fn foo() {}
#[main]
fn f() {} // error: multiple functions with a `#[main]` attribute
```
This error indicates that the compiler found multiple functions with the
`#[main]` attribute. This is an error because there must be a unique entry
point into a Rust program. Example:
```
#![feature(main)]
#[main]
fn f() {} // ok!
```
"##,
E0138: r##"
More than one function was declared with the `#[start]` attribute.
Erroneous code example:
```compile_fail,E0138
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize {}
#[start]
fn f(argc: isize, argv: *const *const u8) -> isize {}
// error: multiple 'start' functions
```
This error indicates that the compiler found multiple functions with the
`#[start]` attribute. This is an error because there must be a unique entry
point into a Rust program. Example:
```
#![feature(start)]
#[start]
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
```
"##,
E0601: r##"
No `main` function was found in a binary crate. To fix this error, add a
`main` function. For example:
```
fn main() {
// Your program will start here.
println!("Hello world!");
}
```
If you don't know the basics of Rust, you can go look to the Rust Book to get
started: https://doc.rust-lang.org/book/
"##,
E0591: r##"
Per [RFC 401][rfc401], if you have a function declaration `foo`:
```
// For the purposes of this explanation, all of these
// different kinds of `fn` declarations are equivalent:
struct S;
fn foo(x: S) { /* ... */ }
# #[cfg(for_demonstration_only)]
extern "C" { fn foo(x: S); }
# #[cfg(for_demonstration_only)]
impl S { fn foo(self) { /* ... */ } }
```
the type of `foo` is **not** `fn(S)`, as one might expect.
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
so you rarely notice this:
```
# struct S;
# fn foo(_: S) {}
let x: fn(S) = foo; // OK, coerces
```
The reason that this matter is that the type `fn(S)` is not specific to
any particular function: it's a function _pointer_. So calling `x()` results
in a virtual call, whereas `foo()` is statically dispatched, because the type
of `foo` tells us precisely what function is being called.
As noted above, coercions mean that most code doesn't have to be
concerned with this distinction. However, you can tell the difference
when using **transmute** to convert a fn item into a fn pointer.
This is sometimes done as part of an FFI:
```compile_fail,E0591
extern "C" fn foo(userdata: Box<i32>) {
/* ... */
}
# fn callback(_: extern "C" fn(*mut i32)) {}
# use std::mem::transmute;
# unsafe {
let f: extern "C" fn(*mut i32) = transmute(foo);
callback(f);
# }
```
Here, transmute is being used to convert the types of the fn arguments.
This pattern is incorrect because, because the type of `foo` is a function
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
is a function pointer, which is not zero-sized.
This pattern should be rewritten. There are a few possible ways to do this:
- change the original fn declaration to match the expected signature,
and do the cast in the fn body (the preferred option)
- cast the fn item fo a fn pointer before calling transmute, as shown here:
```
# extern "C" fn foo(_: Box<i32>) {}
# use std::mem::transmute;
# unsafe {
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
# }
```
The same applies to transmutes to `*mut fn()`, which were observed in practice.
Note though that use of this type is generally incorrect.
The intention is typically to describe a function pointer, but just `fn()`
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
(Since these values are typically just passed to C code, however, this rarely
makes a difference in practice.)
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
"##,
E0512: r##"
Transmute with two differently sized types was attempted. Erroneous code
example:
```compile_fail,E0512
fn takes_u8(_: u8) {}
fn main() {
unsafe { takes_u8(::std::mem::transmute(0u16)); }
// error: cannot transmute between types of different sizes,
// or dependently-sized types
}
```
Please use types with same size or use the expected type directly. Example:
```
fn takes_u8(_: u8) {}
fn main() {
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
// or:
unsafe { takes_u8(0u8); } // ok!
}
```
"##,
;
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target

View File

@ -1,14 +1,14 @@
use crate::hir::def::{Res, DefKind};
use crate::hir::def_id::DefId;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
use crate::ty::query::Providers;
use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
use rustc::ty::query::Providers;
use rustc_target::spec::abi::Abi::RustIntrinsic;
use rustc_index::vec::Idx;
use syntax_pos::{Span, sym};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir;
fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(

View File

@ -13,6 +13,10 @@
#[macro_use]
extern crate rustc;
#[macro_use]
extern crate log;
#[macro_use]
extern crate syntax;
use rustc::ty::query::Providers;
@ -22,7 +26,14 @@ pub mod ast_validation;
pub mod hir_stats;
pub mod layout_test;
pub mod loops;
pub mod dead;
pub mod entry;
mod liveness;
mod intrinsicck;
pub fn provide(providers: &mut Providers<'_>) {
entry::provide(providers);
loops::provide(providers);
liveness::provide(providers);
intrinsicck::provide(providers);
}

View File

@ -96,17 +96,17 @@
use self::LiveNodeKind::*;
use self::VarKind::*;
use crate::hir;
use crate::hir::{Expr, HirId};
use crate::hir::def::*;
use crate::hir::def_id::DefId;
use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
use crate::hir::Node;
use crate::hir::ptr::P;
use crate::ty::{self, TyCtxt};
use crate::ty::query::Providers;
use crate::lint;
use crate::util::nodemap::{HirIdMap, HirIdSet};
use rustc::hir;
use rustc::hir::{Expr, HirId};
use rustc::hir::def::*;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
use rustc::hir::Node;
use rustc::hir::ptr::P;
use rustc::ty::{self, TyCtxt};
use rustc::ty::query::Providers;
use rustc::lint;
use rustc::util::nodemap::{HirIdMap, HirIdSet};
use errors::Applicability;
use rustc_data_structures::fx::FxIndexMap;
@ -373,7 +373,7 @@ fn visit_fn<'tcx>(
for param in &body.params {
let is_shorthand = match param.pat.kind {
crate::hir::PatKind::Struct(..) => true,
rustc::hir::PatKind::Struct(..) => true,
_ => false,
};
param.pat.each_binding(|_bm, hir_id, _x, ident| {
@ -411,7 +411,7 @@ fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P<hir::Pat>) {
let mut pats = VecDeque::new();
pats.push_back(pat);
while let Some(pat) = pats.pop_front() {
use crate::hir::PatKind::*;
use rustc::hir::PatKind::*;
match &pat.kind {
Binding(.., inner_pat) => {
pats.extend(inner_pat.iter());