From b91d211b40300a3c026b330e50a6e3e19d71351c Mon Sep 17 00:00:00 2001 From: Peter Jin Date: Mon, 31 Dec 2018 10:58:13 -0800 Subject: [PATCH 01/14] Add a target option "merge-functions" taking values in ("disabled", "trampolines", or "aliases (the default)) to allow targets to opt out of the MergeFunctions LLVM pass. Also add a corresponding -Z option with the same name and values. This works around: https://github.com/rust-lang/rust/issues/57356 Motivation: Basically, the problem is that the MergeFunctions pass, which rustc currently enables by default at -O2 and -O3, and `extern "ptx-kernel"` functions (specific to the NVPTX target) are currently not compatible with each other. If the MergeFunctions pass is allowed to run, rustc can generate invalid PTX assembly (i.e. a PTX file that is not accepted by the native PTX assembler ptxas). Therefore we would like a way to opt out of the MergeFunctions pass, which is what our target option does. Related work: The current behavior of rustc is to enable MergeFunctions at -O2 and -O3, and also to enable the use of function aliases within MergeFunctions. MergeFunctions both with and without function aliases is incompatible with the NVPTX target. clang's "solution" is to have a "-fmerge-functions" flag that opts in to the MergeFunctions pass, but it is not enabled by default. --- src/librustc/session/config.rs | 28 +++++++++-- src/librustc_codegen_llvm/llvm_util.rs | 10 +++- src/librustc_codegen_ssa/back/write.rs | 21 +++++++- src/librustc_target/spec/mod.rs | 66 +++++++++++++++++++++++++- 4 files changed, 117 insertions(+), 8 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 33409f9b4a74f..ca4ab15d79b1d 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -6,7 +6,7 @@ use std::str::FromStr; use session::{early_error, early_warn, Session}; use session::search_paths::SearchPath; -use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; +use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; use rustc_target::spec::{Target, TargetTriple}; use lint; use middle::cstore; @@ -808,13 +808,16 @@ macro_rules! options { pub const parse_cross_lang_lto: Option<&str> = Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \ or the path to the linker plugin"); + pub const parse_merge_functions: Option<&str> = + Some("one of: `disabled`, `trampolines`, or `aliases`"); } #[allow(dead_code)] mod $mod_set { use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto}; - use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; + use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel}; use std::path::PathBuf; + use std::str::FromStr; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -1046,6 +1049,14 @@ macro_rules! options { }; true } + + fn parse_merge_functions(slot: &mut Option, v: Option<&str>) -> bool { + match v.and_then(|s| MergeFunctions::from_str(s).ok()) { + Some(mergefunc) => *slot = Some(mergefunc), + _ => return false, + } + true + } } ) } @@ -1380,6 +1391,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "whether to use the PLT when calling into shared libraries; only has effect for PIC code on systems with ELF binaries (default: PLT is disabled if full relro is enabled)"), + merge_functions: Option = (None, parse_merge_functions, [TRACKED], + "control the operation of the MergeFunctions LLVM pass, taking + the same values as the target option of the same name"), } pub fn default_lib_output() -> CrateType { @@ -2398,7 +2412,7 @@ mod dep_tracking { use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes, Passes, Sanitizer, LtoCli, CrossLangLto}; use syntax::feature_gate::UnstableFeatures; - use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple}; + use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple}; use syntax::edition::Edition; pub trait DepTrackingHash { @@ -2441,12 +2455,14 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option<(String, u64)>); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(CrateType); + impl_dep_tracking_hash_via_hash!(MergeFunctions); impl_dep_tracking_hash_via_hash!(PanicStrategy); impl_dep_tracking_hash_via_hash!(RelroLevel); impl_dep_tracking_hash_via_hash!(Passes); @@ -2532,7 +2548,7 @@ mod tests { use std::iter::FromIterator; use std::path::PathBuf; use super::{Externs, OutputType, OutputTypes}; - use rustc_target::spec::{PanicStrategy, RelroLevel}; + use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; use syntax::symbol::Symbol; use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; @@ -3187,6 +3203,10 @@ mod tests { opts = reference.clone(); opts.debugging_opts.cross_lang_lto = CrossLangLto::LinkerPluginAuto; assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + + opts = reference.clone(); + opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled); + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); } #[test] diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index ad9ebbcde8ab9..dc70ebcf943a5 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -3,6 +3,7 @@ use back::write::create_target_machine; use llvm; use rustc::session::Session; use rustc::session::config::PrintRequest; +use rustc_target::spec::MergeFunctions; use libc::c_int; use std::ffi::CString; use syntax::feature_gate::UnstableFeatures; @@ -61,7 +62,14 @@ unsafe fn configure_llvm(sess: &Session) { add("-disable-preinline"); } if llvm::LLVMRustIsRustLLVM() { - add("-mergefunc-use-aliases"); + match sess.opts.debugging_opts.merge_functions + .unwrap_or(sess.target.target.options.merge_functions) { + MergeFunctions::Disabled | + MergeFunctions::Trampolines => {} + MergeFunctions::Aliases => { + add("-mergefunc-use-aliases"); + } + } } // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index fb3e7ea696363..39bdc70f8322e 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -24,6 +24,7 @@ use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use rustc_errors::emitter::{Emitter}; +use rustc_target::spec::MergeFunctions; use syntax::attr; use syntax::ext::hygiene::Mark; use syntax_pos::MultiSpan; @@ -152,8 +153,24 @@ impl ModuleConfig { sess.opts.optimize == config::OptLevel::Aggressive && !sess.target.target.options.is_like_emscripten; - self.merge_functions = sess.opts.optimize == config::OptLevel::Default || - sess.opts.optimize == config::OptLevel::Aggressive; + // Some targets (namely, NVPTX) interact badly with the MergeFunctions + // pass. This is because MergeFunctions can generate new function calls + // which may interfere with the target calling convention; e.g. for the + // NVPTX target, PTX kernels should not call other PTX kernels. + // MergeFunctions can also be configured to generate aliases instead, + // but aliases are not supported by some backends (again, NVPTX). + // Therefore, allow targets to opt out of the MergeFunctions pass, + // but otherwise keep the pass enabled (at O2 and O3) since it can be + // useful for reducing code size. + self.merge_functions = match sess.opts.debugging_opts.merge_functions + .unwrap_or(sess.target.target.options.merge_functions) { + MergeFunctions::Disabled => false, + MergeFunctions::Trampolines | + MergeFunctions::Aliases => { + sess.opts.optimize == config::OptLevel::Default || + sess.opts.optimize == config::OptLevel::Aggressive + } + }; } pub fn bitcode_needed(&self) -> bool { diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index f42b0a1c3c958..3a21ca19b176b 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -217,6 +217,46 @@ impl ToJson for RelroLevel { } } +#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] +pub enum MergeFunctions { + Disabled, + Trampolines, + Aliases +} + +impl MergeFunctions { + pub fn desc(&self) -> &str { + match *self { + MergeFunctions::Disabled => "disabled", + MergeFunctions::Trampolines => "trampolines", + MergeFunctions::Aliases => "aliases", + } + } +} + +impl FromStr for MergeFunctions { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "disabled" => Ok(MergeFunctions::Disabled), + "trampolines" => Ok(MergeFunctions::Trampolines), + "aliases" => Ok(MergeFunctions::Aliases), + _ => Err(()), + } + } +} + +impl ToJson for MergeFunctions { + fn to_json(&self) -> Json { + match *self { + MergeFunctions::Disabled => "disabled".to_json(), + MergeFunctions::Trampolines => "trampolines".to_json(), + MergeFunctions::Aliases => "aliases".to_json(), + } + } +} + pub type LinkArgs = BTreeMap>; pub type TargetResult = Result; @@ -690,7 +730,15 @@ pub struct TargetOptions { /// If set, have the linker export exactly these symbols, instead of using /// the usual logic to figure this out from the crate itself. - pub override_export_symbols: Option> + pub override_export_symbols: Option>, + + /// Determines how or whether the MergeFunctions LLVM pass should run for + /// this target. Either "disabled", "trampolines", or "aliases". + /// The MergeFunctions pass is generally useful, but some targets may need + /// to opt out. The default is "aliases". + /// + /// Workaround for: https://github.com/rust-lang/rust/issues/57356 + pub merge_functions: MergeFunctions } impl Default for TargetOptions { @@ -773,6 +821,7 @@ impl Default for TargetOptions { requires_uwtable: false, simd_types_indirect: true, override_export_symbols: None, + merge_functions: MergeFunctions::Aliases, } } } @@ -875,6 +924,19 @@ impl Target { .map(|o| o.as_u64() .map(|s| base.options.$key_name = Some(s))); } ); + ($key_name:ident, MergeFunctions) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s.parse::() { + Ok(mergefunc) => base.options.$key_name = mergefunc, + _ => return Some(Err(format!("'{}' is not a valid value for \ + merge-functions. Use 'disabled', \ + 'trampolines', or 'aliases'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, PanicStrategy) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { @@ -1064,6 +1126,7 @@ impl Target { key!(requires_uwtable, bool); key!(simd_types_indirect, bool); key!(override_export_symbols, opt_list); + key!(merge_functions, MergeFunctions)?; if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { for name in array.iter().filter_map(|abi| abi.as_string()) { @@ -1275,6 +1338,7 @@ impl ToJson for Target { target_option_val!(requires_uwtable); target_option_val!(simd_types_indirect); target_option_val!(override_export_symbols); + target_option_val!(merge_functions); if default.abi_blacklist != self.options.abi_blacklist { d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter() From ff19a53ef07566aa30860023f6eac6e75ffaf900 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 13 Jan 2019 13:06:26 +0100 Subject: [PATCH 02/14] Querify entry_fn --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/middle/dead.rs | 2 +- src/librustc/middle/entry.rs | 77 +++++++++++-------- src/librustc/session/config.rs | 8 +- src/librustc/session/mod.rs | 4 - src/librustc/ty/query/config.rs | 6 ++ src/librustc/ty/query/mod.rs | 4 +- src/librustc/ty/query/plumbing.rs | 1 + src/librustc_codegen_llvm/debuginfo/mod.rs | 7 +- .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/base.rs | 8 +- src/librustc_codegen_utils/lib.rs | 9 +-- src/librustc_driver/driver.rs | 9 ++- src/librustc_mir/monomorphize/collector.rs | 23 ++---- src/librustc_mir/monomorphize/item.rs | 5 +- src/librustc_typeck/check/mod.rs | 28 +++---- src/librustc_typeck/lib.rs | 32 ++++---- 17 files changed, 116 insertions(+), 110 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 427fe51e6ff9c..9df41c981eb7b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -583,6 +583,7 @@ define_dep_nodes!( <'tcx> [] CheckImplItemWellFormed(DefId), [] ReachableNonGenerics(CrateNum), [] NativeLibraries(CrateNum), + [] EntryFn(CrateNum), [] PluginRegistrarFn(CrateNum), [] ProcMacroDeclsStatic(CrateNum), [input] CrateDisambiguator(CrateNum), diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 0c769c91801b8..abbf0ae210c25 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -409,7 +409,7 @@ fn create_and_seed_worklist<'a, 'tcx>( } }).chain( // Seed entry point - tcx.sess.entry_fn.borrow().map(|(id, _, _)| id) + tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap()) ).collect::>(); // Seed implemented trait items diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 6b593a1a9f9b2..218ca3b7553c0 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -1,5 +1,5 @@ use hir::map as hir_map; -use hir::def_id::{CRATE_DEF_INDEX}; +use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use session::{config, Session}; use session::config::EntryFnType; use syntax::ast::NodeId; @@ -8,6 +8,8 @@ use syntax::entry::EntryPointType; use syntax_pos::Span; use hir::{Item, ItemKind, ImplItem, TraitItem}; use hir::itemlikevisit::ItemLikeVisitor; +use ty::TyCtxt; +use ty::query::Providers; struct EntryContext<'a, 'tcx: 'a> { session: &'a Session, @@ -45,36 +47,34 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { } } -pub fn find_entry_point(session: &Session, - hir_map: &hir_map::Map<'_>, - crate_name: &str) { - let any_exe = session.crate_types.borrow().iter().any(|ty| { +fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { + assert_eq!(cnum, LOCAL_CRATE); + + let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| { *ty == config::CrateType::Executable }); if !any_exe { // No need to find a main function - session.entry_fn.set(None); - return + return None; } // If the user wants no main function at all, then stop here. - if attr::contains_name(&hir_map.krate().attrs, "no_main") { - session.entry_fn.set(None); - return + if attr::contains_name(&tcx.hir().krate().attrs, "no_main") { + return None; } let mut ctxt = EntryContext { - session, - map: hir_map, + session: tcx.sess, + map: tcx.hir(), main_fn: None, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new(), }; - hir_map.krate().visit_all_item_likes(&mut ctxt); + tcx.hir().krate().visit_all_item_likes(&mut ctxt); - configure_main(&mut ctxt, crate_name); + configure_main(tcx, &ctxt) } // Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep @@ -135,43 +135,58 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) { .span_label(item.span, "multiple `start` functions") .emit(); } - }, - EntryPointType::None => () + } + EntryPointType::None => (), } } -fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) { - if let Some((node_id, span)) = this.start_fn { - this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start))); - } else if let Some((node_id, span)) = this.attr_main_fn { - this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main))); - } else if let Some((node_id, span)) = this.main_fn { - this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main))); +fn configure_main( + tcx: TyCtxt<'_, '_, '_>, + visitor: &EntryContext<'_, '_>, +) -> Option<(DefId, EntryFnType)> { + if let Some((node_id, _)) = visitor.start_fn { + Some((tcx.hir().local_def_id(node_id), EntryFnType::Start)) + } else if let Some((node_id, _)) = visitor.attr_main_fn { + Some((tcx.hir().local_def_id(node_id), EntryFnType::Main)) + } else if let Some((node_id, _)) = visitor.main_fn { + Some((tcx.hir().local_def_id(node_id), EntryFnType::Main)) } else { // No main function - this.session.entry_fn.set(None); - let mut err = struct_err!(this.session, E0601, - "`main` function not found in crate `{}`", crate_name); - if !this.non_main_fns.is_empty() { + let mut err = struct_err!(tcx.sess, E0601, + "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE)); + if !visitor.non_main_fns.is_empty() { // There were some functions named 'main' though. Try to give the user a hint. err.note("the main function must be defined at the crate level \ but you have one or more functions named 'main' that are not \ defined at the crate level. Either move the definition or \ attach the `#[main]` attribute to override this behavior."); - for &(_, span) in &this.non_main_fns { + for &(_, span) in &visitor.non_main_fns { err.span_note(span, "here is a function named 'main'"); } err.emit(); - this.session.abort_if_errors(); + tcx.sess.abort_if_errors(); } else { - if let Some(ref filename) = this.session.local_crate_source_file { + if let Some(ref filename) = tcx.sess.local_crate_source_file { err.note(&format!("consider adding a `main` function to `{}`", filename.display())); } - if this.session.teach(&err.get_code().unwrap()) { + if tcx.sess.teach(&err.get_code().unwrap()) { err.note("If you don't know the basics of Rust, you can go look to the Rust Book \ to get started: https://doc.rust-lang.org/book/"); } err.emit(); } + + None } } + +pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> { + tcx.entry_fn(LOCAL_CRATE) +} + +pub fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + entry_fn, + ..*providers + }; +} diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 42adc6a87fdba..41e75aa32effc 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -649,15 +649,15 @@ impl Options { } } -// The type of entry function, so -// users can have their own entry -// functions -#[derive(Copy, Clone, PartialEq)] +// The type of entry function, so users can have their own entry functions +#[derive(Copy, Clone, PartialEq, Hash, Debug)] pub enum EntryFnType { Main, Start, } +impl_stable_hash_via_hash!(EntryFnType); + #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)] pub enum CrateType { Executable, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 7363b8b3a78fa..cf00bf330deea 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -67,8 +67,6 @@ pub struct Session { /// This is `None` if the host and target are the same. pub target_tlib_path: Option, pub parse_sess: ParseSess, - /// For a library crate, this is always none - pub entry_fn: Once>, pub sysroot: PathBuf, /// The name of the root source file of the crate, in the local file system. /// `None` means that there is no source file. @@ -1173,8 +1171,6 @@ pub fn build_session_( host_tlib_path, target_tlib_path, parse_sess: p_s, - // For a library crate, this is always none - entry_fn: Once::new(), sysroot, local_crate_source_file, working_dir, diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index ca5d1f6bd3203..38e90d6d823b2 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -629,6 +629,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> { + fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { + "looking up the entry function of a crate".into() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> { fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> { "looking up the plugin registrar for a crate".into() diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 39d76ceed9507..ef5a98e6ecb3b 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -22,7 +22,7 @@ use mir::mono::CodegenUnit; use mir; use mir::interpret::GlobalId; use session::{CompileResult, CrateDisambiguator}; -use session::config::OutputFilenames; +use session::config::{EntryFnType, OutputFilenames}; use traits::{self, Vtable}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, @@ -476,6 +476,8 @@ define_queries! { <'tcx> [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc>, + // For a library crate, this is always none + [] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>, [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, [] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option, [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 562cd75a75ff4..bb47d9a9db970 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1362,6 +1362,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); } DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); } DepKind::NativeLibraries => { force!(native_libraries, krate!()); } + DepKind::EntryFn => { force!(entry_fn, krate!()); } DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); } DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); } DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); } diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 2eab626ae8e6e..b504aa515fd44 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -14,7 +14,7 @@ use llvm; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags, DILexicalBlock}; use rustc::hir::CodegenFnAttrFlags; -use rustc::hir::def_id::{DefId, CrateNum}; +use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ty::subst::{Substs, UnpackedKind}; use abi::Abi; @@ -290,9 +290,8 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let mut flags = DIFlags::FlagPrototyped; - let local_id = self.tcx().hir().as_local_node_id(def_id); - if let Some((id, _, _)) = *self.sess().entry_fn.borrow() { - if local_id == Some(id) { + if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) { + if id == def_id { flags |= DIFlags::FlagMainSubprogram; } } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index bf69089a254a4..c372892c521be 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -194,7 +194,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) .collect(); - if tcx.sess.entry_fn.borrow().is_some() { + if tcx.entry_fn(LOCAL_CRATE).is_some() { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main")); symbols.push((exported_symbol, SymbolExportLevel::C)); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index b88ec075653ba..38caacba4d069 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -441,10 +441,8 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx ) { - let (main_def_id, span) = match *cx.sess().entry_fn.borrow() { - Some((id, span, _)) => { - (cx.tcx().hir().local_def_id(id), span) - } + let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) { + Some((def_id, _)) => { (def_id, cx.tcx().def_span(def_id)) }, None => return, }; @@ -458,7 +456,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let main_llfn = cx.get_fn(instance); - let et = cx.sess().entry_fn.get().map(|e| e.2); + let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1); match et { Some(EntryFnType::Main) => create_entry_fn::(cx, span, main_llfn, main_def_id, true), Some(EntryFnType::Start) => create_entry_fn::(cx, span, main_llfn, main_def_id, false), diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index b59bca0ae0edb..5f61852178d0f 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -31,6 +31,7 @@ extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; use rustc::ty::TyCtxt; +use rustc::hir::def_id::LOCAL_CRATE; pub mod link; pub mod codegen_backend; @@ -42,11 +43,9 @@ pub mod symbol_names_test; /// that actually test that compilation succeeds without /// reporting an error. pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { - if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() { - let main_def_id = tcx.hir().local_def_id(id); - - if tcx.has_attr(main_def_id, "rustc_error") { - tcx.sess.span_fatal(span, "compilation successful"); + if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) { + if tcx.has_attr(def_id, "rustc_error") { + tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful"); } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 3b7de37ae4b3f..4244110072305 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1174,6 +1174,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) { rustc_passes::provide(providers); rustc_traits::provide(providers); middle::region::provide(providers); + middle::entry::provide(providers); cstore::provide(providers); lint::provide(providers); } @@ -1210,10 +1211,6 @@ where rustc_incremental::load_query_result_cache(sess) }); - time(sess, "looking for entry point", || { - middle::entry::find_entry_point(sess, &hir_map, name) - }); - let mut local_providers = ty::query::Providers::default(); default_provide(&mut local_providers); codegen_backend.provide(&mut local_providers); @@ -1243,6 +1240,10 @@ where // tcx available. time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); + time(sess, "looking for entry point", || { + middle::entry::find_entry_point(tcx) + }); + time(sess, "looking for plugin registrar", || { plugin::build::find_plugin_registrar(tcx) }); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a6a8fe5ade56c..eb49547e9bf52 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -177,13 +177,13 @@ use rustc::hir::{self, CodegenFnAttrFlags}; use rustc::hir::itemlikevisit::ItemLikeVisitor; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::ty::subst::Substs; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind}; use rustc::ty::adjustment::CustomCoerceUnsized; -use rustc::session::config; +use rustc::session::config::EntryFnType; use rustc::mir::{self, Location, Promoted}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::MonoItem; @@ -321,9 +321,7 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut roots = Vec::new(); { - let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| { - tcx.hir().local_def_id(node_id) - }); + let entry_fn = tcx.entry_fn(LOCAL_CRATE); debug!("collect_roots: entry_fn = {:?}", entry_fn); @@ -924,7 +922,7 @@ struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> { tcx: TyCtxt<'a, 'tcx, 'tcx>, mode: MonoItemCollectionMode, output: &'b mut Vec>, - entry_fn: Option, + entry_fn: Option<(DefId, EntryFnType)>, } impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { @@ -1023,7 +1021,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { true } MonoItemCollectionMode::Lazy => { - self.entry_fn == Some(def_id) || + self.entry_fn.map(|(id, _)| id) == Some(def_id) || self.tcx.is_reachable_non_generic(def_id) || self.tcx.codegen_fn_attrs(def_id).flags.contains( CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) @@ -1048,14 +1046,9 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { /// the return type of `main`. This is not needed when /// the user writes their own `start` manually. fn push_extra_entry_roots(&mut self) { - if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryFnType::Main) { - return - } - - let main_def_id = if let Some(def_id) = self.entry_fn { - def_id - } else { - return + let main_def_id = match self.entry_fn { + Some((def_id, EntryFnType::Main)) => def_id, + _ => return, }; let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) { diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 7014f539d5754..c831cbd98299c 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -1,6 +1,6 @@ use monomorphize::Instance; use rustc::hir; -use rustc::hir::def_id::DefId; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::session::config::OptLevel; use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts}; use rustc::ty::subst::Substs; @@ -75,8 +75,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { match *self.as_mono_item() { MonoItem::Fn(ref instance) => { - let entry_def_id = - tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir().local_def_id(id)); + let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); // If this function isn't inlined or otherwise has explicit // linkage, then we'll be creating a globally shared version. if self.explicit_linkage(tcx).is_some() || diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b07385d4d1f4..cb7e83985874c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -132,7 +132,8 @@ use std::ops::{self, Deref}; use std::slice; use require_c_abi_if_variadic; -use session::{CompileIncomplete, config, Session}; +use session::{CompileIncomplete, Session}; +use session::config::EntryFnType; use TypeAndSubsts; use lint; use util::captures::Captures; @@ -1163,19 +1164,18 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Check that the main return type implements the termination trait. if let Some(term_id) = fcx.tcx.lang_items().termination() { - if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() { - if id == fn_id { - if let config::EntryFnType::Main = entry_type { - let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]); - let trait_ref = ty::TraitRef::new(term_id, substs); - let return_ty_span = decl.output.span(); - let cause = traits::ObligationCause::new( - return_ty_span, fn_id, ObligationCauseCode::MainFunctionType); - - inherited.register_predicate( - traits::Obligation::new( - cause, param_env, trait_ref.to_predicate())); - } + if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) { + let main_id = fcx.tcx.hir().as_local_node_id(def_id).unwrap(); + if main_id == fn_id { + let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]); + let trait_ref = ty::TraitRef::new(term_id, substs); + let return_ty_span = decl.output.span(); + let cause = traits::ObligationCause::new( + return_ty_span, fn_id, ObligationCauseCode::MainFunctionType); + + inherited.register_predicate( + traits::Obligation::new( + cause, param_env, trait_ref.to_predicate())); } } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c55a1258ce955..fb5b28c55da29 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -104,23 +104,22 @@ mod namespace; mod outlives; mod variance; -use hir::Node; use rustc_target::spec::abi::Abi; -use rustc::hir; +use rustc::hir::{self, Node}; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::infer::InferOk; use rustc::lint; use rustc::middle; use rustc::session; -use rustc::session::config::nightly_options; +use rustc::session::CompileIncomplete; +use rustc::session::config::{EntryFnType, nightly_options}; use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::query::Providers; use rustc::util; use rustc::util::profiling::ProfileCategory; -use session::{CompileIncomplete, config}; use syntax_pos::Span; -use syntax::ast; use util::common::time; use std::iter; @@ -185,10 +184,9 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) } -fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - main_id: ast::NodeId, - main_span: Span) { - let main_def_id = tcx.hir().local_def_id(main_id); +fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) { + let main_id = tcx.hir().as_local_node_id(main_def_id).unwrap(); + let main_span = tcx.def_span(main_def_id); let main_t = tcx.type_of(main_def_id); match main_t.sty { ty::FnDef(..) => { @@ -251,10 +249,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - start_id: ast::NodeId, - start_span: Span) { - let start_def_id = tcx.hir().local_def_id(start_id); +fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) { + let start_id = tcx.hir().as_local_node_id(start_def_id).unwrap(); + let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id); match start_t.sty { ty::FnDef(..) => { @@ -310,11 +307,10 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() { - match entry_type { - config::EntryFnType::Main => check_main_fn_ty(tcx, id, sp), - config::EntryFnType::Start => check_start_fn_ty(tcx, id, sp), - } + match tcx.entry_fn(LOCAL_CRATE) { + Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id), + Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), + _ => {} } } From 096ca873330d61de91d81618ce3a1e9905581ff1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 15 Jan 2019 17:11:07 +0100 Subject: [PATCH 03/14] Remove an unused function argument --- src/librustc/hir/intravisit.rs | 58 +-------------------- src/librustc_borrowck/borrowck/mod.rs | 9 ---- src/librustc_borrowck/borrowck/move_data.rs | 4 -- src/librustc_borrowck/dataflow.rs | 7 ++- 4 files changed, 4 insertions(+), 74 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f633703be56d4..041291e80eee9 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -35,11 +35,9 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute}; use syntax_pos::Span; use hir::*; use hir::def::Def; -use hir::map::{self, Map}; +use hir::map::Map; use super::itemlikevisit::DeepVisitor; -use std::cmp; - #[derive(Copy, Clone)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` @@ -1133,57 +1131,3 @@ pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { // the right thing to do, should content be added in the future, // would be to walk it. } - -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct IdRange { - pub min: NodeId, - pub max: NodeId, -} - -impl IdRange { - pub fn max() -> IdRange { - IdRange { - min: NodeId::MAX, - max: NodeId::from_u32(0), - } - } - - pub fn empty(&self) -> bool { - self.min >= self.max - } - - pub fn contains(&self, id: NodeId) -> bool { - id >= self.min && id < self.max - } - - pub fn add(&mut self, id: NodeId) { - self.min = cmp::min(self.min, id); - self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1)); - } -} - - -pub struct IdRangeComputingVisitor<'a, 'hir: 'a> { - result: IdRange, - map: &'a map::Map<'hir>, -} - -impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> { - pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> { - IdRangeComputingVisitor { result: IdRange::max(), map: map } - } - - pub fn result(&self) -> IdRange { - self.result - } -} - -impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { - NestedVisitorMap::OnlyBodies(&self.map) - } - - fn visit_id(&mut self, id: NodeId) { - self.result.add(id); - } -} diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 66303ab71b25f..72963cb7e7fb4 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,7 +39,6 @@ use syntax_pos::{MultiSpan, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; -use rustc::hir::intravisit::{self, Visitor}; use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; @@ -157,12 +156,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG { // Check the body of fn items. - let tcx = this.tcx; - let id_range = { - let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir()); - visitor.visit_body(this.body); - visitor.result() - }; let (all_loans, move_data) = gather_loans::gather_loans_in_fn(this, body_id); @@ -184,7 +177,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc Some(this.body), cfg, LoanDataFlowOperator, - id_range, all_loans.len()); for (loan_idx, loan) in all_loans.iter().enumerate() { loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx); @@ -198,7 +190,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc let flowed_moves = move_data::FlowedMoveData::new(move_data, this, cfg, - id_range, this.body); Some(AnalysisData { all_loans, diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index c5bee87e90fe4..56c9f928eb03a 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -15,7 +15,6 @@ use std::rc::Rc; use std::usize; use syntax_pos::Span; use rustc::hir; -use rustc::hir::intravisit::IdRange; #[derive(Default)] pub struct MoveData<'tcx> { @@ -559,7 +558,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { pub fn new(move_data: MoveData<'tcx>, bccx: &BorrowckCtxt<'a, 'tcx>, cfg: &cfg::CFG, - id_range: IdRange, body: &hir::Body) -> FlowedMoveData<'a, 'tcx> { let tcx = bccx.tcx; @@ -570,7 +568,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, MoveDataFlowOperator, - id_range, move_data.moves.borrow().len()); let mut dfcx_assign = DataFlowContext::new(tcx, @@ -578,7 +575,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, AssignDataFlowOperator, - id_range, move_data.var_assignments.borrow().len()); move_data.add_gen_kills(bccx, diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs index 56e25bd89c9ad..8cf620567405c 100644 --- a/src/librustc_borrowck/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -15,7 +15,7 @@ use rustc_data_structures::graph::implementation::OUTGOING; use rustc::util::nodemap::FxHashMap; use rustc::hir; -use rustc::hir::intravisit::{self, IdRange}; +use rustc::hir::intravisit; use rustc::hir::print as pprust; @@ -230,16 +230,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { body: Option<&hir::Body>, cfg: &cfg::CFG, oper: O, - id_range: IdRange, bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> { let usize_bits = mem::size_of::() * 8; let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits; let num_nodes = cfg.graph.all_nodes().len(); - debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \ + debug!("DataFlowContext::new(analysis_name: {}, \ bits_per_id={}, words_per_id={}) \ num_nodes: {}", - analysis_name, id_range, bits_per_id, words_per_id, + analysis_name, bits_per_id, words_per_id, num_nodes); let entry = if oper.initial_value() { usize::MAX } else {0}; From b7cd24dd44eafa44797fdd4e418013d1ea0fd1db Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 15 Jan 2019 17:44:41 +0100 Subject: [PATCH 04/14] Make the query comment into a doc comment --- src/librustc/ty/query/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index ef5a98e6ecb3b..6bf99a98d4eff 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -476,7 +476,8 @@ define_queries! { <'tcx> [] fn foreign_modules: ForeignModules(CrateNum) -> Lrc>, - // For a library crate, this is always none + /// Identifies the entry-point (e.g. the `main` function) for a given + /// crate, returning `None` if there is no entry point (such as for library crates). [] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>, [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, [] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option, From 6046be42ab911cf2eddd41cffaa0467098bb2317 Mon Sep 17 00:00:00 2001 From: mark Date: Mon, 14 Jan 2019 15:50:33 -0600 Subject: [PATCH 05/14] fix nested matchers with ? --- src/libsyntax/ext/tt/macro_rules.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 24202ca8fbdc0..9a129e7e8fcd8 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -435,7 +435,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { match *seq_tt { TokenTree::MetaVarDecl(_, _, id) => id.name == "vis", TokenTree::Sequence(_, ref sub_seq) => - sub_seq.op == quoted::KleeneOp::ZeroOrMore, + sub_seq.op == quoted::KleeneOp::ZeroOrMore + || sub_seq.op == quoted::KleeneOp::ZeroOrOne, _ => false, } }) { @@ -543,7 +544,10 @@ impl FirstSets { } // Reverse scan: Sequence comes before `first`. - if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // If sequence is potentially empty, then // union them (preserving first emptiness). first.add_all(&TokenSet { maybe_empty: true, ..subfirst }); @@ -591,8 +595,10 @@ impl FirstSets { assert!(first.maybe_empty); first.add_all(subfirst); - if subfirst.maybe_empty || - seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // continue scanning for more first // tokens, but also make sure we // restore empty-tracking state From dabe86db44c97698bc6a4ab2f8923a3f65b151f0 Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 11:31:49 -0600 Subject: [PATCH 06/14] update/add tests --- src/test/ui/issues/issue-5067.rs | 37 ++++++++++--- src/test/ui/issues/issue-57597.rs | 80 +++++++++++++++++++++++++++ src/test/ui/issues/issue-57597.stderr | 74 +++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/issues/issue-57597.rs create mode 100644 src/test/ui/issues/issue-57597.stderr diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs index 526a68311462e..616fd09907a2b 100644 --- a/src/test/ui/issues/issue-5067.rs +++ b/src/test/ui/issues/issue-5067.rs @@ -1,37 +1,59 @@ #![allow(unused_macros)] +// Tests that repetition matchers cannot match the empty token tree (since that would be +// ambiguous). + +// edition:2018 + macro_rules! foo { ( $()* ) => {}; //~^ ERROR repetition matches empty token tree ( $()+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $()? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(),* ) => {}; // PASS ( $(),+ ) => {}; // PASS - + // `?` cannot have a separator... ( [$()*] ) => {}; //~^ ERROR repetition matches empty token tree ( [$()+] ) => {}; //~^ ERROR repetition matches empty token tree - + ( [$()?] ) => {}; + //~^ ERROR repetition matches empty token tree ( [$(),*] ) => {}; // PASS ( [$(),+] ) => {}; // PASS - + // `?` cannot have a separator... ( $($()* $(),* $(a)* $(a),* )* ) => {}; //~^ ERROR repetition matches empty token tree ( $($()* $(),* $(a)* $(a),* )+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $($()* $(),* $(a)* $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS + + ( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS ( $(a $()+)* ) => {}; //~^ ERROR repetition matches empty token tree ( $(a $()*)+ ) => {}; //~^ ERROR repetition matches empty token tree + ( $(a $()+)? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()?)+ ) => {}; + //~^ ERROR repetition matches empty token tree } - // --- Original Issue --- // macro_rules! make_vec { @@ -43,11 +65,10 @@ fn main() { let _ = make_vec![a 1, a 2, a 3]; } - // --- Minified Issue --- // macro_rules! m { - ( $()* ) => {} + ( $()* ) => {}; //~^ ERROR repetition matches empty token tree } diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs new file mode 100644 index 0000000000000..ebeb3fe07adb4 --- /dev/null +++ b/src/test/ui/issues/issue-57597.rs @@ -0,0 +1,80 @@ +// Regression test for #57597. +// +// Make sure that nested matchers work correctly rather than causing an infinite loop or crash. + +// edition:2018 + +macro_rules! foo1 { + ($($($i:ident)?)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo2 { + ($($($i:ident)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo3 { + ($($($i:ident)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo4 { + ($($($($i:ident)?)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo5 { + ($($($($i:ident)*)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo6 { + ($($($($i:ident)?)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo7 { + ($($($($i:ident)?)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo8 { + ($($($($i:ident)*)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo9 { + ($($($($i:ident)?)*)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo10 { + ($($($($i:ident)?)*)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo11 { + ($($($($i:ident)+)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo12 { + ($($($($i:ident)+)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +fn main() { + foo1!(); + foo2!(); + foo3!(); + foo4!(); + foo5!(); + foo6!(); + foo7!(); + foo8!(); + foo9!(); + foo10!(); + foo11!(); + foo12!(); +} diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr new file mode 100644 index 0000000000000..0a02ac8c499b6 --- /dev/null +++ b/src/test/ui/issues/issue-57597.stderr @@ -0,0 +1,74 @@ +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:8:7 + | +LL | ($($($i:ident)?)+) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:13:7 + | +LL | ($($($i:ident)?)*) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:18:7 + | +LL | ($($($i:ident)?)?) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:23:7 + | +LL | ($($($($i:ident)?)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:28:7 + | +LL | ($($($($i:ident)*)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:33:7 + | +LL | ($($($($i:ident)?)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:38:7 + | +LL | ($($($($i:ident)?)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:43:7 + | +LL | ($($($($i:ident)*)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:48:7 + | +LL | ($($($($i:ident)?)*)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:53:7 + | +LL | ($($($($i:ident)?)*)+) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:58:7 + | +LL | ($($($($i:ident)+)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:63:7 + | +LL | ($($($($i:ident)+)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + From aa1ce32b105ff506257019a22684a98b61ab166a Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 16:40:10 -0600 Subject: [PATCH 07/14] update test output --- src/test/ui/issues/issue-5067.stderr | 72 +++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr index 433b7c8c04907..7ffc6071407c5 100644 --- a/src/test/ui/issues/issue-5067.stderr +++ b/src/test/ui/issues/issue-5067.stderr @@ -1,62 +1,110 @@ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:4:8 + --> $DIR/issue-5067.rs:9:8 | LL | ( $()* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:6:8 + --> $DIR/issue-5067.rs:11:8 | LL | ( $()+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:12:9 + --> $DIR/issue-5067.rs:13:8 + | +LL | ( $()? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:18:9 | LL | ( [$()*] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:14:9 + --> $DIR/issue-5067.rs:20:9 | LL | ( [$()+] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:20:8 + --> $DIR/issue-5067.rs:22:9 + | +LL | ( [$()?] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:27:8 | LL | ( $($()* $(),* $(a)* $(a),* )* ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:22:8 + --> $DIR/issue-5067.rs:29:8 | LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:28:12 + --> $DIR/issue-5067.rs:31:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:33:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )* ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:35:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:37:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:47:12 | LL | ( $(a $()+)* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:30:12 + --> $DIR/issue-5067.rs:49:12 | LL | ( $(a $()*)+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:38:18 + --> $DIR/issue-5067.rs:51:12 + | +LL | ( $(a $()+)? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:53:12 + | +LL | ( $(a $()?)+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:60:18 | LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); | ^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:50:8 + --> $DIR/issue-5067.rs:71:8 | -LL | ( $()* ) => {} +LL | ( $()* ) => {}; | ^^ -error: aborting due to 10 previous errors +error: aborting due to 18 previous errors From 48bee07768fab0f6c96fc51957ac6f18e10b7767 Mon Sep 17 00:00:00 2001 From: mark Date: Tue, 15 Jan 2019 20:02:28 -0600 Subject: [PATCH 08/14] make the contribution doc reference the guide more; deduplication --- CONTRIBUTING.md | 250 ++++-------------------------------------------- 1 file changed, 21 insertions(+), 229 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 65cdfe67b5b08..9924055ca45ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,9 +19,16 @@ hop on [#rust-internals][pound-rust-internals]. As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. +The [rustc-guide] is your friend! It describes how the compiler works and how +to contribute to it in more detail than this document. + +If this is your first time contributing, the [walkthrough] chapter of the guide +can give you a good example of how a typical contribution would go. + [pound-rust-internals]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals [internals]: https://internals.rust-lang.org [coc]: https://www.rust-lang.org/conduct.html +[walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html ## Feature Requests [feature-requests]: #feature-requests @@ -89,222 +96,14 @@ $ RUST_BACKTRACE=1 rustc ... ``` ## The Build System -[the-build-system]: #the-build-system - -Rust's build system allows you to bootstrap the compiler, run tests & -benchmarks, generate documentation, install a fresh build of Rust, and more. -It's your best friend when working on Rust, allowing you to compile & test -your contributions before submission. - -The build system lives in [the `src/bootstrap` directory][bootstrap] in the -project root. Our build system is itself written in Rust and is based on Cargo -to actually build all the compiler's crates. If you have questions on the build -system internals, try asking in [`#rust-internals`][pound-rust-internals]. - -[bootstrap]: https://github.com/rust-lang/rust/tree/master/src/bootstrap/ - -### Configuration -[configuration]: #configuration - -Before you can start building the compiler you need to configure the build for -your system. In most cases, that will just mean using the defaults provided -for Rust. - -To change configuration, you must copy the file `config.toml.example` -to `config.toml` in the directory from which you will be running the build, and -change the settings provided. - -There are large number of options provided in this config file that will alter the -configuration used in the build process. Some options to note: - -#### `[llvm]`: -- `assertions = true` = This enables LLVM assertions, which makes LLVM misuse cause an assertion failure instead of weird misbehavior. This also slows down the compiler's runtime by ~20%. -- `ccache = true` - Use ccache when building llvm - -#### `[build]`: -- `compiler-docs = true` - Build compiler documentation - -#### `[rust]`: -- `debuginfo = true` - Build a compiler with debuginfo. Makes building rustc slower, but then you can use a debugger to debug `rustc`. -- `debuginfo-lines = true` - An alternative to `debuginfo = true` that doesn't let you use a debugger, but doesn't make building rustc slower and still gives you line numbers in backtraces. -- `debuginfo-tools = true` - Build the extended tools with debuginfo. -- `debug-assertions = true` - Makes the log output of `debug!` work. -- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust, but makes the stage1 compiler x100 slower. - -For more options, the `config.toml` file contains commented out defaults, with -descriptions of what each option will do. - -Note: Previously the `./configure` script was used to configure this -project. It can still be used, but it's recommended to use a `config.toml` -file. If you still have a `config.mk` file in your directory - from -`./configure` - you may need to delete it for `config.toml` to work. - -### Building -[building]: #building - -A default configuration requires around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB. -Dependencies -- [build dependencies](README.md#building-from-source) -- `gdb` 6.2.0 minimum, 7.1 or later recommended for test builds +For info on how to configure and build the compiler, please see [this +chapter][rustcguidebuild] of the rustc-guide. This chapter contains info for +contributions to the compiler and the standard library. It also lists some +really useful commands to the build system (`./x.py`), which could save you a +lot of time. -The build system uses the `x.py` script to control the build process. This script -is used to build, test, and document various parts of the compiler. You can -execute it as: - -```sh -python x.py build -``` - -On some systems you can also use the shorter version: - -```sh -./x.py build -``` - -To learn more about the driver and top-level targets, you can execute: - -```sh -python x.py --help -``` - -The general format for the driver script is: - -```sh -python x.py [] -``` - -Some example commands are `build`, `test`, and `doc`. These will build, test, -and document the specified directory. The second argument, ``, is -optional and defaults to working over the entire compiler. If specified, -however, only that specific directory will be built. For example: - -```sh -# build the entire compiler -python x.py build - -# build all documentation -python x.py doc - -# run all test suites -python x.py test - -# build only the standard library -python x.py build src/libstd - -# test only one particular test suite -python x.py test src/test/rustdoc - -# build only the stage0 libcore library -python x.py build src/libcore --stage 0 -``` - -You can explore the build system through the various `--help` pages for each -subcommand. For example to learn more about a command you can run: - -``` -python x.py build --help -``` - -To learn about all possible rules you can execute, run: - -``` -python x.py build --help --verbose -``` - -Note: Previously `./configure` and `make` were used to build this project. -They are still available, but `x.py` is the recommended build system. - -### Useful commands -[useful-commands]: #useful-commands - -Some common invocations of `x.py` are: - -- `x.py build --help` - show the help message and explain the subcommand -- `x.py build src/libtest --stage 1` - build up to (and including) the first - stage. For most cases we don't need to build the stage2 compiler, so we can - save time by not building it. The stage1 compiler is a fully functioning - compiler and (probably) will be enough to determine if your change works as - expected. -- `x.py build src/rustc --stage 1` - This will build just rustc, without libstd. - This is the fastest way to recompile after you changed only rustc source code. - Note however that the resulting rustc binary won't have a stdlib to link - against by default. You can build libstd once with `x.py build src/libstd`, - but it is only guaranteed to work if recompiled, so if there are any issues - recompile it. -- `x.py test` - build the full compiler & run all tests (takes a while). This - is what gets run by the continuous integration system against your pull - request. You should run this before submitting to make sure your tests pass - & everything builds in the correct manner. -- `x.py test src/libstd --stage 1` - test the standard library without - recompiling stage 2. -- `x.py test src/test/run-pass --test-args TESTNAME` - Run a matching set of - tests. - - `TESTNAME` should be a substring of the tests to match against e.g. it could - be the fully qualified test name, or just a part of it. - `TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len` - or `TESTNAME=test_capacity_not_less_than_len`. -- `x.py test src/test/run-pass --stage 1 --test-args ` - - Run a single rpass test with the stage1 compiler (this will be quicker than - running the command above as we only build the stage1 compiler, not the entire - thing). You can also leave off the directory argument to run all stage1 test - types. -- `x.py test src/libcore --stage 1` - Run stage1 tests in `libcore`. -- `x.py test src/tools/tidy` - Check that the source code is in compliance with - Rust's style guidelines. There is no official document describing Rust's full - guidelines as of yet, but basic rules like 4 spaces for indentation and no - more than 99 characters in a single line should be kept in mind when writing - code. - -### Using your local build -[using-local-build]: #using-local-build - -If you use Rustup to manage your rust install, it has a feature called ["custom -toolchains"][toolchain-link] that you can use to access your newly-built compiler -without having to install it to your system or user PATH. If you've run `python -x.py build`, then you can add your custom rustc to a new toolchain like this: - -[toolchain-link]: https://github.com/rust-lang-nursery/rustup.rs#working-with-custom-toolchains-and-local-builds - -``` -rustup toolchain link build//stage2 -``` - -Where `` is the build triple for the host (the triple of your -computer, by default), and `` is the name for your custom toolchain. (If you -added `--stage 1` to your build command, the compiler will be in the `stage1` -folder instead.) You'll only need to do this once - it will automatically point -to the latest build you've done. - -Once this is set up, you can use your custom toolchain just like any other. For -example, if you've named your toolchain `local`, running `cargo +local build` will -compile a project with your custom rustc, setting `rustup override set local` will -override the toolchain for your current directory, and `cargo +local doc` will use -your custom rustc and rustdoc to generate docs. (If you do this with a `--stage 1` -build, you'll need to build rustdoc specially, since it's not normally built in -stage 1. `python x.py build --stage 1 src/libstd src/tools/rustdoc` will build -rustdoc and libstd, which will allow rustdoc to be run with that toolchain.) - -### Out-of-tree builds -[out-of-tree-builds]: #out-of-tree-builds - -Rust's `x.py` script fully supports out-of-tree builds - it looks for -the Rust source code from the directory `x.py` was found in, but it -reads the `config.toml` configuration file from the directory it's -run in, and places all build artifacts within a subdirectory named `build`. - -This means that if you want to do an out-of-tree build, you can just do it: -``` -$ cd my/build/dir -$ cp ~/my-config.toml config.toml # Or fill in config.toml otherwise -$ path/to/rust/x.py build -... -$ # This will use the Rust source code in `path/to/rust`, but build -$ # artifacts will now be in ./build -``` - -It's absolutely fine to have multiple build directories with different -`config.toml` configurations using the same code. +[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html ## Pull Requests [pull-requests]: #pull-requests @@ -320,26 +119,13 @@ bring those changes into the source repository. Please make pull requests against the `master` branch. -Compiling all of `./x.py test` can take a while. When testing your pull request, -consider using one of the more specialized `./x.py` targets to cut down on the -amount of time you have to wait. You need to have built the compiler at least -once before running these will work, but that’s only one full build rather than -one each time. - - $ python x.py test --stage 1 - -is one such example, which builds just `rustc`, and then runs the tests. If -you’re adding something to the standard library, try - - $ python x.py test src/libstd --stage 1 - Please make sure your pull request is in compliance with Rust's style guidelines by running $ python x.py test src/tools/tidy Make this check before every pull request (and every new commit in a pull -request) ; you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) +request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) before every push to make sure you never forget to make this check. All pull requests are reviewed by another person. We have a bot, @@ -532,6 +318,12 @@ to check small fixes. For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. The CSS might be messed up, but you can verify that the HTML is right. +Additionally, contributions to the [rustc-guide] are always welcome. Contributions +can be made directly at [the +rust-lang/rustc-guide](https://github.com/rust-lang/rustc-guide) repo. The issue +tracker in that repo is also a great way to find things that need doing. There +are issues for beginners and advanced compiler devs alike! + ## Issue Triage [issue-triage]: #issue-triage @@ -627,7 +419,7 @@ For people new to Rust, and just starting to contribute, or even for more seasoned developers, some useful places to look for information are: -* The [rustc guide] contains information about how various parts of the compiler work +* The [rustc guide] contains information about how various parts of the compiler work and how to contribute to the compiler * [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks * The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals From 7bddcbae51b9417b9054ea042174416d8f538405 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 16 Jan 2019 14:37:22 +0100 Subject: [PATCH 09/14] With this change, I am able to build and test cross-platform `rustc` In particular, I can use the following in my `config.toml`: ``` [build] host = ["i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu"] target = ["i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu"] ``` Before this change, my attempt to run the test suite would fail because the error output differs depending on what your host and targets are. ---- To be concrete, here are the actual messages one can observe: ``` % ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/huge-enum.rs -Aunused --target=x86_64-unknown-linux-gnu error: the type `std::option::Option<[u32; 35184372088831]>` is too big for the current architecture error: aborting due to previous error % ./build/x86_64-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/huge-enum.rs -Aunused --target=i686-unknown-linux-gnu error: the type `std::option::Option<[u32; 536870911]>` is too big for the current architecture error: aborting due to previous error % ./build/i686-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/huge-enum.rs -Aunused --target=i686-unknown-linux-gnu error: the type `std::option::Option<[u32; 536870911]>` is too big for the current architecture error: aborting due to previous error % ./build/i686-unknown-linux-gnu/stage1/bin/rustc ../src/test/ui/huge-enum.rs -Aunused --target=x86_64-unknown-linux-gnu error: the type `[u32; 35184372088831]` is too big for the current architecture error: aborting due to previous error ``` To address these variations, I changed the test to be more aggressive in its normalization strategy. We cannot (and IMO should not) guarantee that `Option` will appear in the error output here. So I normalized both types `Option<[u32; N]>` and `[u32; N]` to just `TYPE` --- src/test/ui/huge-enum.rs | 6 ++---- src/test/ui/huge-enum.stderr | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs index 18ef45794af19..71c8fd55b23f3 100644 --- a/src/test/ui/huge-enum.rs +++ b/src/test/ui/huge-enum.rs @@ -1,7 +1,5 @@ -// error-pattern: Option -// normalize-stderr-test "<\[u32; \d+\]>" -> "<[u32; N]>" - -// FIXME: work properly with higher limits +// normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE" +// normalize-stderr-test "\[u32; \d+\]" -> "TYPE" #[cfg(target_pointer_width = "32")] fn main() { diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr index b7cf25504614a..67cae3d52ed2d 100644 --- a/src/test/ui/huge-enum.stderr +++ b/src/test/ui/huge-enum.stderr @@ -1,4 +1,4 @@ -error: the type `std::option::Option<[u32; N]>` is too big for the current architecture +error: the type `TYPE` is too big for the current architecture error: aborting due to previous error From 01d0ae96188b99c367178a38906b7269e1ada244 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Jan 2019 23:23:30 +0300 Subject: [PATCH 10/14] Prioritize variants as inherent associated items during name resolution --- src/librustc/lint/builtin.rs | 7 + src/librustc_lint/lib.rs | 5 + src/librustc_typeck/astconv.rs | 162 +++++++++++------- src/librustc_typeck/check/method/mod.rs | 61 +++---- src/librustc_typeck/check/mod.rs | 4 +- .../ui/type-alias-enum-variants-priority-2.rs | 13 ++ ...type-alias-enum-variants-priority-2.stderr | 12 ++ .../ui/type-alias-enum-variants-priority-3.rs | 10 ++ ...type-alias-enum-variants-priority-3.stderr | 8 + .../ui/type-alias-enum-variants-priority.rs | 20 +++ .../type-alias-enum-variants-priority.stderr | 26 +++ 11 files changed, 225 insertions(+), 103 deletions(-) create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority-2.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority-3.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority-3.stderr create mode 100644 src/test/ui/type-alias-enum-variants-priority.rs create mode 100644 src/test/ui/type-alias-enum-variants-priority.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index c8d137a42b2e8..a0bd4f01cd231 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -368,6 +368,12 @@ declare_lint! { report_in_external_macro: true } +declare_lint! { + pub AMBIGUOUS_ASSOCIATED_ITEMS, + Warn, + "ambiguous associated items" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -433,6 +439,7 @@ impl LintPass for HardwiredLints { parser::QUESTION_MARK_MACRO_SEP, parser::ILL_FORMED_ATTRIBUTE_INPUT, DEPRECATED_IN_FUTURE, + AMBIGUOUS_ASSOCIATED_ITEMS, ) } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2d764d11c66aa..71c859d8dbea7 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -341,6 +341,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #57571 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS), + reference: "issue #57644 ", + edition: None, + }, ]); // Register renamed and removed lints. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8e5eaa18b9de0..534279e981d62 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -10,6 +10,7 @@ use hir::HirVec; use lint; use middle::resolve_lifetime as rl; use namespace::Namespace; +use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -1278,29 +1279,50 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Create a type from a path to an associated type. - // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C` + // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for // the whole path. - // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type + // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type // parameter or `Self`. - pub fn associated_path_def_to_ty(&self, - ref_id: ast::NodeId, - span: Span, - ty: Ty<'tcx>, - ty_path_def: Def, - item_segment: &hir::PathSegment) - -> (Ty<'tcx>, Def) - { + pub fn associated_path_to_ty( + &self, + ref_id: ast::NodeId, + span: Span, + qself_ty: Ty<'tcx>, + qself_def: Def, + assoc_segment: &hir::PathSegment, + permit_variants: bool, + ) -> (Ty<'tcx>, Def) { let tcx = self.tcx(); - let assoc_name = item_segment.ident; + let assoc_ident = assoc_segment.ident; - debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name); + debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident); - self.prohibit_generics(slice::from_ref(item_segment)); + self.prohibit_generics(slice::from_ref(assoc_segment)); + + // Check if we have an enum variant. + let mut variant_resolution = None; + if let ty::Adt(adt_def, _) = qself_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + let def = Def::Variant(variant_def.did); + if permit_variants { + check_type_alias_enum_variants_enabled(tcx, span); + tcx.check_stability(variant_def.did, Some(ref_id), span); + return (qself_ty, def); + } else { + variant_resolution = Some(def); + } + } + } + } // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&ty.sty, ty_path_def) { + let bound = match (&qself_ty.sty, qself_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1313,77 +1335,61 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref)) - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident)); - match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) { + match self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } } (&ty::Param(_), Def::SelfTy(Some(param_did), None)) | (&ty::Param(_), Def::TyParam(param_did)) => { - match self.find_bound_for_assoc_item(param_did, assoc_name, span) { + match self.find_bound_for_assoc_item(param_did, assoc_ident, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => { - let ty_str = ty.to_string(); - // Incorrect enum variant. - let mut err = tcx.sess.struct_span_err( - span, - &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), - ); - // Check if it was a typo. - let input = adt_def.variants.iter().map(|variant| &variant.ident.name); - if let Some(suggested_name) = find_best_match_for_name( - input, - &assoc_name.as_str(), - None, - ) { - err.span_suggestion_with_applicability( + _ => { + if variant_resolution.is_some() { + // Variant in type position + let msg = format!("expected type, found variant `{}`", assoc_ident); + tcx.sess.span_err(span, &msg); + } else if qself_ty.is_enum() { + // Report as incorrect enum variant rather than ambiguous type. + let mut err = tcx.sess.struct_span_err( span, - "did you mean", - format!("{}::{}", ty_str, suggested_name.to_string()), - Applicability::MaybeIncorrect, + &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty), ); - } else { - err.span_label(span, "unknown variant"); - } - err.emit(); - return (tcx.types.err, Def::Err); - } - _ => { - // Check if we have an enum variant. - match ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); - } - }, - _ => (), - } - - // Don't print `TyErr` to the user. - if !ty.references_error() { + // Check if it was a typo. + let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); + if let Some(suggested_name) = find_best_match_for_name( + adt_def.variants.iter().map(|variant| &variant.ident.name), + &assoc_ident.as_str(), + None, + ) { + err.span_suggestion_with_applicability( + span, + "did you mean", + format!("{}::{}", qself_ty, suggested_name), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label(span, "unknown variant"); + } + err.emit(); + } else if !qself_ty.references_error() { + // Don't print `TyErr` to the user. self.report_ambiguous_associated_type(span, - &ty.to_string(), + &qself_ty.to_string(), "Trait", - &assoc_name.as_str()); + &assoc_ident.as_str()); } return (tcx.types.err, Def::Err); } }; let trait_did = bound.def_id(); - let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id); + let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident @@ -1394,11 +1400,35 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let def = Def::AssociatedTy(item.def_id); if !item.vis.is_accessible_from(def_scope, tcx) { - let msg = format!("{} `{}` is private", def.kind_name(), assoc_name); + let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident); tcx.sess.span_err(span, &msg); } tcx.check_stability(item.def_id, Some(ref_id), span); + if let Some(variant_def) = variant_resolution { + let mut err = tcx.struct_span_lint_node( + AMBIGUOUS_ASSOCIATED_ITEMS, + ref_id, + span, + "ambiguous associated item", + ); + + let mut could_refer_to = |def: Def, also| { + let note_msg = format!("`{}` could{} refer to {} defined here", + assoc_ident, also, def.kind_name()); + err.span_note(tcx.def_span(def.def_id()), ¬e_msg); + }; + could_refer_to(variant_def, ""); + could_refer_to(def, " also"); + + err.span_suggestion_with_applicability( + span, + "use fully-qualified syntax", + format!("<{} as {}>::{}", qself_ty, "Trait", assoc_ident), + Applicability::HasPlaceholders, + ).emit(); + } + (ty, def) } @@ -1773,7 +1803,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 + self.associated_path_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 02687df6a94fc..e71dc019471bd 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -408,45 +408,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - let mode = probe::Mode::Path; - match self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope) { - Ok(pick) => { - debug!("resolve_ufcs: pick={:?}", pick); - if let Some(import_id) = pick.import_id { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + // Check if we have an enum variant. + if let ty::Adt(adt_def, _) = self_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); } - - let def = pick.item.def(); - debug!("resolve_ufcs: def={:?}", def); - tcx.check_stability(def.def_id(), Some(expr_id), span); - - Ok(def) } - Err(err) => { - // Check if we have an enum variant. - match self_ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(method_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - tcx.check_stability(def.def_id(), Some(expr_id), span); - return Ok(def); - } - }, - _ => (), - } + } - Err(err) - } + let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope)?; + debug!("resolve_ufcs: pick={:?}", pick); + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } + + let def = pick.item.def(); + debug!("resolve_ufcs: def={:?}", def); + tcx.check_stability(def.def_id(), Some(expr_id), span); + Ok(def) } /// Find item with name `item_name` defined in impl/trait `def_id` diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b07385d4d1f4..22300f2ae11ed 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4724,8 +4724,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { Def::Err }; - let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, def, segment); + let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span, + ty, def, segment, true); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs new file mode 100644 index 0000000000000..295f8acf62f85 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V(u8) +} + +impl E { + fn V() {} +} + +fn main() { + ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied +} diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr new file mode 100644 index 0000000000000..c6ec96ebb7d3b --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr @@ -0,0 +1,12 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/type-alias-enum-variants-priority-2.rs:12:5 + | +LL | V(u8) + | ----- defined here +... +LL | ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^^^^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs new file mode 100644 index 0000000000000..33f96553b57f0 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V +} + +fn check() -> ::V {} +//~^ ERROR expected type, found variant `V` + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr new file mode 100644 index 0000000000000..b3451542a2570 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr @@ -0,0 +1,8 @@ +error: expected type, found variant `V` + --> $DIR/type-alias-enum-variants-priority-3.rs:7:15 + | +LL | fn check() -> ::V {} + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs new file mode 100644 index 0000000000000..db1da2b12e256 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_enum_variants)] +#![deny(ambiguous_associated_items)] + +enum E { + V +} + +trait Tr { + type V; + fn f() -> Self::V; +} + +impl Tr for E { + type V = u8; + fn f() -> Self::V { 0 } + //~^ ERROR ambiguous associated item + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr new file mode 100644 index 0000000000000..dcf7dc77ed5ea --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.stderr @@ -0,0 +1,26 @@ +error: ambiguous associated item + --> $DIR/type-alias-enum-variants-priority.rs:15:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` + | +note: lint level defined here + --> $DIR/type-alias-enum-variants-priority.rs:2:9 + | +LL | #![deny(ambiguous_associated_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 +note: `V` could refer to variant defined here + --> $DIR/type-alias-enum-variants-priority.rs:5:5 + | +LL | V + | ^ +note: `V` could also refer to associated type defined here + --> $DIR/type-alias-enum-variants-priority.rs:9:5 + | +LL | type V; + | ^^^^^^^ + +error: aborting due to previous error + From 6c8fdf971cb226a14491dba974ec50812a52e983 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Mon, 7 Jan 2019 10:04:30 +0100 Subject: [PATCH 11/14] Remove access level mention from DocContext Leftover from https://github.com/rust-lang/rust/commit/c754e8240cfbeeaca1672c349eccba3d050f866c. --- src/librustdoc/core.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 78dbf41bf21fd..6c3a973a41484 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -51,9 +51,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { /// The stack of module NodeIds up till this point pub crate_name: Option, pub cstore: Rc, - // Note that external items for which `doc(hidden)` applies to are shown as - // non-reachable while local items aren't. This is because we're reusing - // the access levels from crateanalysis. /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` From 6f1d06d21989e7b606a0c980a9fa99ffdafb91a2 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Mon, 7 Jan 2019 11:46:44 +0100 Subject: [PATCH 12/14] Querify glob map usage (last use of CrateAnalysis) --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/context.rs | 10 +++++++++ src/librustc/ty/mod.rs | 13 ++--------- src/librustc/ty/query/mod.rs | 2 ++ src/librustc/ty/query/plumbing.rs | 1 + src/librustc_driver/driver.rs | 26 +++++----------------- src/librustc_driver/lib.rs | 2 -- src/librustc_driver/pretty.rs | 16 +++---------- src/librustc_save_analysis/dump_visitor.rs | 9 +++----- src/librustc_save_analysis/lib.rs | 3 --- src/librustdoc/core.rs | 7 ++---- src/librustdoc/html/render.rs | 2 +- 12 files changed, 30 insertions(+), 62 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 427fe51e6ff9c..3cc780ec34273 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -630,6 +630,7 @@ define_dep_nodes!( <'tcx> [input] Freevars(DefId), [input] MaybeUnusedTraitImport(DefId), [input] MaybeUnusedExternCrates, + [input] NamesImportedByGlobUse(DefId), [eval_always] StabilityIndex, [eval_always] AllTraits, [input] AllCrateNums, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d69219efbd884..e37eab622df3f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -983,6 +983,9 @@ pub struct GlobalCtxt<'tcx> { maybe_unused_trait_imports: FxHashSet, maybe_unused_extern_crates: Vec<(DefId, Span)>, + /// A map of glob use to a set of names it actually imports. Currently only + /// used in save-analysis. + glob_map: FxHashMap>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. pub extern_prelude: FxHashMap, @@ -1232,6 +1235,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .into_iter() .map(|(id, sp)| (hir.local_def_id(id), sp)) .collect(), + glob_map: resolutions.glob_map.into_iter().map(|(id, names)| { + (hir.local_def_id(id), names) + }).collect(), extern_prelude: resolutions.extern_prelude, hir_map: hir, def_path_hash_to_def_id, @@ -2972,6 +2978,10 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(tcx.maybe_unused_extern_crates.clone()) }; + providers.names_imported_by_glob_use = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + Lrc::new(tcx.glob_map.get(&id).cloned().unwrap_or_default()) + }; providers.stability_index = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 26b4735d926a5..f1b36e8def88b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -4,7 +4,7 @@ pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::fold::TypeFoldable; -use hir::{map as hir_map, FreevarMap, TraitMap}; +use hir::{map as hir_map, FreevarMap, GlobMap, TraitMap}; use hir::Node; use hir::def::{Def, CtorKind, ExportMap}; use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -115,16 +115,6 @@ mod sty; // Data types -/// The complete set of all analyses described in this module. This is -/// produced by the driver and fed to codegen and later passes. -/// -/// N.B., these contents are being migrated into queries using the -/// *on-demand* infrastructure. -#[derive(Clone)] -pub struct CrateAnalysis { - pub glob_map: hir::GlobMap, -} - #[derive(Clone)] pub struct Resolutions { pub freevars: FreevarMap, @@ -132,6 +122,7 @@ pub struct Resolutions { pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, pub export_map: ExportMap, + pub glob_map: GlobMap, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. pub extern_prelude: FxHashMap, diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 39d76ceed9507..27b67487637c7 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -541,6 +541,8 @@ define_queries! { <'tcx> [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(DefId) -> bool, [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum) -> Lrc>, + [] fn names_imported_by_glob_use: NamesImportedByGlobUse(DefId) + -> Lrc>, [] fn stability_index: stability_index_node(CrateNum) -> Lrc>, [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 562cd75a75ff4..681376eaa2acd 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1413,6 +1413,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::MaybeUnusedTraitImport => { force!(maybe_unused_trait_import, def_id!()); } + DepKind::NamesImportedByGlobUse => { force!(names_imported_by_glob_use, def_id!()); } DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); } DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); } DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1ecb8ef112c9e..aa7cb0c695c3c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -168,7 +168,6 @@ pub fn compile_input( let ExpansionResult { expanded_crate, defs, - analysis, resolutions, mut hir_forest, } = { @@ -251,7 +250,6 @@ pub fn compile_input( output, &cstore, &hir_map, - &analysis, &resolutions, &expanded_crate, &hir_map.krate(), @@ -277,12 +275,11 @@ pub fn compile_input( sess, cstore, hir_map, - analysis, resolutions, &mut arenas, &crate_name, &outputs, - |tcx, analysis, rx, result| { + |tcx, rx, result| { { // Eventually, we will want to track plugins. tcx.dep_graph.with_ignore(|| { @@ -293,7 +290,6 @@ pub fn compile_input( output, opt_crate, tcx.hir().krate(), - &analysis, tcx, &crate_name, ); @@ -527,7 +523,6 @@ pub struct CompileState<'a, 'tcx: 'a> { pub hir_crate: Option<&'a hir::Crate>, pub hir_map: Option<&'a hir_map::Map<'tcx>>, pub resolutions: Option<&'a Resolutions>, - pub analysis: Option<&'a ty::CrateAnalysis>, pub tcx: Option>, } @@ -547,7 +542,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { hir_crate: None, hir_map: None, resolutions: None, - analysis: None, tcx: None, } } @@ -595,7 +589,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { out_file: &'a Option, cstore: &'tcx CStore, hir_map: &'a hir_map::Map<'tcx>, - analysis: &'a ty::CrateAnalysis, resolutions: &'a Resolutions, krate: &'a ast::Crate, hir_crate: &'a hir::Crate, @@ -606,7 +599,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { crate_name: Some(crate_name), cstore: Some(cstore), hir_map: Some(hir_map), - analysis: Some(analysis), resolutions: Some(resolutions), expanded_crate: Some(krate), hir_crate: Some(hir_crate), @@ -623,12 +615,10 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { out_file: &'a Option, krate: Option<&'a ast::Crate>, hir_crate: &'a hir::Crate, - analysis: &'a ty::CrateAnalysis, tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_name: &'a str, ) -> Self { CompileState { - analysis: Some(analysis), tcx: Some(tcx), expanded_crate: krate, hir_crate: Some(hir_crate), @@ -711,7 +701,6 @@ fn count_nodes(krate: &ast::Crate) -> usize { pub struct ExpansionResult { pub expanded_crate: ast::Crate, pub defs: hir_map::Definitions, - pub analysis: ty::CrateAnalysis, pub resolutions: Resolutions, pub hir_forest: hir_map::Forest, } @@ -772,16 +761,13 @@ where freevars: resolver.freevars, export_map: resolver.export_map, trait_map: resolver.trait_map, + glob_map: resolver.glob_map, maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, maybe_unused_extern_crates: resolver.maybe_unused_extern_crates, extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { (ident.name, entry.introduced_by_item) }).collect(), }, - - analysis: ty::CrateAnalysis { - glob_map: resolver.glob_map - }, }), Err(x) => Err(x), } @@ -1180,7 +1166,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( sess: &'tcx Session, cstore: &'tcx CStore, hir_map: hir_map::Map<'tcx>, - analysis: ty::CrateAnalysis, resolutions: Resolutions, arenas: &'tcx mut AllArenas<'tcx>, name: &str, @@ -1190,7 +1175,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( where F: for<'a> FnOnce( TyCtxt<'a, 'tcx, 'tcx>, - ty::CrateAnalysis, mpsc::Receiver>, CompileResult, ) -> R, @@ -1254,7 +1238,7 @@ where match typeck::check_crate(tcx) { Ok(x) => x, Err(x) => { - f(tcx, analysis, rx, Err(x)); + f(tcx, rx, Err(x)); return Err(x); } } @@ -1307,7 +1291,7 @@ where // lint warnings and so on -- kindck used to do this abort, but // kindck is gone now). -nmatsakis if sess.err_count() > 0 { - return Ok(f(tcx, analysis, rx, sess.compile_status())); + return Ok(f(tcx, rx, sess.compile_status())); } time(sess, "death checking", || middle::dead::check_crate(tcx)); @@ -1318,7 +1302,7 @@ where time(sess, "lint checking", || lint::check_crate(tcx)); - return Ok(f(tcx, analysis, rx, tcx.sess.compile_status())); + return Ok(f(tcx, rx, tcx.sess.compile_status())); }, ) } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 010ac28cdc944..c8a5bbe8315b3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -879,7 +879,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { pretty::print_after_hir_lowering(state.session, state.cstore.unwrap(), state.hir_map.unwrap(), - state.analysis.unwrap(), state.resolutions.unwrap(), state.input, &state.expanded_crate.take().unwrap(), @@ -940,7 +939,6 @@ pub fn enable_save_analysis(control: &mut CompileController) { time(state.session, "save analysis", || { save::process_crate(state.tcx.unwrap(), state.expanded_crate.unwrap(), - state.analysis.unwrap(), state.crate_name.unwrap(), state.input, None, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index a9ec99358c1b2..d1108304d11d9 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -190,7 +190,6 @@ impl PpSourceMode { sess: &'tcx Session, cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis, resolutions: &Resolutions, output_filenames: &OutputFilenames, id: &str, @@ -223,12 +222,11 @@ impl PpSourceMode { sess, cstore, hir_map.clone(), - analysis.clone(), resolutions.clone(), &mut arenas, id, output_filenames, - |tcx, _, _, _| { + |tcx, _, _| { let empty_tables = ty::TypeckTables::empty(None); let annotation = TypedAnnotation { tcx, @@ -959,7 +957,6 @@ pub fn print_after_parsing(sess: &Session, pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis, resolutions: &Resolutions, input: &Input, krate: &ast::Crate, @@ -972,7 +969,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, print_with_analysis(sess, cstore, hir_map, - analysis, resolutions, crate_name, output_filenames, @@ -1010,7 +1006,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, s.call_with_pp_support_hir(sess, cstore, hir_map, - analysis, resolutions, output_filenames, crate_name, @@ -1033,7 +1028,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, s.call_with_pp_support_hir(sess, cstore, hir_map, - analysis, resolutions, output_filenames, crate_name, @@ -1048,7 +1042,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, s.call_with_pp_support_hir(sess, cstore, hir_map, - analysis, resolutions, output_filenames, crate_name, @@ -1081,7 +1074,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, s.call_with_pp_support_hir(sess, cstore, hir_map, - analysis, resolutions, output_filenames, crate_name, @@ -1103,13 +1095,12 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, } // In an ideal world, this would be a public function called by the driver after -// analsysis is performed. However, we want to call `phase_3_run_analysis_passes` +// analysis is performed. However, we want to call `phase_3_run_analysis_passes` // with a different callback than the standard driver, so that isn't easy. // Instead, we call that function ourselves. fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, cstore: &'a CStore, hir_map: &hir_map::Map<'tcx>, - analysis: &ty::CrateAnalysis, resolutions: &Resolutions, crate_name: &str, output_filenames: &OutputFilenames, @@ -1134,12 +1125,11 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, sess, cstore, hir_map.clone(), - analysis.clone(), resolutions.clone(), &mut arenas, crate_name, output_filenames, - |tcx, _, _, _| { + |tcx, _, _| { match ppm { PpmMir | PpmMirCFG => { if let Some(nodeid) = nodeid { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 05156fb51f9da..995df3802aabd 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1238,12 +1238,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { }; // Make a comma-separated list of names of imported modules. - let glob_map = &self.save_ctxt.analysis.glob_map; - let names = if glob_map.contains_key(&id) { - glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect() - } else { - Vec::new() - }; + let def_id = self.tcx.hir().local_def_id(id); + let names = self.tcx.names_imported_by_glob_use(def_id); + let names: Vec<_> = names.iter().map(|n| n.to_string()).collect(); // Otherwise it's a span with wrong macro expansion info, which // we don't want to track anyway, since it's probably macro-internal `use` diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4d55004a055f0..73eb5de5c76f0 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -71,7 +71,6 @@ pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, tables: &'l ty::TypeckTables<'tcx>, access_levels: &'l AccessLevels, - analysis: &'l ty::CrateAnalysis, span_utils: SpanUtils<'tcx>, config: Config, impl_counter: Cell, @@ -1120,7 +1119,6 @@ impl<'b> SaveHandler for CallbackHandler<'b> { pub fn process_crate<'l, 'tcx, H: SaveHandler>( tcx: TyCtxt<'l, 'tcx, 'tcx>, krate: &ast::Crate, - analysis: &'l ty::CrateAnalysis, cratename: &str, input: &'l Input, config: Option, @@ -1139,7 +1137,6 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let save_ctxt = SaveContext { tcx, tables: &ty::TypeckTables::empty(None), - analysis, access_levels: &access_levels, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 6c3a973a41484..7069f04fe188c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -465,15 +465,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt freevars: resolver.freevars.clone(), export_map: resolver.export_map.clone(), trait_map: resolver.trait_map.clone(), + glob_map: resolver.glob_map.clone(), maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(), maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(), extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { (ident.name, entry.introduced_by_item) }).collect(), }; - let analysis = ty::CrateAnalysis { - glob_map: resolver.glob_map.clone(), - }; let mut arenas = AllArenas::new(); let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs); @@ -489,12 +487,11 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt &sess, &*cstore, hir_map, - analysis, resolutions, &mut arenas, &name, &output_filenames, - |tcx, _, _, result| { + |tcx, _, result| { if result.is_err() { sess.fatal("Compilation failed, aborting rustdoc"); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3a64c56fc8eeb..dc1732dbb1d80 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -309,7 +309,7 @@ pub struct Cache { // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing - // the access levels from crateanalysis. + // the access levels from the privacy check pass. pub access_levels: AccessLevels, /// The version of the crate being documented, if given from the `--crate-version` flag. From 3884cc8df480eba9bb8d19fa46e9fe6c9f9d729b Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 17 Jan 2019 15:32:05 +0100 Subject: [PATCH 13/14] Fix typo bug in DepGraph::try_mark_green(). --- src/librustc/dep_graph/graph.rs | 2 +- .../incremental/change_name_of_static_in_fn.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/incremental/change_name_of_static_in_fn.rs diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 501ef01d74c6e..7384af108edbb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -600,7 +600,7 @@ impl DepGraph { DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if dep_node.extract_def_id(tcx).is_none() { + if dep_dep_node.extract_def_id(tcx).is_none() { // If the node does not exist anymore, we // just fail to mark green. return None diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs new file mode 100644 index 0000000000000..5b27b6808ead2 --- /dev/null +++ b/src/test/incremental/change_name_of_static_in_fn.rs @@ -0,0 +1,17 @@ + +// revisions:rpass1 rpass2 rpass3 + +// See issue #57692. + +#![allow(warnings)] + +fn main() { + #[cfg(rpass1)] + { + static map: u64 = 0; + } + #[cfg(not(rpass1))] + { + static MAP: u64 = 0; + } +} From 0c4602aaef787d94ec01d990744bc9e6941ed2eb Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Fri, 18 Jan 2019 15:28:23 -0600 Subject: [PATCH 14/14] Update README.md Point contributors to the rustc-guide... --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb1f06257ed15..514e420ca457c 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,13 @@ Read ["Installation"] from [The Book]. ["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html [The Book]: https://doc.rust-lang.org/book/index.html -## Building from Source +## Installing from Source [building-from-source]: #building-from-source +_Note: If you wish to contribute to the compiler, you should read +[this chapter](https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html) +of the rustc-guide instead._ + ### Building on *nix 1. Make sure you have installed the dependencies: