Rollup merge of #67806 - Centril:splitsynmore, r=petrochenkov
Extract `rustc_ast_passes`, move gating, & refactor linting Based on https://github.com/rust-lang/rust/pull/67770. This PR extracts a crate `rustc_ast_passes`: - `ast_validation.rs`, which is contributed by `rustc_passes` (now only has HIR based passes) -- the goal here is to improve recompilation of the parser, - `feature_gate.rs`, which is contributed by `syntax` and performs post-expansion-gating & final erroring for pre-expansion gating, - `show_span`, which is contributed by `syntax`. To facilitate this, we first have to also: - Move `{leveled_}feature_err{_err}` from `syntax::feature_gate::check` into `rustc_session::parse`. - Move `get_features` into `rustc_parse::config`, the only place it is used. - Move some some lint datatypes and traits, e.g. `LintBuffer`, `BufferedEarlyLint`, `BuiltinLintDiagnostics`, `LintPass`, and `LintArray` into `rustc_session::lint`. - Move all the hard-wired lint `static`s into `rustc_session::lint::builtin`.
This commit is contained in:
commit
9634e1f7d9
24
Cargo.lock
24
Cargo.lock
@ -3363,6 +3363,21 @@ dependencies = [
|
||||
"syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_ast_passes"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_codes",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_parse",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_builtin_macros"
|
||||
version = "0.0.0"
|
||||
@ -3375,6 +3390,7 @@ dependencies = [
|
||||
"rustc_expand",
|
||||
"rustc_feature",
|
||||
"rustc_parse",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"smallvec 1.0.0",
|
||||
@ -3528,11 +3544,13 @@ name = "rustc_expand"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rustc_ast_passes",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_lexer",
|
||||
"rustc_parse",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"serialize",
|
||||
"smallvec 1.0.0",
|
||||
@ -3602,6 +3620,7 @@ dependencies = [
|
||||
"rustc",
|
||||
"rustc-rayon",
|
||||
"rustc_ast_lowering",
|
||||
"rustc_ast_passes",
|
||||
"rustc_builtin_macros",
|
||||
"rustc_codegen_llvm",
|
||||
"rustc_codegen_ssa",
|
||||
@ -3619,6 +3638,7 @@ dependencies = [
|
||||
"rustc_plugin_impl",
|
||||
"rustc_privacy",
|
||||
"rustc_resolve",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"rustc_traits",
|
||||
@ -3735,6 +3755,7 @@ dependencies = [
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_lexer",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"smallvec 1.0.0",
|
||||
"syntax",
|
||||
@ -3753,7 +3774,7 @@ dependencies = [
|
||||
"rustc_feature",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_parse",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"syntax",
|
||||
@ -3833,6 +3854,7 @@ dependencies = [
|
||||
"log",
|
||||
"num_cpus",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_codes",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_fs_util",
|
||||
|
@ -17,20 +17,21 @@
|
||||
use self::TargetLint::*;
|
||||
|
||||
use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
|
||||
use crate::lint::{EarlyLintPassObject, LateLintPassObject};
|
||||
use crate::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
|
||||
use crate::middle::privacy::AccessLevels;
|
||||
use crate::middle::stability;
|
||||
use crate::session::Session;
|
||||
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
|
||||
use crate::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_error_codes::*;
|
||||
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
|
||||
use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
|
||||
use syntax::ast;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
@ -64,17 +65,6 @@ pub struct LintStore {
|
||||
lint_groups: FxHashMap<&'static str, LintGroup>,
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
/// `LintLevels` is calculated
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct BufferedEarlyLint {
|
||||
pub lint_id: LintId,
|
||||
pub ast_id: ast::NodeId,
|
||||
pub span: MultiSpan,
|
||||
pub msg: String,
|
||||
pub diagnostic: BuiltinLintDiagnostics,
|
||||
}
|
||||
|
||||
/// The target of the `by_name` map, which accounts for renaming/deprecation.
|
||||
enum TargetLint {
|
||||
/// A direct lint target
|
||||
@ -477,6 +467,48 @@ impl LintPassObject for EarlyLintPassObject {}
|
||||
|
||||
impl LintPassObject for LateLintPassObject {}
|
||||
|
||||
pub fn add_elided_lifetime_in_path_suggestion(
|
||||
sess: &Session,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
n: usize,
|
||||
path_span: Span,
|
||||
incl_angl_brckt: bool,
|
||||
insertion_span: Span,
|
||||
anon_lts: String,
|
||||
) {
|
||||
let (replace_span, suggestion) = if incl_angl_brckt {
|
||||
(insertion_span, anon_lts)
|
||||
} else {
|
||||
// When possible, prefer a suggestion that replaces the whole
|
||||
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
|
||||
// at a point (which makes for an ugly/confusing label)
|
||||
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
|
||||
// But our spans can get out of whack due to macros; if the place we think
|
||||
// we want to insert `'_` isn't even within the path expression's span, we
|
||||
// should bail out of making any suggestion rather than panicking on a
|
||||
// subtract-with-overflow or string-slice-out-out-bounds (!)
|
||||
// FIXME: can we do better?
|
||||
if insertion_span.lo().0 < path_span.lo().0 {
|
||||
return;
|
||||
}
|
||||
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
|
||||
if insertion_index > snippet.len() {
|
||||
return;
|
||||
}
|
||||
let (before, after) = snippet.split_at(insertion_index);
|
||||
(path_span, format!("{}{}{}", before, anon_lts, after))
|
||||
} else {
|
||||
(insertion_span, anon_lts)
|
||||
}
|
||||
};
|
||||
db.span_suggestion(
|
||||
replace_span,
|
||||
&format!("indicate the anonymous lifetime{}", pluralize!(n)),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
pub trait LintContext: Sized {
|
||||
type PassObject: LintPassObject;
|
||||
|
||||
@ -495,7 +527,85 @@ pub trait LintContext: Sized {
|
||||
diagnostic: BuiltinLintDiagnostics,
|
||||
) {
|
||||
let mut db = self.lookup(lint, span, msg);
|
||||
diagnostic.run(self.sess(), &mut db);
|
||||
|
||||
let sess = self.sess();
|
||||
match diagnostic {
|
||||
BuiltinLintDiagnostics::Normal => (),
|
||||
BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
|
||||
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
|
||||
Ok(s) if is_global => {
|
||||
(format!("dyn ({})", s), Applicability::MachineApplicable)
|
||||
}
|
||||
Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
|
||||
Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
db.span_suggestion(span, "use `dyn`", sugg, app);
|
||||
}
|
||||
BuiltinLintDiagnostics::AbsPathWithModule(span) => {
|
||||
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
|
||||
Ok(ref s) => {
|
||||
// FIXME(Manishearth) ideally the emitting code
|
||||
// can tell us whether or not this is global
|
||||
let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
|
||||
|
||||
(format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
|
||||
}
|
||||
Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
db.span_suggestion(span, "use `crate`", sugg, app);
|
||||
}
|
||||
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
|
||||
db.span_label(
|
||||
span,
|
||||
"names from parent modules are not accessible without an explicit import",
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
|
||||
db.span_note(span_def, "the macro is defined here");
|
||||
}
|
||||
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
anon_lts,
|
||||
) => {
|
||||
add_elided_lifetime_in_path_suggestion(
|
||||
sess,
|
||||
&mut db,
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
anon_lts,
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
|
||||
db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
|
||||
if !replaces.is_empty() {
|
||||
db.tool_only_multipart_suggestion(
|
||||
&message,
|
||||
replaces,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
|
||||
for (span, is_imported) in spans {
|
||||
let introduced = if is_imported { "imported" } else { "defined" };
|
||||
db.span_label(
|
||||
span,
|
||||
format!("the item `{}` is already {} here", ident, introduced),
|
||||
);
|
||||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
|
||||
stability::deprecation_suggestion(&mut db, suggestion, span)
|
||||
}
|
||||
}
|
||||
|
||||
db.emit();
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
|
||||
//! Clippy.
|
||||
|
||||
use crate::lint::{
|
||||
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
|
||||
};
|
||||
use crate::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind};
|
||||
use rustc_session::declare_tool_lint;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use syntax::ast::{Ident, Item, ItemKind};
|
||||
|
||||
|
@ -13,8 +13,8 @@ use rustc_span::source_map::MultiSpan;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::feature_gate;
|
||||
use syntax::print::pprust;
|
||||
use syntax::sess::feature_err;
|
||||
|
||||
use rustc_error_codes::*;
|
||||
|
||||
@ -223,7 +223,7 @@ impl<'a> LintLevelsBuilder<'a> {
|
||||
// don't have any lint names (`#[level(reason = "foo")]`)
|
||||
if let ast::LitKind::Str(rationale, _) = name_value.kind {
|
||||
if !self.sess.features_untracked().lint_reasons {
|
||||
feature_gate::feature_err(
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
sym::lint_reasons,
|
||||
item.span,
|
||||
|
@ -21,12 +21,11 @@
|
||||
pub use self::Level::*;
|
||||
pub use self::LintSource::*;
|
||||
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use rustc_hir as hir;
|
||||
use rustc_session::node_id::NodeMap;
|
||||
use rustc_session::lint::builtin::HardwiredLints;
|
||||
use rustc_session::{DiagnosticMessageId, Session};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
|
||||
@ -35,48 +34,13 @@ use rustc_span::Span;
|
||||
use syntax::ast;
|
||||
|
||||
pub use crate::lint::context::{
|
||||
BufferedEarlyLint, CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore,
|
||||
add_elided_lifetime_in_path_suggestion, CheckLintNameResult, EarlyContext, LateContext,
|
||||
LintContext, LintStore,
|
||||
};
|
||||
|
||||
pub use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintId};
|
||||
|
||||
/// Declares a static `LintArray` and return it as an expression.
|
||||
#[macro_export]
|
||||
macro_rules! lint_array {
|
||||
($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
|
||||
($( $lint:expr ),*) => {{
|
||||
vec![$($lint),*]
|
||||
}}
|
||||
}
|
||||
|
||||
pub type LintArray = Vec<&'static Lint>;
|
||||
|
||||
pub trait LintPass {
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// Implements `LintPass for $name` with the given list of `Lint` statics.
|
||||
#[macro_export]
|
||||
macro_rules! impl_lint_pass {
|
||||
($name:ident => [$($lint:expr),* $(,)?]) => {
|
||||
impl LintPass for $name {
|
||||
fn name(&self) -> &'static str { stringify!($name) }
|
||||
}
|
||||
impl $name {
|
||||
pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Declares a type named `$name` which implements `LintPass`.
|
||||
/// To the right of `=>` a comma separated list of `Lint` statics is given.
|
||||
#[macro_export]
|
||||
macro_rules! declare_lint_pass {
|
||||
($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
|
||||
$(#[$m])* #[derive(Copy, Clone)] pub struct $name;
|
||||
$crate::impl_lint_pass!($name => [$($lint),*]);
|
||||
};
|
||||
}
|
||||
pub use rustc_session::lint::builtin;
|
||||
pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Level, Lint, LintId};
|
||||
pub use rustc_session::lint::{LintArray, LintPass};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! late_lint_methods {
|
||||
@ -168,6 +132,8 @@ macro_rules! declare_late_lint_pass {
|
||||
|
||||
late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
|
||||
|
||||
impl LateLintPass<'_, '_> for HardwiredLints {}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! expand_combined_late_lint_pass_method {
|
||||
([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
|
||||
@ -366,66 +332,12 @@ pub enum LintSource {
|
||||
|
||||
pub type LevelSource = (Level, LintSource);
|
||||
|
||||
pub mod builtin;
|
||||
mod context;
|
||||
pub mod internal;
|
||||
mod levels;
|
||||
|
||||
pub use self::levels::{LintLevelMap, LintLevelSets, LintLevelsBuilder};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LintBuffer {
|
||||
pub map: NodeMap<Vec<BufferedEarlyLint>>,
|
||||
}
|
||||
|
||||
impl LintBuffer {
|
||||
pub fn add_lint(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
id: ast::NodeId,
|
||||
sp: MultiSpan,
|
||||
msg: &str,
|
||||
diagnostic: BuiltinLintDiagnostics,
|
||||
) {
|
||||
let early_lint = BufferedEarlyLint {
|
||||
lint_id: LintId::of(lint),
|
||||
ast_id: id,
|
||||
span: sp,
|
||||
msg: msg.to_string(),
|
||||
diagnostic,
|
||||
};
|
||||
let arr = self.map.entry(id).or_default();
|
||||
if !arr.contains(&early_lint) {
|
||||
arr.push(early_lint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take(&mut self, id: ast::NodeId) -> Vec<BufferedEarlyLint> {
|
||||
self.map.remove(&id).unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn buffer_lint<S: Into<MultiSpan>>(
|
||||
&mut self,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn struct_lint_level<'a>(
|
||||
sess: &'a Session,
|
||||
lint: &'static Lint,
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
pub use self::StabilityLevel::*;
|
||||
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::lint::{self, in_derive_expansion, Lint};
|
||||
use crate::session::{DiagnosticMessageId, Session};
|
||||
use crate::ty::{self, TyCtxt};
|
||||
@ -14,11 +13,12 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
|
||||
use rustc_hir::{self, HirId};
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use syntax::ast::CRATE_NODE_ID;
|
||||
use syntax::attr::{self, ConstStability, Deprecation, RustcDeprecation, Stability};
|
||||
use syntax::feature_gate::feature_err_issue;
|
||||
use syntax::sess::feature_err_issue;
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
@ -195,7 +195,7 @@ pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String
|
||||
}
|
||||
|
||||
pub fn early_report_deprecation(
|
||||
lint_buffer: &'a mut lint::LintBuffer,
|
||||
lint_buffer: &'a mut LintBuffer,
|
||||
message: &str,
|
||||
suggestion: Option<Symbol>,
|
||||
lint: &'static Lint,
|
||||
|
@ -37,7 +37,6 @@ use rustc::arena::Arena;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions};
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint;
|
||||
use rustc::lint::builtin;
|
||||
use rustc::{bug, span_bug};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
@ -52,6 +51,7 @@ use rustc_hir::intravisit;
|
||||
use rustc_hir::{ConstArg, GenericArg, ParamName};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_session::config::nightly_options;
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||
use rustc_session::node_id::NodeMap;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::ExpnId;
|
||||
@ -198,7 +198,7 @@ pub trait Resolver {
|
||||
ns: Namespace,
|
||||
) -> (ast::Path, Res<NodeId>);
|
||||
|
||||
fn lint_buffer(&mut self) -> &mut lint::LintBuffer;
|
||||
fn lint_buffer(&mut self) -> &mut LintBuffer;
|
||||
|
||||
fn next_node_id(&mut self) -> NodeId;
|
||||
}
|
||||
@ -2617,7 +2617,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
id,
|
||||
span,
|
||||
"trait objects without an explicit `dyn` are deprecated",
|
||||
builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global),
|
||||
BuiltinLintDiagnostics::BareTraitObject(span, is_global),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode};
|
||||
use super::{GenericArgsCtor, ParenthesizedGenericArgs};
|
||||
|
||||
use rustc::lint::builtin::{self, ELIDED_LIFETIMES_IN_PATHS};
|
||||
use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
|
||||
use rustc::span_bug;
|
||||
use rustc_error_codes::*;
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
@ -9,6 +9,7 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_span::Span;
|
||||
use syntax::ast::{self, *};
|
||||
|
||||
@ -304,7 +305,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
E0726,
|
||||
"implicit elided lifetime not allowed here"
|
||||
);
|
||||
crate::lint::builtin::add_elided_lifetime_in_path_suggestion(
|
||||
rustc::lint::add_elided_lifetime_in_path_suggestion(
|
||||
&self.sess,
|
||||
&mut err,
|
||||
expected_lifetimes,
|
||||
@ -321,7 +322,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
CRATE_NODE_ID,
|
||||
path_span,
|
||||
"hidden lifetime parameters in types are deprecated",
|
||||
builtin::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
expected_lifetimes,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
|
20
src/librustc_ast_passes/Cargo.toml
Normal file
20
src/librustc_ast_passes/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_ast_passes"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "rustc_ast_passes"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||
rustc_error_codes = { path = "../librustc_error_codes" }
|
||||
rustc_feature = { path = "../librustc_feature" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
syntax = { path = "../libsyntax" }
|
@ -6,11 +6,12 @@
|
||||
// This pass is supposed to perform only simple checks not requiring name resolution
|
||||
// or type checking or some other kind of complex analysis.
|
||||
|
||||
use rustc::lint;
|
||||
use rustc::session::Session;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{struct_span_err, Applicability, FatalError};
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
|
||||
use rustc_session::lint::LintBuffer;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::Span;
|
||||
@ -65,7 +66,7 @@ struct AstValidator<'a> {
|
||||
/// certain positions.
|
||||
is_assoc_ty_bound_banned: bool,
|
||||
|
||||
lint_buffer: &'a mut lint::LintBuffer,
|
||||
lint_buffer: &'a mut LintBuffer,
|
||||
}
|
||||
|
||||
impl<'a> AstValidator<'a> {
|
||||
@ -906,7 +907,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Some(Constness::Const) => bug!("Parser should reject bare `const` on bounds"),
|
||||
Some(Constness::Const) => panic!("Parser should reject bare `const` on bounds"),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
@ -992,7 +993,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
if mut_ident {
|
||||
self.lint_buffer.buffer_lint(
|
||||
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
ti.id,
|
||||
span,
|
||||
"patterns aren't allowed in methods without bodies",
|
||||
@ -1021,7 +1022,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
|
||||
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
|
||||
let mut validator = AstValidator {
|
||||
session,
|
||||
has_proc_macro_decls: false,
|
@ -1,22 +1,15 @@
|
||||
use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
|
||||
use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
|
||||
use crate::attr;
|
||||
use crate::sess::ParseSess;
|
||||
use crate::visit::{self, FnKind, Visitor};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_error_codes::*;
|
||||
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Handler};
|
||||
use rustc_feature::{find_feature_issue, GateIssue};
|
||||
use rustc_errors::{struct_span_err, Handler};
|
||||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_feature::{Feature, Features, State as FeatureState, UnstableFeatures};
|
||||
use rustc_feature::{
|
||||
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
||||
};
|
||||
use rustc_span::edition::{Edition, ALL_EDITIONS};
|
||||
use rustc_feature::{Features, GateIssue, UnstableFeatures};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use syntax::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
|
||||
use syntax::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
|
||||
use syntax::attr;
|
||||
use syntax::sess::{feature_err, leveled_feature_err, GateStrength, ParseSess};
|
||||
use syntax::visit::{self, FnKind, Visitor};
|
||||
|
||||
use log::debug;
|
||||
|
||||
@ -53,70 +46,6 @@ pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features:
|
||||
PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum GateStrength {
|
||||
/// A hard error. (Most feature gates should use this.)
|
||||
Hard,
|
||||
/// Only a warning. (Use this only as backwards-compatibility demands.)
|
||||
Soft,
|
||||
}
|
||||
|
||||
pub fn feature_err<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
|
||||
}
|
||||
|
||||
pub fn feature_err_issue<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
|
||||
}
|
||||
|
||||
fn leveled_feature_err<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
level: GateStrength,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let diag = &sess.span_diagnostic;
|
||||
|
||||
let mut err = match level {
|
||||
GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)),
|
||||
GateStrength::Soft => diag.struct_span_warn(span, explain),
|
||||
};
|
||||
|
||||
if let Some(n) = find_feature_issue(feature, issue) {
|
||||
err.note(&format!(
|
||||
"for more information, see https://github.com/rust-lang/rust/issues/{}",
|
||||
n,
|
||||
));
|
||||
}
|
||||
|
||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||
if sess.unstable_features.is_nightly_build() {
|
||||
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
|
||||
}
|
||||
|
||||
// If we're on stable and only emitting a "soft" warning, add a note to
|
||||
// clarify that the feature isn't "on" (rather than being on but
|
||||
// warning-worthy).
|
||||
if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
|
||||
err.help("a nightly build of the compiler is required to enable this feature");
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
struct PostExpansionVisitor<'a> {
|
||||
parse_sess: &'a ParseSess,
|
||||
features: &'a Features,
|
||||
@ -724,168 +653,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_features(
|
||||
span_handler: &Handler,
|
||||
krate_attrs: &[ast::Attribute],
|
||||
crate_edition: Edition,
|
||||
allow_features: &Option<Vec<String>>,
|
||||
) -> Features {
|
||||
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
||||
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
||||
err.span_label(span, "feature has been removed");
|
||||
if let Some(reason) = reason {
|
||||
err.note(reason);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
let mut features = Features::default();
|
||||
let mut edition_enabled_features = FxHashMap::default();
|
||||
|
||||
for &edition in ALL_EDITIONS {
|
||||
if edition <= crate_edition {
|
||||
// The `crate_edition` implies its respective umbrella feature-gate
|
||||
// (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
|
||||
edition_enabled_features.insert(edition.feature_name(), edition);
|
||||
}
|
||||
}
|
||||
|
||||
for feature in active_features_up_to(crate_edition) {
|
||||
feature.set(&mut features, DUMMY_SP);
|
||||
edition_enabled_features.insert(feature.name, crate_edition);
|
||||
}
|
||||
|
||||
// Process the edition umbrella feature-gates first, to ensure
|
||||
// `edition_enabled_features` is completed before it's queried.
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
for mi in list {
|
||||
if !mi.is_word() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = mi.name_or_empty();
|
||||
|
||||
let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
|
||||
if let Some(edition) = edition {
|
||||
if edition <= crate_edition {
|
||||
continue;
|
||||
}
|
||||
|
||||
for feature in active_features_up_to(edition) {
|
||||
// FIXME(Manishearth) there is currently no way to set
|
||||
// lib features by edition
|
||||
feature.set(&mut features, DUMMY_SP);
|
||||
edition_enabled_features.insert(feature.name, edition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let bad_input = |span| {
|
||||
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
|
||||
};
|
||||
|
||||
for mi in list {
|
||||
let name = match mi.ident() {
|
||||
Some(ident) if mi.is_word() => ident.name,
|
||||
Some(ident) => {
|
||||
bad_input(mi.span())
|
||||
.span_suggestion(
|
||||
mi.span(),
|
||||
"expected just one word",
|
||||
format!("{}", ident.name),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
None => {
|
||||
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(edition) = edition_enabled_features.get(&name) {
|
||||
let msg =
|
||||
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
|
||||
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
|
||||
// Handled in the separate loop above.
|
||||
continue;
|
||||
}
|
||||
|
||||
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
|
||||
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
|
||||
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
|
||||
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
|
||||
state
|
||||
{
|
||||
feature_removed(span_handler, mi.span(), *reason);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
||||
let since = Some(Symbol::intern(since));
|
||||
features.declared_lang_features.push((name, mi.span(), since));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(allowed) = allow_features.as_ref() {
|
||||
if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
|
||||
struct_span_err!(
|
||||
span_handler,
|
||||
mi.span(),
|
||||
E0725,
|
||||
"the feature `{}` is not in the list of allowed features",
|
||||
name
|
||||
)
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
|
||||
f.set(&mut features, mi.span());
|
||||
features.declared_lang_features.push((name, mi.span(), None));
|
||||
continue;
|
||||
}
|
||||
|
||||
features.declared_lib_features.push((name, mi.span()));
|
||||
}
|
||||
}
|
||||
|
||||
features
|
||||
}
|
||||
|
||||
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
|
||||
ACTIVE_FEATURES.iter().filter(move |feature| {
|
||||
if let Some(feature_edition) = feature.edition { feature_edition <= edition } else { false }
|
||||
})
|
||||
}
|
||||
|
||||
pub fn check_crate(
|
||||
krate: &ast::Crate,
|
||||
parse_sess: &ParseSess,
|
9
src/librustc_ast_passes/lib.rs
Normal file
9
src/librustc_ast_passes/lib.rs
Normal file
@ -0,0 +1,9 @@
|
||||
//! The `rustc_ast_passes` crate contains passes which validate the AST in `syntax`
|
||||
//! parsed by `rustc_parse` and then lowered, after the passes in this crate,
|
||||
//! by `rustc_ast_lowering`.
|
||||
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
pub mod ast_validation;
|
||||
pub mod feature_gate;
|
||||
pub mod show_span;
|
@ -5,9 +5,9 @@
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::ast;
|
||||
use crate::visit;
|
||||
use crate::visit::Visitor;
|
||||
use syntax::ast;
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
|
||||
enum Mode {
|
||||
Expression,
|
@ -17,6 +17,7 @@ rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_feature = { path = "../librustc_feature" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc_expand = { path = "../librustc_expand" }
|
||||
|
@ -1,15 +1,15 @@
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_expand::panictry;
|
||||
use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership};
|
||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{self, Pos, Span};
|
||||
use syntax::ast;
|
||||
use syntax::early_buffered_lints::INCOMPLETE_INCLUDE;
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::token;
|
||||
use syntax::tokenstream::TokenStream;
|
||||
|
||||
use rustc_span::{self, Pos, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
@ -14,10 +14,12 @@ doctest = false
|
||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||
log = "0.4"
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
rustc_ast_passes = { path = "../librustc_ast_passes" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_feature = { path = "../librustc_feature" }
|
||||
rustc_lexer = { path = "../librustc_lexer" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
||||
syntax = { path = "../libsyntax" }
|
||||
|
@ -18,11 +18,10 @@ use rustc_span::{FileName, Span, DUMMY_SP};
|
||||
use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
|
||||
use syntax::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind};
|
||||
use syntax::attr::{self, is_builtin_attr, HasAttrs};
|
||||
use syntax::feature_gate::{self, feature_err};
|
||||
use syntax::mut_visit::*;
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::sess::{feature_err, ParseSess};
|
||||
use syntax::token;
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::util::map_in_place::MapInPlace;
|
||||
@ -1062,7 +1061,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
|
||||
let features = self.cx.ecfg.features.unwrap();
|
||||
for attr in attrs.iter() {
|
||||
feature_gate::check_attribute(attr, self.cx.parse_sess, features);
|
||||
rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.parse_sess, features);
|
||||
validate_attr::check_meta(self.cx.parse_sess, attr);
|
||||
|
||||
// macros are expanded before any lint passes so this warning has to be hardcoded
|
||||
|
@ -106,14 +106,14 @@
|
||||
//! bound.
|
||||
use crate::mbe::{KleeneToken, TokenTree};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{symbol::Ident, MultiSpan, Span};
|
||||
use syntax::ast::NodeId;
|
||||
use syntax::early_buffered_lints::META_VARIABLE_MISUSE;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::token::{DelimToken, Token, TokenKind};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_span::{symbol::Ident, MultiSpan, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
/// Stack represented as linked list.
|
||||
|
@ -17,10 +17,12 @@ syntax = { path = "../libsyntax" }
|
||||
rustc_builtin_macros = { path = "../librustc_builtin_macros" }
|
||||
rustc_expand = { path = "../librustc_expand" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_ast_lowering = { path = "../librustc_ast_lowering" }
|
||||
rustc_ast_passes = { path = "../librustc_ast_passes" }
|
||||
rustc_incremental = { path = "../librustc_incremental" }
|
||||
rustc_traits = { path = "../librustc_traits" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
|
@ -29,7 +29,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_incremental;
|
||||
use rustc_mir as mir;
|
||||
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
|
||||
use rustc_passes::{self, ast_validation, hir_stats, layout_test};
|
||||
use rustc_passes::{self, hir_stats, layout_test};
|
||||
use rustc_plugin_impl as plugin;
|
||||
use rustc_privacy;
|
||||
use rustc_resolve::{Resolver, ResolverArenas};
|
||||
@ -37,7 +37,6 @@ use rustc_span::symbol::Symbol;
|
||||
use rustc_span::FileName;
|
||||
use rustc_traits;
|
||||
use rustc_typeck as typeck;
|
||||
use syntax::early_buffered_lints::BufferedEarlyLint;
|
||||
use syntax::mut_visit::MutVisitor;
|
||||
use syntax::util::node_count::NodeCounter;
|
||||
use syntax::{self, ast, visit};
|
||||
@ -71,7 +70,7 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
|
||||
}
|
||||
|
||||
if let Some(ref s) = sess.opts.debugging_opts.show_span {
|
||||
syntax::show_span::run(sess.diagnostic(), s, &krate);
|
||||
rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
|
||||
}
|
||||
|
||||
if sess.opts.debugging_opts.hir_stats {
|
||||
@ -345,7 +344,7 @@ fn configure_and_expand_inner<'a>(
|
||||
}
|
||||
|
||||
let has_proc_macro_decls = sess.time("AST_validation", || {
|
||||
ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
|
||||
rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
|
||||
});
|
||||
|
||||
let crate_types = sess.crate_types.borrow();
|
||||
@ -400,7 +399,7 @@ fn configure_and_expand_inner<'a>(
|
||||
|
||||
// Needs to go *after* expansion to be able to check the results of macro expansion.
|
||||
sess.time("complete_gated_feature_checking", || {
|
||||
syntax::feature_gate::check_crate(
|
||||
rustc_ast_passes::feature_gate::check_crate(
|
||||
&krate,
|
||||
&sess.parse_sess,
|
||||
&sess.features_untracked(),
|
||||
@ -411,8 +410,8 @@ fn configure_and_expand_inner<'a>(
|
||||
// Add all buffered lints from the `ParseSess` to the `Session`.
|
||||
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
|
||||
info!("{} parse sess buffered_lints", buffered_lints.len());
|
||||
for BufferedEarlyLint { id, span, msg, lint_id } in buffered_lints.drain(..) {
|
||||
resolver.lint_buffer().buffer_lint(lint_id, id, span, &msg);
|
||||
for early_lint in buffered_lints.drain(..) {
|
||||
resolver.lint_buffer().add_early_lint(early_lint);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
use log::info;
|
||||
use rustc::lint;
|
||||
use rustc::session::config::{ErrorOutputType, Input, OutputFilenames};
|
||||
use rustc::session::CrateDisambiguator;
|
||||
use rustc::session::{self, config, early_error, filesearch, DiagnosticOutput, Session};
|
||||
use rustc::ty;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
@ -14,6 +11,11 @@ use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_metadata::dynamic_lib::DynamicLibrary;
|
||||
use rustc_resolve::{self, Resolver};
|
||||
use rustc_session as session;
|
||||
use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||
use rustc_session::CrateDisambiguator;
|
||||
use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
@ -420,7 +422,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat
|
||||
CrateDisambiguator::from(hasher.finish::<Fingerprint>())
|
||||
}
|
||||
|
||||
pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut lint::LintBuffer) {
|
||||
pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer) {
|
||||
// Unconditionally collect crate types from attributes to make them used
|
||||
for a in attrs.iter() {
|
||||
if a.check_name(sym::crate_type) {
|
||||
@ -442,7 +444,7 @@ pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut
|
||||
ast::CRATE_NODE_ID,
|
||||
span,
|
||||
"invalid `crate_type` value",
|
||||
lint::builtin::BuiltinLintDiagnostics::UnknownCrateTypes(
|
||||
BuiltinLintDiagnostics::UnknownCrateTypes(
|
||||
span,
|
||||
"did you mean".to_string(),
|
||||
format!("\"{}\"", candidate),
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::lint::FutureIncompatibleInfo;
|
||||
use rustc::lint::{FutureIncompatibleInfo, LateContext, LateLintPass, LintContext};
|
||||
use rustc::ty;
|
||||
use rustc::ty::adjustment::{Adjust, Adjustment};
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -21,13 +21,8 @@
|
||||
//! If you define a new `LateLintPass`, you will also need to add it to the
|
||||
//! `late_lint_methods!` invocation in `lib.rs`.
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
use lint::{EarlyContext, EarlyLintPass, LateLintPass, LintPass};
|
||||
use lint::{LateContext, LintArray, LintContext};
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint;
|
||||
use rustc::lint::FutureIncompatibleInfo;
|
||||
use rustc::lint::{self, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc::traits::misc::can_type_implement_copy;
|
||||
use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -39,6 +34,7 @@ use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{GenericParamKind, PatKind};
|
||||
use rustc_hir::{HirIdSet, Node};
|
||||
use rustc_session::lint::FutureIncompatibleInfo;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
@ -52,6 +48,7 @@ use syntax::visit::FnKind;
|
||||
use crate::nonstandard_style::{method_context, MethodLateContext};
|
||||
|
||||
use log::debug;
|
||||
use std::fmt::Write;
|
||||
|
||||
// hardwired lints from librustc
|
||||
pub use lint::builtin::*;
|
||||
|
@ -16,15 +16,15 @@
|
||||
|
||||
use rustc::lint::{EarlyContext, LintStore};
|
||||
use rustc::lint::{EarlyLintPass, EarlyLintPassObject};
|
||||
use rustc::lint::{LintBuffer, LintContext, LintPass};
|
||||
use rustc::session::Session;
|
||||
|
||||
use rustc::lint::{LintContext, LintPass};
|
||||
use rustc_session::lint::LintBuffer;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
use std::slice;
|
||||
use syntax::ast;
|
||||
use syntax::visit as ast_visit;
|
||||
|
||||
use log::debug;
|
||||
use std::slice;
|
||||
|
||||
macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
$cx.pass.$f(&$cx.context, $($args),*);
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint::LateContext;
|
||||
use rustc::lint::LintPass;
|
||||
use rustc::lint::{LateLintPass, LateLintPassObject};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
|
||||
@ -24,12 +23,13 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::intravisit as hir_visit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_session::lint::LintPass;
|
||||
use rustc_span::Span;
|
||||
use std::slice;
|
||||
use syntax::ast;
|
||||
use syntax::walk_list;
|
||||
|
||||
use log::debug;
|
||||
use syntax::walk_list;
|
||||
use std::slice;
|
||||
|
||||
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
$cx.pass.$f(&$cx.context, $($args),*);
|
||||
|
@ -38,11 +38,12 @@ use rustc::lint::builtin::{
|
||||
BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS,
|
||||
};
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_session::lint::{LintArray, LintPass};
|
||||
|
||||
use rustc_span::Span;
|
||||
use syntax::ast;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use syntax::ast;
|
||||
|
||||
declare_lint! {
|
||||
|
@ -1,6 +1,4 @@
|
||||
use lint::{EarlyContext, LateContext, LintArray, LintContext};
|
||||
use lint::{EarlyLintPass, LateLintPass, LintPass};
|
||||
use rustc::lint;
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc::ty;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_errors::Applicability;
|
||||
use syntax::ast::{ExprKind, Stmt, StmtKind};
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::hir::def_id::DefId;
|
||||
use lint::{LateContext, LintArray, LintContext};
|
||||
use lint::{LateLintPass, LintPass};
|
||||
use rustc::lint;
|
||||
use rustc::lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc::mir::interpret::{sign_extend, truncate};
|
||||
use rustc::ty::layout::{self, IntegerExt, LayoutOf, SizeSkeleton, VariantIdx};
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
@ -11,6 +8,7 @@ use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{is_range_literal, ExprKind, Node};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_span::source_map;
|
||||
|
@ -1,7 +1,5 @@
|
||||
use lint::{EarlyContext, LateContext, LintArray, LintContext};
|
||||
use lint::{EarlyLintPass, LateLintPass, LintPass};
|
||||
use rustc::lint;
|
||||
use rustc::lint::builtin::UNUSED_ATTRIBUTES;
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc::ty::adjustment;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -1,4 +1,5 @@
|
||||
use rustc::middle::cstore::{self, NativeLibrary};
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -10,7 +11,6 @@ use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::attr;
|
||||
use syntax::feature_gate::feature_err;
|
||||
|
||||
crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
|
||||
let mut collector = Collector { tcx, libs: Vec::new() };
|
||||
|
@ -6,6 +6,7 @@ use super::{PatCtxt, PatKind, PatternError};
|
||||
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::lint;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
@ -19,7 +20,6 @@ use rustc_hir::{HirId, Pat};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::feature_gate::feature_err;
|
||||
|
||||
use std::slice;
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
//! Concrete error types for all operations which may be invalid in a certain const context.
|
||||
|
||||
use rustc::session::config::nightly_options;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use syntax::feature_gate::feature_err;
|
||||
|
||||
use super::{ConstKind, Item};
|
||||
|
||||
|
@ -18,6 +18,7 @@ rustc_lexer = { path = "../librustc_lexer" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_error_codes = { path = "../librustc_error_codes" }
|
||||
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
unicode-normalization = "0.1.11"
|
||||
|
@ -9,18 +9,22 @@
|
||||
//! [#64197]: https://github.com/rust-lang/rust/issues/64197
|
||||
|
||||
use crate::{parse_in, validate_attr};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_feature::Features;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_error_codes::*;
|
||||
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
|
||||
use rustc_feature::{Feature, Features, State as FeatureState};
|
||||
use rustc_feature::{
|
||||
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
||||
};
|
||||
use rustc_span::edition::{Edition, ALL_EDITIONS};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use syntax::ast::{self, AttrItem, Attribute, MetaItem};
|
||||
use syntax::attr;
|
||||
use syntax::attr::HasAttrs;
|
||||
use syntax::feature_gate::{feature_err, get_features};
|
||||
use syntax::mut_visit::*;
|
||||
use syntax::ptr::P;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::sess::{feature_err, ParseSess};
|
||||
use syntax::util::map_in_place::MapInPlace;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
@ -31,6 +35,172 @@ pub struct StripUnconfigured<'a> {
|
||||
pub features: Option<&'a Features>,
|
||||
}
|
||||
|
||||
fn get_features(
|
||||
span_handler: &Handler,
|
||||
krate_attrs: &[ast::Attribute],
|
||||
crate_edition: Edition,
|
||||
allow_features: &Option<Vec<String>>,
|
||||
) -> Features {
|
||||
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
||||
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
||||
err.span_label(span, "feature has been removed");
|
||||
if let Some(reason) = reason {
|
||||
err.note(reason);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
|
||||
ACTIVE_FEATURES.iter().filter(move |feature| {
|
||||
if let Some(feature_edition) = feature.edition {
|
||||
feature_edition <= edition
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let mut features = Features::default();
|
||||
let mut edition_enabled_features = FxHashMap::default();
|
||||
|
||||
for &edition in ALL_EDITIONS {
|
||||
if edition <= crate_edition {
|
||||
// The `crate_edition` implies its respective umbrella feature-gate
|
||||
// (i.e., `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
|
||||
edition_enabled_features.insert(edition.feature_name(), edition);
|
||||
}
|
||||
}
|
||||
|
||||
for feature in active_features_up_to(crate_edition) {
|
||||
feature.set(&mut features, DUMMY_SP);
|
||||
edition_enabled_features.insert(feature.name, crate_edition);
|
||||
}
|
||||
|
||||
// Process the edition umbrella feature-gates first, to ensure
|
||||
// `edition_enabled_features` is completed before it's queried.
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
for mi in list {
|
||||
if !mi.is_word() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = mi.name_or_empty();
|
||||
|
||||
let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
|
||||
if let Some(edition) = edition {
|
||||
if edition <= crate_edition {
|
||||
continue;
|
||||
}
|
||||
|
||||
for feature in active_features_up_to(edition) {
|
||||
// FIXME(Manishearth) there is currently no way to set
|
||||
// lib features by edition
|
||||
feature.set(&mut features, DUMMY_SP);
|
||||
edition_enabled_features.insert(feature.name, edition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for attr in krate_attrs {
|
||||
if !attr.check_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let bad_input = |span| {
|
||||
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
|
||||
};
|
||||
|
||||
for mi in list {
|
||||
let name = match mi.ident() {
|
||||
Some(ident) if mi.is_word() => ident.name,
|
||||
Some(ident) => {
|
||||
bad_input(mi.span())
|
||||
.span_suggestion(
|
||||
mi.span(),
|
||||
"expected just one word",
|
||||
format!("{}", ident.name),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
None => {
|
||||
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(edition) = edition_enabled_features.get(&name) {
|
||||
let msg =
|
||||
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
|
||||
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
|
||||
// Handled in the separate loop above.
|
||||
continue;
|
||||
}
|
||||
|
||||
let removed = REMOVED_FEATURES.iter().find(|f| name == f.name);
|
||||
let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.name);
|
||||
if let Some(Feature { state, .. }) = removed.or(stable_removed) {
|
||||
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
|
||||
state
|
||||
{
|
||||
feature_removed(span_handler, mi.span(), *reason);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
||||
let since = Some(Symbol::intern(since));
|
||||
features.declared_lang_features.push((name, mi.span(), since));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(allowed) = allow_features.as_ref() {
|
||||
if allowed.iter().find(|&f| name.as_str() == *f).is_none() {
|
||||
struct_span_err!(
|
||||
span_handler,
|
||||
mi.span(),
|
||||
E0725,
|
||||
"the feature `{}` is not in the list of allowed features",
|
||||
name
|
||||
)
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) {
|
||||
f.set(&mut features, mi.span());
|
||||
features.declared_lang_features.push((name, mi.span(), None));
|
||||
continue;
|
||||
}
|
||||
|
||||
features.declared_lib_features.push((name, mi.span()));
|
||||
}
|
||||
}
|
||||
|
||||
features
|
||||
}
|
||||
|
||||
// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
||||
pub fn features(
|
||||
mut krate: ast::Crate,
|
||||
|
@ -4,10 +4,10 @@ use crate::parse_in;
|
||||
|
||||
use rustc_errors::{Applicability, PResult};
|
||||
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{sym, Symbol};
|
||||
use syntax::ast::{self, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
|
||||
use syntax::early_buffered_lints::ILL_FORMED_ATTRIBUTE_INPUT;
|
||||
use syntax::sess::ParseSess;
|
||||
use syntax::tokenstream::DelimSpan;
|
||||
|
||||
pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
|
||||
|
@ -16,7 +16,7 @@ rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_feature = { path = "../librustc_feature" }
|
||||
rustc_hir = { path = "../librustc_hir" }
|
||||
rustc_index = { path = "../librustc_index" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_session = { path = "../librustc_session" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::session::config::nightly_options;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_error_codes::*;
|
||||
@ -18,7 +19,6 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
use rustc_span::{sym, Span, Symbol};
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::feature_gate::feature_err;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
|
@ -17,7 +17,6 @@ extern crate log;
|
||||
|
||||
use rustc::ty::query::Providers;
|
||||
|
||||
pub mod ast_validation;
|
||||
mod check_const;
|
||||
pub mod dead;
|
||||
mod diagnostic_items;
|
||||
|
@ -5,6 +5,7 @@ use rustc::hir::map::Map;
|
||||
use rustc::lint;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::stability::{DeprecationEntry, Index};
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::session::Session;
|
||||
use rustc::traits::misc::can_type_implement_copy;
|
||||
use rustc::ty::query::Providers;
|
||||
@ -20,7 +21,6 @@ use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
use syntax::ast::Attribute;
|
||||
use syntax::attr::{self, Stability};
|
||||
use syntax::feature_gate::feature_err;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::mem::replace;
|
||||
|
@ -29,6 +29,7 @@ use crate::Resolver;
|
||||
use rustc::{lint, ty};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::pluralize;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::node_id::NodeMap;
|
||||
use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
||||
use syntax::ast;
|
||||
@ -317,7 +318,7 @@ impl Resolver<'_> {
|
||||
unused.use_tree_id,
|
||||
ms,
|
||||
&msg,
|
||||
lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
|
||||
BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet
|
||||
use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding};
|
||||
|
||||
use rustc::hir::exports::Export;
|
||||
use rustc::lint::builtin::BuiltinLintDiagnostics;
|
||||
use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
|
||||
use rustc::session::DiagnosticMessageId;
|
||||
use rustc::ty;
|
||||
use rustc::{bug, span_bug};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -22,6 +20,8 @@ use rustc_data_structures::ptr_key::PtrKey;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability};
|
||||
use rustc_hir::def::{self, PartialRes};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::hygiene::ExpnId;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
|
@ -24,7 +24,6 @@ use rustc::hir::exports::ExportMap;
|
||||
use rustc::hir::map::{DefKey, Definitions};
|
||||
use rustc::lint;
|
||||
use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn};
|
||||
use rustc::session::Session;
|
||||
use rustc::span_bug;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::{self, DefIdTree, ResolverOutputs};
|
||||
@ -39,7 +38,9 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}
|
||||
use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
|
||||
use rustc_hir::{GlobMap, TraitMap};
|
||||
use rustc_metadata::creader::{CStore, CrateLoader};
|
||||
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
|
||||
use rustc_session::node_id::{NodeMap, NodeSet};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
@ -960,7 +961,7 @@ pub struct Resolver<'a> {
|
||||
/// when visiting the correspondent variants.
|
||||
variant_vis: DefIdMap<ty::Visibility>,
|
||||
|
||||
lint_buffer: lint::LintBuffer,
|
||||
lint_buffer: LintBuffer,
|
||||
|
||||
next_node_id: NodeId,
|
||||
}
|
||||
@ -1082,7 +1083,7 @@ impl rustc_ast_lowering::Resolver for Resolver<'_> {
|
||||
&mut self.definitions
|
||||
}
|
||||
|
||||
fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
|
||||
fn lint_buffer(&mut self) -> &mut LintBuffer {
|
||||
&mut self.lint_buffer
|
||||
}
|
||||
|
||||
@ -1241,7 +1242,7 @@ impl<'a> Resolver<'a> {
|
||||
.chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat))
|
||||
.collect(),
|
||||
variant_vis: Default::default(),
|
||||
lint_buffer: lint::LintBuffer::default(),
|
||||
lint_buffer: LintBuffer::default(),
|
||||
next_node_id: NodeId::from_u32(1),
|
||||
}
|
||||
}
|
||||
@ -1256,7 +1257,7 @@ impl<'a> Resolver<'a> {
|
||||
self.next_node_id
|
||||
}
|
||||
|
||||
pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer {
|
||||
pub fn lint_buffer(&mut self) -> &mut LintBuffer {
|
||||
&mut self.lint_buffer
|
||||
}
|
||||
|
||||
@ -1713,10 +1714,10 @@ impl<'a> Resolver<'a> {
|
||||
if let Some(node_id) = poisoned {
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||
node_id, ident.span,
|
||||
node_id,
|
||||
ident.span,
|
||||
&format!("cannot find {} `{}` in this scope", ns.descr(), ident),
|
||||
lint::builtin::BuiltinLintDiagnostics::
|
||||
ProcMacroDeriveResolutionFallback(ident.span),
|
||||
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(ident.span),
|
||||
);
|
||||
}
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
@ -2267,7 +2268,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let diag = lint::builtin::BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
|
||||
let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span);
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
diag_id,
|
||||
@ -2562,9 +2563,10 @@ impl<'a> Resolver<'a> {
|
||||
cannot be referred to by absolute paths";
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
|
||||
CRATE_NODE_ID, span_use, msg,
|
||||
lint::builtin::BuiltinLintDiagnostics::
|
||||
MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
|
||||
CRATE_NODE_ID,
|
||||
span_use,
|
||||
msg,
|
||||
BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy};
|
||||
use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
|
||||
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
|
||||
use rustc::middle::stability;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::session::Session;
|
||||
use rustc::{lint, span_bug, ty};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -23,7 +24,6 @@ use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use syntax::ast::{self, Ident, NodeId};
|
||||
use syntax::attr::{self, StabilityLevel};
|
||||
use syntax::feature_gate::feature_err;
|
||||
use syntax::print::pprust;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
@ -10,6 +10,7 @@ path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
rustc_error_codes = { path = "../librustc_error_codes" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_feature = { path = "../librustc_feature" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
|
@ -1,8 +1,10 @@
|
||||
pub use self::Level::*;
|
||||
use crate::node_id::NodeId;
|
||||
use crate::node_id::{NodeId, NodeMap};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{sym, MultiSpan, Symbol};
|
||||
use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
|
||||
|
||||
pub mod builtin;
|
||||
|
||||
/// Setting for how to handle a lint.
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
|
||||
@ -174,7 +176,25 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores buffered lint info which can later be passed to `librustc`.
|
||||
// This could be a closure, but then implementing derive trait
|
||||
// becomes hacky (and it gets allocated).
|
||||
#[derive(PartialEq)]
|
||||
pub enum BuiltinLintDiagnostics {
|
||||
Normal,
|
||||
BareTraitObject(Span, /* is_global */ bool),
|
||||
AbsPathWithModule(Span),
|
||||
ProcMacroDeriveResolutionFallback(Span),
|
||||
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
|
||||
ElidedLifetimesInPaths(usize, Span, bool, Span, String),
|
||||
UnknownCrateTypes(Span, String, String),
|
||||
UnusedImports(String, Vec<(Span, String)>),
|
||||
RedundantImport(Vec<(Span, bool)>, Ident),
|
||||
DeprecatedMacro(Option<Symbol>, Span),
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
/// `LintLevels` is calculated. These are later passed to `librustc`.
|
||||
#[derive(PartialEq)]
|
||||
pub struct BufferedEarlyLint {
|
||||
/// The span of code that we are linting on.
|
||||
pub span: MultiSpan,
|
||||
@ -183,10 +203,65 @@ pub struct BufferedEarlyLint {
|
||||
pub msg: String,
|
||||
|
||||
/// The `NodeId` of the AST node that generated the lint.
|
||||
pub id: NodeId,
|
||||
pub node_id: NodeId,
|
||||
|
||||
/// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
|
||||
pub lint_id: &'static Lint,
|
||||
pub lint_id: LintId,
|
||||
|
||||
/// Customization of the `DiagnosticBuilder<'_>` for the lint.
|
||||
pub diagnostic: BuiltinLintDiagnostics,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LintBuffer {
|
||||
pub map: NodeMap<Vec<BufferedEarlyLint>>,
|
||||
}
|
||||
|
||||
impl LintBuffer {
|
||||
pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
|
||||
let arr = self.map.entry(early_lint.node_id).or_default();
|
||||
if !arr.contains(&early_lint) {
|
||||
arr.push(early_lint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_lint(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
node_id: NodeId,
|
||||
span: MultiSpan,
|
||||
msg: &str,
|
||||
diagnostic: BuiltinLintDiagnostics,
|
||||
) {
|
||||
let lint_id = LintId::of(lint);
|
||||
let msg = msg.to_string();
|
||||
self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
|
||||
}
|
||||
|
||||
pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
|
||||
self.map.remove(&id).unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn buffer_lint(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
id: NodeId,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: &str,
|
||||
) {
|
||||
self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
|
||||
}
|
||||
|
||||
pub fn buffer_lint_with_diagnostic(
|
||||
&mut self,
|
||||
lint: &'static Lint,
|
||||
id: NodeId,
|
||||
sp: impl Into<MultiSpan>,
|
||||
msg: &str,
|
||||
diagnostic: BuiltinLintDiagnostics,
|
||||
) {
|
||||
self.add_lint(lint, id, sp.into(), msg, diagnostic)
|
||||
}
|
||||
}
|
||||
|
||||
/// Declares a static item of type `&'static Lint`.
|
||||
@ -253,3 +328,41 @@ macro_rules! declare_tool_lint {
|
||||
};
|
||||
);
|
||||
}
|
||||
|
||||
/// Declares a static `LintArray` and return it as an expression.
|
||||
#[macro_export]
|
||||
macro_rules! lint_array {
|
||||
($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
|
||||
($( $lint:expr ),*) => {{
|
||||
vec![$($lint),*]
|
||||
}}
|
||||
}
|
||||
|
||||
pub type LintArray = Vec<&'static Lint>;
|
||||
|
||||
pub trait LintPass {
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// Implements `LintPass for $name` with the given list of `Lint` statics.
|
||||
#[macro_export]
|
||||
macro_rules! impl_lint_pass {
|
||||
($name:ident => [$($lint:expr),* $(,)?]) => {
|
||||
impl $crate::lint::LintPass for $name {
|
||||
fn name(&self) -> &'static str { stringify!($name) }
|
||||
}
|
||||
impl $name {
|
||||
pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Declares a type named `$name` which implements `LintPass`.
|
||||
/// To the right of `=>` a comma separated list of `Lint` statics is given.
|
||||
#[macro_export]
|
||||
macro_rules! declare_lint_pass {
|
||||
($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
|
||||
$(#[$m])* #[derive(Copy, Clone)] pub struct $name;
|
||||
$crate::impl_lint_pass!($name => [$($lint),*]);
|
||||
};
|
||||
}
|
||||
|
@ -4,16 +4,31 @@
|
||||
//! compiler code, rather than using their own custom pass. Those
|
||||
//! lints are all available in `rustc_lint::builtin`.
|
||||
|
||||
use crate::lint::{FutureIncompatibleInfo, LateLintPass, LintArray, LintPass};
|
||||
use crate::middle::stability;
|
||||
use crate::session::Session;
|
||||
use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
|
||||
use rustc_session::declare_lint;
|
||||
use crate::lint::FutureIncompatibleInfo;
|
||||
use crate::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use syntax::ast;
|
||||
use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
|
||||
|
||||
declare_lint! {
|
||||
pub ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
Deny,
|
||||
"ill-formed attribute inputs that were previously accepted and used in practice",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub META_VARIABLE_MISUSE,
|
||||
Allow,
|
||||
"possible meta-variable misuse at macro definition"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INCOMPLETE_INCLUDE,
|
||||
Deny,
|
||||
"trailing content in included file"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub EXCEEDING_BITSHIFTS,
|
||||
@ -513,145 +528,3 @@ declare_lint_pass! {
|
||||
SOFT_UNSTABLE,
|
||||
]
|
||||
}
|
||||
|
||||
// this could be a closure, but then implementing derive traits
|
||||
// becomes hacky (and it gets allocated)
|
||||
#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum BuiltinLintDiagnostics {
|
||||
Normal,
|
||||
BareTraitObject(Span, /* is_global */ bool),
|
||||
AbsPathWithModule(Span),
|
||||
ProcMacroDeriveResolutionFallback(Span),
|
||||
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
|
||||
ElidedLifetimesInPaths(usize, Span, bool, Span, String),
|
||||
UnknownCrateTypes(Span, String, String),
|
||||
UnusedImports(String, Vec<(Span, String)>),
|
||||
RedundantImport(Vec<(Span, bool)>, ast::Ident),
|
||||
DeprecatedMacro(Option<Symbol>, Span),
|
||||
}
|
||||
|
||||
pub fn add_elided_lifetime_in_path_suggestion(
|
||||
sess: &Session,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
n: usize,
|
||||
path_span: Span,
|
||||
incl_angl_brckt: bool,
|
||||
insertion_span: Span,
|
||||
anon_lts: String,
|
||||
) {
|
||||
let (replace_span, suggestion) = if incl_angl_brckt {
|
||||
(insertion_span, anon_lts)
|
||||
} else {
|
||||
// When possible, prefer a suggestion that replaces the whole
|
||||
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
|
||||
// at a point (which makes for an ugly/confusing label)
|
||||
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
|
||||
// But our spans can get out of whack due to macros; if the place we think
|
||||
// we want to insert `'_` isn't even within the path expression's span, we
|
||||
// should bail out of making any suggestion rather than panicking on a
|
||||
// subtract-with-overflow or string-slice-out-out-bounds (!)
|
||||
// FIXME: can we do better?
|
||||
if insertion_span.lo().0 < path_span.lo().0 {
|
||||
return;
|
||||
}
|
||||
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
|
||||
if insertion_index > snippet.len() {
|
||||
return;
|
||||
}
|
||||
let (before, after) = snippet.split_at(insertion_index);
|
||||
(path_span, format!("{}{}{}", before, anon_lts, after))
|
||||
} else {
|
||||
(insertion_span, anon_lts)
|
||||
}
|
||||
};
|
||||
db.span_suggestion(
|
||||
replace_span,
|
||||
&format!("indicate the anonymous lifetime{}", pluralize!(n)),
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
impl BuiltinLintDiagnostics {
|
||||
pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
|
||||
match self {
|
||||
BuiltinLintDiagnostics::Normal => (),
|
||||
BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
|
||||
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
|
||||
Ok(ref s) if is_global => {
|
||||
(format!("dyn ({})", s), Applicability::MachineApplicable)
|
||||
}
|
||||
Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
|
||||
Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
db.span_suggestion(span, "use `dyn`", sugg, app);
|
||||
}
|
||||
BuiltinLintDiagnostics::AbsPathWithModule(span) => {
|
||||
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
|
||||
Ok(ref s) => {
|
||||
// FIXME(Manishearth) ideally the emitting code
|
||||
// can tell us whether or not this is global
|
||||
let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
|
||||
|
||||
(format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
|
||||
}
|
||||
Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
|
||||
};
|
||||
db.span_suggestion(span, "use `crate`", sugg, app);
|
||||
}
|
||||
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
|
||||
db.span_label(
|
||||
span,
|
||||
"names from parent modules are not \
|
||||
accessible without an explicit import",
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
|
||||
db.span_note(span_def, "the macro is defined here");
|
||||
}
|
||||
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
anon_lts,
|
||||
) => {
|
||||
add_elided_lifetime_in_path_suggestion(
|
||||
sess,
|
||||
db,
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
anon_lts,
|
||||
);
|
||||
}
|
||||
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
|
||||
db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect);
|
||||
}
|
||||
BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
|
||||
if !replaces.is_empty() {
|
||||
db.tool_only_multipart_suggestion(
|
||||
&message,
|
||||
replaces,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
|
||||
for (span, is_imported) in spans {
|
||||
let introduced = if is_imported { "imported" } else { "defined" };
|
||||
db.span_label(
|
||||
span,
|
||||
format!("the item `{}` is already {} here", ident, introduced),
|
||||
);
|
||||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
|
||||
stability::deprecation_suggestion(db, suggestion, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}
|
@ -1,15 +1,15 @@
|
||||
//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
|
||||
//! It also serves as an input to the parser itself.
|
||||
|
||||
use crate::lint::BufferedEarlyLint;
|
||||
use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
|
||||
use crate::node_id::NodeId;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::{Lock, Lrc, Once};
|
||||
use rustc_errors::{
|
||||
emitter::SilentEmitter, Applicability, ColorConfig, DiagnosticBuilder, Handler,
|
||||
};
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_error_codes::E0658;
|
||||
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
|
||||
use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
|
||||
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::hygiene::ExpnId;
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
@ -62,6 +62,81 @@ impl GatedSpans {
|
||||
}
|
||||
}
|
||||
|
||||
/// The strenght of a feature gate.
|
||||
/// Either it is a `Hard` error, or only a `Soft` warning.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum GateStrength {
|
||||
/// A hard error. (Most feature gates should use this.)
|
||||
Hard,
|
||||
/// Only a warning. (Use this only as backwards-compatibility demands.)
|
||||
Soft,
|
||||
}
|
||||
|
||||
/// Construct a diagnostic for a language feature error due to the given `span`.
|
||||
/// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
|
||||
pub fn feature_err<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
|
||||
}
|
||||
|
||||
/// Construct a diagnostic for a feature gate error.
|
||||
///
|
||||
/// This variant allows you to control whether it is a library or language feature.
|
||||
/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
|
||||
pub fn feature_err_issue<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
|
||||
}
|
||||
|
||||
/// Construct a diagnostic for a feature gate error / warning.
|
||||
///
|
||||
/// You should typically just use `feature_err` instead.
|
||||
pub fn leveled_feature_err<'a>(
|
||||
sess: &'a ParseSess,
|
||||
feature: Symbol,
|
||||
span: impl Into<MultiSpan>,
|
||||
issue: GateIssue,
|
||||
explain: &str,
|
||||
level: GateStrength,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let diag = &sess.span_diagnostic;
|
||||
|
||||
let mut err = match level {
|
||||
GateStrength::Hard => diag.struct_span_err_with_code(span, explain, error_code!(E0658)),
|
||||
GateStrength::Soft => diag.struct_span_warn(span, explain),
|
||||
};
|
||||
|
||||
if let Some(n) = find_feature_issue(feature, issue) {
|
||||
err.note(&format!(
|
||||
"for more information, see https://github.com/rust-lang/rust/issues/{}",
|
||||
n,
|
||||
));
|
||||
}
|
||||
|
||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||
if sess.unstable_features.is_nightly_build() {
|
||||
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
|
||||
}
|
||||
|
||||
// If we're on stable and only emitting a "soft" warning, add a note to
|
||||
// clarify that the feature isn't "on" (rather than being on but
|
||||
// warning-worthy).
|
||||
if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
|
||||
err.help("a nightly build of the compiler is required to enable this feature");
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
/// Info about a parsing session.
|
||||
pub struct ParseSess {
|
||||
pub span_diagnostic: Handler,
|
||||
@ -123,17 +198,18 @@ impl ParseSess {
|
||||
|
||||
pub fn buffer_lint(
|
||||
&self,
|
||||
lint_id: &'static crate::lint::Lint,
|
||||
lint: &'static Lint,
|
||||
span: impl Into<MultiSpan>,
|
||||
id: NodeId,
|
||||
node_id: NodeId,
|
||||
msg: &str,
|
||||
) {
|
||||
self.buffered_lints.with_lock(|buffered_lints| {
|
||||
buffered_lints.push(BufferedEarlyLint {
|
||||
span: span.into(),
|
||||
id,
|
||||
node_id,
|
||||
msg: msg.into(),
|
||||
lint_id,
|
||||
lint_id: LintId::of(lint),
|
||||
diagnostic: BuiltinLintDiagnostics::Normal,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use crate::namespace::Namespace;
|
||||
use crate::require_c_abi_if_c_variadic;
|
||||
use crate::util::common::ErrorReported;
|
||||
use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::traits;
|
||||
use rustc::traits::astconv_object_safety_violations;
|
||||
use rustc::traits::error_reporting::report_object_safety_error;
|
||||
@ -30,7 +31,6 @@ use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi;
|
||||
use smallvec::SmallVec;
|
||||
use syntax::ast;
|
||||
use syntax::feature_gate::feature_err;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
@ -53,6 +53,7 @@
|
||||
use crate::check::{FnCtxt, Needs};
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::infer::{Coercion, InferOk, InferResult};
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
use rustc::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
|
||||
@ -62,6 +63,7 @@ use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::relate::RelateResult;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, Ty, TypeAndMut};
|
||||
use rustc_error_codes::*;
|
||||
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -70,9 +72,6 @@ use rustc_span::symbol::sym;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::ops::Deref;
|
||||
use syntax::feature_gate;
|
||||
|
||||
use rustc_error_codes::*;
|
||||
|
||||
struct Coerce<'a, 'tcx> {
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
@ -627,7 +626,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
}
|
||||
|
||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
||||
feature_gate::feature_err(
|
||||
feature_err(
|
||||
&self.tcx.sess.parse_sess,
|
||||
sym::unsized_tuple_coercion,
|
||||
self.cause.span,
|
||||
|
@ -99,6 +99,7 @@ use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc::infer::{self, InferCtxt, InferOk, InferResult};
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::traits::error_reporting::recursive_type_with_infinite_size_error;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::adjustment::{
|
||||
@ -130,7 +131,6 @@ use rustc_span::{self, BytePos, MultiSpan, Span};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::feature_gate::feature_err;
|
||||
use syntax::util::parser::ExprPrecedence;
|
||||
|
||||
use rustc_error_codes::*;
|
||||
|
@ -3,6 +3,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
|
||||
|
||||
use rustc::infer::opaque_types::may_define_opaque_type;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
use rustc::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||
@ -13,7 +14,6 @@ use rustc_hir::ItemKind;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use syntax::ast;
|
||||
use syntax::feature_gate;
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
|
||||
@ -821,7 +821,7 @@ fn check_method_receiver<'fcx, 'tcx>(
|
||||
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
|
||||
if receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
|
||||
// Report error; would have worked with `arbitrary_self_types`.
|
||||
feature_gate::feature_err(
|
||||
feature_err(
|
||||
&fcx.tcx.sess.parse_sess,
|
||||
sym::arbitrary_self_types,
|
||||
span,
|
||||
|
@ -23,6 +23,7 @@ use crate::middle::weak_lang_items;
|
||||
use rustc::hir::map::Map;
|
||||
use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc::mir::mono::Linkage;
|
||||
use rustc::session::parse::feature_err;
|
||||
use rustc::traits;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::GenericArgKind;
|
||||
@ -45,7 +46,6 @@ use rustc_target::spec::abi;
|
||||
use syntax::ast;
|
||||
use syntax::ast::{Ident, MetaItemKind};
|
||||
use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
|
||||
use syntax::feature_gate;
|
||||
|
||||
use rustc_error_codes::*;
|
||||
|
||||
@ -1537,7 +1537,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
_ => None,
|
||||
};
|
||||
if let Some(unsupported_type) = err {
|
||||
feature_gate::feature_err(
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::const_compare_raw_pointers,
|
||||
hir_ty.span,
|
||||
@ -2633,7 +2633,7 @@ fn from_target_feature(
|
||||
None => true,
|
||||
};
|
||||
if !allowed && id.is_local() {
|
||||
feature_gate::feature_err(
|
||||
feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
feature_gate.unwrap(),
|
||||
item.span(),
|
||||
|
@ -2,9 +2,8 @@
|
||||
|
||||
use super::{mark_used, MetaItemKind};
|
||||
use crate::ast::{self, Attribute, MetaItem, NestedMetaItem};
|
||||
use crate::feature_gate::feature_err;
|
||||
use crate::print::pprust;
|
||||
use crate::sess::ParseSess;
|
||||
use crate::sess::{feature_err, ParseSess};
|
||||
|
||||
use rustc_errors::{struct_span_err, Applicability, Handler};
|
||||
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
|
||||
|
@ -1,30 +0,0 @@
|
||||
//! Allows the buffering of lints for later.
|
||||
//!
|
||||
//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
|
||||
//! redundant. Later, these types can be converted to types for use by the rest of the compiler.
|
||||
|
||||
use rustc_session::declare_lint;
|
||||
pub use rustc_session::lint::BufferedEarlyLint;
|
||||
use rustc_session::lint::FutureIncompatibleInfo;
|
||||
|
||||
declare_lint! {
|
||||
pub ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
Deny,
|
||||
"ill-formed attribute inputs that were previously accepted and used in practice",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub META_VARIABLE_MISUSE,
|
||||
Allow,
|
||||
"possible meta-variable misuse at macro definition"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INCOMPLETE_INCLUDE,
|
||||
Deny,
|
||||
"trailing content in included file"
|
||||
}
|
@ -75,13 +75,8 @@ pub mod ast;
|
||||
pub mod attr;
|
||||
pub mod entry;
|
||||
pub mod expand;
|
||||
pub mod feature_gate {
|
||||
mod check;
|
||||
pub use check::{check_attribute, check_crate, feature_err, feature_err_issue, get_features};
|
||||
}
|
||||
pub mod mut_visit;
|
||||
pub mod ptr;
|
||||
pub mod show_span;
|
||||
pub use rustc_session::parse as sess;
|
||||
pub mod token;
|
||||
pub mod tokenstream;
|
||||
@ -93,8 +88,6 @@ pub mod print {
|
||||
pub mod pprust;
|
||||
}
|
||||
|
||||
pub mod early_buffered_lints;
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
|
@ -6,9 +6,8 @@
|
||||
extern crate rustc;
|
||||
extern crate rustc_session;
|
||||
|
||||
use rustc::lint::{LintArray, LintPass};
|
||||
use rustc::{declare_lint_pass, impl_lint_pass};
|
||||
use rustc_session::declare_lint;
|
||||
use rustc_session::lint::{LintArray, LintPass};
|
||||
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
|
||||
|
||||
declare_lint! {
|
||||
pub TEST_LINT,
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: implementing `LintPass` by hand
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:21:6
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:20:6
|
||||
|
|
||||
LL | impl LintPass for Foo {
|
||||
| ^^^^^^^^
|
||||
@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)]
|
||||
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||
|
||||
error: implementing `LintPass` by hand
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:31:14
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:30:14
|
||||
|
|
||||
LL | impl LintPass for Custom {
|
||||
| ^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user