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:
Mazdak Farrokhzad 2020-01-11 04:02:22 +01:00 committed by GitHub
commit 9634e1f7d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 711 additions and 679 deletions

View File

@ -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",

View File

@ -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, &note, 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();
}

View File

@ -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};

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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),
)
}
}

View File

@ -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,

View 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" }

View File

@ -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,

View File

@ -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,

View 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;

View File

@ -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,

View File

@ -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" }

View File

@ -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;

View File

@ -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" }

View File

@ -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

View File

@ -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.

View File

@ -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" }

View File

@ -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);
}
});

View File

@ -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),

View File

@ -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;

View File

@ -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::*;

View File

@ -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),*);

View File

@ -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),*);

View File

@ -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;

View File

@ -1,4 +1,4 @@
use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc::lint::{EarlyContext, EarlyLintPass, LintContext};
use syntax::ast;
declare_lint! {

View File

@ -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;

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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() };

View File

@ -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;

View File

@ -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};

View File

@ -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"

View File

@ -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,

View File

@ -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) {

View File

@ -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" }

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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),
);
}
}

View File

@ -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};

View File

@ -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),
);
}

View File

@ -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;

View File

@ -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" }

View File

@ -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),*]);
};
}

View File

@ -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, &note, 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 {}

View File

@ -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,
});
});
}

View File

@ -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;

View File

@ -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,

View File

@ -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::*;

View File

@ -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,

View File

@ -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(),

View File

@ -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};

View File

@ -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"
}

View 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.

View File

@ -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,

View File

@ -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 {
| ^^^^^^^^