Take commandline arguments into account for incr. comp.
Implements the conservative strategy described in https://github.com/rust-lang/rust/issues/33727.
From now one, every time a new commandline option is added, one has to specify if it influences the incremental compilation cache. I've tried to implement this as automatic as possible: One just has to added either the `[TRACKED]` or the `[UNTRACKED]` marker next to the field. The `Options`, `CodegenOptions`, and `DebuggingOptions` definitions in `session::config` show plenty of examples.
The PR removes some cruft from `session::config::Options`, mostly unnecessary copies of flags also present in `DebuggingOptions` or `CodeGenOptions` in the same struct.
One notable removal is the `cfg` field that contained the values passed via `--cfg` commandline arguments. I chose to remove it because (1) its content is only a subset of what later is stored in `hir::Crate::config` and it's pretty likely that reading the cfgs from `Options` would not be what you wanted, and (2) we could not incorporate it into the dep-tracking hash of the `Options` struct because of how the test framework works, leaving us with a piece of untracked but vital data.
It is now recommended (just as before) to access the crate config via the `krate()` method in the HIR map.
Because the `cfg` field is not present in the `Options` struct any more, some methods in the `CompilerCalls` trait now take the crate config as an explicit parameter -- which might constitute a breaking change for plugin authors.
use rustc_mir as mir;
use rustc::mir::mir_map::MirMap;
use rustc::session::{Session, CompileResult, compile_result_from_err_count};
- use rustc::session::config::{self, Input, OutputFilenames, OutputType};
+ use rustc::session::config::{self, Input, OutputFilenames, OutputType,
+ OutputTypes};
use rustc::session::search_paths::PathKind;
use rustc::lint;
use rustc::middle::{self, dependency_format, stability, reachable};
use serialize::json;
- use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fs;
cfg: ast::CrateConfig,
input: &Input)
-> PResult<'a, ast::Crate> {
- let continue_after_error = sess.opts.continue_parse_after_error;
+ let continue_after_error = sess.opts.debugging_opts.continue_parse_after_error;
sess.diagnostic().set_continue_after_error(continue_after_error);
let krate = time(sess.time_passes(), "parsing", || {
trace_mac: sess.opts.debugging_opts.trace_macros,
should_test: sess.opts.test,
};
- let mut loader = macro_import::MacroLoader::new(sess, &cstore, crate_name);
+ let mut loader = macro_import::MacroLoader::new(sess,
+ &cstore,
+ crate_name,
+ krate.config.clone());
let mut ecx = syntax::ext::base::ExtCtxt::new(&sess.parse_sess,
krate.config.clone(),
cfg,
&mut loader);
syntax_ext::register_builtins(&mut ecx.syntax_env);
- let (ret, macro_names) = syntax::ext::expand::expand_crate(ecx,
- syntax_exts,
- krate);
+ let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate);
if cfg!(windows) {
env::set_var("PATH", &old_path);
}
- *sess.available_macros.borrow_mut() = macro_names;
+ *sess.available_macros.borrow_mut() = ecx.syntax_env.names;
ret
});
trans: &trans::CrateTranslation,
outputs: &OutputFilenames) -> CompileResult {
if sess.opts.cg.no_integrated_as {
- let mut map = HashMap::new();
- map.insert(OutputType::Assembly, None);
+ let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]);
time(sess.time_passes(),
"LLVM passes",
- || write::run_passes(sess, trans, &map, outputs));
+ || write::run_passes(sess, trans, &output_types, outputs));
write::run_assembler(sess, outputs);
if self.hash.is_none() {
self.should_match_name = false;
if let Some(s) = self.sess.opts.externs.get(self.crate_name) {
- return self.find_commandline_library(s);
+ return self.find_commandline_library(s.iter());
}
self.should_match_name = true;
}
(t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone())
}
- fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
+ fn find_commandline_library<'b, LOCS> (&mut self, locs: LOCS) -> Option<Library>
+ where LOCS: Iterator<Item=&'b String>
+ {
// First, filter out all libraries that look suspicious. We only accept
// files which actually exist that have the correct naming scheme for
// rlibs/dylibs.
let mut rlibs = HashMap::new();
let mut dylibs = HashMap::new();
{
- let locs = locs.iter().map(|l| PathBuf::from(l)).filter(|loc| {
+ let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| {
if !loc.exists() {
sess.err(&format!("extern location for {} does not exist: {}",
self.crate_name, loc.display()));
}
pub fn meta_section_name(target: &Target) -> &'static str {
+ // Historical note:
+ //
+ // When using link.exe it was seen that the section name `.note.rustc`
+ // was getting shortened to `.note.ru`, and according to the PE and COFF
+ // specification:
+ //
+ // > Executable images do not use a string table and do not support
+ // > section names longer than 8 characters
+ //
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
+ //
+ // As a result, we choose a slightly shorter name! As to why
+ // `.note.rustc` works on MinGW, that's another good question...
+
if target.options.is_like_osx {
- "__DATA,__note.rustc"
- } else if target.options.is_like_msvc {
- // When using link.exe it was seen that the section name `.note.rustc`
- // was getting shortened to `.note.ru`, and according to the PE and COFF
- // specification:
- //
- // > Executable images do not use a string table and do not support
- // > section names longer than 8 characters
- //
- // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
- //
- // As a result, we choose a slightly shorter name! As to why
- // `.note.rustc` works on MinGW, that's another good question...
- ".rustc"
+ "__DATA,.rustc"
} else {
- ".note.rustc"
+ ".rustc"
}
}
-pub fn read_meta_section_name(target: &Target) -> &'static str {
- if target.options.is_like_osx {
- "__note.rustc"
- } else if target.options.is_like_msvc {
- ".rustc"
- } else {
- ".note.rustc"
- }
+pub fn read_meta_section_name(_target: &Target) -> &'static str {
+ ".rustc"
}
// A diagnostic function for dumping crate metadata to an output stream
};
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
- let name =
+ let section_name =
cx.tcx().sess.cstore.metadata_section_name(&cx.sess().target.target);
- let name = CString::new(name).unwrap();
- llvm::LLVMSetSection(llglobal, name.as_ptr())
+ let name = CString::new(section_name).unwrap();
+ llvm::LLVMSetSection(llglobal, name.as_ptr());
+
+ // Also generate a .section directive to force no
+ // flags, at least for ELF outputs, so that the
+ // metadata doesn't get loaded into memory.
+ let directive = format!(".section {}", section_name);
+ let directive = CString::new(directive).unwrap();
+ llvm::LLVMSetModuleInlineAsm(cx.metadata_llmod(), directive.as_ptr())
}
return metadata;
}
assert_module_sources::assert_module_sources(tcx, &modules);
// Skip crate items and just output metadata in -Z no-trans mode.
- if tcx.sess.opts.no_trans {
+ if tcx.sess.opts.debugging_opts.no_trans {
let linker_info = LinkerInfo::new(&shared_ccx, &[]);
return CrateTranslation {
modules: modules,
(active, cfg_target_has_atomic, "1.9.0", Some(32976)),
// Allows `..` in tuple (struct) patterns
- (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627))
+ (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)),
+
+ // Allows `impl Trait` in function return types.
+ (active, conservative_impl_trait, "1.12.0", Some(34511)),
+
+ // Allows tuple structs and variants in more contexts,
+ // Permits numeric fields in struct expressions and patterns.
+ (active, relaxed_adts, "1.12.0", Some(35626))
);
declare_features! (
(accepted, issue_5723_bootstrap, "1.0.0", None),
(accepted, macro_rules, "1.0.0", None),
// Allows using #![no_std]
- (accepted, no_std, "1.0.0", None),
+ (accepted, no_std, "1.6.0", None),
(accepted, slicing_syntax, "1.0.0", None),
(accepted, struct_variant, "1.0.0", None),
// These are used to test this portion of the compiler, they don't actually
ast::TyKind::BareFn(ref bare_fn_ty) => {
self.check_abi(bare_fn_ty.abi, ty.span);
}
+ ast::TyKind::ImplTrait(..) => {
+ gate_feature_post!(&self, conservative_impl_trait, ty.span,
+ "`impl Trait` is experimental");
+ }
_ => {}
}
visit::walk_ty(self, ty)
}
PatKind::TupleStruct(_, ref fields, ddpos)
if ddpos.is_none() && fields.is_empty() => {
- self.context.span_handler.struct_span_err(pattern.span,
- "nullary enum variants are written with \
- no trailing `( )`").emit();
+ gate_feature_post!(&self, relaxed_adts, pattern.span,
+ "empty tuple structs patterns are unstable");
}
_ => {}
}
visit::walk_impl_item(self, ii);
}
+ fn visit_variant_data(&mut self, vdata: &ast::VariantData, _: ast::Ident,
+ _: &ast::Generics, _: NodeId, span: Span) {
+ if vdata.fields().is_empty() {
+ if vdata.is_tuple() {
+ gate_feature_post!(&self, relaxed_adts, span,
+ "empty tuple structs and enum variants are unstable, \
+ use unit structs and enum variants instead");
+ }
+ }
+
+ visit::walk_struct_def(self, vdata)
+ }
+
fn visit_vis(&mut self, vis: &ast::Visibility) {
let span = match *vis {
ast::Visibility::Crate(span) => span,
visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
}
- #[derive(Clone, Copy)]
+ #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum UnstableFeatures {
/// Hard errors for unstable features are active, as on
/// beta/stable channels.
self.check_correct_failure_status(&proc_res);
- if proc_res.status.success() {
- self.fatal("process did not return an error status");
- }
-
let output_to_check = self.get_output(&proc_res);
let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
if !expected_errors.is_empty() {
// Add an extra flag pointing at the incremental directory.
let mut revision_props = self.props.clone();
revision_props.incremental_dir = Some(incremental_dir);
+ revision_props.compile_flags.push(String::from("-Zincremental-info"));
let revision_cx = TestCx {
config: self.config,