From 8b8488ce8fc047282e7159343f30609417f9fa39 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 24 Mar 2019 17:49:49 +0100 Subject: [PATCH 01/20] bootstrap: build compiler-builtins with -Z emit-stack-sizes --- src/bootstrap/bin/rustc.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ca86aeb8100a9..6f68775a85fd3 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -181,6 +181,30 @@ fn main() { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } + // Build `compiler_builtins` with `-Z emit-stack-sizes` to add stack usage information. + // + // When you use this flag with Cargo you get stack usage information on all crates compiled + // from source, and when you are using LTO you also get information on pre-compiled crates + // like `core` and `std`. However, there's an exception: `compiler_builtins`. This crate + // is special and doesn't participate in LTO because it's always linked as a separate object + // file. Due to this it's impossible to get information about this crate using `RUSTFLAGS` + // + Cargo, or `cargo rustc`. + // + // To make the stack usage information of this crate available to Cargo based stack usage + // analysis tools we compile `compiler_builtins` with the `-Z emit-stack-sizes` flag. The + // flag is known to currently work with targets that produce ELF files so we limit the use + // of the flag to those targets. + // + // NOTE(japaric) if this ever causes problem with an LLVM upgrade or any PR feel free to + // remove it or comment it out + if crate_name == "compiler_builtins" + && (target.contains("-linux-") + || target.contains("-none-eabi") + || target.ends_with("-none-elf")) + { + cmd.arg("-Z").arg("emit-stack-sizes"); + } + if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { cmd.arg("-C").arg(format!("codegen-units={}", s)); } From 7d365cf27f4249fc9b61ba8abfc813abe43f1cb7 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 25 Mar 2019 22:50:07 +0100 Subject: [PATCH 02/20] compile all crates under test w/ -Zemit-stack-sizes --- src/bootstrap/bin/rustc.rs | 29 ++++++++++++++++------------- src/bootstrap/compile.rs | 4 ++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 6f68775a85fd3..28c8a75a13ab4 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -181,28 +181,31 @@ fn main() { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } - // Build `compiler_builtins` with `-Z emit-stack-sizes` to add stack usage information. + // Build all crates in the `std` facade with `-Z emit-stack-sizes` to add stack usage + // information. // - // When you use this flag with Cargo you get stack usage information on all crates compiled - // from source, and when you are using LTO you also get information on pre-compiled crates - // like `core` and `std`. However, there's an exception: `compiler_builtins`. This crate - // is special and doesn't participate in LTO because it's always linked as a separate object - // file. Due to this it's impossible to get information about this crate using `RUSTFLAGS` - // + Cargo, or `cargo rustc`. + // When you use this `-Z` flag with Cargo you get stack usage information on all crates + // compiled from source, and when you are using LTO you also get information on pre-compiled + // crates like `core` and `std`, even if they were not compiled with `-Z emit-stack-sizes`. + // However, there's an exception: `compiler_builtins`. This crate is special and doesn't + // participate in LTO because it's always linked as a separate object file. For this reason + // it's impossible to get stack usage information about `compiler-builtins` using + // `RUSTFLAGS` + Cargo, or `cargo rustc`. // - // To make the stack usage information of this crate available to Cargo based stack usage - // analysis tools we compile `compiler_builtins` with the `-Z emit-stack-sizes` flag. The - // flag is known to currently work with targets that produce ELF files so we limit the use - // of the flag to those targets. + // To make the stack usage information of all crates under the `std` facade available to + // Cargo based stack usage analysis tools, in both LTO and non-LTO mode, we compile them + // with the `-Z emit-stack-sizes` flag. The `RUSTC_EMIT_STACK_SIZES` var helps us apply this + // flag only to the crates in the `std` facade. The `-Z` flag is known to currently work + // with targets that produce ELF files so we limit its use flag to those targets. // // NOTE(japaric) if this ever causes problem with an LLVM upgrade or any PR feel free to // remove it or comment it out - if crate_name == "compiler_builtins" + if env::var_os("RUSTC_EMIT_STACK_SIZES").is_some() && (target.contains("-linux-") || target.contains("-none-eabi") || target.ends_with("-none-elf")) { - cmd.arg("-Z").arg("emit-stack-sizes"); + cmd.arg("-Zemit-stack-sizes"); } if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9498dbb595232..0d51d7c5ef3b8 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -97,6 +97,8 @@ impl Step for Std { let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage)); builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target)); + // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details + cargo.env("RUSTC_EMIT_STACK_SIZES", "1"); run_cargo(builder, &mut cargo, &libstd_stamp(builder, compiler, target), @@ -382,6 +384,8 @@ impl Step for Test { let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage)); builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage, &compiler.host, target)); + // compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details + cargo.env("RUSTC_EMIT_STACK_SIZES", "1"); run_cargo(builder, &mut cargo, &libtest_stamp(builder, compiler, target), From c764890d7c508b401764c79bde9c0f3c430138e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 27 Mar 2019 18:37:21 +0100 Subject: [PATCH 03/20] musl: build toolchain libs with -fPIC --- src/ci/docker/scripts/musl-toolchain.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index 95b7c2869c91f..3caf2852ede42 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -29,6 +29,10 @@ TARGET=$ARCH-linux-musl OUTPUT=/usr/local shift +# Ancient binutils versions don't understand debug symbols produced by more recent tools. +# Apparently applying `-fPIC` everywhere allows them to link successfully. +export CFLAGS="-fPIC $CFLAGS" + git clone https://github.com/richfelker/musl-cross-make -b v0.9.7 cd musl-cross-make From c6e3ea475b9378fd551064e7b4e74ee96855337f Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 23:37:00 +0000 Subject: [PATCH 04/20] Visit path in `walk_mac` --- src/libsyntax/visit.rs | 4 ++-- src/libsyntax_ext/proc_macro_decls.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6b3a30ccb54b7..fbd6641f7c20e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -647,8 +647,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { } } -pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) { - // Empty! +pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) { + visitor.visit_path(&mac.node.path, DUMMY_NODE_ID); } pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index d5f37aff222ef..22fee902aea26 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -317,7 +317,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { self.in_root = prev_in_root; } - fn visit_mac(&mut self, mac: &ast::Mac) { + fn visit_mac(&mut self, mac: &'a ast::Mac) { visit::walk_mac(self, mac) } } From 41316f0449025394fdca6606d3fdb3b8f37a9872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 31 Jan 2019 01:36:11 +0100 Subject: [PATCH 05/20] Combine all builtin late lints --- src/librustc/lint/context.rs | 383 +++++++++++++++++++------------ src/librustc/lint/mod.rs | 11 +- src/librustc_interface/passes.rs | 7 +- src/librustc_lint/lib.rs | 185 +++++++++------ 4 files changed, 362 insertions(+), 224 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 953d0116aa2ba..e0bd795c342eb 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -18,7 +18,7 @@ use self::TargetLint::*; use std::slice; use rustc_data_structures::sync::ReadGuard; -use crate::lint::{EarlyLintPass, EarlyLintPassObject, LateLintPassObject}; +use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::levels::{LintLevelSets, LintLevelsBuilder}; @@ -27,7 +27,6 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use crate::session::{config, early_error, Session}; use crate::ty::{self, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; -use crate::ty::query::Providers; use crate::util::nodemap::FxHashMap; use crate::util::common::time; @@ -203,13 +202,16 @@ impl LintStore { pub fn register_late_pass(&mut self, sess: Option<&Session>, from_plugin: bool, + register_only: bool, per_module: bool, pass: LateLintPassObject) { self.push_pass(sess, from_plugin, &pass); - if per_module { - self.late_module_passes.as_mut().unwrap().push(pass); - } else { - self.late_passes.as_mut().unwrap().push(pass); + if !register_only { + if per_module { + self.late_module_passes.as_mut().unwrap().push(pass); + } else { + self.late_passes.as_mut().unwrap().push(pass); + } } } @@ -538,6 +540,11 @@ pub struct LateContext<'a, 'tcx: 'a> { only_module: bool, } +pub struct LateContextAndPass<'a, 'tcx: 'a, T: LateLintPass<'a, 'tcx>> { + context: LateContext<'a, 'tcx>, + pass: T, +} + /// Context for lint checking of the AST, after expansion, before lowering to /// HIR. pub struct EarlyContext<'a> { @@ -560,17 +567,6 @@ pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { pass: T, } -/// Convenience macro for calling a `LintPass` method on every pass in the context. -macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({ - // Move the vector of passes out of `$cx` so that we can - // iterate over it mutably while passing `$cx` to the methods. - let mut passes = $cx.lint_sess_mut().passes.take().unwrap(); - for obj in &mut passes { - obj.$f($cx, $($args),*); - } - $cx.lint_sess_mut().passes = Some(passes); -}) } - pub trait LintPassObject: Sized {} impl LintPassObject for EarlyLintPassObject {} @@ -668,6 +664,10 @@ impl<'a> EarlyContext<'a> { } } +macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ + $cx.pass.$f(&$cx.context, $($args),*); +}) } + macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } @@ -778,6 +778,21 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { } impl<'a, 'tcx> LateContext<'a, 'tcx> { + pub fn current_lint_root(&self) -> hir::HirId { + self.last_node_with_lint_attrs + } +} + +impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> { + type Ty = Ty<'tcx>; + type TyLayout = Result, LayoutError<'tcx>>; + + fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout { + self.tcx.layout_of(self.param_env.and(ty)) + } +} + +impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> LateContextAndPass<'a, 'tcx, T> { /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. @@ -787,107 +802,98 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { f: F) where F: FnOnce(&mut Self) { - let prev = self.last_node_with_lint_attrs; - self.last_node_with_lint_attrs = id; + let prev = self.context.last_node_with_lint_attrs; + self.context.last_node_with_lint_attrs = id; self.enter_attrs(attrs); f(self); self.exit_attrs(attrs); - self.last_node_with_lint_attrs = prev; - } - - fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { - debug!("late context: enter_attrs({:?})", attrs); - run_lints!(self, enter_lint_attrs, attrs); - } - - fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { - debug!("late context: exit_attrs({:?})", attrs); - run_lints!(self, exit_lint_attrs, attrs); + self.context.last_node_with_lint_attrs = prev; } fn with_param_env(&mut self, id: hir::HirId, f: F) where F: FnOnce(&mut Self), { - let old_param_env = self.param_env; - self.param_env = self.tcx.param_env(self.tcx.hir().local_def_id_from_hir_id(id)); + let old_param_env = self.context.param_env; + self.context.param_env = self.context.tcx.param_env( + self.context.tcx.hir().local_def_id_from_hir_id(id) + ); f(self); - self.param_env = old_param_env; - } - pub fn current_lint_root(&self) -> hir::HirId { - self.last_node_with_lint_attrs + self.context.param_env = old_param_env; } fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) { - run_lints!(self, check_mod, m, s, n); + lint_callback!(self, check_mod, m, s, n); hir_visit::walk_mod(self, m, n); - run_lints!(self, check_mod_post, m, s, n); + lint_callback!(self, check_mod_post, m, s, n); } -} -impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> { - type Ty = Ty<'tcx>; - type TyLayout = Result, LayoutError<'tcx>>; + fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { + debug!("late context: enter_attrs({:?})", attrs); + lint_callback!(self, enter_lint_attrs, attrs); + } - fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout { - self.tcx.layout_of(self.param_env.and(ty)) + fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]) { + debug!("late context: exit_attrs({:?})", attrs); + lint_callback!(self, exit_lint_attrs, attrs); } } -impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { +impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx> +for LateContextAndPass<'a, 'tcx, T> { /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable /// deep-walking. fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'tcx> { - hir_visit::NestedVisitorMap::All(&self.tcx.hir()) + hir_visit::NestedVisitorMap::All(&self.context.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { - let old_tables = self.tables; - self.tables = self.tcx.body_tables(body); - let body = self.tcx.hir().body(body); + let old_tables = self.context.tables; + self.context.tables = self.context.tcx.body_tables(body); + let body = self.context.tcx.hir().body(body); self.visit_body(body); - self.tables = old_tables; + self.context.tables = old_tables; } fn visit_body(&mut self, body: &'tcx hir::Body) { - run_lints!(self, check_body, body); + lint_callback!(self, check_body, body); hir_visit::walk_body(self, body); - run_lints!(self, check_body_post, body); + lint_callback!(self, check_body_post, body); } fn visit_item(&mut self, it: &'tcx hir::Item) { - let generics = self.generics.take(); - self.generics = it.node.generics(); + let generics = self.context.generics.take(); + self.context.generics = it.node.generics(); self.with_lint_attrs(it.hir_id, &it.attrs, |cx| { cx.with_param_env(it.hir_id, |cx| { - run_lints!(cx, check_item, it); + lint_callback!(cx, check_item, it); hir_visit::walk_item(cx, it); - run_lints!(cx, check_item_post, it); + lint_callback!(cx, check_item_post, it); }); }); - self.generics = generics; + self.context.generics = generics; } fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem) { self.with_lint_attrs(it.hir_id, &it.attrs, |cx| { cx.with_param_env(it.hir_id, |cx| { - run_lints!(cx, check_foreign_item, it); + lint_callback!(cx, check_foreign_item, it); hir_visit::walk_foreign_item(cx, it); - run_lints!(cx, check_foreign_item_post, it); + lint_callback!(cx, check_foreign_item_post, it); }); }) } fn visit_pat(&mut self, p: &'tcx hir::Pat) { - run_lints!(self, check_pat, p); + lint_callback!(self, check_pat, p); hir_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &'tcx hir::Expr) { self.with_lint_attrs(e.hir_id, &e.attrs, |cx| { - run_lints!(cx, check_expr, e); + lint_callback!(cx, check_expr, e); hir_visit::walk_expr(cx, e); - run_lints!(cx, check_expr_post, e); + lint_callback!(cx, check_expr_post, e); }) } @@ -897,7 +903,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { // - local // - expression // so we keep track of lint levels there - run_lints!(self, check_stmt, s); + lint_callback!(self, check_stmt, s); hir_visit::walk_stmt(self, s); } @@ -905,13 +911,13 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { body_id: hir::BodyId, span: Span, id: hir::HirId) { // Wrap in tables here, not just in visit_nested_body, // in order for `check_fn` to be able to use them. - let old_tables = self.tables; - self.tables = self.tcx.body_tables(body_id); - let body = self.tcx.hir().body(body_id); - run_lints!(self, check_fn, fk, decl, body, span, id); + let old_tables = self.context.tables; + self.context.tables = self.context.tcx.body_tables(body_id); + let body = self.context.tcx.hir().body(body_id); + lint_callback!(self, check_fn, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id); - run_lints!(self, check_fn_post, fk, decl, body, span, id); - self.tables = old_tables; + lint_callback!(self, check_fn_post, fk, decl, body, span, id); + self.context.tables = old_tables; } fn visit_variant_data(&mut self, @@ -920,14 +926,14 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { g: &'tcx hir::Generics, item_id: hir::HirId, _: Span) { - run_lints!(self, check_struct_def, s, name, g, item_id); + lint_callback!(self, check_struct_def, s, name, g, item_id); hir_visit::walk_struct_def(self, s); - run_lints!(self, check_struct_def_post, s, name, g, item_id); + lint_callback!(self, check_struct_def_post, s, name, g, item_id); } fn visit_struct_field(&mut self, s: &'tcx hir::StructField) { self.with_lint_attrs(s.hir_id, &s.attrs, |cx| { - run_lints!(cx, check_struct_field, s); + lint_callback!(cx, check_struct_field, s); hir_visit::walk_struct_field(cx, s); }) } @@ -937,104 +943,104 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { g: &'tcx hir::Generics, item_id: hir::HirId) { self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| { - run_lints!(cx, check_variant, v, g); + lint_callback!(cx, check_variant, v, g); hir_visit::walk_variant(cx, v, g, item_id); - run_lints!(cx, check_variant_post, v, g); + lint_callback!(cx, check_variant_post, v, g); }) } fn visit_ty(&mut self, t: &'tcx hir::Ty) { - run_lints!(self, check_ty, t); + lint_callback!(self, check_ty, t); hir_visit::walk_ty(self, t); } fn visit_name(&mut self, sp: Span, name: ast::Name) { - run_lints!(self, check_name, sp, name); + lint_callback!(self, check_name, sp, name); } fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) { - if !self.only_module { + if !self.context.only_module { self.process_mod(m, s, n); } } fn visit_local(&mut self, l: &'tcx hir::Local) { self.with_lint_attrs(l.hir_id, &l.attrs, |cx| { - run_lints!(cx, check_local, l); + lint_callback!(cx, check_local, l); hir_visit::walk_local(cx, l); }) } fn visit_block(&mut self, b: &'tcx hir::Block) { - run_lints!(self, check_block, b); + lint_callback!(self, check_block, b); hir_visit::walk_block(self, b); - run_lints!(self, check_block_post, b); + lint_callback!(self, check_block_post, b); } fn visit_arm(&mut self, a: &'tcx hir::Arm) { - run_lints!(self, check_arm, a); + lint_callback!(self, check_arm, a); hir_visit::walk_arm(self, a); } fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) { - run_lints!(self, check_generic_param, p); + lint_callback!(self, check_generic_param, p); hir_visit::walk_generic_param(self, p); } fn visit_generics(&mut self, g: &'tcx hir::Generics) { - run_lints!(self, check_generics, g); + lint_callback!(self, check_generics, g); hir_visit::walk_generics(self, g); } fn visit_where_predicate(&mut self, p: &'tcx hir::WherePredicate) { - run_lints!(self, check_where_predicate, p); + lint_callback!(self, check_where_predicate, p); hir_visit::walk_where_predicate(self, p); } fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef, m: hir::TraitBoundModifier) { - run_lints!(self, check_poly_trait_ref, t, m); + lint_callback!(self, check_poly_trait_ref, t, m); hir_visit::walk_poly_trait_ref(self, t, m); } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { - let generics = self.generics.take(); - self.generics = Some(&trait_item.generics); + let generics = self.context.generics.take(); + self.context.generics = Some(&trait_item.generics); self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |cx| { cx.with_param_env(trait_item.hir_id, |cx| { - run_lints!(cx, check_trait_item, trait_item); + lint_callback!(cx, check_trait_item, trait_item); hir_visit::walk_trait_item(cx, trait_item); - run_lints!(cx, check_trait_item_post, trait_item); + lint_callback!(cx, check_trait_item_post, trait_item); }); }); - self.generics = generics; + self.context.generics = generics; } fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { - let generics = self.generics.take(); - self.generics = Some(&impl_item.generics); + let generics = self.context.generics.take(); + self.context.generics = Some(&impl_item.generics); self.with_lint_attrs(impl_item.hir_id, &impl_item.attrs, |cx| { cx.with_param_env(impl_item.hir_id, |cx| { - run_lints!(cx, check_impl_item, impl_item); + lint_callback!(cx, check_impl_item, impl_item); hir_visit::walk_impl_item(cx, impl_item); - run_lints!(cx, check_impl_item_post, impl_item); + lint_callback!(cx, check_impl_item_post, impl_item); }); }); - self.generics = generics; + self.context.generics = generics; } fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) { - run_lints!(self, check_lifetime, lt); + lint_callback!(self, check_lifetime, lt); hir_visit::walk_lifetime(self, lt); } fn visit_path(&mut self, p: &'tcx hir::Path, id: hir::HirId) { - run_lints!(self, check_path, p, id); + lint_callback!(self, check_path, p, id); hir_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) { - run_lints!(self, check_attribute, attr); + lint_callback!(self, check_attribute, attr); } } @@ -1222,94 +1228,182 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } } -pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { +struct LateLintPassObjects<'a> { + lints: &'a mut [LateLintPassObject], +} + +impl LintPass for LateLintPassObjects<'_> { + fn name(&self) -> &'static str { + panic!() + } + + fn get_lints(&self) -> LintArray { + panic!() + } +} + +macro_rules! expand_late_lint_pass_impl_methods { + ([$a:tt, $hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + $(fn $name(&mut self, context: &LateContext<$a, $hir>, $($param: $arg),*) { + for obj in self.lints.iter_mut() { + obj.$name(context, $($param),*); + } + })* + ) +} + +macro_rules! late_lint_pass_impl { + ([], [$hir:tt], $methods:tt) => ( + impl LateLintPass<'a, $hir> for LateLintPassObjects<'_> { + expand_late_lint_pass_impl_methods!(['a, $hir], $methods); + } + ) +} + +late_lint_methods!(late_lint_pass_impl, [], ['tcx]); + +fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + module_def_id: DefId, + pass: T, +) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let store = &tcx.sess.lint_store; - let passes = store.borrow_mut().late_module_passes.take(); - let mut cx = LateContext { + let context = LateContext { tcx, tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, lint_sess: LintSession { lints: store.borrow(), - passes, + passes: None, }, last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(), generics: None, only_module: true, }; + let mut cx = LateContextAndPass { + context, + pass + }; + let (module, span, hir_id) = tcx.hir().get_module(module_def_id); cx.process_mod(module, span, hir_id); // Visit the crate attributes if hir_id == hir::CRATE_HIR_ID { - walk_list!(cx, visit_attribute, cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID)); + walk_list!(cx, visit_attribute, tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID)); } - - // Put the lint store levels and passes back in the session. - let passes = cx.lint_sess.passes; - drop(cx.lint_sess.lints); - store.borrow_mut().late_module_passes = passes; } -pub(crate) fn provide(providers: &mut Providers<'_>) { - *providers = Providers { - lint_mod, - ..*providers - }; +pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + module_def_id: DefId, + builtin_lints: T, +) { + assert!(!tcx.sess.opts.debugging_opts.no_interleave_lints); + + late_lint_mod_pass(tcx, module_def_id, builtin_lints); + + let mut passes = tcx.sess.lint_store.borrow_mut().late_module_passes.take().unwrap(); + + if !passes.is_empty() { + late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); + } + + // Put the passes back in the session. + tcx.sess.lint_store.borrow_mut().late_module_passes = Some(passes); } -fn lint_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { +fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + pass: T +) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let krate = tcx.hir().krate(); - let passes = tcx.sess.lint_store.borrow_mut().late_passes.take(); - - let passes = { - let mut cx = LateContext { - tcx, - tables: &ty::TypeckTables::empty(None), - param_env: ty::ParamEnv::empty(), - access_levels, - lint_sess: LintSession { - passes, - lints: tcx.sess.lint_store.borrow(), - }, - last_node_with_lint_attrs: hir::CRATE_HIR_ID, - generics: None, - only_module: false, - }; - // Visit the whole crate. - cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| { - // since the root module isn't visited as an item (because it isn't an - // item), warn for it here. - run_lints!(cx, check_crate, krate); - - hir_visit::walk_crate(cx, krate); + let context = LateContext { + tcx, + tables: &ty::TypeckTables::empty(None), + param_env: ty::ParamEnv::empty(), + access_levels, + lint_sess: LintSession { + passes: None, + lints: tcx.sess.lint_store.borrow(), + }, + last_node_with_lint_attrs: hir::CRATE_HIR_ID, + generics: None, + only_module: false, + }; - run_lints!(cx, check_crate_post, krate); - }); - cx.lint_sess.passes + let mut cx = LateContextAndPass { + context, + pass }; - // Put the lint store levels and passes back in the session. - tcx.sess.lint_store.borrow_mut().late_passes = passes; + // Visit the whole crate. + cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| { + // since the root module isn't visited as an item (because it isn't an + // item), warn for it here. + lint_callback!(cx, check_crate, krate); + + hir_visit::walk_crate(cx, krate); + + lint_callback!(cx, check_crate_post, krate); + }) +} + +fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + builtin_lints: T +) { + let mut passes = tcx.sess.lint_store.borrow_mut().late_passes.take().unwrap(); + + if !tcx.sess.opts.debugging_opts.no_interleave_lints { + if !passes.is_empty() { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: &mut passes[..] }); + } + + late_lint_pass_crate(tcx, builtin_lints); + } else { + for pass in &mut passes { + time(tcx.sess, &format!("running late lint: {}", pass.name()), || { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }); + } + + let mut passes = tcx.sess.lint_store.borrow_mut().late_module_passes.take().unwrap(); + + for pass in &mut passes { + time(tcx.sess, &format!("running late module lint: {}", pass.name()), || { + late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); + }); + } + + // Put the passes back in the session. + tcx.sess.lint_store.borrow_mut().late_module_passes = Some(passes); + } + + // Put the passes back in the session. + tcx.sess.lint_store.borrow_mut().late_passes = Some(passes); } /// Performs lint checking on a crate. -pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { +pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + builtin_lints: T, +) { // Run per-module lints for &module in tcx.hir().krate().modules.keys() { tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); } // Run whole crate non-incremental lints - lint_crate(tcx); + late_lint_crate(tcx, builtin_lints); } struct EarlyLintPassObjects<'a> { @@ -1346,7 +1440,6 @@ macro_rules! early_lint_pass_impl { early_lint_methods!(early_lint_pass_impl, []); - fn early_lint_crate( sess: &Session, krate: &ast::Crate, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index cf1c5d50000fa..b54da5e5e80d8 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -42,8 +42,8 @@ use syntax::symbol::Symbol; use syntax_pos::Span; pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore, - check_crate, check_ast_crate, CheckLintNameResult, - FutureIncompatibleInfo, BufferedEarlyLint}; + check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult, + FutureIncompatibleInfo, BufferedEarlyLint,}; /// Specification of a single lint. #[derive(Copy, Clone, Debug)] @@ -298,14 +298,14 @@ macro_rules! expand_combined_late_lint_pass_methods { #[macro_export] macro_rules! declare_combined_late_lint_pass { - ([$name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => ( + ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => ( #[allow(non_snake_case)] - struct $name { + $v struct $name { $($passes: $passes,)* } impl $name { - fn new() -> Self { + $v fn new() -> Self { Self { $($passes: $constructor,)* } @@ -824,7 +824,6 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { pub fn provide(providers: &mut Providers<'_>) { providers.lint_levels = lint_levels; - context::provide(providers); } /// Returns whether `span` originates in a foreign crate's external macro. diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 44ca11df694a9..6a6f56332a8bc 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -330,7 +330,7 @@ pub fn register_plugins<'a>( ls.register_early_pass(Some(sess), true, false, pass); } for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, false, pass); + ls.register_late_pass(Some(sess), true, false, false, pass); } for (name, (to, deprecated_name)) in lint_groups { @@ -783,6 +783,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { middle::entry::provide(providers); cstore::provide(providers); lint::provide(providers); + rustc_lint::provide(providers); } pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { @@ -988,7 +989,9 @@ fn analysis<'tcx>( stability::check_unused_or_stable_features(tcx) }); }, { - time(sess, "lint checking", || lint::check_crate(tcx)); + time(sess, "lint checking", || { + lint::check_crate(tcx, rustc_lint::BuiltinCombinedLateLintPass::new()); + }); }); }, { time(sess, "privacy checking modules", || { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 4c624a267af9b..c9301a32d83c4 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -45,6 +45,9 @@ use rustc::lint::builtin::{ }; use rustc::session; use rustc::hir; +use rustc::hir::def_id::DefId; +use rustc::ty::query::Providers; +use rustc::ty::TyCtxt; use syntax::ast; use syntax::edition::Edition; @@ -62,6 +65,17 @@ use unused::*; /// Useful for other parts of the compiler. pub use builtin::SoftLints; +pub fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + lint_mod, + ..*providers + }; +} + +fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + lint::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); +} + macro_rules! pre_expansion_lint_passes { ($macro:path, $args:tt) => ( $macro!($args, [ @@ -94,6 +108,88 @@ macro_rules! declare_combined_early_pass { pre_expansion_lint_passes!(declare_combined_early_pass, [BuiltinCombinedPreExpansionLintPass]); early_lint_passes!(declare_combined_early_pass, [BuiltinCombinedEarlyLintPass]); +macro_rules! late_lint_passes { + ($macro:path, $args:tt) => ( + $macro!($args, [ + // FIXME: Look into regression when this is used as a module lint + // May Depend on constants elsewhere + UnusedBrokenConst: UnusedBrokenConst, + + // Uses attr::is_used which is untracked, can't be an incremental module pass. + UnusedAttributes: UnusedAttributes, + + // Needs to run after UnusedAttributes as it marks all `feature` attributes as used. + UnstableFeatures: UnstableFeatures, + + // Tracks state across modules + UnnameableTestItems: UnnameableTestItems::new(), + + // Tracks attributes of parents + MissingDoc: MissingDoc::new(), + + // Depends on access levels + // FIXME: Turn the computation of types which implement Debug into a query + // and change this to a module lint pass + MissingDebugImplementations: MissingDebugImplementations::new(), + ]); + ) +} + +macro_rules! late_lint_mod_passes { + ($macro:path, $args:tt) => ( + $macro!($args, [ + HardwiredLints: HardwiredLints, + WhileTrue: WhileTrue, + ImproperCTypes: ImproperCTypes, + VariantSizeDifferences: VariantSizeDifferences, + BoxPointers: BoxPointers, + PathStatements: PathStatements, + + // Depends on referenced function signatures in expressions + UnusedResults: UnusedResults, + + NonUpperCaseGlobals: NonUpperCaseGlobals, + NonShorthandFieldPatterns: NonShorthandFieldPatterns, + UnusedAllocation: UnusedAllocation, + + // Depends on types used in type definitions + MissingCopyImplementations: MissingCopyImplementations, + + PluginAsLibrary: PluginAsLibrary, + + // Depends on referenced function signatures in expressions + MutableTransmutes: MutableTransmutes, + + // Depends on types of fields, checks if they implement Drop + UnionsWithDropFields: UnionsWithDropFields, + + TypeAliasBounds: TypeAliasBounds, + + TrivialConstraints: TrivialConstraints, + TypeLimits: TypeLimits::new(), + + NonSnakeCase: NonSnakeCase, + InvalidNoMangleItems: InvalidNoMangleItems, + + // Depends on access levels + UnreachablePub: UnreachablePub, + + ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, + ]); + ) +} + +macro_rules! declare_combined_late_pass { + ([$v:vis $name:ident], $passes:tt) => ( + late_lint_methods!(declare_combined_late_lint_pass, [$v $name, $passes], ['tcx]); + ) +} + +// FIXME: Make a separate lint type which do not require typeck tables +late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]); + +late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]); + /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in /// `rustc::lint::builtin`). @@ -104,17 +200,25 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { ) } + macro_rules! register_pass { + ($method:ident, $constructor:expr, [$($args:expr),*]) => ( + store.$method(sess, false, false, $($args,)* box $constructor); + ) + } + macro_rules! register_passes { - ([$method:ident], [$($passes:ident: $constructor:expr,)*]) => ( + ([$method:ident, $args:tt], [$($passes:ident: $constructor:expr,)*]) => ( $( - store.$method(sess, false, false, box $constructor); + register_pass!($method, $constructor, $args); )* ) } if sess.map(|sess| sess.opts.debugging_opts.no_interleave_lints).unwrap_or(false) { - pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass]); - early_lint_passes!(register_passes, [register_early_pass]); + pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass, []]); + early_lint_passes!(register_passes, [register_early_pass, []]); + late_lint_passes!(register_passes, [register_late_pass, [false]]); + late_lint_mod_passes!(register_passes, [register_late_pass, [true]]); } else { store.register_pre_expansion_pass( sess, @@ -123,75 +227,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { box BuiltinCombinedPreExpansionLintPass::new() ); store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new()); + store.register_late_pass( + sess, false, true, true, box BuiltinCombinedModuleLateLintPass::new() + ); + store.register_late_pass( + sess, false, true, false, box BuiltinCombinedLateLintPass::new() + ); } - late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [ - HardwiredLints: HardwiredLints, - WhileTrue: WhileTrue, - ImproperCTypes: ImproperCTypes, - VariantSizeDifferences: VariantSizeDifferences, - BoxPointers: BoxPointers, - PathStatements: PathStatements, - - // Depends on referenced function signatures in expressions - UnusedResults: UnusedResults, - - NonUpperCaseGlobals: NonUpperCaseGlobals, - NonShorthandFieldPatterns: NonShorthandFieldPatterns, - UnusedAllocation: UnusedAllocation, - - // Depends on types used in type definitions - MissingCopyImplementations: MissingCopyImplementations, - - PluginAsLibrary: PluginAsLibrary, - - // Depends on referenced function signatures in expressions - MutableTransmutes: MutableTransmutes, - - // Depends on types of fields, checks if they implement Drop - UnionsWithDropFields: UnionsWithDropFields, - - TypeAliasBounds: TypeAliasBounds, - - TrivialConstraints: TrivialConstraints, - TypeLimits: TypeLimits::new(), - - NonSnakeCase: NonSnakeCase, - InvalidNoMangleItems: InvalidNoMangleItems, - - // Depends on access levels - UnreachablePub: UnreachablePub, - - ExplicitOutlivesRequirements: ExplicitOutlivesRequirements, - ]], ['tcx]); - - store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new()); - - late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ - // FIXME: Look into regression when this is used as a module lint - // May Depend on constants elsewhere - UnusedBrokenConst: UnusedBrokenConst, - - // Uses attr::is_used which is untracked, can't be an incremental module pass. - UnusedAttributes: UnusedAttributes, - - // Needs to run after UnusedAttributes as it marks all `feature` attributes as used. - UnstableFeatures: UnstableFeatures, - - // Tracks state across modules - UnnameableTestItems: UnnameableTestItems::new(), - - // Tracks attributes of parents - MissingDoc: MissingDoc::new(), - - // Depends on access levels - // FIXME: Turn the computation of types which implement Debug into a query - // and change this to a module lint pass - MissingDebugImplementations: MissingDebugImplementations::new(), - ]], ['tcx]); - - store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new()); - add_lint_group!(sess, "nonstandard_style", NON_CAMEL_CASE_TYPES, From cd32f9bccaaf021a3327fc28df3401dc32a644e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 31 Jan 2019 03:04:39 +0100 Subject: [PATCH 06/20] Remove LintSession and run incremental and whole crate lints in parallel --- src/librustc/lint/context.rs | 106 ++++++++++++------------------- src/librustc_interface/passes.rs | 2 +- 2 files changed, 40 insertions(+), 68 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index e0bd795c342eb..49e3eee4e52ef 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -17,7 +17,7 @@ use self::TargetLint::*; use std::slice; -use rustc_data_structures::sync::ReadGuard; +use rustc_data_structures::sync::{ReadGuard, Lock, join}; use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; use crate::lint::builtin::BuiltinLintDiagnostics; @@ -55,8 +55,8 @@ pub struct LintStore { /// This is only `None` while performing a lint pass. pre_expansion_passes: Option>, early_passes: Option>, - late_passes: Option>, - late_module_passes: Option>, + late_passes: Lock>>, + late_module_passes: Lock>>, /// Lints indexed by name. by_name: FxHashMap, @@ -69,14 +69,6 @@ pub struct LintStore { future_incompatible: FxHashMap, } -pub struct LintSession<'a, PassObject> { - /// Reference to the store of registered lints. - lints: ReadGuard<'a, LintStore>, - - /// Trait objects for each lint pass. - passes: Option>, -} - /// Lints that are buffered up early on in the `Session` before the /// `LintLevels` is calculated #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] @@ -151,8 +143,8 @@ impl LintStore { lints: vec![], pre_expansion_passes: Some(vec![]), early_passes: Some(vec![]), - late_passes: Some(vec![]), - late_module_passes: Some(vec![]), + late_passes: Lock::new(Some(vec![])), + late_module_passes: Lock::new(Some(vec![])), by_name: Default::default(), future_incompatible: Default::default(), lint_groups: Default::default(), @@ -208,9 +200,9 @@ impl LintStore { self.push_pass(sess, from_plugin, &pass); if !register_only { if per_module { - self.late_module_passes.as_mut().unwrap().push(pass); + self.late_module_passes.lock().as_mut().unwrap().push(pass); } else { - self.late_passes.as_mut().unwrap().push(pass); + self.late_passes.lock().as_mut().unwrap().push(pass); } } } @@ -529,7 +521,7 @@ pub struct LateContext<'a, 'tcx: 'a> { pub access_levels: &'a AccessLevels, /// The store of registered lints and the lint levels. - lint_sess: LintSession<'tcx, LateLintPassObject>, + lint_store: ReadGuard<'a, LintStore>, last_node_with_lint_attrs: hir::HirId, @@ -557,7 +549,7 @@ pub struct EarlyContext<'a> { builder: LintLevelsBuilder<'a>, /// The store of registered lints and the lint levels. - lint_sess: LintSession<'a, EarlyLintPassObject>, + lint_store: ReadGuard<'a, LintStore>, buffered: LintBuffer, } @@ -578,8 +570,6 @@ pub trait LintContext<'tcx>: Sized { fn sess(&self) -> &Session; fn lints(&self) -> &LintStore; - fn lint_sess(&self) -> &LintSession<'tcx, Self::PassObject>; - fn lint_sess_mut(&mut self) -> &mut LintSession<'tcx, Self::PassObject>; fn lookup_and_emit>(&self, lint: &'static Lint, @@ -654,10 +644,7 @@ impl<'a> EarlyContext<'a> { EarlyContext { sess, krate, - lint_sess: LintSession { - lints: sess.lint_store.borrow(), - passes: None, - }, + lint_store: sess.lint_store.borrow(), builder: LintLevelSets::builder(sess), buffered, } @@ -721,15 +708,7 @@ impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> { } fn lints(&self) -> &LintStore { - &*self.lint_sess.lints - } - - fn lint_sess(&self) -> &LintSession<'tcx, Self::PassObject> { - &self.lint_sess - } - - fn lint_sess_mut(&mut self) -> &mut LintSession<'tcx, Self::PassObject> { - &mut self.lint_sess + &*self.lint_store } fn lookup>(&self, @@ -757,15 +736,7 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { } fn lints(&self) -> &LintStore { - &*self.lint_sess.lints - } - - fn lint_sess(&self) -> &LintSession<'a, Self::PassObject> { - &self.lint_sess - } - - fn lint_sess_mut(&mut self) -> &mut LintSession<'a, Self::PassObject> { - &mut self.lint_sess + &*self.lint_store } fn lookup>(&self, @@ -1269,17 +1240,12 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( ) { let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); - let store = &tcx.sess.lint_store; - let context = LateContext { tcx, tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_sess: LintSession { - lints: store.borrow(), - passes: None, - }, + lint_store: tcx.sess.lint_store.borrow(), last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(), generics: None, only_module: true, @@ -1304,18 +1270,21 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( module_def_id: DefId, builtin_lints: T, ) { - assert!(!tcx.sess.opts.debugging_opts.no_interleave_lints); + if tcx.sess.opts.debugging_opts.no_interleave_lints { + // These passes runs in late_lint_crate with -Z no_interleave_lints + return; + } late_lint_mod_pass(tcx, module_def_id, builtin_lints); - let mut passes = tcx.sess.lint_store.borrow_mut().late_module_passes.take().unwrap(); + let mut passes = tcx.sess.lint_store.borrow().late_module_passes.lock().take().unwrap(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); } // Put the passes back in the session. - tcx.sess.lint_store.borrow_mut().late_module_passes = Some(passes); + *tcx.sess.lint_store.borrow().late_module_passes.lock() = Some(passes); } fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( @@ -1331,10 +1300,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_sess: LintSession { - passes: None, - lints: tcx.sess.lint_store.borrow(), - }, + lint_store: tcx.sess.lint_store.borrow(), last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, @@ -1361,7 +1327,7 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tcx: TyCtxt<'_, 'tcx, 'tcx>, builtin_lints: T ) { - let mut passes = tcx.sess.lint_store.borrow_mut().late_passes.take().unwrap(); + let mut passes = tcx.sess.lint_store.borrow().late_passes.lock().take().unwrap(); if !tcx.sess.opts.debugging_opts.no_interleave_lints { if !passes.is_empty() { @@ -1376,8 +1342,8 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( }); } - let mut passes = tcx.sess.lint_store.borrow_mut().late_module_passes.take().unwrap(); - + let mut passes = tcx.sess.lint_store.borrow().late_module_passes.lock().take().unwrap(); + for pass in &mut passes { time(tcx.sess, &format!("running late module lint: {}", pass.name()), || { late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); @@ -1385,25 +1351,31 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( } // Put the passes back in the session. - tcx.sess.lint_store.borrow_mut().late_module_passes = Some(passes); + *tcx.sess.lint_store.borrow().late_module_passes.lock() = Some(passes); } // Put the passes back in the session. - tcx.sess.lint_store.borrow_mut().late_passes = Some(passes); + *tcx.sess.lint_store.borrow().late_passes.lock() = Some(passes); } /// Performs lint checking on a crate. pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tcx: TyCtxt<'_, 'tcx, 'tcx>, - builtin_lints: T, + builtin_lints: impl FnOnce() -> T + Send, ) { - // Run per-module lints - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); - } - - // Run whole crate non-incremental lints - late_lint_crate(tcx, builtin_lints); + join(|| { + time(tcx.sess, "crate lints", || { + // Run whole crate non-incremental lints + late_lint_crate(tcx, builtin_lints()); + }); + }, || { + time(tcx.sess, "module lints", || { + // Run per-module lints + for &module in tcx.hir().krate().modules.keys() { + tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); + } + }); + }); } struct EarlyLintPassObjects<'a> { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6a6f56332a8bc..1547e15fd48c5 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -990,7 +990,7 @@ fn analysis<'tcx>( }); }, { time(sess, "lint checking", || { - lint::check_crate(tcx, rustc_lint::BuiltinCombinedLateLintPass::new()); + lint::check_crate(tcx, || rustc_lint::BuiltinCombinedLateLintPass::new()); }); }); }, { From dee389f749ebe2b6a80e08550ccd8aa8e5a1f019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 31 Jan 2019 04:36:37 +0100 Subject: [PATCH 07/20] Run module lint passes in parallel --- src/librustc/lint/context.rs | 24 ++++++++++-------------- src/librustc/lint/mod.rs | 3 +++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 49e3eee4e52ef..e5eafd768bb0b 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -17,7 +17,7 @@ use self::TargetLint::*; use std::slice; -use rustc_data_structures::sync::{ReadGuard, Lock, join}; +use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; use crate::lint::builtin::BuiltinLintDiagnostics; @@ -56,7 +56,7 @@ pub struct LintStore { pre_expansion_passes: Option>, early_passes: Option>, late_passes: Lock>>, - late_module_passes: Lock>>, + late_module_passes: Vec, /// Lints indexed by name. by_name: FxHashMap, @@ -144,7 +144,7 @@ impl LintStore { pre_expansion_passes: Some(vec![]), early_passes: Some(vec![]), late_passes: Lock::new(Some(vec![])), - late_module_passes: Lock::new(Some(vec![])), + late_module_passes: vec![], by_name: Default::default(), future_incompatible: Default::default(), lint_groups: Default::default(), @@ -200,7 +200,7 @@ impl LintStore { self.push_pass(sess, from_plugin, &pass); if !register_only { if per_module { - self.late_module_passes.lock().as_mut().unwrap().push(pass); + self.late_module_passes.push(pass); } else { self.late_passes.lock().as_mut().unwrap().push(pass); } @@ -1277,14 +1277,12 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( late_lint_mod_pass(tcx, module_def_id, builtin_lints); - let mut passes = tcx.sess.lint_store.borrow().late_module_passes.lock().take().unwrap(); + let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes + .iter().map(|pass| pass.fresh_late_pass()).collect(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); } - - // Put the passes back in the session. - *tcx.sess.lint_store.borrow().late_module_passes.lock() = Some(passes); } fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( @@ -1342,16 +1340,14 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( }); } - let mut passes = tcx.sess.lint_store.borrow().late_module_passes.lock().take().unwrap(); + let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes + .iter().map(|pass| pass.fresh_late_pass()).collect(); for pass in &mut passes { time(tcx.sess, &format!("running late module lint: {}", pass.name()), || { late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) }); }); } - - // Put the passes back in the session. - *tcx.sess.lint_store.borrow().late_module_passes.lock() = Some(passes); } // Put the passes back in the session. @@ -1371,9 +1367,9 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( }, || { time(tcx.sess, "module lints", || { // Run per-module lints - for &module in tcx.hir().krate().modules.keys() { + par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); - } + }); }); }); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index b54da5e5e80d8..a5506bb8f59f4 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -273,6 +273,9 @@ macro_rules! expand_lint_pass_methods { macro_rules! declare_late_lint_pass { ([], [$hir:tt], [$($methods:tt)*]) => ( pub trait LateLintPass<'a, $hir>: LintPass { + fn fresh_late_pass(&self) -> LateLintPassObject { + panic!() + } expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]); } ) From e9a8befd2d4c0e19a9ec85cc047ef335a2b8b943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 28 Mar 2019 18:58:43 +0100 Subject: [PATCH 08/20] Remove unnecessary with_globals calls --- src/librustc_interface/interface.rs | 14 ++++++-------- src/librustdoc/lib.rs | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index bec868be505b5..245a2bf92d530 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -136,14 +136,12 @@ where F: FnOnce(&Compiler) -> R + Send, R: Send, { - syntax::with_globals(move || { - let stderr = config.stderr.take(); - util::spawn_thread_pool( - config.opts.debugging_opts.threads, - &stderr, - || run_compiler_in_existing_thread_pool(config, f), - ) - }) + let stderr = config.stderr.take(); + util::spawn_thread_pool( + config.opts.debugging_opts.threads, + &stderr, + || run_compiler_in_existing_thread_pool(config, f), + ) } pub fn default_thread_pool(f: F) -> R diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index fccf5a67ad465..2ebb465d53dbe 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -443,7 +443,7 @@ where R: 'static + Send, let (tx, rx) = channel(); - let result = rustc_driver::report_ices_to_stderr_if_any(move || syntax::with_globals(move || { + let result = rustc_driver::report_ices_to_stderr_if_any(move || { let crate_name = options.crate_name.clone(); let crate_version = options.crate_version.clone(); let (mut krate, renderinfo, renderopts, passes) = core::run_core(options); @@ -462,7 +462,7 @@ where R: 'static + Send, renderopts, passes: passes })).unwrap(); - })); + }); match result { Ok(()) => rx.recv().unwrap(), From 8dbae794b0683668d1b46d2c319ab36dcd9bd96d Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Thu, 28 Mar 2019 11:28:39 -0700 Subject: [PATCH 09/20] Use write_all instead of write in example code --- src/libstd/io/mod.rs | 2 +- src/libstd/io/stdio.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 7147b641e4743..14c850b6b0547 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1151,7 +1151,7 @@ pub trait Write { /// fn main() -> std::io::Result<()> { /// let mut buffer = BufWriter::new(File::create("foo.txt")?); /// - /// buffer.write(b"some bytes")?; + /// buffer.write_all(b"some bytes")?; /// buffer.flush()?; /// Ok(()) /// } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index d53a294fa6a9e..7e151041a9ea8 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -405,7 +405,7 @@ pub struct StdoutLock<'a> { /// use std::io::{self, Write}; /// /// fn main() -> io::Result<()> { -/// io::stdout().write(b"hello world")?; +/// io::stdout().write_all(b"hello world")?; /// /// Ok(()) /// } @@ -420,7 +420,7 @@ pub struct StdoutLock<'a> { /// let stdout = io::stdout(); /// let mut handle = stdout.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write_all(b"hello world")?; /// /// Ok(()) /// } @@ -460,7 +460,7 @@ impl Stdout { /// let stdout = io::stdout(); /// let mut handle = stdout.lock(); /// - /// handle.write(b"hello world")?; + /// handle.write_all(b"hello world")?; /// /// Ok(()) /// } @@ -558,7 +558,7 @@ pub struct StderrLock<'a> { /// use std::io::{self, Write}; /// /// fn main() -> io::Result<()> { -/// io::stderr().write(b"hello world")?; +/// io::stderr().write_all(b"hello world")?; /// /// Ok(()) /// } @@ -573,7 +573,7 @@ pub struct StderrLock<'a> { /// let stderr = io::stderr(); /// let mut handle = stderr.lock(); /// -/// handle.write(b"hello world")?; +/// handle.write_all(b"hello world")?; /// /// Ok(()) /// } @@ -613,7 +613,7 @@ impl Stderr { /// let stderr = io::stderr(); /// let mut handle = stderr.lock(); /// - /// handle.write(b"hello world")?; + /// handle.write_all(b"hello world")?; /// /// Ok(()) /// } From d9bdd01ac034344f32d9fd94e404e67b54dbcddb Mon Sep 17 00:00:00 2001 From: CrLF0710 Date: Fri, 29 Mar 2019 03:09:29 +0800 Subject: [PATCH 10/20] Stablize {f32,f64}::copysign(). --- src/libstd/f32.rs | 3 +-- src/libstd/f64.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 796908b0df943..2952c6aea0023 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -202,7 +202,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(copysign)] /// use std::f32; /// /// let f = 3.5_f32; @@ -216,7 +215,7 @@ impl f32 { /// ``` #[inline] #[must_use] - #[unstable(feature="copysign", issue="55169")] + #[stable(feature = "copysign", since = "1.35.0")] pub fn copysign(self, y: f32) -> f32 { unsafe { intrinsics::copysignf32(self, y) } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index e679a7d2e8c04..3c3a35573adaa 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -180,7 +180,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(copysign)] /// use std::f64; /// /// let f = 3.5_f64; @@ -194,7 +193,7 @@ impl f64 { /// ``` #[inline] #[must_use] - #[unstable(feature="copysign", issue="55169")] + #[stable(feature = "copysign", since = "1.35.0")] pub fn copysign(self, y: f64) -> f64 { unsafe { intrinsics::copysignf64(self, y) } } From 9f14e146ed7805c4190c0c71c28935103820f75f Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 23 Mar 2019 21:58:55 -0500 Subject: [PATCH 11/20] deny duplicate matcher bindings by default --- src/librustc/lint/builtin.rs | 3 ++- .../ui/macros/macro-multiple-matcher-bindings.rs | 1 + .../macros/macro-multiple-matcher-bindings.stderr | 14 +++++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index ad0ed39185c1c..10a5c1479fa6a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -354,7 +354,7 @@ declare_lint! { declare_lint! { pub DUPLICATE_MATCHER_BINDING_NAME, - Warn, + Deny, "duplicate macro matcher binding name" } @@ -464,6 +464,7 @@ impl LintPass for HardwiredLints { DEPRECATED_IN_FUTURE, AMBIGUOUS_ASSOCIATED_ITEMS, NESTED_IMPL_TRAIT, + DUPLICATE_MATCHER_BINDING_NAME, ) } } diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.rs b/src/test/ui/macros/macro-multiple-matcher-bindings.rs index 9e0fa3887163d..23d566780c855 100644 --- a/src/test/ui/macros/macro-multiple-matcher-bindings.rs +++ b/src/test/ui/macros/macro-multiple-matcher-bindings.rs @@ -6,6 +6,7 @@ // compile-pass #![allow(unused_macros)] +#![warn(duplicate_matcher_binding_name)] macro_rules! foo1 { ($a:ident, $a:ident) => {}; //~WARNING duplicate matcher binding diff --git a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr index 41e9a3286aefb..f7970dbd2eb22 100644 --- a/src/test/ui/macros/macro-multiple-matcher-bindings.stderr +++ b/src/test/ui/macros/macro-multiple-matcher-bindings.stderr @@ -1,15 +1,19 @@ warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:11:6 + --> $DIR/macro-multiple-matcher-bindings.rs:12:6 | LL | ($a:ident, $a:ident) => {}; | ^^^^^^^^ ^^^^^^^^ | - = note: #[warn(duplicate_matcher_binding_name)] on by default +note: lint level defined here + --> $DIR/macro-multiple-matcher-bindings.rs:9:9 + | +LL | #![warn(duplicate_matcher_binding_name)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57593 warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:12:6 + --> $DIR/macro-multiple-matcher-bindings.rs:13:6 | LL | ($a:ident, $a:path) => {}; | ^^^^^^^^ ^^^^^^^ @@ -18,7 +22,7 @@ LL | ($a:ident, $a:path) => {}; = note: for more information, see issue #57593 warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:21:6 + --> $DIR/macro-multiple-matcher-bindings.rs:22:6 | LL | ($a:ident, $($a:ident),*) => {}; | ^^^^^^^^ ^^^^^^^^ @@ -27,7 +31,7 @@ LL | ($a:ident, $($a:ident),*) => {}; = note: for more information, see issue #57593 warning: duplicate matcher binding - --> $DIR/macro-multiple-matcher-bindings.rs:22:8 + --> $DIR/macro-multiple-matcher-bindings.rs:23:8 | LL | ($($a:ident)+ # $($($a:path),+);*) => {}; | ^^^^^^^^ ^^^^^^^ From 3ba7454152e65beb7519580d8f74cf433f20b724 Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Fri, 22 Mar 2019 04:38:22 +0900 Subject: [PATCH 12/20] Use track_errors --- src/librustc_mir/const_eval.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 6ab89f80ef528..0cf6c4593e8dd 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -645,10 +645,14 @@ pub fn const_eval_raw_provider<'a, 'tcx>( "could not evaluate static initializer"); // Ensure that if the above error was either `TooGeneric` or `Reported` // an error must be reported. - if tcx.sess.err_count() == 0 { - tcx.sess.delay_span_bug(err.span, + let errs = tcx.sess.track_errors(|| { + tcx.sess.err_count(); + }); + match errs { + Ok(_) => tcx.sess.delay_span_bug(err.span, &format!("static eval failure did not emit an error: {:#?}", - reported_err)); + reported_err)), + Err(_) => (), } reported_err } else if def_id.is_local() { From 526b3558581187c87ca8ca533254c1cbb6275e7b Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Sat, 23 Mar 2019 00:03:50 +0900 Subject: [PATCH 13/20] Remove err_count --- src/librustc_mir/const_eval.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 0cf6c4593e8dd..80076c6f03533 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -645,13 +645,14 @@ pub fn const_eval_raw_provider<'a, 'tcx>( "could not evaluate static initializer"); // Ensure that if the above error was either `TooGeneric` or `Reported` // an error must be reported. - let errs = tcx.sess.track_errors(|| { - tcx.sess.err_count(); + let tracked_err = tcx.sess.track_errors(|| { + err.report_as_error(ecx.tcx, + "could not evaluate static initializer"); }); - match errs { + match tracked_err { Ok(_) => tcx.sess.delay_span_bug(err.span, &format!("static eval failure did not emit an error: {:#?}", - reported_err)), + tracked_err)), Err(_) => (), } reported_err From ee0e1b7615b92103fa2f4ca280d5b5f189e8def9 Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Sat, 23 Mar 2019 00:51:08 +0900 Subject: [PATCH 14/20] Set ok value --- src/librustc_mir/const_eval.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 80076c6f03533..9f73c2aa06e6b 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -650,9 +650,9 @@ pub fn const_eval_raw_provider<'a, 'tcx>( "could not evaluate static initializer"); }); match tracked_err { - Ok(_) => tcx.sess.delay_span_bug(err.span, + Ok(reported_err) => tcx.sess.delay_span_bug(err.span, &format!("static eval failure did not emit an error: {:#?}", - tracked_err)), + reported_err)), Err(_) => (), } reported_err From 0e76b34aa7021265630cc9933f1c918f184ba8d8 Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Sun, 24 Mar 2019 14:45:27 +0900 Subject: [PATCH 15/20] WIP: remove report_as_error --- src/librustc_mir/const_eval.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 9f73c2aa06e6b..964f721508832 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -641,19 +641,17 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors if tcx.is_static(def_id).is_some() { - let reported_err = err.report_as_error(ecx.tcx, - "could not evaluate static initializer"); // Ensure that if the above error was either `TooGeneric` or `Reported` // an error must be reported. - let tracked_err = tcx.sess.track_errors(|| { + let reported_err = tcx.sess.track_errors(|| { err.report_as_error(ecx.tcx, "could not evaluate static initializer"); }); - match tracked_err { - Ok(reported_err) => tcx.sess.delay_span_bug(err.span, + match reported_err { + Ok(v) => tcx.sess.delay_span_bug(err.span, &format!("static eval failure did not emit an error: {:#?}", - reported_err)), - Err(_) => (), + v)), + Err(err) => err, } reported_err } else if def_id.is_local() { From f0de8e82b868f7f4484b6e3e42543791c8b24b7f Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Mon, 25 Mar 2019 03:19:48 +0900 Subject: [PATCH 16/20] Return correct values --- src/librustc_mir/const_eval.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 964f721508832..1542cdf1e3e77 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -645,15 +645,17 @@ pub fn const_eval_raw_provider<'a, 'tcx>( // an error must be reported. let reported_err = tcx.sess.track_errors(|| { err.report_as_error(ecx.tcx, - "could not evaluate static initializer"); + "could not evaluate static initializer") }); match reported_err { - Ok(v) => tcx.sess.delay_span_bug(err.span, + Ok(v) => { + tcx.sess.delay_span_bug(err.span, &format!("static eval failure did not emit an error: {:#?}", - v)), - Err(err) => err, + v)); + v + }, + Err(ErrorReported) => ErrorHandled::Reported, } - reported_err } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.describe_def(def_id) { From 6c8e3a5378e41e08a323139bb7aaa8a8823ec9bc Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Mon, 25 Mar 2019 03:55:13 +0900 Subject: [PATCH 17/20] Remove unused variable --- src/librustc_mir/const_eval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 1542cdf1e3e77..1c3f7882b9fcf 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -654,7 +654,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( v)); v }, - Err(ErrorReported) => ErrorHandled::Reported, + Err(_) => ErrorHandled::Reported, } } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! From 07788478332d645293a81686d5d225b8aafabe90 Mon Sep 17 00:00:00 2001 From: Yuki OKUSHI Date: Fri, 29 Mar 2019 04:42:03 +0900 Subject: [PATCH 18/20] Use ErrorReported --- src/librustc_mir/const_eval.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 1c3f7882b9fcf..2268568c5f82d 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -14,6 +14,7 @@ use rustc::ty::{self, TyCtxt, query::TyCtxtAt}; use rustc::ty::layout::{self, LayoutOf, VariantIdx}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; +use rustc::util::common::ErrorReported; use rustc_data_structures::fx::FxHashMap; use syntax::ast::Mutability; @@ -654,7 +655,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( v)); v }, - Err(_) => ErrorHandled::Reported, + Err(ErrorReported) => ErrorHandled::Reported, } } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! From 17a8aff20abdef46ae90801c85cc232e81443e1b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 28 Mar 2019 12:27:26 +1100 Subject: [PATCH 19/20] Use `SmallVec` in `TokenStreamBuilder`. This reduces by 12% the number of allocations done for a "clean incremental" of `webrender_api`, which reduces the instruction count by about 0.5%. It also reduces instruction counts by up to 1.4% across a range of rustc-perf benchmark runs. --- src/libsyntax/parse/attr.rs | 3 ++- src/libsyntax/tokenstream.rs | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 4211268f33efe..e99a86e807f7f 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -6,6 +6,7 @@ use crate::parse::parser::{Parser, TokenType, PathStyle}; use crate::tokenstream::{TokenStream, TokenTree}; use log::debug; +use smallvec::smallvec; #[derive(Debug)] enum InnerAttributeParsePolicy<'a> { @@ -171,7 +172,7 @@ impl<'a> Parser<'a> { } else { self.parse_unsuffixed_lit()?.tokens() }; - TokenStream::from_streams(vec![eq.into(), tokens]) + TokenStream::from_streams(smallvec![eq.into(), tokens]) } else { TokenStream::empty() }; diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 80a7bde606afa..2d47b982ebdd9 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -24,6 +24,7 @@ use syntax_pos::{BytePos, Mark, Span, DUMMY_SP}; use rustc_data_structures::static_assert; use rustc_data_structures::sync::Lrc; use serialize::{Decoder, Decodable, Encoder, Encodable}; +use smallvec::{SmallVec, smallvec}; use std::borrow::Cow; use std::{fmt, iter, mem}; @@ -224,7 +225,7 @@ impl From for TokenStream { impl> iter::FromIterator for TokenStream { fn from_iter>(iter: I) -> Self { - TokenStream::from_streams(iter.into_iter().map(Into::into).collect::>()) + TokenStream::from_streams(iter.into_iter().map(Into::into).collect::>()) } } @@ -256,7 +257,7 @@ impl TokenStream { } } - pub(crate) fn from_streams(mut streams: Vec) -> TokenStream { + pub(crate) fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { match streams.len() { 0 => TokenStream::empty(), 1 => streams.pop().unwrap(), @@ -393,12 +394,13 @@ impl TokenStream { } } +// 99.5%+ of the time we have 1 or 2 elements in this vector. #[derive(Clone)] -pub struct TokenStreamBuilder(Vec); +pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>); impl TokenStreamBuilder { pub fn new() -> TokenStreamBuilder { - TokenStreamBuilder(Vec::new()) + TokenStreamBuilder(SmallVec::new()) } pub fn push>(&mut self, stream: T) { @@ -485,7 +487,7 @@ impl Cursor { } let index = self.index; let stream = mem::replace(&mut self.stream, TokenStream(None)); - *self = TokenStream::from_streams(vec![stream, new_stream]).into_trees(); + *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees(); self.index = index; } @@ -572,7 +574,7 @@ mod tests { let test_res = string_to_ts("foo::bar::baz"); let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); - let eq_res = TokenStream::from_streams(vec![test_fst, test_snd]); + let eq_res = TokenStream::from_streams(smallvec![test_fst, test_snd]); assert_eq!(test_res.trees().count(), 5); assert_eq!(eq_res.trees().count(), 5); assert_eq!(test_res.eq_unspanned(&eq_res), true); From 93fb4d83178dde230eb55ce02468867ea6ac44f0 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Thu, 28 Mar 2019 17:50:01 -0700 Subject: [PATCH 20/20] Fix missed fn rename in #59284 --- src/libstd/sys/sgx/rwlock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 7e2d13b9e2476..784303f3a65e8 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -268,7 +268,7 @@ mod tests { #[inline(never)] unsafe fn rwlock_new(init: &mut MaybeUninit) { - init.set(RWLock::new()); + init.write(RWLock::new()); } unsafe {