1
Fork 0

Auto merge of #65835 - Mark-Simulacrum:lockless-lintbuffer, r=nikomatsakis

Remove LintBuffer from Session

This moves the `LintBuffer` from `Session` into the `Resolver`, where it is used until lowering is done and then consumed by early lint passes. This also happily removes the failure mode of buffering lints too late where it would have previously lead to ICEs; it is statically no longer possible to do so.

I suspect that with a bit more work a similar move could be done for the lint buffer inside `ParseSess`, but this PR doesn't touch it (in part to keep itself small).

The last commit is the "interesting" commit -- the ones before it don't work (though they compile) as they sort of prepare the various crates for the lint buffer to be passed in rather than accessed through Session.
This commit is contained in:
bors 2019-11-04 09:00:39 +00:00
commit ab6e47851b
16 changed files with 173 additions and 153 deletions

View file

@ -43,6 +43,7 @@ use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS};
use crate::hir::{GenericArg, ConstArg}; use crate::hir::{GenericArg, ConstArg};
use crate::hir::ptr::P; use crate::hir::ptr::P;
use crate::lint;
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
ELIDED_LIFETIMES_IN_PATHS}; ELIDED_LIFETIMES_IN_PATHS};
use crate::middle::cstore::CrateStore; use crate::middle::cstore::CrateStore;
@ -184,6 +185,8 @@ pub trait Resolver {
) -> (ast::Path, Res<NodeId>); ) -> (ast::Path, Res<NodeId>);
fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
} }
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
@ -1857,7 +1860,7 @@ impl<'a> LoweringContext<'a> {
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Warn => { ParenthesizedGenericArgs::Warn => {
self.sess.buffer_lint( self.resolver.lint_buffer().buffer_lint(
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
CRATE_NODE_ID, CRATE_NODE_ID,
data.span, data.span,
@ -1953,7 +1956,7 @@ impl<'a> LoweringContext<'a> {
} }
AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::PassThrough |
AnonymousLifetimeMode::ReportError => { AnonymousLifetimeMode::ReportError => {
self.sess.buffer_lint_with_diagnostic( self.resolver.lint_buffer().buffer_lint_with_diagnostic(
ELIDED_LIFETIMES_IN_PATHS, ELIDED_LIFETIMES_IN_PATHS,
CRATE_NODE_ID, CRATE_NODE_ID,
path_span, path_span,
@ -3346,7 +3349,7 @@ impl<'a> LoweringContext<'a> {
} }
} }
fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) {
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
// call site which do not have a macro backtrace. See #61963. // call site which do not have a macro backtrace. See #61963.
let is_macro_callsite = self.sess.source_map() let is_macro_callsite = self.sess.source_map()
@ -3354,7 +3357,7 @@ impl<'a> LoweringContext<'a> {
.map(|snippet| snippet.starts_with("#[")) .map(|snippet| snippet.starts_with("#["))
.unwrap_or(true); .unwrap_or(true);
if !is_macro_callsite { if !is_macro_callsite {
self.sess.buffer_lint_with_diagnostic( self.resolver.lint_buffer().buffer_lint_with_diagnostic(
builtin::BARE_TRAIT_OBJECTS, builtin::BARE_TRAIT_OBJECTS,
id, id,
span, span,

View file

@ -34,7 +34,6 @@ use crate::util::common::time;
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use std::slice; use std::slice;
use std::default::Default as StdDefault;
use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter};
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
use syntax::ast; use syntax::ast;
@ -584,12 +583,13 @@ impl<'a> EarlyContext<'a> {
lint_store: &'a LintStore, lint_store: &'a LintStore,
krate: &'a ast::Crate, krate: &'a ast::Crate,
buffered: LintBuffer, buffered: LintBuffer,
warn_about_weird_lints: bool,
) -> EarlyContext<'a> { ) -> EarlyContext<'a> {
EarlyContext { EarlyContext {
sess, sess,
krate, krate,
lint_store, lint_store,
builder: LintLevelSets::builder(sess, lint_store), builder: LintLevelSets::builder(sess, warn_about_weird_lints, lint_store),
buffered, buffered,
} }
} }
@ -1490,9 +1490,10 @@ fn early_lint_crate<T: EarlyLintPass>(
krate: &ast::Crate, krate: &ast::Crate,
pass: T, pass: T,
buffered: LintBuffer, buffered: LintBuffer,
warn_about_weird_lints: bool,
) -> LintBuffer { ) -> LintBuffer {
let mut cx = EarlyContextAndPass { let mut cx = EarlyContextAndPass {
context: EarlyContext::new(sess, lint_store, krate, buffered), context: EarlyContext::new(sess, lint_store, krate, buffered, warn_about_weird_lints),
pass, pass,
}; };
@ -1514,22 +1515,19 @@ pub fn check_ast_crate<T: EarlyLintPass>(
lint_store: &LintStore, lint_store: &LintStore,
krate: &ast::Crate, krate: &ast::Crate,
pre_expansion: bool, pre_expansion: bool,
lint_buffer: Option<LintBuffer>,
builtin_lints: T, builtin_lints: T,
) { ) {
let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion { let mut passes: Vec<_> = if pre_expansion {
( lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect()
lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(),
LintBuffer::default(),
)
} else { } else {
( lint_store.early_passes.iter().map(|p| (p)()).collect()
lint_store.early_passes.iter().map(|p| (p)()).collect(),
sess.buffered_lints.borrow_mut().take().unwrap(),
)
}; };
let mut buffered = lint_buffer.unwrap_or_default();
if !sess.opts.debugging_opts.no_interleave_lints { if !sess.opts.debugging_opts.no_interleave_lints {
buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered); buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered,
pre_expansion);
if !passes.is_empty() { if !passes.is_empty() {
buffered = early_lint_crate( buffered = early_lint_crate(
@ -1538,6 +1536,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
krate, krate,
EarlyLintPassObjects { lints: &mut passes[..] }, EarlyLintPassObjects { lints: &mut passes[..] },
buffered, buffered,
pre_expansion,
); );
} }
} else { } else {
@ -1549,6 +1548,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
krate, krate,
EarlyLintPassObjects { lints: slice::from_mut(pass) }, EarlyLintPassObjects { lints: slice::from_mut(pass) },
buffered, buffered,
pre_expansion,
) )
}); });
} }

View file

@ -44,8 +44,12 @@ impl LintLevelSets {
return me return me
} }
pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> { pub fn builder<'a>(
LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store)) sess: &'a Session,
warn_about_weird_lints: bool,
store: &LintStore,
) -> LintLevelsBuilder<'a> {
LintLevelsBuilder::new(sess, warn_about_weird_lints, LintLevelSets::new(sess, store))
} }
fn process_command_line(&mut self, sess: &Session, store: &LintStore) { fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
@ -160,14 +164,18 @@ pub struct BuilderPush {
} }
impl<'a> LintLevelsBuilder<'a> { impl<'a> LintLevelsBuilder<'a> {
pub fn new(sess: &'a Session, sets: LintLevelSets) -> LintLevelsBuilder<'a> { pub fn new(
sess: &'a Session,
warn_about_weird_lints: bool,
sets: LintLevelSets,
) -> LintLevelsBuilder<'a> {
assert_eq!(sets.list.len(), 1); assert_eq!(sets.list.len(), 1);
LintLevelsBuilder { LintLevelsBuilder {
sess, sess,
sets, sets,
cur: 0, cur: 0,
id_to_set: Default::default(), id_to_set: Default::default(),
warn_about_weird_lints: sess.buffered_lints.borrow().is_some(), warn_about_weird_lints,
} }
} }

View file

@ -643,13 +643,29 @@ impl LintBuffer {
} }
} }
pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> { fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
self.map.remove(&id).unwrap_or_default() self.map.remove(&id).unwrap_or_default()
} }
pub fn get_any(&self) -> Option<&[BufferedEarlyLint]> { pub fn buffer_lint<S: Into<MultiSpan>>(
let key = self.map.keys().next().map(|k| *k); &mut self,
key.map(|k| &self.map[&k][..]) lint: &'static Lint,
id: ast::NodeId,
sp: S,
msg: &str,
) {
self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
}
pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
&mut self,
lint: &'static Lint,
id: ast::NodeId,
sp: S,
msg: &str,
diagnostic: BuiltinLintDiagnostics,
) {
self.add_lint(lint, id, sp.into(), msg, diagnostic)
} }
} }
@ -779,7 +795,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
assert_eq!(cnum, LOCAL_CRATE); assert_eq!(cnum, LOCAL_CRATE);
let store = &tcx.lint_store; let store = &tcx.lint_store;
let mut builder = LintLevelMapBuilder { let mut builder = LintLevelMapBuilder {
levels: LintLevelSets::builder(tcx.sess, &store), levels: LintLevelSets::builder(tcx.sess, false, &store),
tcx: tcx, tcx: tcx,
store: store, store: store,
}; };

View file

@ -586,7 +586,7 @@ pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String
} }
pub fn early_report_deprecation( pub fn early_report_deprecation(
sess: &Session, lint_buffer: &'a mut lint::LintBuffer,
message: &str, message: &str,
suggestion: Option<Symbol>, suggestion: Option<Symbol>,
lint: &'static Lint, lint: &'static Lint,
@ -597,7 +597,7 @@ pub fn early_report_deprecation(
} }
let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span);
sess.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); lint_buffer.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag);
} }
fn late_report_deprecation( fn late_report_deprecation(

View file

@ -1469,7 +1469,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
(such as entering an empty infinite loop) by inserting llvm.sideeffect"), (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
} }
pub fn default_lib_output() -> CrateType { pub const fn default_lib_output() -> CrateType {
CrateType::Rlib CrateType::Rlib
} }

View file

@ -6,7 +6,6 @@ use crate::hir::def_id::CrateNum;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use crate::lint; use crate::lint;
use crate::lint::builtin::BuiltinLintDiagnostics;
use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
use crate::session::search_paths::{PathKind, SearchPath}; use crate::session::search_paths::{PathKind, SearchPath};
use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::util::nodemap::{FxHashMap, FxHashSet};
@ -77,13 +76,6 @@ pub struct Session {
/// if the value stored here has been affected by path remapping. /// if the value stored here has been affected by path remapping.
pub working_dir: (PathBuf, bool), pub working_dir: (PathBuf, bool),
/// This is intended to be used from a single thread.
///
/// FIXME: there was a previous comment about this not being thread safe,
/// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread
/// safe at least from a "Rust safety" standpoint.
pub buffered_lints: Lock<Option<lint::LintBuffer>>,
/// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
/// (sub)diagnostics that have been set once, but should not be set again, /// (sub)diagnostics that have been set once, but should not be set again,
/// in order to avoid redundantly verbose output (Issue #24690, #44953). /// in order to avoid redundantly verbose output (Issue #24690, #44953).
@ -366,35 +358,6 @@ impl Session {
self.diagnostic().span_note_without_error(sp, msg) self.diagnostic().span_note_without_error(sp, msg)
} }
pub fn buffer_lint<S: Into<MultiSpan>>(
&self,
lint: &'static lint::Lint,
id: ast::NodeId,
sp: S,
msg: &str,
) {
match *self.buffered_lints.borrow_mut() {
Some(ref mut buffer) => {
buffer.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
}
None => bug!("can't buffer lints after HIR lowering"),
}
}
pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
&self,
lint: &'static lint::Lint,
id: ast::NodeId,
sp: S,
msg: &str,
diagnostic: BuiltinLintDiagnostics,
) {
match *self.buffered_lints.borrow_mut() {
Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg, diagnostic),
None => bug!("can't buffer lints after HIR lowering"),
}
}
pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
let id = self.next_node_id.get(); let id = self.next_node_id.get();
@ -1218,7 +1181,6 @@ fn build_session_(
sysroot, sysroot,
local_crate_source_file, local_crate_source_file,
working_dir, working_dir,
buffered_lints: Lock::new(Some(Default::default())),
one_time_diagnostics: Default::default(), one_time_diagnostics: Default::default(),
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
plugin_attributes: Lock::new(Vec::new()), plugin_attributes: Lock::new(Vec::new()),

View file

@ -267,6 +267,7 @@ fn configure_and_expand_inner<'a>(
lint_store, lint_store,
&krate, &krate,
true, true,
None,
rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); rustc_lint::BuiltinCombinedPreExpansionLintPass::new());
}); });
@ -293,6 +294,8 @@ fn configure_and_expand_inner<'a>(
krate krate
}); });
util::check_attr_crate_type(&krate.attrs, &mut resolver.lint_buffer());
syntax_ext::plugin_macro_defs::inject( syntax_ext::plugin_macro_defs::inject(
&mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition() &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
); );
@ -366,7 +369,7 @@ fn configure_and_expand_inner<'a>(
for span in missing_fragment_specifiers { for span in missing_fragment_specifiers {
let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
let msg = "missing fragment specifier"; let msg = "missing fragment specifier";
sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); resolver.lint_buffer().buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
} }
if cfg!(windows) { if cfg!(windows) {
env::set_var("PATH", &old_path); env::set_var("PATH", &old_path);
@ -395,7 +398,7 @@ fn configure_and_expand_inner<'a>(
} }
let has_proc_macro_decls = time(sess, "AST validation", || { let has_proc_macro_decls = time(sess, "AST validation", || {
ast_validation::check_crate(sess, &krate) ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
}); });
@ -464,7 +467,7 @@ fn configure_and_expand_inner<'a>(
info!("{} parse sess buffered_lints", buffered_lints.len()); info!("{} parse sess buffered_lints", buffered_lints.len());
for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) { for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) {
let lint = lint::Lint::from_parser_lint_id(lint_id); let lint = lint::Lint::from_parser_lint_id(lint_id);
sess.buffer_lint(lint, id, span, &msg); resolver.lint_buffer().buffer_lint(lint, id, span, &msg);
} }
}); });
@ -496,6 +499,7 @@ pub fn lower_to_hir(
lint_store, lint_store,
&krate, &krate,
false, false,
Some(std::mem::take(resolver.lint_buffer())),
rustc_lint::BuiltinCombinedEarlyLintPass::new(), rustc_lint::BuiltinCombinedEarlyLintPass::new(),
) )
}); });

View file

@ -526,40 +526,24 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat
CrateDisambiguator::from(hasher.finish::<Fingerprint>()) CrateDisambiguator::from(hasher.finish::<Fingerprint>())
} }
pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> { pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) {
// Unconditionally collect crate types from attributes to make them used // Unconditionally collect crate types from attributes to make them used
let attr_types: Vec<config::CrateType> = attrs for a in attrs.iter() {
.iter()
.filter_map(|a| {
if a.check_name(sym::crate_type) { if a.check_name(sym::crate_type) {
match a.value_str() { if let Some(n) = a.value_str() {
Some(sym::rlib) => Some(config::CrateType::Rlib), if let Some(_) = categorize_crate_type(n) {
Some(sym::dylib) => Some(config::CrateType::Dylib), return;
Some(sym::cdylib) => Some(config::CrateType::Cdylib), }
Some(sym::lib) => Some(config::default_lib_output()),
Some(sym::staticlib) => Some(config::CrateType::Staticlib),
Some(sym::proc_dash_macro) => Some(config::CrateType::ProcMacro),
Some(sym::bin) => Some(config::CrateType::Executable),
Some(n) => {
let crate_types = vec![
sym::rlib,
sym::dylib,
sym::cdylib,
sym::lib,
sym::staticlib,
sym::proc_dash_macro,
sym::bin
];
if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind {
let span = spanned.span; let span = spanned.span;
let lev_candidate = find_best_match_for_name( let lev_candidate = find_best_match_for_name(
crate_types.iter(), CRATE_TYPES.iter().map(|(k, _)| k),
&n.as_str(), &n.as_str(),
None None
); );
if let Some(candidate) = lev_candidate { if let Some(candidate) = lev_candidate {
session.buffer_lint_with_diagnostic( lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::UNKNOWN_CRATE_TYPES, lint::builtin::UNKNOWN_CRATE_TYPES,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
span, span,
@ -572,7 +556,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
) )
); );
} else { } else {
session.buffer_lint( lint_buffer.buffer_lint(
lint::builtin::UNKNOWN_CRATE_TYPES, lint::builtin::UNKNOWN_CRATE_TYPES,
ast::CRATE_NODE_ID, ast::CRATE_NODE_ID,
span, span,
@ -580,9 +564,34 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
); );
} }
} }
None
} }
None => None }
}
}
const CRATE_TYPES: &[(Symbol, config::CrateType)] = &[
(sym::rlib, config::CrateType::Rlib),
(sym::dylib, config::CrateType::Dylib),
(sym::cdylib, config::CrateType::Cdylib),
(sym::lib, config::default_lib_output()),
(sym::staticlib, config::CrateType::Staticlib),
(sym::proc_dash_macro, config::CrateType::ProcMacro),
(sym::bin, config::CrateType::Executable),
];
fn categorize_crate_type(s: Symbol) -> Option<config::CrateType> {
Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1)
}
pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
// Unconditionally collect crate types from attributes to make them used
let attr_types: Vec<config::CrateType> = attrs
.iter()
.filter_map(|a| {
if a.check_name(sym::crate_type) {
match a.value_str() {
Some(s) => categorize_crate_type(s),
_ => None,
} }
} else { } else {
None None

View file

@ -73,6 +73,8 @@ struct AstValidator<'a> {
/// these booleans. /// these booleans.
warning_period_57979_didnt_record_next_impl_trait: bool, warning_period_57979_didnt_record_next_impl_trait: bool,
warning_period_57979_impl_trait_in_proj: bool, warning_period_57979_impl_trait_in_proj: bool,
lint_buffer: &'a mut lint::LintBuffer,
} }
impl<'a> AstValidator<'a> { impl<'a> AstValidator<'a> {
@ -229,7 +231,7 @@ impl<'a> AstValidator<'a> {
err.emit(); err.emit();
} }
fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err: ReportFn) { fn check_decl_no_pat<F: FnMut(Span, bool)>(decl: &FnDecl, mut report_err: F) {
for arg in &decl.inputs { for arg in &decl.inputs {
match arg.pat.kind { match arg.pat.kind {
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
@ -460,7 +462,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match ty.kind { match ty.kind {
TyKind::BareFn(ref bfty) => { TyKind::BareFn(ref bfty) => {
self.check_fn_decl(&bfty.decl); self.check_fn_decl(&bfty.decl);
self.check_decl_no_pat(&bfty.decl, |span, _| { Self::check_decl_no_pat(&bfty.decl, |span, _| {
struct_span_err!(self.session, span, E0561, struct_span_err!(self.session, span, E0561,
"patterns aren't allowed in function pointer types").emit(); "patterns aren't allowed in function pointer types").emit();
}); });
@ -483,7 +485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
TyKind::ImplTrait(_, ref bounds) => { TyKind::ImplTrait(_, ref bounds) => {
if self.is_impl_trait_banned { if self.is_impl_trait_banned {
if self.warning_period_57979_impl_trait_in_proj { if self.warning_period_57979_impl_trait_in_proj {
self.session.buffer_lint( self.lint_buffer.buffer_lint(
NESTED_IMPL_TRAIT, ty.id, ty.span, NESTED_IMPL_TRAIT, ty.id, ty.span,
"`impl Trait` is not allowed in path parameters"); "`impl Trait` is not allowed in path parameters");
} else { } else {
@ -494,7 +496,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if let Some(outer_impl_trait) = self.outer_impl_trait { if let Some(outer_impl_trait) = self.outer_impl_trait {
if outer_impl_trait.should_warn_instead_of_error() { if outer_impl_trait.should_warn_instead_of_error() {
self.session.buffer_lint_with_diagnostic( self.lint_buffer.buffer_lint_with_diagnostic(
NESTED_IMPL_TRAIT, ty.id, ty.span, NESTED_IMPL_TRAIT, ty.id, ty.span,
"nested `impl Trait` is not allowed", "nested `impl Trait` is not allowed",
BuiltinLintDiagnostics::NestedImplTrait { BuiltinLintDiagnostics::NestedImplTrait {
@ -634,9 +636,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node); self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_const(sig.header.constness);
if block.is_none() { if block.is_none() {
self.check_decl_no_pat(&sig.decl, |span, mut_ident| { Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
if mut_ident { if mut_ident {
self.session.buffer_lint( self.lint_buffer.buffer_lint(
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
trait_item.id, span, trait_item.id, span,
"patterns aren't allowed in methods without bodies"); "patterns aren't allowed in methods without bodies");
@ -655,7 +657,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if attr::contains_name(&item.attrs, sym::warn_directory_ownership) { if attr::contains_name(&item.attrs, sym::warn_directory_ownership) {
let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
let msg = "cannot declare a new module at this location"; let msg = "cannot declare a new module at this location";
self.session.buffer_lint(lint, item.id, item.span, msg); self.lint_buffer.buffer_lint(lint, item.id, item.span, msg);
} }
} }
ItemKind::Union(ref vdata, _) => { ItemKind::Union(ref vdata, _) => {
@ -686,7 +688,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match fi.kind { match fi.kind {
ForeignItemKind::Fn(ref decl, _) => { ForeignItemKind::Fn(ref decl, _) => {
self.check_fn_decl(decl); self.check_fn_decl(decl);
self.check_decl_no_pat(decl, |span, _| { Self::check_decl_no_pat(decl, |span, _| {
struct_span_err!(self.session, span, E0130, struct_span_err!(self.session, span, E0130,
"patterns aren't allowed in foreign function declarations") "patterns aren't allowed in foreign function declarations")
.span_label(span, "pattern not allowed in foreign function").emit(); .span_label(span, "pattern not allowed in foreign function").emit();
@ -840,7 +842,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
} }
pub fn check_crate(session: &Session, krate: &Crate) -> bool { pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
let mut validator = AstValidator { let mut validator = AstValidator {
session, session,
has_proc_macro_decls: false, has_proc_macro_decls: false,
@ -849,6 +851,7 @@ pub fn check_crate(session: &Session, krate: &Crate) -> bool {
is_assoc_ty_bound_banned: false, is_assoc_ty_bound_banned: false,
warning_period_57979_didnt_record_next_impl_trait: false, warning_period_57979_didnt_record_next_impl_trait: false,
warning_period_57979_impl_trait_in_proj: false, warning_period_57979_impl_trait_in_proj: false,
lint_buffer: lints,
}; };
visit::walk_crate(&mut validator, krate); visit::walk_crate(&mut validator, krate);

View file

@ -232,7 +232,7 @@ impl Resolver<'_> {
directive.span.is_dummy() => { directive.span.is_dummy() => {
if let ImportDirectiveSubclass::MacroUse = directive.subclass { if let ImportDirectiveSubclass::MacroUse = directive.subclass {
if !directive.span.is_dummy() { if !directive.span.is_dummy() {
self.session.buffer_lint( self.lint_buffer.buffer_lint(
lint::builtin::MACRO_USE_EXTERN_CRATE, lint::builtin::MACRO_USE_EXTERN_CRATE,
directive.id, directive.id,
directive.span, directive.span,
@ -250,7 +250,7 @@ impl Resolver<'_> {
ImportDirectiveSubclass::MacroUse => { ImportDirectiveSubclass::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS; let lint = lint::builtin::UNUSED_IMPORTS;
let msg = "unused `#[macro_use]` import"; let msg = "unused `#[macro_use]` import";
self.session.buffer_lint(lint, directive.id, directive.span, msg); self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg);
} }
_ => {} _ => {}
} }
@ -312,7 +312,7 @@ impl Resolver<'_> {
"remove the unused import" "remove the unused import"
}; };
visitor.r.session.buffer_lint_with_diagnostic( visitor.r.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_IMPORTS, lint::builtin::UNUSED_IMPORTS,
unused.use_tree_id, unused.use_tree_id,
ms, ms,

View file

@ -1548,7 +1548,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
if is_expected(ctor_res) && if is_expected(ctor_res) &&
self.r.is_accessible_from(ctor_vis, self.parent_scope.module) { self.r.is_accessible_from(ctor_vis, self.parent_scope.module) {
let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
self.r.session.buffer_lint(lint, id, span, self.r.lint_buffer.buffer_lint(lint, id, span,
"private struct constructors are not usable through \ "private struct constructors are not usable through \
re-exports in outer modules", re-exports in outer modules",
); );
@ -1774,7 +1774,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
}; };
if result.base_res() == unqualified_result { if result.base_res() == unqualified_result {
let lint = lint::builtin::UNUSED_QUALIFICATIONS; let lint = lint::builtin::UNUSED_QUALIFICATIONS;
self.r.session.buffer_lint(lint, id, span, "unnecessary qualification") self.r.lint_buffer.buffer_lint(lint, id, span, "unnecessary qualification")
} }
} }
@ -2111,7 +2111,7 @@ impl<'a> Resolver<'a> {
let mut late_resolution_visitor = LateResolutionVisitor::new(self); let mut late_resolution_visitor = LateResolutionVisitor::new(self);
visit::walk_crate(&mut late_resolution_visitor, krate); visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() { for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
self.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label"); self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
} }
} }
} }

View file

@ -962,6 +962,8 @@ pub struct Resolver<'a> {
/// Stores enum visibilities to properly build a reduced graph /// Stores enum visibilities to properly build a reduced graph
/// when visiting the correspondent variants. /// when visiting the correspondent variants.
variant_vis: DefIdMap<ty::Visibility>, variant_vis: DefIdMap<ty::Visibility>,
lint_buffer: lint::LintBuffer,
} }
/// Nothing really interesting here; it just provides memory for the rest of the crate. /// Nothing really interesting here; it just provides memory for the rest of the crate.
@ -1081,6 +1083,10 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
let expn_id = self.definitions.expansion_that_defined(def_id.index); let expn_id = self.definitions.expansion_that_defined(def_id.index);
self.has_derives(expn_id, derives) self.has_derives(expn_id, derives)
} }
fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
&mut self.lint_buffer
}
} }
impl<'a> Resolver<'a> { impl<'a> Resolver<'a> {
@ -1227,10 +1233,15 @@ impl<'a> Resolver<'a> {
features.declared_lib_features.iter().map(|(feat, ..)| *feat) features.declared_lib_features.iter().map(|(feat, ..)| *feat)
.chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
.collect(), .collect(),
variant_vis: Default::default() variant_vis: Default::default(),
lint_buffer: lint::LintBuffer::default(),
} }
} }
pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
&mut self.lint_buffer
}
pub fn arenas() -> ResolverArenas<'a> { pub fn arenas() -> ResolverArenas<'a> {
Default::default() Default::default()
} }
@ -1653,7 +1664,7 @@ impl<'a> Resolver<'a> {
match result { match result {
Ok(binding) => { Ok(binding) => {
if let Some(node_id) = poisoned { if let Some(node_id) = poisoned {
self.session.buffer_lint_with_diagnostic( self.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
node_id, ident.span, node_id, ident.span,
&format!("cannot find {} `{}` in this scope", ns.descr(), ident), &format!("cannot find {} `{}` in this scope", ns.descr(), ident),
@ -2118,7 +2129,7 @@ impl<'a> Resolver<'a> {
} }
fn lint_if_path_starts_with_module( fn lint_if_path_starts_with_module(
&self, &mut self,
crate_lint: CrateLint, crate_lint: CrateLint,
path: &[Segment], path: &[Segment],
path_span: Span, path_span: Span,
@ -2169,7 +2180,7 @@ impl<'a> Resolver<'a> {
let diag = lint::builtin::BuiltinLintDiagnostics let diag = lint::builtin::BuiltinLintDiagnostics
::AbsPathWithModule(diag_span); ::AbsPathWithModule(diag_span);
self.session.buffer_lint_with_diagnostic( self.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
diag_id, diag_span, diag_id, diag_span,
"absolute paths must start with `self`, `super`, \ "absolute paths must start with `self`, `super`, \
@ -2419,7 +2430,7 @@ impl<'a> Resolver<'a> {
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors { for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
let msg = "macro-expanded `macro_export` macros from the current crate \ let msg = "macro-expanded `macro_export` macros from the current crate \
cannot be referred to by absolute paths"; cannot be referred to by absolute paths";
self.session.buffer_lint_with_diagnostic( self.lint_buffer.buffer_lint_with_diagnostic(
lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
CRATE_NODE_ID, span_use, msg, CRATE_NODE_ID, span_use, msg,
lint::builtin::BuiltinLintDiagnostics:: lint::builtin::BuiltinLintDiagnostics::

View file

@ -247,9 +247,9 @@ impl<'a> base::Resolver for Resolver<'a> {
Ok(InvocationRes::Single(ext)) Ok(InvocationRes::Single(ext))
} }
fn check_unused_macros(&self) { fn check_unused_macros(&mut self) {
for (&node_id, &span) in self.unused_macros.iter() { for (&node_id, &span) in self.unused_macros.iter() {
self.session.buffer_lint( self.lint_buffer.buffer_lint(
lint::builtin::UNUSED_MACROS, node_id, span, "unused macro definition" lint::builtin::UNUSED_MACROS, node_id, span, "unused macro definition"
); );
} }
@ -789,15 +789,17 @@ impl<'a> Resolver<'a> {
} }
} }
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) { fn check_stability_and_deprecation(&mut self, ext: &SyntaxExtension, path: &ast::Path) {
let span = path.span; let span = path.span;
if let Some(stability) = &ext.stability { if let Some(stability) = &ext.stability {
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
let feature = stability.feature; let feature = stability.feature;
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
let node_id = ast::CRATE_NODE_ID; let node_id = ast::CRATE_NODE_ID;
let soft_handler = let lint_buffer = &mut self.lint_buffer;
|lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg); let soft_handler = |lint, span, msg: &_| {
lint_buffer.buffer_lint(lint, node_id, span, msg)
};
stability::report_unstable( stability::report_unstable(
self.session, feature, reason, issue, is_soft, span, soft_handler self.session, feature, reason, issue, is_soft, span, soft_handler
); );
@ -807,14 +809,14 @@ impl<'a> Resolver<'a> {
let path = pprust::path_to_string(path); let path = pprust::path_to_string(path);
let (message, lint) = stability::rustc_deprecation_message(depr, &path); let (message, lint) = stability::rustc_deprecation_message(depr, &path);
stability::early_report_deprecation( stability::early_report_deprecation(
self.session, &message, depr.suggestion, lint, span &mut self.lint_buffer, &message, depr.suggestion, lint, span
); );
} }
} }
if let Some(depr) = &ext.deprecation { if let Some(depr) = &ext.deprecation {
let path = pprust::path_to_string(&path); let path = pprust::path_to_string(&path);
let (message, lint) = stability::deprecation_message(depr, &path); let (message, lint) = stability::deprecation_message(depr, &path);
stability::early_report_deprecation(self.session, &message, None, lint, span); stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span);
} }
} }

View file

@ -496,7 +496,7 @@ impl<'a> Resolver<'a> {
if let (&NameBindingKind::Res(_, true), &NameBindingKind::Res(_, true)) = if let (&NameBindingKind::Res(_, true), &NameBindingKind::Res(_, true)) =
(&old_binding.kind, &binding.kind) { (&old_binding.kind, &binding.kind) {
this.session.buffer_lint_with_diagnostic( this.lint_buffer.buffer_lint_with_diagnostic(
DUPLICATE_MACRO_EXPORTS, DUPLICATE_MACRO_EXPORTS,
CRATE_NODE_ID, CRATE_NODE_ID,
binding.span, binding.span,
@ -979,7 +979,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
!max_vis.get().is_at_least(directive.vis.get(), &*self) { !max_vis.get().is_at_least(directive.vis.get(), &*self) {
let msg = let msg =
"glob import doesn't reexport anything because no candidate is public enough"; "glob import doesn't reexport anything because no candidate is public enough";
self.r.session.buffer_lint(UNUSED_IMPORTS, directive.id, directive.span, msg); self.r.lint_buffer.buffer_lint(
UNUSED_IMPORTS, directive.id, directive.span, msg,
);
} }
return None; return None;
} }
@ -1148,7 +1150,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
re-exported (error E0365), consider declaring with \ re-exported (error E0365), consider declaring with \
`pub`", `pub`",
ident); ident);
self.r.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, self.r.lint_buffer.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
directive.id, directive.id,
directive.span, directive.span,
&msg); &msg);
@ -1273,7 +1275,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect(); let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
redundant_spans.sort(); redundant_spans.sort();
redundant_spans.dedup(); redundant_spans.dedup();
self.r.session.buffer_lint_with_diagnostic( self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_IMPORTS, UNUSED_IMPORTS,
directive.id, directive.id,
directive.span, directive.span,

View file

@ -858,7 +858,7 @@ pub trait Resolver {
&mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool &mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool
) -> Result<InvocationRes, Indeterminate>; ) -> Result<InvocationRes, Indeterminate>;
fn check_unused_macros(&self); fn check_unused_macros(&mut self);
fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool; fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool;
fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives); fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives);
@ -1053,7 +1053,7 @@ impl<'a> ExtCtxt<'a> {
Symbol::intern(st) Symbol::intern(st)
} }
pub fn check_unused_macros(&self) { pub fn check_unused_macros(&mut self) {
self.resolver.check_unused_macros(); self.resolver.check_unused_macros();
} }