Auto merge of #22801 - huonw:crateify-lint, r=kmcallister
This pulls out the implementations of most built-in lints into a separate crate, to reduce edit-compile-test iteration times with librustc_lint and increase parallelism. This should enable lints to be refactored, added and deleted much more easily as it slashes the edit-compile cycle to get a minimal working compiler to test with (`make rustc-stage1`) from librustc -> librustc_typeck -> ... -> librustc_driver -> libcore -> ... -> libstd to librustc_lint -> librustc_driver -> libcore -> ... libstd which is significantly faster, mainly due to avoiding the librustc build itself. The intention would be to move as much as possible of the infrastructure into the crate too, but the plumbing is deeply intertwined with librustc itself at the moment. Also, there are lints for which diagnostics are registered directly in the compiler code, not in their own crate traversal, and their definitions have to remain in librustc. This is a [breaking-change] for direct users of the compiler APIs: callers of `rustc::session::build_session` or `rustc::session::build_session_` need to manually call `rustc_lint::register_builtins` on their return value. This should make #22206 easier.
This commit is contained in:
commit
48aeaba934
13
mk/crates.mk
13
mk/crates.mk
@ -54,7 +54,7 @@ TARGET_CRATES := libc std flate arena term \
|
||||
log graphviz core rbml alloc \
|
||||
unicode rustc_bitflags
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint
|
||||
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
|
||||
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
|
||||
TOOLS := compiletest rustdoc rustc rustbook
|
||||
@ -70,7 +70,7 @@ DEPS_graphviz := std
|
||||
DEPS_syntax := std term serialize log fmt_macros arena libc
|
||||
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
|
||||
rustc_typeck rustc_resolve log syntax serialize rustc_llvm \
|
||||
rustc_trans rustc_privacy
|
||||
rustc_trans rustc_privacy rustc_lint
|
||||
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm
|
||||
@ -78,12 +78,13 @@ DEPS_rustc_typeck := rustc syntax
|
||||
DEPS_rustc_borrowck := rustc log graphviz syntax
|
||||
DEPS_rustc_resolve := rustc log syntax
|
||||
DEPS_rustc_privacy := rustc log syntax
|
||||
DEPS_rustc_lint := rustc log syntax
|
||||
DEPS_rustc := syntax flate arena serialize getopts rbml \
|
||||
log graphviz rustc_llvm rustc_back
|
||||
DEPS_rustc_llvm := native:rustllvm libc std
|
||||
DEPS_rustc_back := std syntax rustc_llvm flate log libc
|
||||
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
|
||||
test
|
||||
test rustc_lint
|
||||
DEPS_rustc_bitflags := core
|
||||
DEPS_flate := std native:miniz
|
||||
DEPS_arena := std
|
||||
@ -128,11 +129,13 @@ DOC_CRATES := $(filter-out rustc, \
|
||||
$(filter-out rustc_resolve, \
|
||||
$(filter-out rustc_driver, \
|
||||
$(filter-out rustc_privacy, \
|
||||
$(filter-out rustc_lint, \
|
||||
$(filter-out log, \
|
||||
$(filter-out getopts, \
|
||||
$(filter-out syntax, $(CRATES)))))))))))
|
||||
$(filter-out syntax, $(CRATES))))))))))))
|
||||
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
|
||||
rustc_typeck rustc_driver syntax rustc_privacy
|
||||
rustc_typeck rustc_driver syntax rustc_privacy \
|
||||
rustc_lint
|
||||
|
||||
# This macro creates some simple definitions for each crate being built, just
|
||||
# some munging of all of the parameters above.
|
||||
|
@ -21,7 +21,7 @@ $(eval $(call RUST_CRATE,coretest))
|
||||
|
||||
TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest
|
||||
TEST_DOC_CRATES = $(DOC_CRATES)
|
||||
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans,\
|
||||
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\
|
||||
$(HOST_CRATES))
|
||||
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#![feature(unsafe_destructor)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
#![feature(os)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -159,7 +159,7 @@ impl LintStore {
|
||||
}
|
||||
}
|
||||
|
||||
fn register_renamed(&mut self, old_name: &str, new_name: &str) {
|
||||
pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
|
||||
let target = match self.by_name.get(new_name) {
|
||||
Some(&Id(lint_id)) => lint_id.clone(),
|
||||
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
|
||||
@ -167,80 +167,6 @@ impl LintStore {
|
||||
self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
|
||||
}
|
||||
|
||||
pub fn register_builtin(&mut self, sess: Option<&Session>) {
|
||||
macro_rules! add_builtin {
|
||||
($sess:ident, $($name:ident),*,) => (
|
||||
{$(
|
||||
self.register_pass($sess, false, box builtin::$name as LintPassObject);
|
||||
)*}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! add_builtin_with_new {
|
||||
($sess:ident, $($name:ident),*,) => (
|
||||
{$(
|
||||
self.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
|
||||
)*}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! add_lint_group {
|
||||
($sess:ident, $name:expr, $($lint:ident),*) => (
|
||||
self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
|
||||
)
|
||||
}
|
||||
|
||||
add_builtin!(sess,
|
||||
HardwiredLints,
|
||||
WhileTrue,
|
||||
UnusedCasts,
|
||||
ImproperCTypes,
|
||||
BoxPointers,
|
||||
UnusedAttributes,
|
||||
PathStatements,
|
||||
UnusedResults,
|
||||
NonCamelCaseTypes,
|
||||
NonSnakeCase,
|
||||
NonUpperCaseGlobals,
|
||||
UnusedParens,
|
||||
UnusedImportBraces,
|
||||
NonShorthandFieldPatterns,
|
||||
UnusedUnsafe,
|
||||
UnsafeCode,
|
||||
UnusedMut,
|
||||
UnusedAllocation,
|
||||
MissingCopyImplementations,
|
||||
UnstableFeatures,
|
||||
Stability,
|
||||
UnconditionalRecursion,
|
||||
InvalidNoMangleItems,
|
||||
PluginAsLibrary,
|
||||
);
|
||||
|
||||
add_builtin_with_new!(sess,
|
||||
TypeLimits,
|
||||
RawPointerDerive,
|
||||
MissingDoc,
|
||||
MissingDebugImplementations,
|
||||
);
|
||||
|
||||
add_lint_group!(sess, "bad_style",
|
||||
NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
|
||||
|
||||
add_lint_group!(sess, "unused",
|
||||
UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
|
||||
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
|
||||
UNUSED_UNSAFE, PATH_STATEMENTS);
|
||||
|
||||
// We have one lint pass defined in this module.
|
||||
self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);
|
||||
|
||||
// Insert temporary renamings for a one-time deprecation
|
||||
self.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
|
||||
|
||||
self.register_renamed("unknown_features", "unused_features");
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
|
||||
-> Option<LintId>
|
||||
@ -741,7 +667,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
|
||||
// nodes, so that the variant size difference check in trans can call
|
||||
// `raw_emit_lint`.
|
||||
|
||||
struct GatherNodeLevels;
|
||||
pub struct GatherNodeLevels;
|
||||
|
||||
impl LintPass for GatherNodeLevels {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
|
@ -37,7 +37,8 @@ use syntax::codemap::Span;
|
||||
use syntax::visit::FnKind;
|
||||
use syntax::ast;
|
||||
|
||||
pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs};
|
||||
pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs,
|
||||
GatherNodeLevels};
|
||||
|
||||
/// Specification of a single lint.
|
||||
#[derive(Copy, Debug)]
|
||||
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use lint;
|
||||
use metadata::cstore::CStore;
|
||||
use metadata::filesearch;
|
||||
@ -389,7 +388,6 @@ pub fn build_session_(sopts: config::Options,
|
||||
can_print_warnings: can_print_warnings
|
||||
};
|
||||
|
||||
sess.lint_store.borrow_mut().register_builtin(Some(&sess));
|
||||
sess
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_privacy;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_trans;
|
||||
@ -133,6 +134,7 @@ pub fn run_compiler<'a>(args: &[String],
|
||||
};
|
||||
|
||||
let mut sess = build_session(sopts, input_file_path, descriptions);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
if sess.unstable_options() {
|
||||
sess.opts.show_span = matches.opt_str("show-span");
|
||||
}
|
||||
@ -299,11 +301,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
0 => {
|
||||
if sopts.describe_lints {
|
||||
let mut ls = lint::LintStore::new();
|
||||
ls.register_builtin(None);
|
||||
rustc_lint::register_builtins(&mut ls, None);
|
||||
describe_lints(&ls, false);
|
||||
return None;
|
||||
}
|
||||
let sess = build_session(sopts.clone(), None, descriptions.clone());
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let should_stop = RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
|
||||
if should_stop == Compilation::Stop {
|
||||
return None;
|
||||
@ -844,4 +847,3 @@ pub fn main() {
|
||||
let result = run(env::args().collect());
|
||||
std::env::set_exit_status(result as i32);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
use diagnostic;
|
||||
use diagnostic::Emitter;
|
||||
use driver;
|
||||
use rustc_lint;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_typeck::middle::lang_items;
|
||||
use rustc_typeck::middle::region::{self, CodeExtent, DestructionScopeData};
|
||||
@ -108,6 +109,7 @@ fn test_env<F>(source_string: &str,
|
||||
diagnostic::mk_span_handler(diagnostic_handler, codemap);
|
||||
|
||||
let sess = session::build_session_(options, None, span_diagnostic_handler);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let krate_config = Vec::new();
|
||||
let input = config::Input::Str(source_string.to_string());
|
||||
let krate = driver::phase_1_parse_input(&sess, krate_config, &input);
|
||||
|
2098
src/librustc_lint/builtin.rs
Normal file
2098
src/librustc_lint/builtin.rs
Normal file
File diff suppressed because it is too large
Load Diff
137
src/librustc_lint/lib.rs
Normal file
137
src/librustc_lint/lib.rs
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Lints in the Rust compiler.
|
||||
//!
|
||||
//! This currently only contains the definitions and implementations
|
||||
//! of most of the lints that `rustc` supports directly, it does not
|
||||
//! contain the infrastructure for defining/registering lints. That is
|
||||
//! available in `rustc::lint` and `rustc::plugin` respectively.
|
||||
//!
|
||||
//! # Note
|
||||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![crate_name = "rustc_lint"]
|
||||
#![unstable(feature = "rustc_private")]
|
||||
#![staged_api]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(unsafe_destructor)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
extern crate syntax;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
pub use rustc::lint as lint;
|
||||
pub use rustc::metadata as metadata;
|
||||
pub use rustc::middle as middle;
|
||||
pub use rustc::session as session;
|
||||
pub use rustc::util as util;
|
||||
|
||||
use session::Session;
|
||||
use lint::{LintPassObject, LintId};
|
||||
|
||||
mod builtin;
|
||||
|
||||
/// Tell the `LintStore` about all the built-in lints (the ones
|
||||
/// defined in this crate and the ones defined in
|
||||
/// `rustc::lint::builtin`).
|
||||
pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
macro_rules! add_builtin {
|
||||
($sess:ident, $($name:ident),*,) => (
|
||||
{$(
|
||||
store.register_pass($sess, false, box builtin::$name as LintPassObject);
|
||||
)*}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! add_builtin_with_new {
|
||||
($sess:ident, $($name:ident),*,) => (
|
||||
{$(
|
||||
store.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
|
||||
)*}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! add_lint_group {
|
||||
($sess:ident, $name:expr, $($lint:ident),*) => (
|
||||
store.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
|
||||
)
|
||||
}
|
||||
|
||||
add_builtin!(sess,
|
||||
HardwiredLints,
|
||||
WhileTrue,
|
||||
UnusedCasts,
|
||||
ImproperCTypes,
|
||||
BoxPointers,
|
||||
UnusedAttributes,
|
||||
PathStatements,
|
||||
UnusedResults,
|
||||
NonCamelCaseTypes,
|
||||
NonSnakeCase,
|
||||
NonUpperCaseGlobals,
|
||||
UnusedParens,
|
||||
UnusedImportBraces,
|
||||
NonShorthandFieldPatterns,
|
||||
UnusedUnsafe,
|
||||
UnsafeCode,
|
||||
UnusedMut,
|
||||
UnusedAllocation,
|
||||
MissingCopyImplementations,
|
||||
UnstableFeatures,
|
||||
Stability,
|
||||
UnconditionalRecursion,
|
||||
InvalidNoMangleItems,
|
||||
PluginAsLibrary,
|
||||
);
|
||||
|
||||
add_builtin_with_new!(sess,
|
||||
TypeLimits,
|
||||
RawPointerDerive,
|
||||
MissingDoc,
|
||||
MissingDebugImplementations,
|
||||
);
|
||||
|
||||
add_lint_group!(sess, "bad_style",
|
||||
NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
|
||||
|
||||
add_lint_group!(sess, "unused",
|
||||
UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
|
||||
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
|
||||
UNUSED_UNSAFE, PATH_STATEMENTS);
|
||||
|
||||
// We have one lint pass defined specially
|
||||
store.register_pass(sess, false, box lint::GatherNodeLevels as LintPassObject);
|
||||
|
||||
// Insert temporary renamings for a one-time deprecation
|
||||
store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
|
||||
|
||||
store.register_renamed("unknown_features", "unused_features");
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
pub use self::MaybeTyped::*;
|
||||
|
||||
use rustc_lint;
|
||||
use rustc_driver::driver;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::UnstableFeatures;
|
||||
@ -114,6 +115,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
|
||||
|
||||
let sess = session::build_session_(sessopts, cpath,
|
||||
span_diagnostic_handler);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let cfg = config::build_configuration(&sess);
|
||||
|
||||
|
@ -42,6 +42,7 @@ extern crate rustc;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_lint;
|
||||
extern crate serialize;
|
||||
extern crate syntax;
|
||||
extern crate "test" as testing;
|
||||
|
@ -20,6 +20,7 @@ use std::thunk::Thunk;
|
||||
|
||||
use std::collections::{HashSet, HashMap};
|
||||
use testing;
|
||||
use rustc_lint;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::get_unstable_features_setting;
|
||||
use rustc::session::search_paths::{SearchPaths, PathKind};
|
||||
@ -62,6 +63,7 @@ pub fn run(input: &str,
|
||||
let sess = session::build_session_(sessopts,
|
||||
Some(input_path.clone()),
|
||||
span_diagnostic_handler);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let mut cfg = config::build_configuration(&sess);
|
||||
cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
|
||||
@ -165,6 +167,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
||||
let sess = session::build_session_(sessopts,
|
||||
None,
|
||||
span_diagnostic_handler);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
|
||||
let out = Some(outdir.path().clone());
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_lint;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::session::{build_session, Session};
|
||||
@ -46,6 +47,7 @@ fn basic_sess(sysroot: Path) -> Session {
|
||||
|
||||
let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS);
|
||||
let sess = build_session(opts, None, descriptions);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
sess
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user