diff --git a/Cargo.lock b/Cargo.lock index 680a454fb68ea..54ad60e71506b 100644 --- a/Cargo.lock +++ b/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", diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 944df66431fe8..110c8b844d54c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -493,9 +493,13 @@ impl Config { config.mandir = install.mandir.clone().map(PathBuf::from); } + // We want the llvm-skip-rebuild flag to take precedence over the + // skip-rebuild config.toml option so we store it separately + // so that we can infer the right value + let mut llvm_skip_rebuild = flags.llvm_skip_rebuild; + // Store off these values as options because if they're not provided // we'll infer default values for them later - let mut llvm_skip_rebuild = None; let mut llvm_assertions = None; let mut debug = None; let mut debug_assertions = None; @@ -517,7 +521,7 @@ impl Config { } set(&mut config.ninja, llvm.ninja); llvm_assertions = llvm.assertions; - llvm_skip_rebuild = llvm.skip_rebuild; + llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild); set(&mut config.llvm_optimize, llvm.optimize); set(&mut config.llvm_thin_lto, llvm.thin_lto); set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index ffc24367db6e9..1fbdd50a51133 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -38,6 +38,8 @@ pub struct Flags { // // true => deny, false => warn pub deny_warnings: Option, + + pub llvm_skip_rebuild: Option, } pub enum Subcommand { @@ -150,6 +152,14 @@ To learn more about a subcommand, run `./x.py -h`", "VALUE", ); opts.optopt("", "error-format", "rustc error format", "FORMAT"); + opts.optopt( + "", + "llvm-skip-rebuild", + "whether rebuilding llvm should be skipped \ + a VALUE of TRUE indicates that llvm will not be rebuilt \ + VALUE overrides the skip-rebuild option in config.toml.", + "VALUE", + ); // fn usage() let usage = @@ -487,6 +497,9 @@ Arguments: .map(|p| p.into()) .collect::>(), deny_warnings: parse_deny_warnings(&matches), + llvm_skip_rebuild: matches.opt_str("llvm-skip-rebuild").map(|s| s.to_lowercase()).map( + |s| s.parse::().expect("`llvm-skip-rebuild` should be either true or false"), + ), } } } diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 2098404ee1b9d..9d3fe5254f8a9 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -63,7 +63,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { pub unsafe fn panic(data: Box) -> u32 { let sz = mem::size_of_val(&data); let exception = __cxa_allocate_exception(sz); - if exception == ptr::null_mut() { + if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } ptr::write(exception as *mut _, data); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index bd561b41c57f5..3f18f4dbd1fe7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -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` 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 ".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::".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(); } diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 7b99b4af4f9ab..30679226b9b71 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -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}; diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 6ca98b44bf80c..e586ad1836c73 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -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, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index a8c1f9a664f18..4afeb14494850 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -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>, -} - -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 { - self.map.remove(&id).unwrap_or_default() - } - - pub fn buffer_lint>( - &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>( - &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, diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 93c23e40d2e2b..17e84c24881c1 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -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, lint: &'static Lint, diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 527aa6796bc22..58b8e8a089ad3 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -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); - fn lint_buffer(&mut self) -> &mut lint::LintBuffer; + fn lint_buffer(&mut self) -> &mut LintBuffer; fn next_node_id(&mut self) -> NodeId; } @@ -268,7 +268,7 @@ pub fn lower_crate<'a, 'hir>( // incr. comp. yet. dep_graph.assert_ignored(); - let _prof_timer = sess.prof.generic_activity("hir_lowering"); + let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); LoweringContext { crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), @@ -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), ) } } diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index 9b504704ae06c..65347d379bd6a 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -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, diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml new file mode 100644 index 0000000000000..dced4a0d15b0c --- /dev/null +++ b/src/librustc_ast_passes/Cargo.toml @@ -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" } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs similarity index 99% rename from src/librustc_passes/ast_validation.rs rename to src/librustc_ast_passes/ast_validation.rs index be58a790fa878..c915b7ba21692 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -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, diff --git a/src/libsyntax/feature_gate/check.rs b/src/librustc_ast_passes/feature_gate.rs similarity index 75% rename from src/libsyntax/feature_gate/check.rs rename to src/librustc_ast_passes/feature_gate.rs index 4eee4e943c2cd..1e396d6fe8e47 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -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, - 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, - 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, - 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>, -) -> 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 { - 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, diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs new file mode 100644 index 0000000000000..eadbc485296e8 --- /dev/null +++ b/src/librustc_ast_passes/lib.rs @@ -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; diff --git a/src/libsyntax/show_span.rs b/src/librustc_ast_passes/show_span.rs similarity index 96% rename from src/libsyntax/show_span.rs rename to src/librustc_ast_passes/show_span.rs index b70e2ce0d3eb7..4596e8ff53dde 100644 --- a/src/libsyntax/show_span.rs +++ b/src/librustc_ast_passes/show_span.rs @@ -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, diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml index ca57068fb9a33..f291eaf93580b 100644 --- a/src/librustc_builtin_macros/Cargo.toml +++ b/src/librustc_builtin_macros/Cargo.toml @@ -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" } diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs index c96ba516f0ced..a992b6e2662d2 100644 --- a/src/librustc_builtin_macros/assert.rs +++ b/src/librustc_builtin_macros/assert.rs @@ -106,7 +106,7 @@ fn parse_assert<'a>( let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind { let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal"); - let comma_span = cx.source_map().next_point(parser.prev_span); + let comma_span = parser.prev_span.shrink_to_hi(); err.span_suggestion_short( comma_span, "try adding a comma", diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 19a766de1f47f..dc85a92d272c4 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -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; diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 17582862c4d6a..53ee5996432ce 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -53,6 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( crate_name: &str, target_cpu: &str, ) { + let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); for &crate_type in sess.crate_types.borrow().iter() { // Ignore executable crates if we have -Z no-codegen, as they will error. @@ -71,9 +72,11 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( ); } - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - check_file_is_writeable(obj, sess); - } + sess.time("link_binary_check_files_are_writeable", || { + for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { + check_file_is_writeable(obj, sess); + } + }); let tmpdir = TempFileBuilder::new() .prefix("rustc") @@ -84,6 +87,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( let out_filename = out_filename(sess, crate_type, outputs, crate_name); match crate_type { config::CrateType::Rlib => { + let _timer = sess.timer("link_rlib"); link_rlib::( sess, codegen_results, @@ -118,29 +122,34 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } // Remove the temporary object file and metadata if we aren't saving temps - if !sess.opts.cg.save_temps { - if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) { - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - remove(sess, obj); + sess.time("link_binary_remove_temps", || { + if !sess.opts.cg.save_temps { + if sess.opts.output_types.should_codegen() + && !preserve_objects_for_their_debuginfo(sess) + { + for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { + remove(sess, obj); + } } - } - for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) { - remove(sess, obj); - } - if let Some(ref metadata_module) = codegen_results.metadata_module { - if let Some(ref obj) = metadata_module.object { + for obj in codegen_results.modules.iter().filter_map(|m| m.bytecode_compressed.as_ref()) + { remove(sess, obj); } - } - if let Some(ref allocator_module) = codegen_results.allocator_module { - if let Some(ref obj) = allocator_module.object { - remove(sess, obj); + if let Some(ref metadata_module) = codegen_results.metadata_module { + if let Some(ref obj) = metadata_module.object { + remove(sess, obj); + } } - if let Some(ref bc) = allocator_module.bytecode_compressed { - remove(sess, bc); + if let Some(ref allocator_module) = codegen_results.allocator_module { + if let Some(ref obj) = allocator_module.object { + remove(sess, obj); + } + if let Some(ref bc) = allocator_module.bytecode_compressed { + remove(sess, bc); + } } } - } + }); } // The third parameter is for env vars, used on windows to set up the diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 1ce0a29d55d9d..4d09e23ee7f7a 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -479,6 +479,8 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( return work_products; } + let _timer = sess.timer("incr_comp_copy_cgu_workproducts"); + for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { let mut files = vec![]; @@ -1714,8 +1716,11 @@ pub struct OngoingCodegen { impl OngoingCodegen { pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap) { + let _timer = sess.timer("finish_ongoing_codegen"); + self.shared_emitter_main.check(sess, true); - let compiled_modules = match self.future.join() { + let future = self.future; + let compiled_modules = sess.time("join_worker_thread", || match future.join() { Ok(Ok(compiled_modules)) => compiled_modules, Ok(Err(())) => { sess.abort_if_errors(); @@ -1724,7 +1729,7 @@ impl OngoingCodegen { Err(_) => { bug!("panic during codegen/LLVM phase"); } - }; + }); sess.cgu_reuse_tracker.check_expected_reuse(sess.diagnostic()); diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index e8a70d58f0cff..8deb43d50f938 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -495,6 +495,12 @@ impl<'a> TimingGuard<'a> { pub fn none() -> TimingGuard<'a> { TimingGuard(None) } + + #[inline(always)] + pub fn run(self, f: impl FnOnce() -> R) -> R { + let _timer = self; + f() + } } #[must_use] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a1318d3506711..3d31f240a34e0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -389,6 +389,7 @@ pub fn run_compiler( })?; } else { // Drop AST after creating GlobalCtxt to free memory + let _timer = sess.prof.generic_activity("drop_ast"); mem::drop(queries.expansion()?.take()); } @@ -413,6 +414,7 @@ pub fn run_compiler( })?; if let Some(linker) = linker { + let _timer = sess.timer("link"); linker.link()? } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 99a6d6f8ec2d4..e24e8719133a9 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -182,7 +182,7 @@ impl CodeSuggestion { // Find the bounding span. let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap(); - let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap(); + let hi = substitution.parts.iter().map(|part| part.span.hi()).max().unwrap(); let bounding_span = Span::with_root_ctxt(lo, hi); let lines = cm.span_to_lines(bounding_span).unwrap(); assert!(!lines.lines.is_empty()); diff --git a/src/librustc_expand/Cargo.toml b/src/librustc_expand/Cargo.toml index c23846063c1dc..d04dd079be75d 100644 --- a/src/librustc_expand/Cargo.toml +++ b/src/librustc_expand/Cargo.toml @@ -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" } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 8426391a2f389..3254d0c913da3 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -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 diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs index 992764ab6a41d..47865b2fb9fc3 100644 --- a/src/librustc_expand/mbe/macro_check.rs +++ b/src/librustc_expand/mbe/macro_check.rs @@ -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. diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 441c1b75a7c73..246f66084b813 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -696,7 +696,7 @@ pub(super) fn parse( if parser.token.span.is_dummy() { parser.token.span } else { - sess.source_map().next_point(parser.token.span) + parser.token.span.shrink_to_hi() }, ), "missing tokens in macro arguments", diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index adf8f57f01d08..ba20006d73ccc 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -190,6 +190,8 @@ pub fn prepare_session_directory( return; } + let _timer = sess.timer("incr_comp_prepare_session_directory"); + debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} @@ -306,6 +308,8 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { return; } + let _timer = sess.timer("incr_comp_finalize_session_directory"); + let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone(); if sess.has_errors_or_delayed_span_bugs() { diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 0732ddd3261a4..6c57f79e1a7fb 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -102,6 +102,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() }); } + let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph"); + // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. let path = dep_graph_path_from(&sess.incr_comp_session_dir()); diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index be60b75bc47eb..eb0551c606548 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -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" } diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index c4449945dd19d..d00875f6fee88 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -177,11 +177,17 @@ pub fn run_compiler_in_existing_thread_pool( override_queries: config.override_queries, }; - let _sess_abort_error = OnDrop(|| { - compiler.sess.diagnostic().print_error_count(registry); - }); + let r = { + let _sess_abort_error = OnDrop(|| { + compiler.sess.diagnostic().print_error_count(registry); + }); - f(&compiler) + f(&compiler) + }; + + let prof = compiler.sess.prof.clone(); + prof.generic_activity("drop_compiler").run(move || drop(compiler)); + r } pub fn run_compiler(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a7e174f04553c..9119466cbc048 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -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); } }); @@ -611,6 +610,8 @@ pub fn prepare_outputs( boxed_resolver: &Steal>>, crate_name: &str, ) -> Result { + let _timer = sess.timer("prepare_outputs"); + // FIXME: rustdoc passes &[] instead of &krate.attrs here let outputs = util::build_output_filenames( &compiler.input, @@ -734,20 +735,22 @@ pub fn create_global_ctxt<'tcx>( callback(sess, &mut local_providers, &mut extern_providers); } - let gcx = global_ctxt.init_locking(|| { - TyCtxt::create_global_ctxt( - sess, - lint_store, - local_providers, - extern_providers, - &all_arenas, - arena, - resolver_outputs, - hir_map, - query_result_on_disk_cache, - &crate_name, - &outputs, - ) + let gcx = sess.time("setup_global_ctxt", || { + global_ctxt.init_locking(|| { + TyCtxt::create_global_ctxt( + sess, + lint_store, + local_providers, + extern_providers, + &all_arenas, + arena, + resolver_outputs, + hir_map, + query_result_on_disk_cache, + &crate_name, + &outputs, + ) + }) }); // Do some initialization of the DepGraph that can only be done with the tcx available. diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 6033569d765b4..7de1c36ce4b2e 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -176,6 +176,7 @@ impl<'tcx> Queries<'tcx> { self.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let (krate, lint_store) = self.register_plugins()?.take(); + let _timer = self.session().timer("configure_and_expand"); passes::configure_and_expand( self.session().clone(), lint_store.clone(), @@ -256,6 +257,7 @@ impl<'tcx> Queries<'tcx> { let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?.peek(); let (ref hir_forest, ref resolver_outputs) = &*hir; + let _timer = self.session().timer("create_global_ctxt"); Ok(passes::create_global_ctxt( self.compiler, lint_store, @@ -312,14 +314,19 @@ pub struct Linker { impl Linker { pub fn link(self) -> Result<()> { - self.codegen_backend + let r = self + .codegen_backend .join_codegen_and_link( self.ongoing_codegen, &self.sess, &self.dep_graph, &self.prepare_outputs, ) - .map_err(|_| ErrorReported) + .map_err(|_| ErrorReported); + let prof = self.sess.prof.clone(); + let dep_graph = self.dep_graph; + prof.generic_activity("drop_dep_graph").run(move || drop(dep_graph)); + r } } @@ -328,6 +335,7 @@ impl Compiler { where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T, { + let mut _timer = None; let queries = Queries::new(&self); let ret = f(&queries); @@ -337,6 +345,8 @@ impl Compiler { } } + _timer = Some(self.session().timer("free_global_ctxt")); + ret } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8e381a27b414f..2fafd3af7a5ff 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -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::()) } -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), diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs index d8ddf7435b458..19d1052d1b243 100644 --- a/src/librustc_lint/array_into_iter.rs +++ b/src/librustc_lint/array_into_iter.rs @@ -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; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 25f6361e0507d..befeb84e57c9c 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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::*; diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index 67c0c98b20380..9a90171985158 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -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),*); diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 07c3b95d69972..d8e0274cf43b9 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -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),*); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index e272c3af46824..e708ded603b25 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -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; diff --git a/src/librustc_lint/non_ascii_idents.rs b/src/librustc_lint/non_ascii_idents.rs index f30d0bcbdd53f..522aeb6b14420 100644 --- a/src/librustc_lint/non_ascii_idents.rs +++ b/src/librustc_lint/non_ascii_idents.rs @@ -1,4 +1,4 @@ -use crate::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintContext}; use syntax::ast; declare_lint! { diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 7e5ad0976989e..f75bb9ba32c3d 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -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; diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs index 9fc147f2a0c5a..dc18f15fe40cb 100644 --- a/src/librustc_lint/redundant_semicolon.rs +++ b/src/librustc_lint/redundant_semicolon.rs @@ -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}; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f128e25f35bf2..ab6841c0c09bc 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -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; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d57f565d919be..da8a23f041e58 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -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; diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index ae67efb966c96..9426d5e26f5e5 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -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 { let mut collector = Collector { tcx, libs: Vec::new() }; diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index ce0c081bc1608..0e9d16cfa56a8 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -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; diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index abef008a8eccb..edb4eb4d7c344 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -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}; @@ -350,16 +350,18 @@ impl NonConstOp for StaticAccess { item.tcx.sess, span, E0013, - "{}s cannot refer to statics, use \ - a constant instead", + "{}s cannot refer to statics", item.const_kind() ); + err.help( + "consider extracting the value of the `static` to a `const`, and referring to that", + ); if item.tcx.sess.teach(&err.get_code().unwrap()) { err.note( - "Static and const variables can refer to other const variables. \ - But a const variable cannot refer to a static variable.", + "`static` and `const` variables can refer to other `const` variables. \ + A `const` variable, however, cannot refer to a `static` variable.", ); - err.help("To fix this, the value can be extracted as a const and then used."); + err.help("To fix this, the value can be extracted to a `const` and then used."); } err.emit(); } diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml index d41d89902efcd..aa159c55ff284 100644 --- a/src/librustc_parse/Cargo.toml +++ b/src/librustc_parse/Cargo.toml @@ -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" diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index f2ffd9470ed76..8467acc759c2b 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -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>, +) -> 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 { + 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, diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index d321383424cab..a5056c1665e30 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -259,10 +259,7 @@ impl<'a> Parser<'a> { }; ( format!("expected one of {}, found {}", expect, actual), - ( - self.sess.source_map().next_point(self.prev_span), - format!("expected one of {}", short_expect), - ), + (self.prev_span.shrink_to_hi(), format!("expected one of {}", short_expect)), ) } else if expected.is_empty() { ( @@ -272,7 +269,7 @@ impl<'a> Parser<'a> { } else { ( format!("expected {}, found {}", expect, actual), - (self.sess.source_map().next_point(self.prev_span), format!("expected {}", expect)), + (self.prev_span.shrink_to_hi(), format!("expected {}", expect)), ) }; self.last_unexpected_token_span = Some(self.token.span); @@ -803,7 +800,7 @@ impl<'a> Parser<'a> { _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span), // EOF, don't want to point at the following char, but rather the last token. (token::Eof, None) => (self.prev_span, self.token.span), - _ => (self.sess.source_map().next_point(self.prev_span), self.token.span), + _ => (self.prev_span.shrink_to_hi(), self.token.span), }; let msg = format!( "expected `{}`, found {}", @@ -1126,7 +1123,7 @@ impl<'a> Parser<'a> { err.span_label(sp, "unclosed delimiter"); } err.span_suggestion_short( - self.sess.source_map().next_point(self.prev_span), + self.prev_span.shrink_to_hi(), &format!("{} may belong here", delim.to_string()), delim.to_string(), Applicability::MaybeIncorrect, diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 2d6a94ce620cf..b0c78ad7e4bcc 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1645,7 +1645,7 @@ impl<'a> Parser<'a> { // | | // | parsed until here as `"y" & X` err.span_suggestion_short( - cm.next_point(arm_start_span), + arm_start_span.shrink_to_hi(), "missing a comma here to end this `match` arm", ",".to_owned(), Applicability::MachineApplicable, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f6199da3f1d83..d4756dff49a9d 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1510,7 +1510,7 @@ impl<'a> Parser<'a> { } } _ => { - let sp = self.sess.source_map().next_point(self.prev_span); + let sp = self.prev_span.shrink_to_hi(); let mut err = self.struct_span_err( sp, &format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), @@ -1649,7 +1649,7 @@ impl<'a> Parser<'a> { // it's safe to peel off one character only when it has the close delim self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)) } else { - self.sess.source_map().next_point(self.prev_span) + self.prev_span.shrink_to_hi() }; self.struct_span_err( @@ -1665,7 +1665,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ) .span_suggestion( - self.sess.source_map().next_point(self.prev_span), + self.prev_span.shrink_to_hi(), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 8d695eda98d04..a1035d320b31c 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -765,7 +765,7 @@ impl<'a> Parser<'a> { break; } Err(mut expect_err) => { - let sp = self.sess.source_map().next_point(self.prev_span); + let sp = self.prev_span.shrink_to_hi(); let token_str = pprust::token_kind_to_string(t); // Attempt to keep parsing if it was a similar separator. diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index f089361220777..84562fbb46ff2 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -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) { diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 4adc6dabb9fdb..639d8639c4bb2 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -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" } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index a2944918a4748..39ba2fbc63b43 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -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; diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index f128d3891d7b8..65eb07b989d83 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -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; diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 588386e6f8d69..af37d218d68f0 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -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; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index a96d59340237d..70d4841ec244b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -652,6 +652,9 @@ impl EmbargoVisitor<'tcx> { if let Some(item) = module .res .and_then(|res| res.mod_def_id()) + // If the module is `self`, i.e. the current crate, + // there will be no corresponding item. + .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE) .and_then(|def_id| self.tcx.hir().as_local_hir_id(def_id)) .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) { diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index d6f365fce7929..4a6df92d82260 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -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), ); } } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 813e6ac96911e..8fe17e89444cd 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -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}; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e6be9f6d328c0..8e4630cf7d696 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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, - 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), ); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 1103d5b5b7c97..85b5d8ef1cb5d 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -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; diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml index 47c23bc4dcf98..377ea141ed57c 100644 --- a/src/librustc_session/Cargo.toml +++ b/src/librustc_session/Cargo.toml @@ -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" } diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs index 0cce7e848fd60..2ba3932c7d97e 100644 --- a/src/librustc_session/lint.rs +++ b/src/librustc_session/lint.rs @@ -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 ToStableHashKey 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, 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>, +} + +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 { + self.map.remove(&id).unwrap_or_default() + } + + pub fn buffer_lint( + &mut self, + lint: &'static Lint, + id: NodeId, + sp: impl Into, + 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, + 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),*]); + }; +} diff --git a/src/librustc/lint/builtin.rs b/src/librustc_session/lint/builtin.rs similarity index 67% rename from src/librustc/lint/builtin.rs rename to src/librustc_session/lint/builtin.rs index f5845dcae1288..3e8503ef661f0 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -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 ", + 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, 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` 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 ".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::".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 {} diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 6cc6a1ec276ca..946e77d35595e 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -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, + 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, + 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, + 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, - 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, }); }); } diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index ec1f9f3a7bdaf..fb5fcf4a8303b 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -710,7 +710,7 @@ impl SourceMap { pub fn next_point(&self, sp: Span) -> Span { let start_of_next_point = sp.hi().0; - let width = self.find_width_of_character_at_span(sp, true); + let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true); // If the width is 1, then the next span should point to the same `lo` and `hi`. However, // in the case of a multibyte character, where the width != 1, the next span should // span multiple bytes to include the whole character. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 851c2f76adab7..c15bcd81443d6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index bff6765314ab8..58f407b890278 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -240,7 +240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) = (parent_node, callee_node) { let start = sp.shrink_to_lo(); - let end = self.tcx.sess.source_map().next_point(callee_span); + let end = callee_span.shrink_to_hi(); err.multipart_suggestion( "if you meant to create this closure and immediately call it, surround the \ closure with parenthesis", @@ -317,9 +317,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span); if call_is_multiline { - let span = self.tcx.sess.source_map().next_point(callee.span); err.span_suggestion( - span, + callee.span.shrink_to_hi(), "try adding a semicolon", ";".to_owned(), Applicability::MaybeIncorrect, diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index feab31523f265..1afb703ca1506 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -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, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 32225cd417f2d..92a7e18a8600f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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::*; @@ -4952,9 +4952,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ExprKind::Loop(..) | ExprKind::Match(..) | ExprKind::Block(..) => { - let sp = self.tcx.sess.source_map().next_point(cause_span); err.span_suggestion( - sp, + cause_span.shrink_to_hi(), "try adding a semicolon", ";".to_string(), Applicability::MachineApplicable, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index df1eecdcfa8c5..a496a6e12ce1a 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64e71cc42e0ca..ad750d5ab8341 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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(), diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 1407fe2771553..b480581e21ba9 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -250,6 +250,7 @@ impl From for Box { /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` + #[inline] fn from(err: String) -> Box { struct StringError(String); @@ -317,6 +318,7 @@ impl<'a> From<&str> for Box { /// assert!( /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` + #[inline] fn from(err: &str) -> Box { From::from(String::from(err)) } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 4c308327b83b7..77da97219b147 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -615,6 +615,7 @@ impl OsStr { /// assert!(!os_str.is_empty()); /// ``` #[stable(feature = "osstring_simple_functions", since = "1.9.0")] + #[inline] pub fn is_empty(&self) -> bool { self.inner.inner.is_empty() } @@ -965,6 +966,7 @@ impl AsRef for OsStr { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for OsString { + #[inline] fn as_ref(&self) -> &OsStr { self } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index fbbdc1ddac297..a703cb748e06b 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1475,6 +1475,7 @@ impl From for PathBuf { /// Converts a `OsString` into a `PathBuf` /// /// This conversion does not allocate or copy memory. + #[inline] fn from(s: OsString) -> PathBuf { PathBuf { inner: s } } @@ -1535,7 +1536,7 @@ impl fmt::Debug for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for PathBuf { type Target = Path; - + #[inline] fn deref(&self) -> &Path { Path::new(&self.inner) } @@ -2655,6 +2656,7 @@ impl AsRef for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for str { + #[inline] fn as_ref(&self) -> &Path { Path::new(self) } @@ -2669,6 +2671,7 @@ impl AsRef for String { #[stable(feature = "rust1", since = "1.0.0")] impl AsRef for PathBuf { + #[inline] fn as_ref(&self) -> &Path { self } diff --git a/src/libstd/sys/hermit/os.rs b/src/libstd/sys/hermit/os.rs index 5999fdd4f8d58..78eabf8f81e98 100644 --- a/src/libstd/sys/hermit/os.rs +++ b/src/libstd/sys/hermit/os.rs @@ -6,7 +6,6 @@ use crate::io; use crate::marker::PhantomData; use crate::memchr; use crate::path::{self, PathBuf}; -use crate::ptr; use crate::str; use crate::sync::Mutex; use crate::sys::hermit::abi; @@ -77,13 +76,17 @@ pub fn init_environment(env: *const *const i8) { unsafe { ENV = Some(Mutex::new(HashMap::new())); + if env.is_null() { + return; + } + let mut guard = ENV.as_ref().unwrap().lock().unwrap(); let mut environ = env; - while environ != ptr::null() && *environ != ptr::null() { + while !(*environ).is_null() { if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) { guard.insert(key, value); } - environ = environ.offset(1); + environ = environ.add(1); } } diff --git a/src/libstd/sys/hermit/thread_local.rs b/src/libstd/sys/hermit/thread_local.rs index ba967c7676c3f..c6f8adb21623a 100644 --- a/src/libstd/sys/hermit/thread_local.rs +++ b/src/libstd/sys/hermit/thread_local.rs @@ -18,14 +18,14 @@ static KEYS_LOCK: Mutex = Mutex::new(); static mut LOCALS: *mut BTreeMap = ptr::null_mut(); unsafe fn keys() -> &'static mut BTreeMap> { - if KEYS == ptr::null_mut() { + if KEYS.is_null() { KEYS = Box::into_raw(Box::new(BTreeMap::new())); } &mut *KEYS } unsafe fn locals() -> &'static mut BTreeMap { - if LOCALS == ptr::null_mut() { + if LOCALS.is_null() { LOCALS = Box::into_raw(Box::new(BTreeMap::new())); } &mut *LOCALS diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs index 81a766e367d6e..2b0485c4f0363 100644 --- a/src/libstd/sys/sgx/abi/tls.rs +++ b/src/libstd/sys/sgx/abi/tls.rs @@ -70,7 +70,7 @@ impl<'a> Drop for ActiveTls<'a> { any_non_null_dtor = false; for (value, dtor) in TLS_KEY_IN_USE.iter().filter_map(&value_with_destructor) { let value = value.replace(ptr::null_mut()); - if value != ptr::null_mut() { + if !value.is_null() { any_non_null_dtor = true; unsafe { dtor(value) } } diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index b277b3d5899b8..91f7d1524ccef 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -480,11 +480,13 @@ pub fn env() -> Env { let _guard = env_lock(); let mut environ = *environ(); let mut result = Vec::new(); - while environ != ptr::null() && *environ != ptr::null() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); } - environ = environ.offset(1); } return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; } diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs index d421915449944..1fadf71613561 100644 --- a/src/libstd/sys/vxworks/os.rs +++ b/src/libstd/sys/vxworks/os.rs @@ -7,7 +7,6 @@ use crate::marker::PhantomData; use crate::mem; use crate::memchr; use crate::path::{self, Path, PathBuf}; -use crate::ptr; use crate::slice; use crate::str; use crate::sys::cvt; @@ -226,15 +225,15 @@ pub fn env() -> Env { unsafe { let _guard = env_lock(); let mut environ = *environ(); - if environ == ptr::null() { + if environ.is_null() { panic!("os::env() failure getting env string from OS: {}", io::Error::last_os_error()); } let mut result = Vec::new(); - while *environ != ptr::null() { + while !(*environ).is_null() { if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { result.push(key_value); } - environ = environ.offset(1); + environ = environ.add(1); } return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; } diff --git a/src/libstd/sys/wasi/os.rs b/src/libstd/sys/wasi/os.rs index 3baec6bf09924..8052c0aa8a8d9 100644 --- a/src/libstd/sys/wasi/os.rs +++ b/src/libstd/sys/wasi/os.rs @@ -6,7 +6,6 @@ use crate::io; use crate::marker::PhantomData; use crate::os::wasi::prelude::*; use crate::path::{self, PathBuf}; -use crate::ptr; use crate::str; use crate::sys::memchr; use crate::sys::{unsupported, Void}; @@ -107,11 +106,13 @@ pub fn env() -> Env { let _guard = env_lock(); let mut environ = libc::environ; let mut result = Vec::new(); - while environ != ptr::null_mut() && *environ != ptr::null_mut() { - if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { - result.push(key_value); + if !environ.is_null() { + while !(*environ).is_null() { + if let Some(key_value) = parse(CStr::from_ptr(*environ).to_bytes()) { + result.push(key_value); + } + environ = environ.add(1); } - environ = environ.offset(1); } return Env { iter: result.into_iter(), _dont_send_or_sync_me: PhantomData }; } diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index c5354671c9843..cc4ae40590693 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -43,7 +43,7 @@ pub fn error_string(mut errnum: i32) -> String { ]; module = c::GetModuleHandleW(NTDLL_DLL.as_ptr()); - if module != ptr::null_mut() { + if !module.is_null() { errnum ^= c::FACILITY_NT_BIT as i32; flags = c::FORMAT_MESSAGE_FROM_HMODULE; } diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index eb8a881ec8881..e965ea79aa039 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -104,6 +104,7 @@ impl Buf { self.inner.shrink_to(min_capacity) } + #[inline] pub fn as_slice(&self) -> &Slice { unsafe { mem::transmute(&*self.inner) } } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 958e4373cc0ed..70f4f47621a34 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -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}; diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs deleted file mode 100644 index 7724107888ad0..0000000000000 --- a/src/libsyntax/early_buffered_lints.rs +++ /dev/null @@ -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 ", - 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" -} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 7ee4ca4603c9c..a96fee0cf8f16 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -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. diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs index 7ce2a1dd9a62d..8d9cbe45fc696 100644 --- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -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, diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr index ad8670c6c83c8..39ac0019aac23 100644 --- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr @@ -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 { | ^^^^^^^^ diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr index 2d4175ea8eb7d..df793d7dd7ec9 100644 --- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr +++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr @@ -4,17 +4,21 @@ error[E0015]: calls in constant functions are limited to constant functions, tup LL | random() | ^^^^^^^^ -error[E0013]: constant functions cannot refer to statics, use a constant instead +error[E0013]: constant functions cannot refer to statics --> $DIR/const-fn-not-safe-for-const.rs:20:5 | LL | Y | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0013]: constant functions cannot refer to statics, use a constant instead +error[E0013]: constant functions cannot refer to statics --> $DIR/const-fn-not-safe-for-const.rs:25:6 | LL | &Y | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr index 14bf5dc38b47a..e45d8b6c740e0 100644 --- a/src/test/ui/issues/issue-17718-const-bad-values.stderr +++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr @@ -7,17 +7,21 @@ LL | const C1: &'static mut [usize] = &mut []; = note: for more information, see https://github.com/rust-lang/rust/issues/57349 = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-const-bad-values.rs:5:46 | LL | const C2: &'static mut usize = unsafe { &mut S }; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-const-bad-values.rs:5:46 | LL | const C2: &'static mut usize = unsafe { &mut S }; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0658]: references in constants may only refer to immutable values --> $DIR/issue-17718-const-bad-values.rs:5:41 diff --git a/src/test/ui/issues/issue-17718-references.stderr b/src/test/ui/issues/issue-17718-references.stderr index 27aad9c03cebe..e3c3b369ffb32 100644 --- a/src/test/ui/issues/issue-17718-references.stderr +++ b/src/test/ui/issues/issue-17718-references.stderr @@ -1,20 +1,26 @@ -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-references.rs:9:29 | LL | const T2: &'static usize = &S; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-references.rs:14:19 | LL | const T6: usize = S; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-17718-references.rs:19:33 | LL | const T10: Struct = Struct { a: S }; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-18118-2.rs b/src/test/ui/issues/issue-18118-2.rs index 6d52156b3d2de..f712a2eedb7e9 100644 --- a/src/test/ui/issues/issue-18118-2.rs +++ b/src/test/ui/issues/issue-18118-2.rs @@ -1,7 +1,6 @@ pub fn main() { const z: &'static isize = { static p: isize = 3; - &p - //~^ ERROR constants cannot refer to statics, use a constant instead + &p //~ ERROR constants cannot refer to statics }; } diff --git a/src/test/ui/issues/issue-18118-2.stderr b/src/test/ui/issues/issue-18118-2.stderr index d58822f16eb35..4fc3ca78f961c 100644 --- a/src/test/ui/issues/issue-18118-2.stderr +++ b/src/test/ui/issues/issue-18118-2.stderr @@ -1,8 +1,10 @@ -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-18118-2.rs:4:10 | LL | &p | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that error: aborting due to previous error diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index c69145c1fe833..502825e9766e3 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -1,8 +1,10 @@ -error[E0013]: constants cannot refer to statics, use a constant instead +error[E0013]: constants cannot refer to statics --> $DIR/issue-52060.rs:4:26 | LL | static B: [u32; 1] = [0; A.len()]; | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0080]: evaluation of constant value failed --> $DIR/issue-52060.rs:4:26 diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs new file mode 100644 index 0000000000000..3c49a5a975209 --- /dev/null +++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.rs @@ -0,0 +1,6 @@ +pub struct Foo { + pub bar: Vecö + //~^ ERROR expected `,`, or `}`, found `ö` +} //~ ERROR expected `:`, found `}` + +fn main() {} diff --git a/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr new file mode 100644 index 0000000000000..ef365a616437b --- /dev/null +++ b/src/test/ui/issues/issue-68000-unicode-ident-after-missing-comma.stderr @@ -0,0 +1,17 @@ +error: expected `,`, or `}`, found `ö` + --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:2:22 + | +LL | pub bar: Vecö + | ^ help: try adding a comma: `,` + +error: expected `:`, found `}` + --> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1 + | +LL | pub bar: Vecö + | - expected `:` +LL | +LL | } + | ^ unexpected token + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs new file mode 100644 index 0000000000000..00f90cc73b344 --- /dev/null +++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.rs @@ -0,0 +1,9 @@ +macro_rules! x { + ($($c:tt)*) => { + $($c)ö* {} //~ ERROR missing condition for `if` expression + }; //~| ERROR mismatched types +} + +fn main() { + x!(if); +} diff --git a/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr new file mode 100644 index 0000000000000..8d1a03ac207e1 --- /dev/null +++ b/src/test/ui/issues/issue-68091-unicode-ident-after-if.stderr @@ -0,0 +1,18 @@ +error: missing condition for `if` expression + --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14 + | +LL | $($c)ö* {} + | ^ expected if condition here + +error[E0308]: mismatched types + --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17 + | +LL | $($c)ö* {} + | ^^ expected `bool`, found `()` +... +LL | x!(if); + | ------- in this macro invocation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs new file mode 100644 index 0000000000000..1a90b4724d49d --- /dev/null +++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.rs @@ -0,0 +1,9 @@ +macro_rules! x { + ($($c:tt)*) => { + $($c)ö* //~ ERROR macro expansion ends with an incomplete expression: expected expression + }; +} + +fn main() { + x!(!); +} diff --git a/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr new file mode 100644 index 0000000000000..0b9c364f1f1fb --- /dev/null +++ b/src/test/ui/issues/issue-68092-unicode-ident-after-incomplete-expr.stderr @@ -0,0 +1,8 @@ +error: macro expansion ends with an incomplete expression: expected expression + --> $DIR/issue-68092-unicode-ident-after-incomplete-expr.rs:3:14 + | +LL | $($c)ö* + | ^ expected expression + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-68103.rs b/src/test/ui/issues/issue-68103.rs new file mode 100644 index 0000000000000..e775678fc6053 --- /dev/null +++ b/src/test/ui/issues/issue-68103.rs @@ -0,0 +1,6 @@ +// check-pass + +pub extern crate self as name; +pub use name::name as bug; + +fn main() {}