mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-30 06:43:20 +03:00
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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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![];
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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
@@ -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(),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user