Auto merge of #35340 - michaelwoerister:incr-comp-cli-args, r=nikomatsakis

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.
This commit is contained in:
bors
2016-08-15 08:35:18 -07:00
committed by GitHub
26 changed files with 1183 additions and 245 deletions
+1 -1
View File
@@ -269,7 +269,7 @@ pub fn as_str(&self) -> String {
}
/// Setting for how to handle a lint.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug)]
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub enum Level {
Allow, Warn, Deny, Forbid
}
+1 -1
View File
@@ -73,7 +73,7 @@ pub enum LinkagePreference {
}
enum_from_u32! {
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
NativeFramework, // OSX-specific
+1023 -171
View File
@@ -33,9 +33,15 @@
use errors::{ColorConfig, FatalError, Handler};
use getopts;
use std::collections::HashMap;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as BTreeMapIter;
use std::collections::btree_map::Keys as BTreeMapKeysIter;
use std::collections::btree_map::Values as BTreeMapValuesIter;
use std::env;
use std::fmt;
use std::hash::{Hasher, SipHasher};
use std::iter::FromIterator;
use std::path::PathBuf;
pub struct Config {
@@ -44,7 +50,7 @@ pub struct Config {
pub uint_type: UintTy,
}
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum OptLevel {
No, // -O0
Less, // -O1
@@ -54,14 +60,15 @@ pub enum OptLevel {
SizeMin, // -Oz
}
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum DebugInfoLevel {
NoDebugInfo,
LimitedDebugInfo,
FullDebugInfo,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord,
RustcEncodable, RustcDecodable)]
pub enum OutputType {
Bitcode,
Assembly,
@@ -118,57 +125,173 @@ pub fn extension(&self) -> &'static str {
}
}
#[derive(Clone)]
pub struct Options {
// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process
pub crate_types: Vec<CrateType>,
// Use tree-based collections to cheaply get a deterministic Hash implementation.
// DO NOT switch BTreeMap out for an unsorted container type! That would break
// dependency tracking for commandline arguments.
#[derive(Clone, Hash)]
pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
pub optimize: OptLevel,
pub debug_assertions: bool,
pub debuginfo: DebugInfoLevel,
pub lint_opts: Vec<(String, lint::Level)>,
pub lint_cap: Option<lint::Level>,
pub describe_lints: bool,
pub output_types: HashMap<OutputType, Option<PathBuf>>,
// This was mutable for rustpkg, which updates search paths based on the
// parsed code. It remains mutable in case its replacements wants to use
// this.
pub search_paths: SearchPaths,
pub libs: Vec<(String, cstore::NativeLibraryKind)>,
pub maybe_sysroot: Option<PathBuf>,
pub target_triple: String,
// User-specified cfg meta items. The compiler itself will add additional
// items to the crate config, and during parsing the entire crate config
// will be added to the crate AST node. This should not be used for
// anything except building the full crate config prior to parsing.
pub cfg: ast::CrateConfig,
pub test: bool,
pub parse_only: bool,
pub no_trans: bool,
pub error_format: ErrorOutputType,
pub treat_err_as_bug: bool,
pub continue_parse_after_error: bool,
pub mir_opt_level: usize,
impl OutputTypes {
pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
OutputTypes(BTreeMap::from_iter(entries.iter()
.map(|&(k, ref v)| (k, v.clone()))))
}
/// if Some, enable incremental compilation, using the given
/// directory to store intermediate results
pub incremental: Option<PathBuf>,
pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> {
self.0.get(key)
}
pub no_analysis: bool,
pub debugging_opts: DebuggingOptions,
pub prints: Vec<PrintRequest>,
pub cg: CodegenOptions,
pub externs: HashMap<String, Vec<String>>,
pub crate_name: Option<String>,
/// An optional name to use as the crate for std during std injection,
/// written `extern crate std = "name"`. Default to "std". Used by
/// out-of-tree drivers.
pub alt_std_name: Option<String>,
/// Indicates how the compiler should treat unstable features
pub unstable_features: UnstableFeatures
pub fn contains_key(&self, key: &OutputType) -> bool {
self.0.contains_key(key)
}
pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
self.0.keys()
}
pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
self.0.values()
}
}
// Use tree-based collections to cheaply get a deterministic Hash implementation.
// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
// would break dependency tracking for commandline arguments.
#[derive(Clone, Hash)]
pub struct Externs(BTreeMap<String, BTreeSet<String>>);
impl Externs {
pub fn new(data: BTreeMap<String, BTreeSet<String>>) -> Externs {
Externs(data)
}
pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
self.0.get(key)
}
pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
self.0.iter()
}
}
macro_rules! hash_option {
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
if $sub_hashes.insert(stringify!($opt_name),
$opt_expr as &dep_tracking::DepTrackingHash).is_some() {
bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
}
});
($opt_name:ident,
$opt_expr:expr,
$sub_hashes:expr,
[UNTRACKED_WITH_WARNING $warn_val:expr, $warn_text:expr, $error_format:expr]) => ({
if *$opt_expr == $warn_val {
early_warn($error_format, $warn_text)
}
});
}
macro_rules! top_level_options {
(pub struct Options { $(
$opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*],
)* } ) => (
#[derive(Clone)]
pub struct Options {
$(pub $opt: $t),*
}
impl Options {
pub fn dep_tracking_hash(&self) -> u64 {
let mut sub_hashes = BTreeMap::new();
$({
hash_option!($opt,
&self.$opt,
&mut sub_hashes,
[$dep_tracking_marker $($warn_val,
$warn_text,
self.error_format)*]);
})*
let mut hasher = SipHasher::new();
dep_tracking::stable_hash(sub_hashes,
&mut hasher,
self.error_format);
hasher.finish()
}
}
);
}
// The top-level commandline options struct
//
// For each option, one has to specify how it behaves with regard to the
// dependency tracking system of incremental compilation. This is done via the
// square-bracketed directive after the field type. The options are:
//
// [TRACKED]
// A change in the given field will cause the compiler to completely clear the
// incremental compilation cache before proceeding.
//
// [UNTRACKED]
// Incremental compilation is not influenced by this option.
//
// [UNTRACKED_WITH_WARNING(val, warning)]
// The option is incompatible with incremental compilation in some way. If it
// has the value `val`, the string `warning` is emitted as a warning.
//
// If you add a new option to this struct or one of the sub-structs like
// CodegenOptions, think about how it influences incremental compilation. If in
// doubt, specify [TRACKED], which is always "correct" but might lead to
// unnecessary re-compilation.
top_level_options!(
pub struct Options {
// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process
crate_types: Vec<CrateType> [TRACKED],
optimize: OptLevel [TRACKED],
// Include the debug_assertions flag into dependency tracking, since it
// can influence whether overflow checks are done or not.
debug_assertions: bool [TRACKED],
debuginfo: DebugInfoLevel [TRACKED],
lint_opts: Vec<(String, lint::Level)> [TRACKED],
lint_cap: Option<lint::Level> [TRACKED],
describe_lints: bool [UNTRACKED],
output_types: OutputTypes [TRACKED],
// FIXME(mw): We track this for now but it actually doesn't make too
// much sense: The search path can stay the same while the
// things discovered there might have changed on disk.
search_paths: SearchPaths [TRACKED],
libs: Vec<(String, cstore::NativeLibraryKind)> [TRACKED],
maybe_sysroot: Option<PathBuf> [TRACKED],
target_triple: String [TRACKED],
test: bool [TRACKED],
error_format: ErrorOutputType [UNTRACKED],
mir_opt_level: usize [TRACKED],
// if Some, enable incremental compilation, using the given
// directory to store intermediate results
incremental: Option<PathBuf> [UNTRACKED],
debugging_opts: DebuggingOptions [TRACKED],
prints: Vec<PrintRequest> [UNTRACKED],
cg: CodegenOptions [TRACKED],
// FIXME(mw): We track this for now but it actually doesn't make too
// much sense: The value of this option can stay the same
// while the files they refer to might have changed on disk.
externs: Externs [TRACKED],
crate_name: Option<String> [TRACKED],
// An optional name to use as the crate for std during std injection,
// written `extern crate std = "name"`. Default to "std". Used by
// out-of-tree drivers.
alt_std_name: Option<String> [TRACKED],
// Indicates how the compiler should treat unstable features
unstable_features: UnstableFeatures [TRACKED],
}
);
#[derive(Clone, PartialEq, Eq)]
pub enum PrintRequest {
FileNames,
@@ -209,7 +332,7 @@ pub struct OutputFilenames {
pub out_filestem: String,
pub single_output_file: Option<PathBuf>,
pub extra: String,
pub outputs: HashMap<OutputType, Option<PathBuf>>,
pub outputs: OutputTypes,
}
/// Codegen unit names generated by the numbered naming scheme will contain this
@@ -301,24 +424,18 @@ pub fn basic_options() -> Options {
lint_opts: Vec::new(),
lint_cap: None,
describe_lints: false,
output_types: HashMap::new(),
output_types: OutputTypes(BTreeMap::new()),
search_paths: SearchPaths::new(),
maybe_sysroot: None,
target_triple: host_triple().to_string(),
cfg: Vec::new(),
test: false,
parse_only: false,
no_trans: false,
treat_err_as_bug: false,
continue_parse_after_error: false,
mir_opt_level: 1,
incremental: None,
no_analysis: false,
debugging_opts: basic_debugging_options(),
prints: Vec::new(),
cg: basic_codegen_options(),
error_format: ErrorOutputType::default(),
externs: HashMap::new(),
externs: Externs(BTreeMap::new()),
crate_name: None,
alt_std_name: None,
libs: Vec::new(),
@@ -361,7 +478,7 @@ pub enum CrateType {
CrateTypeCdylib,
}
#[derive(Clone)]
#[derive(Clone, Hash)]
pub enum Passes {
SomePasses(Vec<String>),
AllPasses,
@@ -376,7 +493,7 @@ pub fn is_empty(&self) -> bool {
}
}
#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Hash)]
pub enum PanicStrategy {
Unwind,
Abort,
@@ -405,7 +522,12 @@ macro_rules! options {
($struct_name:ident, $setter_name:ident, $defaultfn:ident,
$buildfn:ident, $prefix:expr, $outputname:expr,
$stat:ident, $mod_desc:ident, $mod_set:ident,
$($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
$($opt:ident : $t:ty = (
$init:expr,
$parse:ident,
[$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*],
$desc:expr)
),* ,) =>
(
#[derive(Clone)]
pub struct $struct_name { $(pub $opt: $t),* }
@@ -457,6 +579,22 @@ pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $s
return op;
}
impl<'a> dep_tracking::DepTrackingHash for $struct_name {
fn hash(&self, hasher: &mut SipHasher, error_format: ErrorOutputType) {
let mut sub_hashes = BTreeMap::new();
$({
hash_option!($opt,
&self.$opt,
&mut sub_hashes,
[$dep_tracking_marker $($dep_warn_val,
$dep_warn_text,
error_format)*]);
})*
dep_tracking::stable_hash(sub_hashes, hasher, error_format);
}
}
pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
pub const $stat: &'static [(&'static str, $setter_name,
Option<&'static str>, &'static str)] =
@@ -622,168 +760,177 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
options! {CodegenOptions, CodegenSetter, basic_codegen_options,
build_codegen_options, "C", "codegen",
CG_OPTIONS, cg_type_desc, cgsetters,
ar: Option<String> = (None, parse_opt_string,
ar: Option<String> = (None, parse_opt_string, [UNTRACKED],
"tool to assemble archives with"),
linker: Option<String> = (None, parse_opt_string,
linker: Option<String> = (None, parse_opt_string, [UNTRACKED],
"system linker to link outputs with"),
link_args: Option<Vec<String>> = (None, parse_opt_list,
link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
"extra arguments to pass to the linker (space separated)"),
link_dead_code: bool = (false, parse_bool,
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
"don't let linker strip dead code (turning it on can be used for code coverage)"),
lto: bool = (false, parse_bool,
lto: bool = (false, parse_bool, [TRACKED],
"perform LLVM link-time optimizations"),
target_cpu: Option<String> = (None, parse_opt_string,
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select target processor (rustc --print target-cpus for details)"),
target_feature: String = ("".to_string(), parse_string,
target_feature: String = ("".to_string(), parse_string, [TRACKED],
"target specific attributes (rustc --print target-features for details)"),
passes: Vec<String> = (Vec::new(), parse_list,
passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list of extra LLVM passes to run (space separated)"),
llvm_args: Vec<String> = (Vec::new(), parse_list,
llvm_args: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list of arguments to pass to llvm (space separated)"),
save_temps: bool = (false, parse_bool,
save_temps: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"`-C save-temps` might not produce all requested temporary products \
when incremental compilation is enabled.")],
"save all temporary output files during compilation"),
rpath: bool = (false, parse_bool,
rpath: bool = (false, parse_bool, [UNTRACKED],
"set rpath values in libs/exes"),
no_prepopulate_passes: bool = (false, parse_bool,
no_prepopulate_passes: bool = (false, parse_bool, [TRACKED],
"don't pre-populate the pass manager with a list of passes"),
no_vectorize_loops: bool = (false, parse_bool,
no_vectorize_loops: bool = (false, parse_bool, [TRACKED],
"don't run the loop vectorization optimization passes"),
no_vectorize_slp: bool = (false, parse_bool,
no_vectorize_slp: bool = (false, parse_bool, [TRACKED],
"don't run LLVM's SLP vectorization pass"),
soft_float: bool = (false, parse_bool,
soft_float: bool = (false, parse_bool, [TRACKED],
"generate software floating point library calls"),
prefer_dynamic: bool = (false, parse_bool,
prefer_dynamic: bool = (false, parse_bool, [TRACKED],
"prefer dynamic linking to static linking"),
no_integrated_as: bool = (false, parse_bool,
no_integrated_as: bool = (false, parse_bool, [TRACKED],
"use an external assembler rather than LLVM's integrated one"),
no_redzone: Option<bool> = (None, parse_opt_bool,
no_redzone: Option<bool> = (None, parse_opt_bool, [TRACKED],
"disable the use of the redzone"),
relocation_model: Option<String> = (None, parse_opt_string,
relocation_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the relocation model to use (rustc --print relocation-models for details)"),
code_model: Option<String> = (None, parse_opt_string,
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the code model to use (rustc --print code-models for details)"),
metadata: Vec<String> = (Vec::new(), parse_list,
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"metadata to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string,
extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
"extra data to put in each output filename"),
codegen_units: usize = (1, parse_uint,
codegen_units: usize = (1, parse_uint, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
remark: Passes = (SomePasses(Vec::new()), parse_passes,
remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED],
"print remarks for these optimization passes (space separated, or \"all\")"),
no_stack_check: bool = (false, parse_bool,
no_stack_check: bool = (false, parse_bool, [UNTRACKED],
"disable checks for stack exhaustion (a memory-safety hazard!)"),
debuginfo: Option<usize> = (None, parse_opt_uint,
debuginfo: Option<usize> = (None, parse_opt_uint, [TRACKED],
"debug info emission level, 0 = no debug info, 1 = line tables only, \
2 = full debug info with variable and type information"),
opt_level: Option<String> = (None, parse_opt_string,
opt_level: Option<String> = (None, parse_opt_string, [TRACKED],
"optimize with possible levels 0-3, s, or z"),
debug_assertions: Option<bool> = (None, parse_opt_bool,
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the cfg(debug_assertions) directive"),
inline_threshold: Option<usize> = (None, parse_opt_uint,
inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
"set the inlining threshold for"),
panic: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy,
"panic strategy to compile crate with"),
[TRACKED], "panic strategy to compile crate with"),
}
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
build_debugging_options, "Z", "debugging",
DB_OPTIONS, db_type_desc, dbsetters,
verbose: bool = (false, parse_bool,
verbose: bool = (false, parse_bool, [UNTRACKED],
"in general, enable more debug printouts"),
time_passes: bool = (false, parse_bool,
time_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each rustc pass"),
count_llvm_insns: bool = (false, parse_bool,
[UNTRACKED_WITH_WARNING(true,
"The output generated by `-Z count_llvm_insns` might not be reliable \
when used with incremental compilation")],
"count where LLVM instrs originate"),
time_llvm_passes: bool = (false, parse_bool,
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z time-llvm-passes` will only reflect timings of \
re-translated modules when used with incremental compilation" )],
"measure time of each LLVM pass"),
input_stats: bool = (false, parse_bool,
input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input"),
trans_stats: bool = (false, parse_bool,
trans_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z trans-stats` might not be accurate when incremental \
compilation is enabled")],
"gather trans statistics"),
asm_comments: bool = (false, parse_bool,
asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior)"),
no_verify: bool = (false, parse_bool,
no_verify: bool = (false, parse_bool, [TRACKED],
"skip LLVM verification"),
borrowck_stats: bool = (false, parse_bool,
borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
"gather borrowck statistics"),
no_landing_pads: bool = (false, parse_bool,
no_landing_pads: bool = (false, parse_bool, [TRACKED],
"omit landing pads for unwinding"),
debug_llvm: bool = (false, parse_bool,
debug_llvm: bool = (false, parse_bool, [UNTRACKED],
"enable debug output from LLVM"),
meta_stats: bool = (false, parse_bool,
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics"),
print_link_args: bool = (false, parse_bool,
print_link_args: bool = (false, parse_bool, [UNTRACKED],
"print the arguments passed to the linker"),
print_llvm_passes: bool = (false, parse_bool,
print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
"prints the llvm optimization passes being run"),
ast_json: bool = (false, parse_bool,
ast_json: bool = (false, parse_bool, [UNTRACKED],
"print the AST as JSON and halt"),
ast_json_noexpand: bool = (false, parse_bool,
ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED],
"print the pre-expansion AST as JSON and halt"),
ls: bool = (false, parse_bool,
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate"),
save_analysis: bool = (false, parse_bool,
save_analysis: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in JSON format) information in addition to normal output"),
save_analysis_csv: bool = (false, parse_bool,
save_analysis_csv: bool = (false, parse_bool, [UNTRACKED],
"write syntax and type analysis (in CSV format) information in addition to normal output"),
print_move_fragments: bool = (false, parse_bool,
print_move_fragments: bool = (false, parse_bool, [UNTRACKED],
"print out move-fragment data for every fn"),
flowgraph_print_loans: bool = (false, parse_bool,
flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
"include loan analysis data in --unpretty flowgraph output"),
flowgraph_print_moves: bool = (false, parse_bool,
flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
"include move analysis data in --unpretty flowgraph output"),
flowgraph_print_assigns: bool = (false, parse_bool,
flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
"include assignment analysis data in --unpretty flowgraph output"),
flowgraph_print_all: bool = (false, parse_bool,
flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
"include all dataflow analysis data in --unpretty flowgraph output"),
print_region_graph: bool = (false, parse_bool,
print_region_graph: bool = (false, parse_bool, [UNTRACKED],
"prints region inference graph. \
Use with RUST_REGION_GRAPH=help for more info"),
parse_only: bool = (false, parse_bool,
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link"),
no_trans: bool = (false, parse_bool,
no_trans: bool = (false, parse_bool, [TRACKED],
"run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool,
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
"treat all errors that occur as bugs"),
continue_parse_after_error: bool = (false, parse_bool,
continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
"attempt to recover from parse errors (experimental)"),
incremental: Option<String> = (None, parse_opt_string,
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation (experimental)"),
incremental_info: bool = (false, parse_bool,
incremental_info: bool = (false, parse_bool, [UNTRACKED],
"print high-level information about incremental reuse (or the lack thereof)"),
dump_dep_graph: bool = (false, parse_bool,
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
query_dep_graph: bool = (false, parse_bool,
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"enable queries of the dependency graph for regression testing"),
no_analysis: bool = (false, parse_bool,
no_analysis: bool = (false, parse_bool, [UNTRACKED],
"parse and expand the source, but run no analysis"),
extra_plugins: Vec<String> = (Vec::new(), parse_list,
extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"load extra plugins"),
unstable_options: bool = (false, parse_bool,
unstable_options: bool = (false, parse_bool, [UNTRACKED],
"adds unstable command line options to rustc interface"),
force_overflow_checks: Option<bool> = (None, parse_opt_bool,
force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"force overflow checks on or off"),
force_dropflag_checks: Option<bool> = (None, parse_opt_bool,
force_dropflag_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"force drop flag checks on or off"),
trace_macros: bool = (false, parse_bool,
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments"),
enable_nonzeroing_move_hints: bool = (false, parse_bool,
enable_nonzeroing_move_hints: bool = (false, parse_bool, [TRACKED],
"force nonzeroing move optimization on"),
keep_hygiene_data: bool = (false, parse_bool,
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
"don't clear the hygiene data after analysis"),
keep_ast: bool = (false, parse_bool,
keep_ast: bool = (false, parse_bool, [UNTRACKED],
"keep the AST after lowering it to HIR"),
show_span: Option<String> = (None, parse_opt_string,
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
"show spans for compiler debugging (expr|pat|ty)"),
print_trans_items: Option<String> = (None, parse_opt_string,
print_trans_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
"print the result of the translation item collection pass"),
mir_opt_level: Option<usize> = (None, parse_opt_uint,
mir_opt_level: Option<usize> = (None, parse_opt_uint, [TRACKED],
"set the MIR optimization level (0-3)"),
dump_mir: Option<String> = (None, parse_opt_string,
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"dump MIR state at various points in translation"),
dump_mir_dir: Option<String> = (None, parse_opt_string,
dump_mir_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"the directory the MIR is dumped into"),
orbit: bool = (true, parse_all_bool,
orbit: bool = (true, parse_all_bool, [UNTRACKED],
"get MIR where it belongs - everywhere; most importantly, in orbit"),
}
@@ -849,11 +996,12 @@ pub fn append_configuration(cfg: &mut ast::CrateConfig,
}
}
pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
pub fn build_configuration(sess: &Session,
mut user_cfg: ast::CrateConfig)
-> ast::CrateConfig {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items
let default_cfg = default_configuration(sess);
let mut user_cfg = sess.opts.cfg.clone();
// If the user wants a test runner, then add the test cfg
if sess.opts.test {
append_configuration(&mut user_cfg, InternedString::new("test"))
@@ -1115,7 +1263,8 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
}).collect::<ast::CrateConfig>()
}
pub fn build_session_options(matches: &getopts::Matches) -> Options {
pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
-> (Options, ast::CrateConfig) {
let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
@@ -1185,14 +1334,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
debugging_opts.orbit = true;
}
let parse_only = debugging_opts.parse_only;
let no_trans = debugging_opts.no_trans;
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
let continue_parse_after_error = debugging_opts.continue_parse_after_error;
let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
let no_analysis = debugging_opts.no_analysis;
let mut output_types = HashMap::new();
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
for output_type in list.split(',') {
@@ -1360,7 +1504,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
--debuginfo");
}
let mut externs = HashMap::new();
let mut externs = BTreeMap::new();
for arg in &matches.opt_strs("extern") {
let mut parts = arg.splitn(2, '=');
let name = match parts.next() {
@@ -1372,44 +1516,41 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
None => early_error(error_format, "--extern value must be of the format `foo=bar`"),
};
externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string());
externs.entry(name.to_string())
.or_insert_with(BTreeSet::new)
.insert(location.to_string());
}
let crate_name = matches.opt_str("crate-name");
let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m));
Options {
(Options {
crate_types: crate_types,
optimize: opt_level,
debuginfo: debuginfo,
lint_opts: lint_opts,
lint_cap: lint_cap,
describe_lints: describe_lints,
output_types: output_types,
output_types: OutputTypes(output_types),
search_paths: search_paths,
maybe_sysroot: sysroot_opt,
target_triple: target,
cfg: cfg,
test: test,
parse_only: parse_only,
no_trans: no_trans,
treat_err_as_bug: treat_err_as_bug,
continue_parse_after_error: continue_parse_after_error,
mir_opt_level: mir_opt_level,
incremental: incremental,
no_analysis: no_analysis,
debugging_opts: debugging_opts,
prints: prints,
cg: cg,
error_format: error_format,
externs: externs,
externs: Externs(externs),
crate_name: crate_name,
alt_std_name: None,
libs: libs,
unstable_features: get_unstable_features_setting(),
debug_assertions: debug_assertions,
}
},
cfg)
}
pub fn get_unstable_features_setting() -> UnstableFeatures {
@@ -1530,15 +1671,139 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
/// Commandline arguments passed to the compiler have to be incorporated with
/// the dependency tracking system for incremental compilation. This module
/// provides some utilities to make this more convenient.
///
/// The values of all commandline arguments that are relevant for dependency
/// tracking are hashed into a single value that determines whether the
/// incremental compilation cache can be re-used or not. This hashing is done
/// via the DepTrackingHash trait defined below, since the standard Hash
/// implementation might not be suitable (e.g. arguments are stored in a Vec,
/// the hash of which is order dependent, but we might not want the order of
/// arguments to make a difference for the hash).
///
/// However, since the value provided by Hash::hash often *is* suitable,
/// especially for primitive types, there is the
/// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
/// Hash implementation for DepTrackingHash. It's important though that
/// we have an opt-in scheme here, so one is hopefully forced to think about
/// how the hash should be calculated when adding a new commandline argument.
mod dep_tracking {
use lint;
use middle::cstore;
use session::search_paths::{PathKind, SearchPaths};
use std::collections::BTreeMap;
use std::hash::{Hash, SipHasher};
use std::path::PathBuf;
use super::{Passes, PanicStrategy, CrateType, OptLevel, DebugInfoLevel,
OutputTypes, Externs, ErrorOutputType};
use syntax::feature_gate::UnstableFeatures;
pub trait DepTrackingHash {
fn hash(&self, &mut SipHasher, ErrorOutputType);
}
macro_rules! impl_dep_tracking_hash_via_hash {
($t:ty) => (
impl DepTrackingHash for $t {
fn hash(&self, hasher: &mut SipHasher, _: ErrorOutputType) {
Hash::hash(self, hasher);
}
}
)
}
macro_rules! impl_dep_tracking_hash_for_sortable_vec_of {
($t:ty) => (
impl DepTrackingHash for Vec<$t> {
fn hash(&self, hasher: &mut SipHasher, error_format: ErrorOutputType) {
let mut elems: Vec<&$t> = self.iter().collect();
elems.sort();
Hash::hash(&elems.len(), hasher);
for (index, elem) in elems.iter().enumerate() {
Hash::hash(&index, hasher);
DepTrackingHash::hash(*elem, hasher, error_format);
}
}
}
);
}
impl_dep_tracking_hash_via_hash!(bool);
impl_dep_tracking_hash_via_hash!(usize);
impl_dep_tracking_hash_via_hash!(String);
impl_dep_tracking_hash_via_hash!(lint::Level);
impl_dep_tracking_hash_via_hash!(Option<bool>);
impl_dep_tracking_hash_via_hash!(Option<usize>);
impl_dep_tracking_hash_via_hash!(Option<String>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
impl_dep_tracking_hash_via_hash!(CrateType);
impl_dep_tracking_hash_via_hash!(PanicStrategy);
impl_dep_tracking_hash_via_hash!(Passes);
impl_dep_tracking_hash_via_hash!(OptLevel);
impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
impl_dep_tracking_hash_via_hash!(Externs);
impl_dep_tracking_hash_via_hash!(OutputTypes);
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
impl_dep_tracking_hash_for_sortable_vec_of!((String, cstore::NativeLibraryKind));
impl DepTrackingHash for SearchPaths {
fn hash(&self, hasher: &mut SipHasher, _: ErrorOutputType) {
let mut elems: Vec<_> = self
.iter(PathKind::All)
.collect();
elems.sort();
Hash::hash(&elems, hasher);
}
}
impl<T1, T2> DepTrackingHash for (T1, T2)
where T1: DepTrackingHash,
T2: DepTrackingHash
{
fn hash(&self, hasher: &mut SipHasher, error_format: ErrorOutputType) {
Hash::hash(&0, hasher);
DepTrackingHash::hash(&self.0, hasher, error_format);
Hash::hash(&1, hasher);
DepTrackingHash::hash(&self.1, hasher, error_format);
}
}
// This is a stable hash because BTreeMap is a sorted container
pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &DepTrackingHash>,
hasher: &mut SipHasher,
error_format: ErrorOutputType) {
for (key, sub_hash) in sub_hashes {
// Using Hash::hash() instead of DepTrackingHash::hash() is fine for
// the keys, as they are just plain strings
Hash::hash(&key.len(), hasher);
Hash::hash(key, hasher);
sub_hash.hash(hasher, error_format);
}
}
}
#[cfg(test)]
mod tests {
use dep_graph::DepGraph;
use middle::cstore::DummyCrateStore;
use session::config::{build_configuration, build_session_options};
use session::build_session;
use errors;
use std::rc::Rc;
use getopts::{getopts, OptGroup};
use lint;
use middle::cstore::{self, DummyCrateStore};
use session::config::{build_configuration, build_session_options_and_crate_config};
use session::build_session;
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
use std::path::PathBuf;
use std::rc::Rc;
use super::{OutputType, OutputTypes, Externs, PanicStrategy};
use syntax::attr;
use syntax::attr::AttrMetaMethods;
@@ -1548,6 +1813,14 @@ fn optgroups() -> Vec<OptGroup> {
.collect()
}
fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
BTreeMap::from_iter(entries.into_iter())
}
fn mk_set<V: Ord>(entries: Vec<V>) -> BTreeSet<V> {
BTreeSet::from_iter(entries.into_iter())
}
// When the user supplies --test we should implicitly supply --cfg test
#[test]
fn test_switch_implies_cfg_test() {
@@ -1558,9 +1831,9 @@ fn test_switch_implies_cfg_test() {
Err(f) => panic!("test_switch_implies_cfg_test: {}", f)
};
let registry = errors::registry::Registry::new(&[]);
let sessopts = build_session_options(matches);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore));
let cfg = build_configuration(&sess);
let cfg = build_configuration(&sess, cfg);
assert!((attr::contains_name(&cfg[..], "test")));
}
@@ -1578,10 +1851,10 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
}
};
let registry = errors::registry::Registry::new(&[]);
let sessopts = build_session_options(matches);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
let sess = build_session(sessopts, &dep_graph, None, registry,
Rc::new(DummyCrateStore));
let cfg = build_configuration(&sess);
let cfg = build_configuration(&sess, cfg);
let mut test_items = cfg.iter().filter(|m| m.name() == "test");
assert!(test_items.next().is_some());
assert!(test_items.next().is_none());
@@ -1595,7 +1868,7 @@ fn test_can_print_warnings() {
"-Awarnings".to_string()
], &optgroups()).unwrap();
let registry = errors::registry::Registry::new(&[]);
let sessopts = build_session_options(&matches);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, &dep_graph, None, registry,
Rc::new(DummyCrateStore));
assert!(!sess.diagnostic().can_emit_warnings);
@@ -1607,7 +1880,7 @@ fn test_can_print_warnings() {
"-Dwarnings".to_string()
], &optgroups()).unwrap();
let registry = errors::registry::Registry::new(&[]);
let sessopts = build_session_options(&matches);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, &dep_graph, None, registry,
Rc::new(DummyCrateStore));
assert!(sess.diagnostic().can_emit_warnings);
@@ -1618,10 +1891,589 @@ fn test_can_print_warnings() {
"-Adead_code".to_string()
], &optgroups()).unwrap();
let registry = errors::registry::Registry::new(&[]);
let sessopts = build_session_options(&matches);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, &dep_graph, None, registry,
Rc::new(DummyCrateStore));
assert!(sess.diagnostic().can_emit_warnings);
}
}
#[test]
fn test_output_types_tracking_hash_different_paths() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
v1.output_types = OutputTypes::new(&[(OutputType::Exe,
Some(PathBuf::from("./some/thing")))]);
v2.output_types = OutputTypes::new(&[(OutputType::Exe,
Some(PathBuf::from("/some/thing")))]);
v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_output_types_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
v1.output_types = OutputTypes::new(&[
(OutputType::Exe, Some(PathBuf::from("./some/thing"))),
(OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
]);
v2.output_types = OutputTypes::new(&[
(OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
(OutputType::Exe, Some(PathBuf::from("./some/thing"))),
]);
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
}
#[test]
fn test_externs_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
v1.externs = Externs::new(mk_map(vec![
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
(String::from("d"), mk_set(vec![String::from("e"),
String::from("f")])),
]));
v2.externs = Externs::new(mk_map(vec![
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
(String::from("X"), mk_set(vec![String::from("e"),
String::from("f")])),
]));
v3.externs = Externs::new(mk_map(vec![
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
(String::from("d"), mk_set(vec![String::from("X"),
String::from("f")])),
]));
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_externs_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
v1.externs = Externs::new(mk_map(vec![
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
(String::from("d"), mk_set(vec![String::from("e"),
String::from("f")])),
]));
v2.externs = Externs::new(mk_map(vec![
(String::from("d"), mk_set(vec![String::from("e"),
String::from("f")])),
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
]));
v3.externs = Externs::new(mk_map(vec![
(String::from("a"), mk_set(vec![String::from("b"),
String::from("c")])),
(String::from("d"), mk_set(vec![String::from("f"),
String::from("e")])),
]));
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_lints_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
v1.lint_opts = vec![(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Deny),
(String::from("d"), lint::Forbid)];
v2.lint_opts = vec![(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("X"), lint::Deny),
(String::from("d"), lint::Forbid)];
v3.lint_opts = vec![(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Forbid),
(String::from("d"), lint::Deny)];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_lints_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
v1.lint_opts = vec![(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Deny),
(String::from("d"), lint::Forbid)];
v2.lint_opts = vec![(String::from("a"), lint::Allow),
(String::from("c"), lint::Deny),
(String::from("b"), lint::Warn),
(String::from("d"), lint::Forbid)];
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
}
#[test]
fn test_search_paths_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
let mut v4 = super::basic_options();
let mut v5 = super::basic_options();
// Reference
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
// Native changed
v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
// Crate changed
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
// Dependency changed
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json);
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
// Framework changed
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json);
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
// All changed
v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json);
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v5.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
assert_eq!(v5.dep_tracking_hash(), v5.clone().dep_tracking_hash());
}
#[test]
fn test_search_paths_tracking_hash_different_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
let mut v4 = super::basic_options();
// Reference
v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
}
#[test]
fn test_native_libs_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
// Reference
v1.libs = vec![(String::from("a"), cstore::NativeStatic),
(String::from("b"), cstore::NativeFramework),
(String::from("c"), cstore::NativeUnknown)];
// Change label
v2.libs = vec![(String::from("a"), cstore::NativeStatic),
(String::from("X"), cstore::NativeFramework),
(String::from("c"), cstore::NativeUnknown)];
// Change kind
v3.libs = vec![(String::from("a"), cstore::NativeStatic),
(String::from("b"), cstore::NativeStatic),
(String::from("c"), cstore::NativeUnknown)];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_native_libs_tracking_hash_different_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
// Reference
v1.libs = vec![(String::from("a"), cstore::NativeStatic),
(String::from("b"), cstore::NativeFramework),
(String::from("c"), cstore::NativeUnknown)];
v2.libs = vec![(String::from("b"), cstore::NativeFramework),
(String::from("a"), cstore::NativeStatic),
(String::from("c"), cstore::NativeUnknown)];
v3.libs = vec![(String::from("c"), cstore::NativeUnknown),
(String::from("a"), cstore::NativeStatic),
(String::from("b"), cstore::NativeFramework)];
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_codegen_options_tracking_hash() {
let reference = super::basic_options();
let mut opts = super::basic_options();
// Make sure the changing an [UNTRACKED] option leaves the hash unchanged
opts.cg.ar = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.linker = Some(String::from("linker"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]);
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_dead_code = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.rpath = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.extra_filename = String::from("extra-filename");
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.codegen_units = 42;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.remark = super::SomePasses(vec![String::from("pass1"),
String::from("pass2")]);
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.save_temps = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
// Make sure changing a [TRACKED] option changes the hash
opts = reference.clone();
opts.cg.lto = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.target_cpu = Some(String::from("abc"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.target_feature = String::from("all the features, all of them");
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.passes = vec![String::from("1"), String::from("2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.llvm_args = vec![String::from("1"), String::from("2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_prepopulate_passes = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_vectorize_loops = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_vectorize_slp = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.soft_float = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.prefer_dynamic = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_integrated_as = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_redzone = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.relocation_model = Some(String::from("relocation model"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.code_model = Some(String::from("code model"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.metadata = vec![String::from("A"), String::from("B")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debuginfo = Some(0xdeadbeef);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debuginfo = Some(0xba5eba11);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debug_assertions = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.inline_threshold = Some(0xf007ba11);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.panic = PanicStrategy::Abort;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
#[test]
fn test_debugging_options_tracking_hash() {
let reference = super::basic_options();
let mut opts = super::basic_options();
// Make sure the changing an [UNTRACKED] option leaves the hash unchanged
opts.debugging_opts.verbose = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.count_llvm_insns = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.input_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.trans_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.debug_llvm = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_link_args = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ast_json = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ast_json_noexpand = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ls = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.save_analysis = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.save_analysis_csv = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_move_fragments = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_loans = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_moves = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_assigns = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_all = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_region_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.parse_only = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.incremental = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_dep_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.query_dep_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.no_analysis = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.unstable_options = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.trace_macros = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.keep_hygiene_data = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.keep_ast = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_trans_items = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir_dir = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.orbit = false;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
// Make sure changing a [TRACKED] option changes the hash
opts = reference.clone();
opts.debugging_opts.asm_comments = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_verify = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_landing_pads = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_trans = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.treat_err_as_bug = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.continue_parse_after_error = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.force_overflow_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.force_dropflag_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.enable_nonzeroing_move_hints = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.show_span = Some(String::from("abc"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.mir_opt_level = Some(1);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
}
+1 -1
View File
@@ -363,7 +363,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
.map(|&(_, ref level)| *level != lint::Allow)
.last()
.unwrap_or(true);
let treat_err_as_bug = sopts.treat_err_as_bug;
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
let emitter: Box<Emitter> = match sopts.error_format {
config::ErrorOutputType::HumanReadable(color_config) => {
+1 -1
View File
@@ -22,7 +22,7 @@ pub struct Iter<'a> {
iter: slice::Iter<'a, (PathKind, PathBuf)>,
}
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
#[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash)]
pub enum PathKind {
Native,
Crate,
+9 -7
View File
@@ -15,7 +15,8 @@
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};
@@ -42,7 +43,6 @@
use serialize::json;
use std::collections::HashMap;
use std::env;
use std::ffi::{OsString, OsStr};
use std::fs;
@@ -478,7 +478,7 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session,
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", || {
@@ -667,7 +667,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
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,
@@ -1024,11 +1027,10 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
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);
+29 -15
View File
@@ -181,7 +181,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
None => return (Ok(()), None),
};
let sopts = config::build_session_options(&matches);
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
if sopts.debugging_opts.debug_llvm {
unsafe { llvm::LLVMRustSetDebug(1); }
@@ -191,6 +191,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
do_or_return!(callbacks.early_callback(&matches,
&sopts,
&cfg,
&descriptions,
sopts.error_format),
None);
@@ -198,7 +199,7 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
let (odir, ofile) = make_output(&matches);
let (input, input_file_path) = match make_input(&matches.free) {
Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
None => match callbacks.no_input(&matches, &sopts, &cfg, &odir, &ofile, &descriptions) {
Some((input, input_file_path)) => (input, input_file_path),
None => return (Ok(()), None),
},
@@ -214,10 +215,11 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
cstore.clone(),
codemap);
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess);
let mut cfg = config::build_configuration(&sess, cfg);
target_features::add_configuration(&mut cfg, &sess);
do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
do_or_return!(callbacks.late_callback(&matches, &sess, &cfg, &input, &odir, &ofile),
Some(sess));
let plugins = sess.opts.debugging_opts.extra_plugins.clone();
let control = callbacks.build_controller(&sess, &matches);
@@ -297,6 +299,7 @@ pub trait CompilerCalls<'a> {
fn early_callback(&mut self,
_: &getopts::Matches,
_: &config::Options,
_: &ast::CrateConfig,
_: &errors::registry::Registry,
_: ErrorOutputType)
-> Compilation {
@@ -309,6 +312,7 @@ fn early_callback(&mut self,
fn late_callback(&mut self,
_: &getopts::Matches,
_: &Session,
_: &ast::CrateConfig,
_: &Input,
_: &Option<PathBuf>,
_: &Option<PathBuf>)
@@ -334,6 +338,7 @@ fn some_input(&mut self,
fn no_input(&mut self,
_: &getopts::Matches,
_: &config::Options,
_: &ast::CrateConfig,
_: &Option<PathBuf>,
_: &Option<PathBuf>,
_: &errors::registry::Registry)
@@ -375,7 +380,7 @@ fn handle_explain(code: &str,
}
}
fn check_cfg(sopts: &config::Options,
fn check_cfg(cfg: &ast::CrateConfig,
output: ErrorOutputType) {
let emitter: Box<Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
@@ -386,7 +391,7 @@ fn check_cfg(sopts: &config::Options,
let handler = errors::Handler::with_emitter(true, false, emitter);
let mut saw_invalid_predicate = false;
for item in sopts.cfg.iter() {
for item in cfg.iter() {
if item.is_meta_item_list() {
saw_invalid_predicate = true;
handler.emit(&MultiSpan::new(),
@@ -404,7 +409,8 @@ fn check_cfg(sopts: &config::Options,
impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
fn early_callback(&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
_: &config::Options,
cfg: &ast::CrateConfig,
descriptions: &errors::registry::Registry,
output: ErrorOutputType)
-> Compilation {
@@ -413,13 +419,14 @@ fn early_callback(&mut self,
return Compilation::Stop;
}
check_cfg(sopts, output);
check_cfg(cfg, output);
Compilation::Continue
}
fn no_input(&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
cfg: &ast::CrateConfig,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
descriptions: &errors::registry::Registry)
@@ -440,7 +447,13 @@ fn no_input(&mut self,
descriptions.clone(),
cstore.clone());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let should_stop = RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
let mut cfg = config::build_configuration(&sess, cfg.clone());
target_features::add_configuration(&mut cfg, &sess);
let should_stop = RustcDefaultCalls::print_crate_info(&sess,
&cfg,
None,
odir,
ofile);
if should_stop == Compilation::Stop {
return None;
}
@@ -456,11 +469,12 @@ fn no_input(&mut self,
fn late_callback(&mut self,
matches: &getopts::Matches,
sess: &Session,
cfg: &ast::CrateConfig,
input: &Input,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>)
-> Compilation {
RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile)
RustcDefaultCalls::print_crate_info(sess, cfg, Some(input), odir, ofile)
.and_then(|| RustcDefaultCalls::list_metadata(sess, matches, input))
}
@@ -506,12 +520,14 @@ fn build_controller(&mut self,
return control;
}
if sess.opts.parse_only || sess.opts.debugging_opts.show_span.is_some() ||
if sess.opts.debugging_opts.parse_only ||
sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
control.after_parse.stop = Compilation::Stop;
}
if sess.opts.no_analysis || sess.opts.debugging_opts.ast_json {
if sess.opts.debugging_opts.no_analysis ||
sess.opts.debugging_opts.ast_json {
control.after_hir_lowering.stop = Compilation::Stop;
}
@@ -577,6 +593,7 @@ pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input)
fn print_crate_info(sess: &Session,
cfg: &ast::CrateConfig,
input: Option<&Input>,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>)
@@ -629,9 +646,6 @@ fn print_crate_info(sess: &Session,
}
}
PrintRequest::Cfg => {
let mut cfg = config::build_configuration(&sess);
target_features::add_configuration(&mut cfg, &sess);
let allow_unstable_cfg = match get_unstable_features_setting() {
UnstableFeatures::Disallow => false,
_ => true,
@@ -158,6 +158,10 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
}
}
pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
self.tcx
}
pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
let tcx = self.tcx;
+17 -2
View File
@@ -101,8 +101,25 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
work_products_data: &[u8])
-> Result<(), Error>
{
// Decode the list of work_products
let mut work_product_decoder = Decoder::new(work_products_data, 0);
let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
// Deserialize the directory and dep-graph.
let mut dep_graph_decoder = Decoder::new(dep_graph_data, 0);
let prev_commandline_args_hash = try!(u64::decode(&mut dep_graph_decoder));
if prev_commandline_args_hash != tcx.sess.opts.dep_tracking_hash() {
// We can't reuse the cache, purge it.
debug!("decode_dep_graph: differing commandline arg hashes");
for swp in work_products {
delete_dirty_work_product(tcx, swp);
}
// No need to do any further work
return Ok(());
}
let directory = try!(DefIdDirectory::decode(&mut dep_graph_decoder));
let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut dep_graph_decoder));
@@ -179,8 +196,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Add in work-products that are still clean, and delete those that are
// dirty.
let mut work_product_decoder = Decoder::new(work_products_data, 0);
let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
reconcile_work_products(tcx, work_products, &dirty_target_nodes);
dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_source_nodes, &retraced);
+4
View File
@@ -105,6 +105,10 @@ pub fn encode_dep_graph(preds: &Predecessors,
builder: &mut DefIdDirectoryBuilder,
encoder: &mut Encoder)
-> io::Result<()> {
// First encode the commandline arguments hash
let tcx = builder.tcx();
try!(tcx.sess.opts.dep_tracking_hash().encode(encoder));
// Create a flat list of (Input, WorkProduct) edges for
// serialization.
let mut edges = vec![];
+7 -3
View File
@@ -56,6 +56,7 @@ pub struct CrateReader<'a> {
next_crate_num: ast::CrateNum,
foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
local_crate_name: String,
local_crate_config: ast::CrateConfig,
}
impl<'a> visit::Visitor for LocalCrateReader<'a> {
@@ -152,13 +153,16 @@ enum LoadResult {
impl<'a> CrateReader<'a> {
pub fn new(sess: &'a Session,
cstore: &'a CStore,
local_crate_name: &str) -> CrateReader<'a> {
local_crate_name: &str,
local_crate_config: ast::CrateConfig)
-> CrateReader<'a> {
CrateReader {
sess: sess,
cstore: cstore,
next_crate_num: cstore.next_crate_num(),
foreign_item_map: FnvHashMap(),
local_crate_name: local_crate_name.to_owned(),
local_crate_config: local_crate_config,
}
}
@@ -561,7 +565,7 @@ pub fn read_exported_macros(&mut self, item: &ast::Item) -> Vec<ast::MacroDef> {
// NB: Don't use parse::parse_tts_from_source_str because it parses with
// quote_depth > 0.
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
self.sess.opts.cfg.clone(),
self.local_crate_config.clone(),
source_name.clone(),
body);
let lo = p.span.lo;
@@ -863,7 +867,7 @@ fn new(sess: &'a Session,
LocalCrateReader {
sess: sess,
cstore: cstore,
creader: CrateReader::new(sess, cstore, local_crate_name),
creader: CrateReader::new(sess, cstore, local_crate_name, krate.config.clone()),
krate: krate,
definitions: defs,
}
+5 -3
View File
@@ -400,7 +400,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
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;
}
@@ -661,7 +661,9 @@ fn staticlibname(&self) -> (String, String) {
(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.
@@ -670,7 +672,7 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
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()));
+6 -2
View File
@@ -29,10 +29,14 @@ pub struct MacroLoader<'a> {
}
impl<'a> MacroLoader<'a> {
pub fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> MacroLoader<'a> {
pub fn new(sess: &'a Session,
cstore: &'a CStore,
crate_name: &str,
crate_config: ast::CrateConfig)
-> MacroLoader<'a> {
MacroLoader {
sess: sess,
reader: CrateReader::new(sess, cstore, crate_name),
reader: CrateReader::new(sess, cstore, crate_name, crate_config),
}
}
}
+7 -3
View File
@@ -49,7 +49,7 @@ pub fn load_plugins(sess: &Session,
krate: &ast::Crate,
crate_name: &str,
addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
let mut loader = PluginLoader::new(sess, cstore, crate_name);
let mut loader = PluginLoader::new(sess, cstore, crate_name, krate.config.clone());
// do not report any error now. since crate attributes are
// not touched by expansion, every use of plugin without
@@ -90,10 +90,14 @@ pub fn load_plugins(sess: &Session,
}
impl<'a> PluginLoader<'a> {
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> PluginLoader<'a> {
fn new(sess: &'a Session,
cstore: &'a CStore,
crate_name: &str,
crate_config: ast::CrateConfig)
-> PluginLoader<'a> {
PluginLoader {
sess: sess,
reader: CrateReader::new(sess, cstore, crate_name),
reader: CrateReader::new(sess, cstore, crate_name, crate_config),
plugins: vec![],
}
}
+2 -1
View File
@@ -190,7 +190,8 @@ pub fn link_binary(sess: &Session,
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
// Ignore executable crates if we have -Z no-trans, as they will error.
if sess.opts.no_trans && crate_type == config::CrateTypeExecutable {
if sess.opts.debugging_opts.no_trans &&
crate_type == config::CrateTypeExecutable {
continue;
}
+2 -3
View File
@@ -11,7 +11,7 @@
use back::lto;
use back::link::{get_linker, remove};
use rustc_incremental::save_trans_partition;
use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses};
use session::Session;
use session::config::{self, OutputType};
use llvm;
@@ -26,7 +26,6 @@
use syntax_pos::MultiSpan;
use context::{is_pie_binary, get_reloc_model};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::fs;
use std::path::{Path, PathBuf};
@@ -641,7 +640,7 @@ pub fn cleanup_llvm(trans: &CrateTranslation) {
pub fn run_passes(sess: &Session,
trans: &CrateTranslation,
output_types: &HashMap<OutputType, Option<PathBuf>>,
output_types: &OutputTypes,
crate_output: &OutputFilenames) {
// It's possible that we have `codegen_units > 1` but only one item in
// `trans.modules`. We could theoretically proceed and do LTO in that
+1 -1
View File
@@ -2576,7 +2576,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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,
+2 -4
View File
@@ -45,7 +45,6 @@ pub enum MaybeTyped<'a, 'tcx: 'a> {
NotTyped(&'a session::Session)
}
pub type Externs = HashMap<String, Vec<String>>;
pub type ExternalPaths = HashMap<DefId, (Vec<String>, clean::TypeKind)>;
pub struct DocContext<'a, 'tcx: 'a> {
@@ -99,7 +98,7 @@ fn is_doc_reachable(&self, did: DefId) -> bool {
pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
externs: Externs,
externs: config::Externs,
input: Input,
triple: Option<String>) -> (clean::Crate, RenderInfo)
{
@@ -120,7 +119,6 @@ pub fn run_core(search_paths: SearchPaths,
lint_cap: Some(lint::Allow),
externs: externs,
target_triple: triple.unwrap_or(config::host_triple().to_string()),
cfg: config::parse_cfgspecs(cfgs),
// Ensure that rustdoc works even if rustc is feature-staged
unstable_features: UnstableFeatures::Allow,
..config::basic_options().clone()
@@ -139,7 +137,7 @@ pub fn run_core(search_paths: SearchPaths,
codemap, cstore.clone());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess);
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
target_features::add_configuration(&mut cfg, &sess);
let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
+10 -9
View File
@@ -51,7 +51,7 @@
extern crate serialize as rustc_serialize; // used by deriving
use std::collections::HashMap;
use std::collections::{BTreeMap, BTreeSet};
use std::default::Default;
use std::env;
use std::path::PathBuf;
@@ -60,7 +60,8 @@
use externalfiles::ExternalHtml;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options};
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
Externs};
#[macro_use]
pub mod externalfiles;
@@ -323,7 +324,7 @@ pub fn main_args(args: &[String]) -> isize {
/// Looks inside the command line arguments to extract the relevant input format
/// and files and then generates the necessary rustdoc output for formatting.
fn acquire_input(input: &str,
externs: core::Externs,
externs: Externs,
matches: &getopts::Matches) -> Result<Output, String> {
match matches.opt_str("r").as_ref().map(|s| &**s) {
Some("rust") => Ok(rust_input(input, externs, matches)),
@@ -335,10 +336,10 @@ fn acquire_input(input: &str,
}
/// Extracts `--extern CRATE=PATH` arguments from `matches` and
/// returns a `HashMap` mapping crate names to their paths or else an
/// returns a map mapping crate names to their paths or else an
/// error message.
fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
let mut externs = HashMap::new();
fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
let mut externs = BTreeMap::new();
for arg in &matches.opt_strs("extern") {
let mut parts = arg.splitn(2, '=');
let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
@@ -346,9 +347,9 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
.ok_or("--extern value must be of the format `foo=bar`"
.to_string())?;
let name = name.to_string();
externs.entry(name).or_insert(vec![]).push(location.to_string());
externs.entry(name).or_insert_with(BTreeSet::new).insert(location.to_string());
}
Ok(externs)
Ok(Externs::new(externs))
}
/// Interprets the input file as a rust source file, passing it through the
@@ -356,7 +357,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
/// generated from the cleaned AST of the crate.
///
/// This form of input will run all of the plug/cleaning passes
fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matches) -> Output {
fn rust_input(cratefile: &str, externs: Externs, matches: &getopts::Matches) -> Output {
let mut default_passes = !matches.opt_present("no-defaults");
let mut passes = matches.opt_strs("passes");
let mut plugins = matches.opt_strs("plugins");
+2 -2
View File
@@ -14,10 +14,10 @@
use std::io;
use std::path::{PathBuf, Path};
use core;
use getopts;
use testing;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::Externs;
use externalfiles::ExternalHtml;
@@ -142,7 +142,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
}
/// Run any tests/code examples in the markdown file `input`.
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: core::Externs,
pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
mut test_args: Vec<String>) -> isize {
let input_str = load_or_return!(input, 1, 2);
+9 -11
View File
@@ -26,7 +26,8 @@
use rustc::dep_graph::DepGraph;
use rustc::hir::map as hir_map;
use rustc::session::{self, config};
use rustc::session::config::{get_unstable_features_setting, OutputType};
use rustc::session::config::{get_unstable_features_setting, OutputType,
OutputTypes, Externs};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_back::dynamic_lib::DynamicLibrary;
use rustc_back::tempdir::TempDir;
@@ -55,7 +56,7 @@ pub struct TestOptions {
pub fn run(input: &str,
cfgs: Vec<String>,
libs: SearchPaths,
externs: core::Externs,
externs: Externs,
mut test_args: Vec<String>,
crate_name: Option<String>)
-> isize {
@@ -89,8 +90,7 @@ pub fn run(input: &str,
cstore.clone());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let mut cfg = config::build_configuration(&sess);
cfg.extend(config::parse_cfgspecs(cfgs.clone()));
let cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
let driver::ExpansionResult { defs, mut hir_forest, .. } = {
phase_2_configure_and_expand(
@@ -172,7 +172,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
}
fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
externs: core::Externs,
externs: Externs,
should_panic: bool, no_run: bool, as_test_harness: bool,
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions) {
// the test harness wants its own `main` & top level functions, so
@@ -182,8 +182,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
name: driver::anon_src(),
input: test.to_owned(),
};
let mut outputs = HashMap::new();
outputs.insert(OutputType::Exe, None);
let outputs = OutputTypes::new(&[(OutputType::Exe, None)]);
let sessopts = config::Options {
maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
@@ -247,8 +246,7 @@ fn drop(&mut self) {
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
let mut control = driver::CompileController::basic();
let mut cfg = config::build_configuration(&sess);
cfg.extend(config::parse_cfgspecs(cfgs.clone()));
let cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
let out = Some(outdir.lock().unwrap().path().to_path_buf());
if no_run {
@@ -396,7 +394,7 @@ pub struct Collector {
names: Vec<String>,
cfgs: Vec<String>,
libs: SearchPaths,
externs: core::Externs,
externs: Externs,
cnt: usize,
use_headers: bool,
current_header: Option<String>,
@@ -405,7 +403,7 @@ pub struct Collector {
}
impl Collector {
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: core::Externs,
pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
use_headers: bool, opts: TestOptions) -> Collector {
Collector {
tests: Vec::new(),
+1 -1
View File
@@ -1194,7 +1194,7 @@ pub fn check_crate(krate: &ast::Crate,
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.
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that changing a tracked commandline argument invalidates
// the cache while changing an untracked one doesn't.
// revisions:rpass1 rpass2 rpass3
#![feature(rustc_attrs)]
#![rustc_partition_translated(module="commandline_args", cfg="rpass2")]
#![rustc_partition_reused(module="commandline_args", cfg="rpass3")]
// Between revisions 1 and 2, we are changing the debuginfo-level, which should
// invalidate the cache. Between revisions 2 and 3, we are adding `--verbose`
// which should have no effect on the cache:
//[rpass1] compile-flags: -C debuginfo=0
//[rpass2] compile-flags: -C debuginfo=2
//[rpass3] compile-flags: -C debuginfo=2 --verbose
pub fn main() {
// empty
}
+4 -3
View File
@@ -19,7 +19,8 @@
use rustc::dep_graph::DepGraph;
use rustc::session::{build_session, Session};
use rustc::session::config::{basic_options, build_configuration, Input, OutputType};
use rustc::session::config::{basic_options, build_configuration, Input,
OutputType, OutputTypes};
use rustc_driver::driver::{compile_input, CompileController, anon_src};
use rustc_metadata::cstore::CStore;
use rustc_errors::registry::Registry;
@@ -51,7 +52,7 @@ fn main() {}
fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
let mut opts = basic_options();
opts.output_types.insert(OutputType::Exe, None);
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
opts.maybe_sysroot = Some(sysroot);
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
@@ -64,7 +65,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
let (sess, cstore) = basic_sess(sysroot);
let cfg = build_configuration(&sess);
let cfg = build_configuration(&sess, vec![]);
let control = CompileController::basic();
compile_input(&sess, &cstore,
@@ -24,6 +24,7 @@
use rustc::session::Session;
use rustc::session::config::{self, Input};
use rustc_driver::{driver, CompilerCalls, Compilation};
use syntax::ast;
use std::path::PathBuf;
@@ -35,6 +36,7 @@ impl<'a> CompilerCalls<'a> for TestCalls {
fn early_callback(&mut self,
_: &getopts::Matches,
_: &config::Options,
_: &ast::CrateConfig,
_: &errors::registry::Registry,
_: config::ErrorOutputType)
-> Compilation {
@@ -45,6 +47,7 @@ fn early_callback(&mut self,
fn late_callback(&mut self,
_: &getopts::Matches,
_: &Session,
_: &ast::CrateConfig,
_: &Input,
_: &Option<PathBuf>,
_: &Option<PathBuf>)
@@ -62,6 +65,7 @@ fn some_input(&mut self, input: Input, input_path: Option<PathBuf>)
fn no_input(&mut self,
_: &getopts::Matches,
_: &config::Options,
_: &ast::CrateConfig,
_: &Option<PathBuf>,
_: &Option<PathBuf>,
_: &errors::registry::Registry)
+1
View File
@@ -2008,6 +2008,7 @@ fn run_incremental_test(&self) {
// 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,