summaryrefslogtreecommitdiffstats
path: root/src/test/incremental
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/incremental
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs18
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs73
-rw-r--r--src/test/incremental/async-lifetimes.rs19
-rw-r--r--src/test/incremental/auxiliary/incremental_proc_macro_aux.rs22
-rw-r--r--src/test/incremental/auxiliary/issue-49482-macro-def.rs40
-rw-r--r--src/test/incremental/auxiliary/issue-49482-reexport.rs6
-rw-r--r--src/test/incremental/auxiliary/issue-54059.rs50
-rw-r--r--src/test/incremental/auxiliary/issue-79661.rs6
-rw-r--r--src/test/incremental/auxiliary/issue-79890.rs1
-rw-r--r--src/test/incremental/auxiliary/rustc-rust-log-aux.rs8
-rw-r--r--src/test/incremental/cache_file_headers.rs20
-rw-r--r--src/test/incremental/callee_caller_cross_crate/auxiliary/a.rs14
-rw-r--r--src/test/incremental/callee_caller_cross_crate/b.rs19
-rw-r--r--src/test/incremental/change_add_field/struct_point.rs152
-rw-r--r--src/test/incremental/change_crate_dep_kind.rs15
-rw-r--r--src/test/incremental/change_crate_order/auxiliary/a.rs3
-rw-r--r--src/test/incremental/change_crate_order/auxiliary/b.rs3
-rw-r--r--src/test/incremental/change_crate_order/main.rs24
-rw-r--r--src/test/incremental/change_implementation_cross_crate/auxiliary/a.rs31
-rw-r--r--src/test/incremental/change_implementation_cross_crate/main.rs20
-rw-r--r--src/test/incremental/change_name_of_static_in_fn.rs16
-rw-r--r--src/test/incremental/change_private_fn/struct_point.rs104
-rw-r--r--src/test/incremental/change_private_fn_cc/auxiliary/point.rs25
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs72
-rw-r--r--src/test/incremental/change_private_impl_method/struct_point.rs100
-rw-r--r--src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs25
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs73
-rw-r--r--src/test/incremental/change_pub_inherent_method_body/struct_point.rs91
-rw-r--r--src/test/incremental/change_pub_inherent_method_sig/struct_point.rs101
-rw-r--r--src/test/incremental/change_symbol_export_status.rs41
-rw-r--r--src/test/incremental/commandline-args.rs25
-rw-r--r--src/test/incremental/const-generics/hash-tyvid-regression-1.rs16
-rw-r--r--src/test/incremental/const-generics/hash-tyvid-regression-2.rs18
-rw-r--r--src/test/incremental/const-generics/hash-tyvid-regression-3.rs26
-rw-r--r--src/test/incremental/const-generics/hash-tyvid-regression-4.rs40
-rw-r--r--src/test/incremental/const-generics/issue-61338.rs12
-rw-r--r--src/test/incremental/const-generics/issue-61516.rs14
-rw-r--r--src/test/incremental/const-generics/issue-62536.rs9
-rw-r--r--src/test/incremental/const-generics/issue-64087.rs9
-rw-r--r--src/test/incremental/const-generics/issue-65623.rs12
-rw-r--r--src/test/incremental/const-generics/issue-68477.rs25
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs23
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs18
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs22
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs34
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs23
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs14
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs25
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs16
-rw-r--r--src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs28
-rw-r--r--src/test/incremental/crate_hash_reorder.rs27
-rw-r--r--src/test/incremental/cyclic-trait-hierarchy.rs13
-rw-r--r--src/test/incremental/delayed_span_bug.rs8
-rw-r--r--src/test/incremental/dirty_clean.rs49
-rw-r--r--src/test/incremental/extern_static/issue-49153.rs11
-rw-r--r--src/test/incremental/feature_gate.rs13
-rw-r--r--src/test/incremental/foreign.rs38
-rw-r--r--src/test/incremental/hash-module-order.rs28
-rw-r--r--src/test/incremental/hashes/call_expressions.rs200
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs127
-rw-r--r--src/test/incremental/hashes/consts.rs109
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs390
-rw-r--r--src/test/incremental/hashes/enum_defs.rs718
-rw-r--r--src/test/incremental/hashes/exported_vs_not.rs75
-rw-r--r--src/test/incremental/hashes/extern_mods.rs224
-rw-r--r--src/test/incremental/hashes/for_loops.rs302
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs414
-rw-r--r--src/test/incremental/hashes/if_expressions.rs228
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs137
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs790
-rw-r--r--src/test/incremental/hashes/inline_asm.rs222
-rw-r--r--src/test/incremental/hashes/let_expressions.rs222
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs227
-rw-r--r--src/test/incremental/hashes/match_expressions.rs337
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs151
-rw-r--r--src/test/incremental/hashes/statics.rs186
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs270
-rw-r--r--src/test/incremental/hashes/struct_defs.rs335
-rw-r--r--src/test/incremental/hashes/trait_defs.rs1412
-rw-r--r--src/test/incremental/hashes/trait_impls.rs620
-rw-r--r--src/test/incremental/hashes/type_defs.rs220
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs509
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs250
-rw-r--r--src/test/incremental/hashes/while_loops.rs252
-rw-r--r--src/test/incremental/hello_world.rs37
-rw-r--r--src/test/incremental/hygiene/auxiliary/cached_hygiene.rs36
-rw-r--r--src/test/incremental/hygiene/load_cached_hygiene.rs48
-rw-r--r--src/test/incremental/ich_method_call_trait_scope.rs40
-rw-r--r--src/test/incremental/ich_nested_items.rs23
-rw-r--r--src/test/incremental/ich_resolve_results.rs45
-rw-r--r--src/test/incremental/incremental_proc_macro.rs16
-rw-r--r--src/test/incremental/inlined_hir_34991/main.rs23
-rw-r--r--src/test/incremental/issue-35593.rs12
-rw-r--r--src/test/incremental/issue-38222.rs27
-rw-r--r--src/test/incremental/issue-39569.rs27
-rw-r--r--src/test/incremental/issue-39828/auxiliary/generic.rs8
-rw-r--r--src/test/incremental/issue-39828/issue-39828.rs12
-rw-r--r--src/test/incremental/issue-42602.rs44
-rw-r--r--src/test/incremental/issue-49043.rs12
-rw-r--r--src/test/incremental/issue-49482.rs30
-rw-r--r--src/test/incremental/issue-49595/auxiliary/lit_a.rs1
-rw-r--r--src/test/incremental/issue-49595/auxiliary/lit_b.rs1
-rw-r--r--src/test/incremental/issue-49595/issue-49595.rs31
-rw-r--r--src/test/incremental/issue-51409.rs10
-rw-r--r--src/test/incremental/issue-54059.rs8
-rw-r--r--src/test/incremental/issue-54242.rs20
-rw-r--r--src/test/incremental/issue-59523-on-implemented-is-not-unused.rs27
-rw-r--r--src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs19
-rw-r--r--src/test/incremental/issue-60629.rs10
-rw-r--r--src/test/incremental/issue-61323.rs15
-rw-r--r--src/test/incremental/issue-61530.rs18
-rw-r--r--src/test/incremental/issue-62649-path-collisions-happen.rs13
-rw-r--r--src/test/incremental/issue-69596.rs21
-rw-r--r--src/test/incremental/issue-72386.rs21
-rw-r--r--src/test/incremental/issue-79661-missing-def-path-hash.rs14
-rw-r--r--src/test/incremental/issue-79890-imported-crates-changed.rs7
-rw-r--r--src/test/incremental/issue-80336-invalid-span.rs10
-rw-r--r--src/test/incremental/issue-80691-bad-eval-cache.rs184
-rw-r--r--src/test/incremental/issue-82920-predicate-order-miscompile.rs31
-rw-r--r--src/test/incremental/issue-84252-global-alloc.rs12
-rw-r--r--src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs11
-rw-r--r--src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs14
-rw-r--r--src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs19
-rw-r--r--src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs24
-rw-r--r--src/test/incremental/issue-85360-eval-obligation-ice.rs118
-rw-r--r--src/test/incremental/issue-86753.rs50
-rw-r--r--src/test/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs3
-rw-r--r--src/test/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs10
-rw-r--r--src/test/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs31
-rw-r--r--src/test/incremental/issue-92987-provisional-dep-node.rs24
-rw-r--r--src/test/incremental/issue-96319-coinductive-cycle.rs34
-rw-r--r--src/test/incremental/krate-inherent.rs23
-rw-r--r--src/test/incremental/krate-inlined.rs25
-rw-r--r--src/test/incremental/krate_reassign_34991/auxiliary/a.rs3
-rw-r--r--src/test/incremental/krate_reassign_34991/main.rs20
-rw-r--r--src/test/incremental/link_order/auxiliary/my_lib.rs3
-rw-r--r--src/test/incremental/link_order/main.rs12
-rw-r--r--src/test/incremental/lto-in-linker.rs9
-rw-r--r--src/test/incremental/lto.rs40
-rw-r--r--src/test/incremental/macro_export.rs12
-rw-r--r--src/test/incremental/mir-opt.rs11
-rw-r--r--src/test/incremental/no_mangle.rs10
-rw-r--r--src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs11
-rw-r--r--src/test/incremental/remapped_paths_cc/main.rs28
-rw-r--r--src/test/incremental/remove-private-item-cross-crate/auxiliary/a.rs8
-rw-r--r--src/test/incremental/remove-private-item-cross-crate/main.rs20
-rw-r--r--src/test/incremental/remove_crate/auxiliary/extern_crate.rs3
-rw-r--r--src/test/incremental/remove_crate/main.rs24
-rw-r--r--src/test/incremental/remove_source_file/auxiliary/mod.rs3
-rw-r--r--src/test/incremental/remove_source_file/main.rs24
-rw-r--r--src/test/incremental/reorder_vtable.rs41
-rw-r--r--src/test/incremental/rlib-lto.rs8
-rw-r--r--src/test/incremental/rlib_cross_crate/auxiliary/a.rs16
-rw-r--r--src/test/incremental/rlib_cross_crate/b.rs28
-rw-r--r--src/test/incremental/rustc-rust-log.rs16
-rw-r--r--src/test/incremental/source_loc_macros.rs55
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/mod.rs7
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub1.rs5
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub2.rs5
-rw-r--r--src/test/incremental/span_hash_stable/main.rs24
-rw-r--r--src/test/incremental/spans_in_type_debuginfo.rs53
-rw-r--r--src/test/incremental/spans_significant_w_debuginfo.rs21
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs29
-rw-r--r--src/test/incremental/spike-neg1.rs52
-rw-r--r--src/test/incremental/spike-neg2.rs52
-rw-r--r--src/test/incremental/spike.rs49
-rw-r--r--src/test/incremental/split_debuginfo_cached.rs25
-rw-r--r--src/test/incremental/split_debuginfo_mode.rs33
-rw-r--r--src/test/incremental/static_cycle/b.rs9
-rw-r--r--src/test/incremental/static_refering_to_other_static/issue-49081.rs8
-rw-r--r--src/test/incremental/static_refering_to_other_static2/issue.rs10
-rw-r--r--src/test/incremental/static_refering_to_other_static3/issue.rs15
-rw-r--r--src/test/incremental/static_stable_hash/issue-49301.rs18
-rw-r--r--src/test/incremental/string_constant.rs47
-rw-r--r--src/test/incremental/struct_add_field.rs39
-rw-r--r--src/test/incremental/struct_change_field_name.rs47
-rw-r--r--src/test/incremental/struct_change_field_type.rs44
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs19
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/b.rs27
-rw-r--r--src/test/incremental/struct_change_nothing.rs44
-rw-r--r--src/test/incremental/struct_remove_field.rs43
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_via_import.rs48
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs26
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs26
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs62
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs74
-rw-r--r--src/test/incremental/thinlto/cgu_keeps_identical_fn.rs72
-rw-r--r--src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs58
-rw-r--r--src/test/incremental/type_alias_cross_crate/auxiliary/a.rs15
-rw-r--r--src/test/incremental/type_alias_cross_crate/b.rs22
-rw-r--r--src/test/incremental/unchecked_dirty_clean.rs34
-rw-r--r--src/test/incremental/warnings-reemitted.rs9
192 files changed, 13590 insertions, 0 deletions
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs
new file mode 100644
index 000000000..16aaad348
--- /dev/null
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs
@@ -0,0 +1,18 @@
+pub struct Point {
+ pub x: f32,
+ pub y: f32,
+}
+
+#[cfg(rpass2)]
+fn unused_helper() {
+}
+
+pub fn distance_squared(this: &Point) -> f32 {
+ return this.x * this.x + this.y * this.y;
+}
+
+impl Point {
+ pub fn distance_from_origin(&self) -> f32 {
+ distance_squared(self).sqrt()
+ }
+}
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
new file mode 100644
index 000000000..ea1ea1943
--- /dev/null
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
@@ -0,0 +1,73 @@
+// Test where we add a private item into the root of an external.
+// crate. This should not cause anything we use to be invalidated.
+// Regression test for #36168.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// aux-build:point.rs
+// build-pass
+
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+
+extern crate point;
+
+/// A fn item that calls (public) methods on `Point` from the same impl
+pub mod fn_calls_methods_in_same_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ x.distance_from_origin();
+ }
+}
+
+/// A fn item that calls (public) methods on `Point` from another impl
+pub mod fn_calls_free_fn {
+ use point::{self, Point};
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ point::distance_squared(&x);
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/async-lifetimes.rs b/src/test/incremental/async-lifetimes.rs
new file mode 100644
index 000000000..90a0b93b9
--- /dev/null
+++ b/src/test/incremental/async-lifetimes.rs
@@ -0,0 +1,19 @@
+// revisions: rpass1 rpass2
+// edition:2021
+
+// See https://github.com/rust-lang/rust/issues/98890
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+ async fn f(&self, _: &&()) -> &() {
+ &()
+ }
+}
+
+#[cfg(rpass2)]
+enum Bar {}
+
+fn main() {}
diff --git a/src/test/incremental/auxiliary/incremental_proc_macro_aux.rs b/src/test/incremental/auxiliary/incremental_proc_macro_aux.rs
new file mode 100644
index 000000000..6961450b4
--- /dev/null
+++ b/src/test/incremental/auxiliary/incremental_proc_macro_aux.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// Add a function to shift DefIndex of registrar function
+#[cfg(cfail2)]
+fn foo() {}
+
+#[proc_macro_derive(IncrementalMacro)]
+pub fn derive(input: TokenStream) -> TokenStream {
+ #[cfg(cfail2)]
+ {
+ foo();
+ }
+
+ "".parse().unwrap()
+}
diff --git a/src/test/incremental/auxiliary/issue-49482-macro-def.rs b/src/test/incremental/auxiliary/issue-49482-macro-def.rs
new file mode 100644
index 000000000..bfa7abb1a
--- /dev/null
+++ b/src/test/incremental/auxiliary/issue-49482-macro-def.rs
@@ -0,0 +1,40 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type="proc-macro"]
+#![allow(non_snake_case)]
+
+extern crate proc_macro;
+
+macro_rules! proc_macro_expr_impl {
+ ($(
+ $( #[$attr:meta] )*
+ pub fn $func:ident($input:ident: &str) -> String;
+ )+) => {
+ $(
+ $( #[$attr] )*
+ #[proc_macro_derive($func)]
+ pub fn $func(_input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
+ panic!()
+ }
+ )+
+ };
+}
+
+proc_macro_expr_impl! {
+ pub fn f1(input: &str) -> String;
+ pub fn f2(input: &str) -> String;
+ pub fn f3(input: &str) -> String;
+ pub fn f4(input: &str) -> String;
+ pub fn f5(input: &str) -> String;
+ pub fn f6(input: &str) -> String;
+ pub fn f7(input: &str) -> String;
+ pub fn f8(input: &str) -> String;
+ pub fn f9(input: &str) -> String;
+ pub fn fA(input: &str) -> String;
+ pub fn fB(input: &str) -> String;
+ pub fn fC(input: &str) -> String;
+ pub fn fD(input: &str) -> String;
+ pub fn fE(input: &str) -> String;
+ pub fn fF(input: &str) -> String;
+}
diff --git a/src/test/incremental/auxiliary/issue-49482-reexport.rs b/src/test/incremental/auxiliary/issue-49482-reexport.rs
new file mode 100644
index 000000000..39f19e3f1
--- /dev/null
+++ b/src/test/incremental/auxiliary/issue-49482-reexport.rs
@@ -0,0 +1,6 @@
+#[macro_use]
+extern crate issue_49482_macro_def;
+
+pub use issue_49482_macro_def::*;
+
+pub fn foo() {}
diff --git a/src/test/incremental/auxiliary/issue-54059.rs b/src/test/incremental/auxiliary/issue-54059.rs
new file mode 100644
index 000000000..fa2814a77
--- /dev/null
+++ b/src/test/incremental/auxiliary/issue-54059.rs
@@ -0,0 +1,50 @@
+// force-host
+// no-prefer-dynamic
+
+// check that having extern "C" functions in a proc macro doesn't crash.
+
+#![crate_type="proc-macro"]
+#![allow(non_snake_case)]
+
+extern crate proc_macro;
+
+macro_rules! proc_macro_tokenstream {
+ () => {
+ ::proc_macro::TokenStream
+ };
+}
+
+macro_rules! proc_macro_expr_impl {
+ ($(
+ $( #[$attr:meta] )*
+ pub fn $func:ident($input:ident: &str) -> String $body:block
+ )+) => {
+ $(
+ // Parses an input that looks like:
+ //
+ // ```
+ // #[allow(unused)]
+ // enum ProcMacroHack {
+ // Input = (stringify!(ARGS), 0).1,
+ // }
+ // ```
+ $( #[$attr] )*
+ #[proc_macro_derive($func)]
+ pub fn $func(input: proc_macro_tokenstream!()) -> proc_macro_tokenstream!() {
+ unsafe { rust_dbg_extern_identity_u64(0); }
+ panic!()
+ }
+ )+
+ };
+}
+
+proc_macro_expr_impl! {
+ pub fn base2_impl(input: &str) -> String {
+ panic!()
+ }
+}
+
+#[link(name="rust_test_helpers")]
+extern "C" {
+ pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
+}
diff --git a/src/test/incremental/auxiliary/issue-79661.rs b/src/test/incremental/auxiliary/issue-79661.rs
new file mode 100644
index 000000000..cd32a52eb
--- /dev/null
+++ b/src/test/incremental/auxiliary/issue-79661.rs
@@ -0,0 +1,6 @@
+#![feature(rustc_attrs)]
+
+#[cfg_attr(any(rpass2, rpass3), doc = "Some comment")]
+pub struct Foo;
+
+pub struct Wrapper(Foo);
diff --git a/src/test/incremental/auxiliary/issue-79890.rs b/src/test/incremental/auxiliary/issue-79890.rs
new file mode 100644
index 000000000..8eaeafa52
--- /dev/null
+++ b/src/test/incremental/auxiliary/issue-79890.rs
@@ -0,0 +1 @@
+pub trait MyTrait {}
diff --git a/src/test/incremental/auxiliary/rustc-rust-log-aux.rs b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs
new file mode 100644
index 000000000..a361373dc
--- /dev/null
+++ b/src/test/incremental/auxiliary/rustc-rust-log-aux.rs
@@ -0,0 +1,8 @@
+// rustc-env:RUSTC_LOG=debug
+#[cfg(rpass1)]
+pub fn foo() {}
+
+#[cfg(rpass2)]
+pub fn foo() {
+ println!();
+}
diff --git a/src/test/incremental/cache_file_headers.rs b/src/test/incremental/cache_file_headers.rs
new file mode 100644
index 000000000..9cf611c33
--- /dev/null
+++ b/src/test/incremental/cache_file_headers.rs
@@ -0,0 +1,20 @@
+// This test case makes sure that the compiler does not try to re-use anything
+// from the incremental compilation cache if the cache was produced by a
+// different compiler version. This is tested by artificially forcing the
+// emission of a different compiler version in the header of rpass1 artifacts,
+// and then making sure that the only object file of the test program gets
+// re-codegened although the program stays unchanged.
+
+// The `l33t haxx0r` Rust compiler is known to produce incr. comp. artifacts
+// that are outrageously incompatible with just about anything, even itself:
+//[rpass1] rustc-env:RUSTC_FORCE_RUSTC_VERSION="l33t haxx0r rustc 2.1 LTS"
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![rustc_partition_codegened(module="cache_file_headers", cfg="rpass2")]
+
+fn main() {
+ // empty
+}
diff --git a/src/test/incremental/callee_caller_cross_crate/auxiliary/a.rs b/src/test/incremental/callee_caller_cross_crate/auxiliary/a.rs
new file mode 100644
index 000000000..6445f87f7
--- /dev/null
+++ b/src/test/incremental/callee_caller_cross_crate/auxiliary/a.rs
@@ -0,0 +1,14 @@
+#![crate_type="rlib"]
+
+#[cfg(rpass1)]
+pub fn function0(x: u32) -> u32 {
+ x
+}
+
+#[cfg(rpass2)]
+pub fn function0(x: i32) -> i32 {
+ x
+}
+
+pub fn function1(x: u32) {
+}
diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs
new file mode 100644
index 000000000..084ed232a
--- /dev/null
+++ b/src/test/incremental/callee_caller_cross_crate/b.rs
@@ -0,0 +1,19 @@
+// aux-build:a.rs
+// revisions:rpass1 rpass2
+// compile-flags:-Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn call_function0() {
+ a::function0(77);
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn call_function1() {
+ a::function1(77);
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
new file mode 100644
index 000000000..3308ea562
--- /dev/null
+++ b/src/test/incremental/change_add_field/struct_point.rs
@@ -0,0 +1,152 @@
+// Test where we change a type definition by adding a field. Fns with
+// this type in their signature are recompiled, as are their callers.
+// Fns with that type used only in their body are also recompiled, but
+// their callers are not.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass
+
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+#![crate_type = "rlib"]
+
+// These are expected to require codegen.
+#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-call_fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_with_type_in_body", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_write_field", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="cfail2")]
+
+pub mod point {
+ #[cfg(cfail1)]
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ }
+
+ #[cfg(cfail2)]
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ pub z: f32,
+ }
+
+ impl Point {
+ pub fn origin() -> Point {
+ #[cfg(cfail1)]
+ return Point { x: 0.0, y: 0.0 };
+
+ #[cfg(cfail2)]
+ return Point { x: 0.0, y: 0.0, z: 0.0 };
+ }
+
+ pub fn total(&self) -> f32 {
+ #[cfg(cfail1)]
+ return self.x + self.y;
+
+ #[cfg(cfail2)]
+ return self.x + self.y + self.z;
+ }
+
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+ }
+}
+
+/// A function that has the changed type in its signature; must currently be
+/// rebuilt.
+///
+/// You could imagine that, in the future, if the change were
+/// sufficiently "private", we might not need to type-check again.
+/// Rebuilding is probably always necessary since the layout may be
+/// affected.
+pub mod fn_with_type_in_sig {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
+ pub fn boop(p: Option<&Point>) -> f32 {
+ p.map(|p| p.total()).unwrap_or(0.0)
+ }
+}
+
+/// Call a function that has the changed type in its signature; this
+/// currently must also be rebuilt.
+///
+/// You could imagine that, in the future, if the change were
+/// sufficiently "private", we might not need to type-check again.
+/// Rebuilding is probably always necessary since the layout may be
+/// affected.
+pub mod call_fn_with_type_in_sig {
+ use fn_with_type_in_sig;
+
+ #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
+ pub fn bip() -> f32 {
+ fn_with_type_in_sig::boop(None)
+ }
+}
+
+/// A function that uses the changed type, but only in its body, not its
+/// signature.
+///
+/// You could imagine that, in the future, if the change were
+/// sufficiently "private", we might not need to type-check again.
+/// Rebuilding is probably always necessary since the layout may be
+/// affected.
+pub mod fn_with_type_in_body {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
+ pub fn boop() -> f32 {
+ Point::origin().total()
+ }
+}
+
+/// A function `X` that calls a function `Y`, where `Y` uses the changed type in its
+/// body. In this case, the effects of the change should be contained
+/// to `Y`; `X` should not have to be rebuilt, nor should it need to be
+/// type-checked again.
+pub mod call_fn_with_type_in_body {
+ use fn_with_type_in_body;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn bip() -> f32 {
+ fn_with_type_in_body::boop()
+ }
+}
+
+/// A function item that makes an instance of `Point` but does not invoke methods.
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
+ pub fn make_origin(p: Point) -> Point {
+ Point { ..p }
+ }
+}
+
+/// A function item that reads fields from `Point` but does not invoke methods.
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A function item that writes to a field of `Point` but does not invoke methods.
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_crate_dep_kind.rs b/src/test/incremental/change_crate_dep_kind.rs
new file mode 100644
index 000000000..8c35f6ca0
--- /dev/null
+++ b/src/test/incremental/change_crate_dep_kind.rs
@@ -0,0 +1,15 @@
+// Test that we detect changes to the `dep_kind` query. If the change is not
+// detected then -Zincremental-verify-ich will trigger an assertion.
+
+// ignore-wasm32-bare compiled with panic=abort by default
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph -Cpanic=unwind
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(panic_unwind)]
+
+// Turn the panic_unwind crate from an explicit into an implicit query:
+#[cfg(cfail1)]
+extern crate panic_unwind;
+
+fn main() {}
diff --git a/src/test/incremental/change_crate_order/auxiliary/a.rs b/src/test/incremental/change_crate_order/auxiliary/a.rs
new file mode 100644
index 000000000..1bd48714a
--- /dev/null
+++ b/src/test/incremental/change_crate_order/auxiliary/a.rs
@@ -0,0 +1,3 @@
+#![crate_type="rlib"]
+
+pub static A : u32 = 32;
diff --git a/src/test/incremental/change_crate_order/auxiliary/b.rs b/src/test/incremental/change_crate_order/auxiliary/b.rs
new file mode 100644
index 000000000..001b88912
--- /dev/null
+++ b/src/test/incremental/change_crate_order/auxiliary/b.rs
@@ -0,0 +1,3 @@
+#![crate_type="rlib"]
+
+pub static B: u32 = 32;
diff --git a/src/test/incremental/change_crate_order/main.rs b/src/test/incremental/change_crate_order/main.rs
new file mode 100644
index 000000000..7448b54dd
--- /dev/null
+++ b/src/test/incremental/change_crate_order/main.rs
@@ -0,0 +1,24 @@
+// aux-build:a.rs
+// aux-build:b.rs
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+
+#[cfg(rpass1)]
+extern crate a;
+#[cfg(rpass1)]
+extern crate b;
+
+#[cfg(rpass2)]
+extern crate b;
+#[cfg(rpass2)]
+extern crate a;
+
+use a::A;
+use b::B;
+
+//? #[rustc_clean(label="typeck", cfg="rpass2")]
+pub fn main() {
+ A + B;
+}
diff --git a/src/test/incremental/change_implementation_cross_crate/auxiliary/a.rs b/src/test/incremental/change_implementation_cross_crate/auxiliary/a.rs
new file mode 100644
index 000000000..7320a97b9
--- /dev/null
+++ b/src/test/incremental/change_implementation_cross_crate/auxiliary/a.rs
@@ -0,0 +1,31 @@
+#![allow(warnings)]
+#![crate_name = "a"]
+#![crate_type = "rlib"]
+
+#[cfg(rpass1)]
+#[inline(never)]
+pub fn foo(b: u8) -> u32 {
+ b as u32
+}
+
+#[cfg(rpass2)]
+#[inline(never)]
+pub fn foo(b: u8) -> u32 {
+ (b + 42) as u32
+}
+
+pub fn bar(b: u8) -> u32 {
+ bar_impl(b) as u32
+}
+
+#[cfg(rpass1)]
+#[inline(never)]
+fn bar_impl(b: u8) -> u16 {
+ b as u16
+}
+
+#[cfg(rpass2)]
+#[inline(never)]
+fn bar_impl(b: u8) -> u32 {
+ (b + 42) as u32
+}
diff --git a/src/test/incremental/change_implementation_cross_crate/main.rs b/src/test/incremental/change_implementation_cross_crate/main.rs
new file mode 100644
index 000000000..dee9ebd74
--- /dev/null
+++ b/src/test/incremental/change_implementation_cross_crate/main.rs
@@ -0,0 +1,20 @@
+// Test that we are able to reuse `main` despite the changes in the implementation of `foo` and
+// `bar`.
+
+// revisions: rpass1 rpass2
+// aux-build: a.rs
+// compile-flags: -Zquery-dep-graph
+
+#![feature(rustc_attrs)]
+#![crate_type = "bin"]
+#![rustc_partition_reused(module = "main", cfg = "rpass2")]
+
+extern crate a;
+
+pub fn main() {
+ let vec: Vec<u8> = vec![0, 1, 2, 3];
+ for b in vec {
+ println!("{}", a::foo(b));
+ println!("{}", a::bar(b));
+ }
+}
diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs
new file mode 100644
index 000000000..fd16ad2dc
--- /dev/null
+++ b/src/test/incremental/change_name_of_static_in_fn.rs
@@ -0,0 +1,16 @@
+// revisions:rpass1 rpass2 rpass3
+
+// See issue #57692.
+
+#![allow(warnings)]
+
+fn main() {
+ #[cfg(rpass1)]
+ {
+ static map: u64 = 0;
+ }
+ #[cfg(not(rpass1))]
+ {
+ static MAP: u64 = 0;
+ }
+}
diff --git a/src/test/incremental/change_private_fn/struct_point.rs b/src/test/incremental/change_private_fn/struct_point.rs
new file mode 100644
index 000000000..d57267adc
--- /dev/null
+++ b/src/test/incremental/change_private_fn/struct_point.rs
@@ -0,0 +1,104 @@
+// Test where we change the body of a private method in an impl.
+// We then test what sort of functions must be rebuilt as a result.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+
+pub mod point {
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ }
+
+ fn distance_squared(this: &Point) -> f32 {
+ #[cfg(cfail1)]
+ return this.x + this.y;
+
+ #[cfg(cfail2)]
+ return this.x * this.x + this.y * this.y;
+ }
+
+ impl Point {
+ pub fn distance_from_origin(&self) -> f32 {
+ distance_squared(self).sqrt()
+ }
+ }
+
+ impl Point {
+ pub fn translate(&mut self, x: f32, y: f32) {
+ self.x += x;
+ self.y += y;
+ }
+ }
+
+}
+
+/// A fn item that calls (public) methods on `Point` from the same impl which changed
+pub mod fn_calls_methods_in_same_impl {
+ use point::Point;
+
+ // The cached result should actually be loaded from disk
+ // (not just marked green) - for example, `DeadVisitor`
+ // always runs during compilation as a "pass", and loads
+ // the typeck results for bodies.
+ #[rustc_clean(cfg="cfail2", loaded_from_disk="typeck")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ x.distance_from_origin();
+ }
+}
+
+/// A fn item that calls (public) methods on `Point` from another impl
+pub mod fn_calls_methods_in_another_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let mut x = Point { x: 2.0, y: 2.0 };
+ x.translate(3.0, 3.0);
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_private_fn_cc/auxiliary/point.rs b/src/test/incremental/change_private_fn_cc/auxiliary/point.rs
new file mode 100644
index 000000000..483f20572
--- /dev/null
+++ b/src/test/incremental/change_private_fn_cc/auxiliary/point.rs
@@ -0,0 +1,25 @@
+pub struct Point {
+ pub x: f32,
+ pub y: f32,
+}
+
+fn distance_squared(this: &Point) -> f32 {
+ #[cfg(cfail1)]
+ return this.x + this.y;
+
+ #[cfg(cfail2)]
+ return this.x * this.x + this.y * this.y;
+}
+
+impl Point {
+ pub fn distance_from_origin(&self) -> f32 {
+ distance_squared(self).sqrt()
+ }
+}
+
+impl Point {
+ pub fn translate(&mut self, x: f32, y: f32) {
+ self.x += x;
+ self.y += y;
+ }
+}
diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs
new file mode 100644
index 000000000..1c27ec3a3
--- /dev/null
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -0,0 +1,72 @@
+// Test where we change the body of a private method in an impl.
+// We then test what sort of functions must be rebuilt as a result.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// aux-build:point.rs
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![crate_type = "rlib"]
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+
+extern crate point;
+
+/// A fn item that calls (public) methods on `Point` from the same impl which changed
+pub mod fn_calls_methods_in_same_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ x.distance_from_origin();
+ }
+}
+
+/// A fn item that calls (public) methods on `Point` from another impl
+pub mod fn_calls_methods_in_another_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let mut x = Point { x: 2.0, y: 2.0 };
+ x.translate(3.0, 3.0);
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs
new file mode 100644
index 000000000..cf43e4757
--- /dev/null
+++ b/src/test/incremental/change_private_impl_method/struct_point.rs
@@ -0,0 +1,100 @@
+// Test where we change the body of a private method in an impl.
+// We then test what sort of functions must be rebuilt as a result.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass
+
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+
+pub mod point {
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ }
+
+ impl Point {
+ pub fn distance_squared(&self) -> f32 {
+ #[cfg(cfail1)]
+ return self.x + self.y;
+
+ #[cfg(cfail2)]
+ return self.x * self.x + self.y * self.y;
+ }
+
+ pub fn distance_from_origin(&self) -> f32 {
+ self.distance_squared().sqrt()
+ }
+ }
+
+ impl Point {
+ pub fn translate(&mut self, x: f32, y: f32) {
+ self.x += x;
+ self.y += y;
+ }
+ }
+
+}
+
+/// A fn item that calls (public) methods on `Point` from the same impl which changed
+pub mod fn_calls_methods_in_same_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ x.distance_from_origin();
+ }
+}
+
+/// A fn item that calls (public) methods on `Point` from another impl
+pub mod fn_calls_methods_in_another_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let mut x = Point { x: 2.0, y: 2.0 };
+ x.translate(3.0, 3.0);
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs b/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
new file mode 100644
index 000000000..2441da06b
--- /dev/null
+++ b/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
@@ -0,0 +1,25 @@
+pub struct Point {
+ pub x: f32,
+ pub y: f32,
+}
+
+impl Point {
+ fn distance_squared(&self) -> f32 {
+ #[cfg(cfail1)]
+ return self.x + self.y;
+
+ #[cfg(cfail2)]
+ return self.x * self.x + self.y * self.y;
+ }
+
+ pub fn distance_from_origin(&self) -> f32 {
+ self.distance_squared().sqrt()
+ }
+}
+
+impl Point {
+ pub fn translate(&mut self, x: f32, y: f32) {
+ self.x += x;
+ self.y += y;
+ }
+}
diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
new file mode 100644
index 000000000..9fe8b5df9
--- /dev/null
+++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
@@ -0,0 +1,73 @@
+// Test where we change the body of a private method in an impl.
+// We then test what sort of functions must be rebuilt as a result.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// aux-build:point.rs
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![crate_type = "rlib"]
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+
+extern crate point;
+
+/// A fn item that calls (public) methods on `Point` from the same impl which changed
+pub mod fn_calls_methods_in_same_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let x = Point { x: 2.0, y: 2.0 };
+ x.distance_from_origin();
+ }
+}
+
+/// A fn item that calls (public) methods on `Point` from another impl
+pub mod fn_calls_methods_in_another_impl {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn dirty() {
+ let mut x = Point { x: 2.0, y: 2.0 };
+ x.translate(3.0, 3.0);
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
new file mode 100644
index 000000000..1b87b18fc
--- /dev/null
+++ b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
@@ -0,0 +1,91 @@
+// Test where we change the body of a public, inherent method.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass
+
+#![crate_type = "rlib"]
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+
+#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+
+pub mod point {
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ }
+
+ impl Point {
+ pub fn distance_from_origin(&self) -> f32 {
+ #[cfg(cfail1)]
+ return self.x * self.x + self.y * self.y;
+
+ #[cfg(cfail2)]
+ return (self.x * self.x + self.y * self.y).sqrt();
+ }
+
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+ }
+}
+
+/// A fn item that calls the method on `Point` which changed
+pub mod fn_calls_changed_method {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let p = Point { x: 2.0, y: 2.0 };
+ p.distance_from_origin();
+ }
+}
+
+/// A fn item that calls a method on `Point` which did not change
+pub mod fn_calls_another_method {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let p = Point { x: 2.0, y: 2.0 };
+ p.x();
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
new file mode 100644
index 000000000..0a6729567
--- /dev/null
+++ b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
@@ -0,0 +1,101 @@
+// Test where we change the *signature* of a public, inherent method.
+
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass
+
+#![crate_type = "rlib"]
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![allow(dead_code)]
+
+// These are expected to require codegen.
+#![rustc_partition_codegened(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_codegened(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+
+pub mod point {
+ pub struct Point {
+ pub x: f32,
+ pub y: f32,
+ }
+
+ impl Point {
+ #[cfg(cfail1)]
+ pub fn distance_from_point(&self, p: Option<Point>) -> f32 {
+ let p = p.unwrap_or(Point { x: 0.0, y: 0.0 });
+ let x_diff = self.x - p.x;
+ let y_diff = self.y - p.y;
+ return x_diff * x_diff + y_diff * y_diff;
+ }
+
+ #[cfg(cfail2)]
+ pub fn distance_from_point(&self, p: Option<&Point>) -> f32 {
+ const ORIGIN: &Point = &Point { x: 0.0, y: 0.0 };
+ let p = p.unwrap_or(ORIGIN);
+ let x_diff = self.x - p.x;
+ let y_diff = self.y - p.y;
+ return x_diff * x_diff + y_diff * y_diff;
+ }
+
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+ }
+}
+
+/// A fn item that calls the method that was changed
+pub mod fn_calls_changed_method {
+ use point::Point;
+
+ #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
+ pub fn check() {
+ let p = Point { x: 2.0, y: 2.0 };
+ p.distance_from_point(None);
+ }
+}
+
+/// A fn item that calls a method that was not changed
+pub mod fn_calls_another_method {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn check() {
+ let p = Point { x: 2.0, y: 2.0 };
+ p.x();
+ }
+}
+
+/// A fn item that makes an instance of `Point` but does not invoke methods
+pub mod fn_make_struct {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn make_origin() -> Point {
+ Point { x: 2.0, y: 2.0 }
+ }
+}
+
+/// A fn item that reads fields from `Point` but does not invoke methods
+pub mod fn_read_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn get_x(p: Point) -> f32 {
+ p.x
+ }
+}
+
+/// A fn item that writes to a field of `Point` but does not invoke methods
+pub mod fn_write_field {
+ use point::Point;
+
+ #[rustc_clean(cfg="cfail2")]
+ pub fn inc_x(p: &mut Point) {
+ p.x += 1.0;
+ }
+}
diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs
new file mode 100644
index 000000000..dd3dce4e7
--- /dev/null
+++ b/src/test/incremental/change_symbol_export_status.rs
@@ -0,0 +1,41 @@
+// revisions: rpass1 rpass2 rpass3 rpass4
+// compile-flags: -Zquery-dep-graph
+// [rpass1]compile-flags: -Zincremental-ignore-spans
+// [rpass2]compile-flags: -Zincremental-ignore-spans
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
+
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass4")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass4")]
+
+// This test case makes sure that a change in symbol visibility is detected by
+// our dependency tracking. We do this by changing a module's visibility to
+// `private` in rpass2, causing the contained function to go from `default` to
+// `hidden` visibility.
+// The function is marked with #[no_mangle] so it is considered for exporting
+// even from an executable. Plain Rust functions are only exported from Rust
+// libraries, which our test infrastructure does not support.
+
+#[cfg(any(rpass1,rpass3))]
+pub mod mod1 {
+ #[no_mangle]
+ pub fn foo() {}
+}
+
+#[cfg(any(rpass2,rpass4))]
+mod mod1 {
+ #[no_mangle]
+ pub fn foo() {}
+}
+
+pub mod mod2 {
+ #[no_mangle]
+ pub fn bar() {}
+}
+
+fn main() {
+ mod1::foo();
+}
diff --git a/src/test/incremental/commandline-args.rs b/src/test/incremental/commandline-args.rs
new file mode 100644
index 000000000..35b7183db
--- /dev/null
+++ b/src/test/incremental/commandline-args.rs
@@ -0,0 +1,25 @@
+// Test that changing a tracked commandline argument invalidates
+// the cache while changing an untracked one doesn't.
+
+// ignore-asmjs wasm2js does not support source maps yet
+// revisions:rpass1 rpass2 rpass3 rpass4
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_codegened(module="commandline_args", cfg="rpass2")]
+#![rustc_partition_reused(module="commandline_args", cfg="rpass3")]
+#![rustc_partition_codegened(module="commandline_args", cfg="rpass4")]
+
+// 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. Between revisions, we are adding
+// `--remap-path-prefix` which should invalidate the cache:
+//[rpass1] compile-flags: -C debuginfo=0
+//[rpass2] compile-flags: -C debuginfo=2
+//[rpass3] compile-flags: -C debuginfo=2 --verbose
+//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
+
+pub fn main() {
+ // empty
+}
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-1.rs b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs
new file mode 100644
index 000000000..5ff7b19d8
--- /dev/null
+++ b/src/test/incremental/const-generics/hash-tyvid-regression-1.rs
@@ -0,0 +1,16 @@
+// revisions: cfail
+#![feature(generic_const_exprs, adt_const_params)]
+#![allow(incomplete_features)]
+// regression test for #77650
+fn c<T, const N: std::num::NonZeroUsize>()
+where
+ [T; N.get()]: Sized,
+{
+ use std::convert::TryFrom;
+ <[T; N.get()]>::try_from(())
+ //~^ error: the trait bound
+ //~| error: the trait bound
+ //~| error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-2.rs b/src/test/incremental/const-generics/hash-tyvid-regression-2.rs
new file mode 100644
index 000000000..5cdd43cd7
--- /dev/null
+++ b/src/test/incremental/const-generics/hash-tyvid-regression-2.rs
@@ -0,0 +1,18 @@
+// revisions: cfail
+#![feature(generic_const_exprs, adt_const_params)]
+#![allow(incomplete_features)]
+// regression test for #77650
+struct C<T, const N: core::num::NonZeroUsize>([T; N.get()])
+where
+ [T; N.get()]: Sized;
+impl<'a, const N: core::num::NonZeroUsize, A, B: PartialEq<A>> PartialEq<&'a [A]> for C<B, N>
+where
+ [B; N.get()]: Sized,
+{
+ fn eq(&self, other: &&'a [A]) -> bool {
+ self.0 == other
+ //~^ error: can't compare
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-3.rs b/src/test/incremental/const-generics/hash-tyvid-regression-3.rs
new file mode 100644
index 000000000..61f568f79
--- /dev/null
+++ b/src/test/incremental/const-generics/hash-tyvid-regression-3.rs
@@ -0,0 +1,26 @@
+// revisions: cfail
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+// regression test for #79251
+struct Node<const D: usize>
+where
+ SmallVec<{ D * 2 }>: ,
+{
+ keys: SmallVec<{ D * 2 }>,
+}
+
+impl<const D: usize> Node<D>
+where
+ SmallVec<{ D * 2 }>: ,
+{
+ fn new() -> Self {
+ let mut node = Node::new();
+ node.keys.some_function();
+ //~^ error: no method named
+ node
+ }
+}
+
+struct SmallVec<const D: usize> {}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-4.rs b/src/test/incremental/const-generics/hash-tyvid-regression-4.rs
new file mode 100644
index 000000000..12e8ac7ab
--- /dev/null
+++ b/src/test/incremental/const-generics/hash-tyvid-regression-4.rs
@@ -0,0 +1,40 @@
+// revisions: cfail
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+// regression test for #79251
+#[derive(Debug)]
+struct Node<K, const D: usize>
+where
+ SmallVec<K, { D * 2 }>: ,
+{
+ keys: SmallVec<K, { D * 2 }>,
+}
+
+impl<K, const D: usize> Node<K, D>
+where
+ SmallVec<K, { D * 2 }>: ,
+{
+ fn new() -> Self {
+ panic!()
+ }
+
+ #[inline(never)]
+ fn split(&mut self, i: usize, k: K, right: bool) -> Node<K, D> {
+ let mut node = Node::new();
+ node.keys.push(k);
+ //~^ error: no method named
+ node
+ }
+}
+
+#[derive(Debug)]
+struct SmallVec<T, const D: usize> {
+ data: [T; D],
+}
+impl<T, const D: usize> SmallVec<T, D> {
+ fn new() -> Self {
+ panic!()
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/issue-61338.rs b/src/test/incremental/const-generics/issue-61338.rs
new file mode 100644
index 000000000..e9d67fee2
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-61338.rs
@@ -0,0 +1,12 @@
+// revisions:rpass1
+
+struct Struct<T>(T);
+
+impl<T, const N: usize> Struct<[T; N]> {
+ fn f() {}
+ fn g() { Self::f(); }
+}
+
+fn main() {
+ Struct::<[u32; 3]>::g();
+}
diff --git a/src/test/incremental/const-generics/issue-61516.rs b/src/test/incremental/const-generics/issue-61516.rs
new file mode 100644
index 000000000..c781484d1
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-61516.rs
@@ -0,0 +1,14 @@
+// revisions:rpass1
+
+struct FakeArray<T, const N: usize>(T);
+
+impl<T, const N: usize> FakeArray<T, N> {
+ fn len(&self) -> usize {
+ N
+ }
+}
+
+fn main() {
+ let fa = FakeArray::<u32, { 32 }>(1);
+ assert_eq!(fa.len(), 32);
+}
diff --git a/src/test/incremental/const-generics/issue-62536.rs b/src/test/incremental/const-generics/issue-62536.rs
new file mode 100644
index 000000000..93c1dbf44
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-62536.rs
@@ -0,0 +1,9 @@
+// revisions:cfail1
+struct S<T, const N: usize>([T; N]);
+
+fn f<T, const N: usize>(x: T) -> S<T, {N}> { panic!() }
+
+fn main() {
+ f(0u8);
+ //[cfail1]~^ ERROR type annotations needed
+}
diff --git a/src/test/incremental/const-generics/issue-64087.rs b/src/test/incremental/const-generics/issue-64087.rs
new file mode 100644
index 000000000..81c813531
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-64087.rs
@@ -0,0 +1,9 @@
+// revisions:cfail1
+
+fn combinator<T, const S: usize>() -> [T; S] {}
+//[cfail1]~^ ERROR mismatched types
+
+fn main() {
+ combinator().into_iter();
+ //[cfail1]~^ ERROR type annotations needed
+}
diff --git a/src/test/incremental/const-generics/issue-65623.rs b/src/test/incremental/const-generics/issue-65623.rs
new file mode 100644
index 000000000..22bbcbcab
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-65623.rs
@@ -0,0 +1,12 @@
+// revisions:rpass1
+pub struct Foo<T, const N: usize>([T; 0]);
+
+impl<T, const N: usize> Foo<T, {N}> {
+ pub fn new() -> Self {
+ Foo([])
+ }
+}
+
+fn main() {
+ let _: Foo<u32, 0> = Foo::new();
+}
diff --git a/src/test/incremental/const-generics/issue-68477.rs b/src/test/incremental/const-generics/issue-68477.rs
new file mode 100644
index 000000000..9e35cf93d
--- /dev/null
+++ b/src/test/incremental/const-generics/issue-68477.rs
@@ -0,0 +1,25 @@
+// edition:2018
+// revisions:rpass1
+
+// Needed to supply generic arguments to the anon const in `[(); FOO]`.
+#![feature(generic_const_exprs)]
+
+const FOO: usize = 1;
+
+struct Container<T> {
+ val: std::marker::PhantomData<T>,
+ blah: [(); FOO]
+}
+
+async fn dummy() {}
+
+async fn foo() {
+ let a: Container<&'static ()>;
+ dummy().await;
+}
+
+fn is_send<T: Send>(_: T) {}
+
+fn main() {
+ is_send(foo());
+}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs
new file mode 100644
index 000000000..8262a2a21
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs
@@ -0,0 +1,23 @@
+// revisions: cfail
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_braces)]
+
+trait Delegates<T> {}
+
+struct FileCap<const Op: bool> {}
+
+fn writes_to_path<C>(cap: &C)
+where
+ C: Delegates<FileCap<{ false }>>,
+{
+ writes_to_specific_path(&cap);
+ //~^ error: the trait bound
+}
+
+fn writes_to_specific_path<C>(cap: &C)
+where
+ C: Delegates<FileCap<{ false }>>,
+{
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs
new file mode 100644
index 000000000..92bbcba4b
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs
@@ -0,0 +1,18 @@
+// revisions: rpass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Z;
+const fn one() -> usize {
+ 1
+}
+
+fn from_a_to_b<T>(source: [u8; one()]) -> T {
+ todo!()
+}
+
+fn not_main() {
+ let _: &Z = from_a_to_b([0; 1]);
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs
new file mode 100644
index 000000000..fc114f224
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs
@@ -0,0 +1,22 @@
+// revisions: rpass
+#![feature(generic_const_exprs, adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::{convert::TryFrom, num::NonZeroUsize};
+
+struct A<const N: NonZeroUsize>([u8; N.get()])
+where
+ [u8; N.get()]: Sized;
+
+impl<'a, const N: NonZeroUsize> TryFrom<&'a [u8]> for A<N>
+where
+ [u8; N.get()]: Sized,
+{
+ type Error = ();
+ fn try_from(slice: &'a [u8]) -> Result<A<N>, ()> {
+ let _x = <&[u8; N.get()] as TryFrom<&[u8]>>::try_from(slice);
+ unimplemented!();
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs
new file mode 100644
index 000000000..c05d8355c
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs
@@ -0,0 +1,34 @@
+// revisions: rpass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+pub trait IsTrue {}
+pub trait IsFalse {}
+
+pub struct Assert<const CHECK: bool> {}
+
+impl IsTrue for Assert<true> {}
+impl IsFalse for Assert<false> {}
+
+pub struct SliceConstWriter<'a, const N: usize> {
+ ptr: &'a mut [u8],
+}
+impl<'a, const N: usize> SliceConstWriter<'a, { N }> {
+ pub fn from_slice(vec: &'a mut [u8]) -> Self {
+ Self { ptr: vec }
+ }
+
+ pub fn convert<const NN: usize>(mut self) -> SliceConstWriter<'a, { NN }> {
+ SliceConstWriter { ptr: self.ptr }
+ }
+}
+
+impl<'a, const N: usize> SliceConstWriter<'a, { N }>
+where
+ Assert<{ N >= 2 }>: IsTrue,
+{
+ pub fn write_u8(mut self) -> SliceConstWriter<'a, { N - 2 }> {
+ self.convert()
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs
new file mode 100644
index 000000000..8886a556d
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs
@@ -0,0 +1,23 @@
+// revisions: rpass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub struct Ref<'a, const NUM: usize>(&'a i32);
+
+impl<'a, const NUM: usize> Ref<'a, NUM> {
+ pub fn foo<const A: usize>(r: Ref<'a, A>) -> Self
+ where
+ ([(); NUM - A], [(); A - NUM]): Sized,
+ {
+ Self::bar(r)
+ }
+
+ pub fn bar<const A: usize>(r: Ref<'a, A>) -> Self
+ where
+ ([(); NUM - A], [(); A - NUM]): Sized,
+ {
+ Self(r.0)
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs
new file mode 100644
index 000000000..db1e2fc2a
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs
@@ -0,0 +1,14 @@
+// revisions: cfail
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+pub struct Ref<'a>(&'a i32);
+
+impl<'a> Ref<'a> {
+ pub fn foo<const A: usize>() -> [(); A - 0] {
+ Self::foo()
+ //~^ error: type annotations needed
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs
new file mode 100644
index 000000000..5b2f5edc8
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs
@@ -0,0 +1,25 @@
+// revisions: rpass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn test<const SIZE: usize>() {}
+
+trait SomeTrait {
+ const SIZE: usize;
+}
+
+struct A<'a, T> {
+ some_ref: &'a str,
+ _maker: core::marker::PhantomData<T>,
+}
+
+impl<'a, T: SomeTrait> A<'a, T>
+where
+ [(); T::SIZE]: ,
+{
+ fn call_test() {
+ test::<{ T::SIZE }>();
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs
new file mode 100644
index 000000000..d659c5676
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs
@@ -0,0 +1,16 @@
+// revisions: rpass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo;
+impl<'a> std::ops::Add<&'a Foo> for Foo
+where
+ [(); 0 + 0]: Sized,
+{
+ type Output = ();
+ fn add(self, _: &Foo) -> Self::Output {
+ loop {}
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
new file mode 100644
index 000000000..5f5435ba9
--- /dev/null
+++ b/src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
@@ -0,0 +1,28 @@
+// revisions: cfail
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_braces)]
+
+struct Buffer<T, const S: usize>
+where
+ [(); { S * 2 }]: Default,
+{
+ data: [T; { S * 2 }],
+}
+
+struct BufferIter<'a, T, const S: usize>(&'a Buffer<T, S>)
+where
+ [(); { S * 2 }]: Default;
+
+impl<'a, T, const S: usize> Iterator for BufferIter<'a, T, S> {
+ //~^ error: the trait bound
+ //~^^ error: unconstrained generic constant
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ //~^ error: the trait bound
+ //~^^ error: unconstrained generic constant
+ None
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/crate_hash_reorder.rs b/src/test/incremental/crate_hash_reorder.rs
new file mode 100644
index 000000000..ca476b4d2
--- /dev/null
+++ b/src/test/incremental/crate_hash_reorder.rs
@@ -0,0 +1,27 @@
+// Test that the crate hash is not affected by reordering items.
+
+// revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+// Check that reordering otherwise identical items is not considered a
+// change at all.
+#[rustc_clean(cfg = "rpass2")]
+// But removing an item, naturally, is.
+#[rustc_clean(except="hir_crate", cfg = "rpass3")]
+#[cfg(rpass1)]
+pub struct X {
+ pub x: u32,
+}
+
+pub struct Y {
+ pub x: u32,
+}
+
+#[cfg(rpass2)]
+pub struct X {
+ pub x: u32,
+}
+
+pub fn main() {}
diff --git a/src/test/incremental/cyclic-trait-hierarchy.rs b/src/test/incremental/cyclic-trait-hierarchy.rs
new file mode 100644
index 000000000..b502e7207
--- /dev/null
+++ b/src/test/incremental/cyclic-trait-hierarchy.rs
@@ -0,0 +1,13 @@
+// Adapted from rust-lang/rust#58813
+
+// revisions: rpass1 cfail2
+
+#[cfg(rpass1)]
+pub trait T2 {}
+#[cfg(cfail2)]
+pub trait T2: T1 {}
+//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2`
+
+pub trait T1: T2 {}
+
+fn main() {}
diff --git a/src/test/incremental/delayed_span_bug.rs b/src/test/incremental/delayed_span_bug.rs
new file mode 100644
index 000000000..2529e531e
--- /dev/null
+++ b/src/test/incremental/delayed_span_bug.rs
@@ -0,0 +1,8 @@
+// revisions: cfail1 cfail2
+// should-ice
+// error-pattern: delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]
+
+#![feature(rustc_attrs)]
+
+#[rustc_error(delay_span_bug_from_inside_query)]
+fn main() {}
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
new file mode 100644
index 000000000..11d999ab3
--- /dev/null
+++ b/src/test/incremental/dirty_clean.rs
@@ -0,0 +1,49 @@
+// revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Sanity check for the dirty-clean system. Give the opposite
+// annotations that we expect to see, so that we check that errors are
+// reported.
+
+fn main() { }
+
+mod x {
+ #[cfg(rpass1)]
+ pub fn x() -> usize {
+ 22
+ }
+
+ #[cfg(cfail2)]
+ pub fn x() -> u32 {
+ 22
+ }
+}
+
+mod y {
+ use x;
+
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig",
+ cfg="cfail2",
+ )]
+ pub fn y() {
+ //[cfail2]~^ ERROR `hir_owner(y)` should be dirty but is not
+ //[cfail2]~| ERROR `hir_owner_nodes(y)` should be dirty but is not
+ //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not
+ //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not
+ //[cfail2]~| ERROR `type_of(y)` should be dirty but is not
+ //[cfail2]~| ERROR `fn_sig(y)` should be dirty but is not
+ //[cfail2]~| ERROR `typeck(y)` should be clean but is not
+ x::x();
+ }
+}
+
+mod z {
+ #[rustc_clean(except="typeck", cfg="cfail2")]
+ pub fn z() {
+ //[cfail2]~^ ERROR `typeck(z)` should be dirty but is not
+ }
+}
diff --git a/src/test/incremental/extern_static/issue-49153.rs b/src/test/incremental/extern_static/issue-49153.rs
new file mode 100644
index 000000000..f1dbac288
--- /dev/null
+++ b/src/test/incremental/extern_static/issue-49153.rs
@@ -0,0 +1,11 @@
+// https://github.com/rust-lang/rust/issues/49153
+
+// revisions:rpass1 rpass2
+
+extern "C" {
+ pub static __ImageBase: u8;
+}
+
+pub static FOO: &'static u8 = unsafe { &__ImageBase };
+
+fn main() {}
diff --git a/src/test/incremental/feature_gate.rs b/src/test/incremental/feature_gate.rs
new file mode 100644
index 000000000..5317a9962
--- /dev/null
+++ b/src/test/incremental/feature_gate.rs
@@ -0,0 +1,13 @@
+// This test makes sure that we detect changed feature gates.
+
+// revisions:rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![cfg_attr(rpass1, feature(abi_unadjusted))]
+
+fn main() {
+}
+
+extern "unadjusted" fn foo() {}
+//[cfail2]~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
diff --git a/src/test/incremental/foreign.rs b/src/test/incremental/foreign.rs
new file mode 100644
index 000000000..f46f92eb5
--- /dev/null
+++ b/src/test/incremental/foreign.rs
@@ -0,0 +1,38 @@
+// Test what happens we save incremental compilation state that makes
+// use of foreign items. This used to ICE (#34991).
+// ignore-sgx no libc
+
+// revisions: rpass1
+
+#![feature(rustc_private)]
+
+extern crate libc;
+
+use std::ffi::CString;
+
+mod mlibc {
+ use libc::{c_char, c_long, c_longlong};
+
+ extern "C" {
+ pub fn atol(x: *const c_char) -> c_long;
+ pub fn atoll(x: *const c_char) -> c_longlong;
+ }
+}
+
+fn atol(s: String) -> isize {
+ let c = CString::new(s).unwrap();
+ unsafe { mlibc::atol(c.as_ptr()) as isize }
+}
+
+fn atoll(s: String) -> i64 {
+ let c = CString::new(s).unwrap();
+ unsafe { mlibc::atoll(c.as_ptr()) as i64 }
+}
+
+pub fn main() {
+ assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
+ assert_eq!(
+ (atoll("11111111111111111".to_string()) * 10),
+ atoll("111111111111111110".to_string())
+ );
+}
diff --git a/src/test/incremental/hash-module-order.rs b/src/test/incremental/hash-module-order.rs
new file mode 100644
index 000000000..fe9af9eeb
--- /dev/null
+++ b/src/test/incremental/hash-module-order.rs
@@ -0,0 +1,28 @@
+// revisions: rpass1 rpass2
+// compile-flags: -Z incremental-ignore-spans -Z query-dep-graph
+
+// Tests that module hashing depends on the order of the items
+// (since the order is exposed through `Mod.item_ids`).
+// Changing the order of items (while keeping `Span`s the same)
+// should still result in `hir_owner` being invalidated.
+// Note that it's possible to keep the spans unchanged using
+// a proc-macro (e.g. producing the module via `quote!`)
+// but we use `-Z incremental-ignore-spans` for simplicity
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+#[rustc_clean(cfg="rpass1",except="hir_owner")]
+mod foo {
+ struct First;
+ struct Second;
+}
+
+#[cfg(rpass2)]
+#[rustc_clean(cfg="rpass2",except="hir_owner")]
+mod foo {
+ struct Second;
+ struct First;
+}
+
+fn main() {}
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
new file mode 100644
index 000000000..f3a7722cd
--- /dev/null
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -0,0 +1,200 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for function and method call expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+fn callee1(_x: u32, _y: i64) {}
+fn callee2(_x: u32, _y: i64) {}
+
+
+// Change Callee (Function)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_callee_function() {
+ callee1(1, 2)
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_callee_function() {
+ callee2(1, 2)
+}
+
+
+
+// Change Argument (Function)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_argument_function() {
+ callee1(1, 2)
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_argument_function() {
+ callee1(1, 3)
+}
+
+
+
+// Change Callee Indirectly (Function)
+mod change_callee_indirectly_function {
+ #[cfg(any(cfail1,cfail4))]
+ use super::callee1 as callee;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::callee2 as callee;
+
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_callee_indirectly_function() {
+ callee(1, 2)
+ }
+}
+
+
+struct Struct;
+impl Struct {
+ fn method1(&self, _x: char, _y: bool) {}
+ fn method2(&self, _x: char, _y: bool) {}
+}
+
+// Change Callee (Method)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_callee_method() {
+ let s = Struct;
+ s.method1('x', true);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_callee_method() {
+ let s = Struct;
+ s.method2('x', true);
+}
+
+
+
+// Change Argument (Method)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_argument_method() {
+ let s = Struct;
+ s.method1('x', true);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_argument_method() {
+ let s = Struct;
+ s.method1('y', true);
+}
+
+
+
+// Change Callee (Method, UFCS)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_ufcs_callee_method() {
+ let s = Struct;
+ Struct::method1(&s, 'x', true);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_ufcs_callee_method() {
+ let s = Struct;
+ Struct::method2(&s, 'x', true);
+}
+
+
+
+// Change Argument (Method, UFCS)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_argument_method_ufcs() {
+ let s = Struct;
+ Struct::method1(&s, 'x', true);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_argument_method_ufcs() {
+ let s = Struct;
+ Struct::method1(&s, 'x',false);
+}
+
+
+
+// Change To UFCS
+#[cfg(any(cfail1,cfail4))]
+pub fn change_to_ufcs() {
+ let s = Struct;
+ s.method1('x', true); // ------
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+// One might think this would be expanded in the hir_owner_nodes/Mir, but it actually
+// results in slightly different hir_owner/Mir.
+pub fn change_to_ufcs() {
+ let s = Struct;
+ Struct::method1(&s, 'x', true);
+}
+
+
+struct Struct2;
+impl Struct2 {
+ fn method1(&self, _x: char, _y: bool) {}
+}
+
+// Change UFCS Callee Indirectly
+pub mod change_ufcs_callee_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::Struct as Struct;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Struct2 as Struct;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_ufcs_callee_indirectly() {
+ let s = Struct;
+ Struct::method1(&s, 'q', false)
+ }
+}
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
new file mode 100644
index 000000000..c769246b2
--- /dev/null
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -0,0 +1,127 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for closure expression.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change closure body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_closure_body() {
+ let _ = || 1u32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_closure_body() {
+ let _ = || 3u32;
+}
+
+
+
+// Add parameter
+#[cfg(any(cfail1,cfail4))]
+pub fn add_parameter() {
+ let x = 0u32;
+ let _ = | | x + 1;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_parameter() {
+ let x = 0u32;
+ let _ = |x: u32| x + 1;
+}
+
+
+
+// Change parameter pattern
+#[cfg(any(cfail1,cfail4))]
+pub fn change_parameter_pattern() {
+ let _ = | x : (u32,)| x;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_parameter_pattern() {
+ let _ = |(x,): (u32,)| x;
+}
+
+
+
+// Add `move` to closure
+#[cfg(any(cfail1,cfail4))]
+pub fn add_move() {
+ let _ = || 1;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_move() {
+ let _ = move || 1;
+}
+
+
+
+// Add type ascription to parameter
+#[cfg(any(cfail1,cfail4))]
+pub fn add_type_ascription_to_parameter() {
+ let closure = |x | x + 1u32;
+ let _: u32 = closure(1);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn add_type_ascription_to_parameter() {
+ let closure = |x: u32| x + 1u32;
+ let _: u32 = closure(1);
+}
+
+
+
+// Change parameter type
+#[cfg(any(cfail1,cfail4))]
+pub fn change_parameter_type() {
+ let closure = |x: u32| (x as u64) + 1;
+ let _ = closure(1);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_parameter_type() {
+ let closure = |x: u16| (x as u64) + 1;
+ let _ = closure(1);
+}
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
new file mode 100644
index 000000000..eaef63386
--- /dev/null
+++ b/src/test/incremental/hashes/consts.rs
@@ -0,0 +1,109 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for consts.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph -O
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change const visibility
+#[cfg(cfail1)]
+const CONST_VISIBILITY: u8 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+pub const CONST_VISIBILITY: u8 = 0;
+
+
+// Change type from i32 to u32
+#[cfg(cfail1)]
+const CONST_CHANGE_TYPE_1: i32 = 0;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_TYPE_1: u32 = 0;
+
+
+// Change type from Option<u32> to Option<u64>
+#[cfg(cfail1)]
+const CONST_CHANGE_TYPE_2: Option<u32> = None;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_TYPE_2: Option<u64> = None;
+
+
+// Change value between simple literals
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_1: i16 = {
+ #[cfg(cfail1)]
+ { 1 }
+
+ #[cfg(not(cfail1))]
+ { 2 }
+};
+
+
+// Change value between expressions
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_2: i16 = {
+ #[cfg(cfail1)]
+ { 1 + 1 }
+
+ #[cfg(not(cfail1))]
+ { 1 + 2 }
+};
+
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_3: i16 = {
+ #[cfg(cfail1)]
+ { 2 + 3 }
+
+ #[cfg(not(cfail1))]
+ { 2 * 3 }
+};
+
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+const CONST_CHANGE_VALUE_4: i16 = {
+ #[cfg(cfail1)]
+ { 1 + 2 * 3 }
+
+ #[cfg(not(cfail1))]
+ { 1 + 2 * 4 }
+};
+
+
+// Change type indirectly
+struct ReferencedType1;
+struct ReferencedType2;
+
+mod const_change_type_indirectly {
+ #[cfg(cfail1)]
+ use super::ReferencedType1 as Type;
+
+ #[cfg(not(cfail1))]
+ use super::ReferencedType2 as Type;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail3")]
+ const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail3")]
+ const CONST_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
+}
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
new file mode 100644
index 000000000..70ef10645
--- /dev/null
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -0,0 +1,390 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for struct constructor expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+pub enum Enum {
+ Struct {
+ x: i32,
+ y: i64,
+ z: i16,
+ },
+ Tuple(i32, i64, i16)
+}
+
+// Change field value (struct-like) -----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_value_struct_like() -> Enum {
+ Enum::Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_value_struct_like() -> Enum {
+ Enum::Struct {
+ x: 0,
+ y: 2,
+ z: 2,
+ }
+}
+
+
+
+// Change field order (struct-like) -----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_order_struct_like() -> Enum {
+ Enum::Struct {
+ x: 3,
+ y: 4,
+ z: 5,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+// FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
+// would if it were not all constants
+pub fn change_field_order_struct_like() -> Enum {
+ Enum::Struct {
+ y: 4,
+ x: 3,
+ z: 5,
+ }
+}
+
+
+pub enum Enum2 {
+ Struct {
+ x: i8,
+ y: i8,
+ z: i8,
+ },
+ Struct2 {
+ x: i8,
+ y: i8,
+ z: i8,
+ },
+ Tuple(u16, u16, u16),
+ Tuple2(u64, u64, u64),
+}
+
+// Change constructor path (struct-like) ------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_path_struct_like() {
+ let _ = Enum ::Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_path_struct_like() {
+ let _ = Enum2::Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+
+
+// Change variant (regular struct) ------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_variant_struct_like() {
+ let _ = Enum2::Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_variant_struct_like() {
+ let _ = Enum2::Struct2 {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+
+// Change constructor path indirectly (struct-like) -------------------------
+pub mod change_constructor_path_indirectly_struct_like {
+ #[cfg(any(cfail1,cfail4))]
+ use super::Enum as TheEnum;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Enum2 as TheEnum;
+
+ #[rustc_clean(
+ cfg="cfail2",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> TheEnum {
+ TheEnum::Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+ }
+}
+
+
+// Change constructor variant indirectly (struct-like) ---------------------------
+pub mod change_constructor_variant_indirectly_struct_like {
+ use super::Enum2;
+ #[cfg(any(cfail1,cfail4))]
+ use super::Enum2::Struct as Variant;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Enum2::Struct2 as Variant;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> Enum2 {
+ Variant {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+ }
+}
+
+
+// Change field value (tuple-like) -------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_value_tuple_like() -> Enum {
+ Enum::Tuple(0, 1, 2)
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_value_tuple_like() -> Enum {
+ Enum::Tuple(0, 1, 3)
+}
+
+
+
+// Change constructor path (tuple-like) --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_path_tuple_like() {
+ let _ = Enum ::Tuple(0, 1, 2);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner_nodes,typeck"
+)]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_path_tuple_like() {
+ let _ = Enum2::Tuple(0, 1, 2);
+}
+
+
+
+// Change constructor variant (tuple-like) --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_variant_tuple_like() {
+ let _ = Enum2::Tuple (0, 1, 2);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner_nodes,typeck"
+)]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_variant_tuple_like() {
+ let _ = Enum2::Tuple2(0, 1, 2);
+}
+
+
+// Change constructor path indirectly (tuple-like) ---------------------------
+pub mod change_constructor_path_indirectly_tuple_like {
+ #[cfg(any(cfail1,cfail4))]
+ use super::Enum as TheEnum;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Enum2 as TheEnum;
+
+ #[rustc_clean(
+ cfg="cfail2",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> TheEnum {
+ TheEnum::Tuple(0, 1, 2)
+ }
+}
+
+
+
+// Change constructor variant indirectly (tuple-like) ---------------------------
+pub mod change_constructor_variant_indirectly_tuple_like {
+ use super::Enum2;
+ #[cfg(any(cfail1,cfail4))]
+ use super::Enum2::Tuple as Variant;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Enum2::Tuple2 as Variant;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> Enum2 {
+ Variant(0, 1, 2)
+ }
+}
+
+
+pub enum Clike {
+ A,
+ B,
+ C
+}
+
+pub enum Clike2 {
+ B,
+ C,
+ D
+}
+
+// Change constructor path (C-like) --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_path_c_like() {
+ let _x = Clike ::B;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_path_c_like() {
+ let _x = Clike2::B;
+}
+
+
+
+// Change constructor variant (C-like) --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_variant_c_like() {
+ let _x = Clike::A;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_variant_c_like() {
+ let _x = Clike::C;
+}
+
+
+// Change constructor path indirectly (C-like) ---------------------------
+pub mod change_constructor_path_indirectly_c_like {
+ #[cfg(any(cfail1,cfail4))]
+ use super::Clike as TheEnum;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Clike2 as TheEnum;
+
+ #[rustc_clean(
+ cfg="cfail2",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+ typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> TheEnum {
+ TheEnum::B
+ }
+}
+
+
+
+// Change constructor variant indirectly (C-like) ---------------------------
+pub mod change_constructor_variant_indirectly_c_like {
+ use super::Clike;
+ #[cfg(any(cfail1,cfail4))]
+ use super::Clike::A as Variant;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::Clike::B as Variant;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> Clike {
+ Variant
+ }
+}
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
new file mode 100644
index 000000000..b466cfdd5
--- /dev/null
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -0,0 +1,718 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for enum definitions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// We also test the ICH for enum definitions exported in metadata. Same as
+// above, we want to make sure that the change between rev1 and rev2 also
+// results in a change of the ICH for the enum's metadata, and that it stays
+// the same between rev2 and rev3.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+#![crate_type="rlib"]
+
+
+
+// Change enum visibility -----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumVisibility { A }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub enum EnumVisibility { A }
+
+
+
+// Change name of a c-style variant -------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeNameCStyleVariant {
+ Variant1,
+ Variant2,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeNameCStyleVariant {
+ Variant1,
+ Variant2Changed,
+}
+
+
+
+// Change name of a tuple-style variant ---------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeNameTupleStyleVariant {
+ Variant1,
+ Variant2(u32, f32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeNameTupleStyleVariant {
+ Variant1,
+ Variant2Changed(u32, f32),
+}
+
+
+
+// Change name of a struct-style variant --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeNameStructStyleVariant {
+ Variant1,
+ Variant2 { a: u32, b: f32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeNameStructStyleVariant {
+ Variant1,
+ Variant2Changed { a: u32, b: f32 },
+}
+
+
+
+// Change the value of a c-style variant --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeValueCStyleVariant0 {
+ Variant1,
+ Variant2 = 11,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeValueCStyleVariant0 {
+ Variant1,
+ Variant2 = 22,
+}
+
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeValueCStyleVariant1 {
+ Variant1,
+ Variant2,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeValueCStyleVariant1 {
+ Variant1,
+ Variant2 = 11,
+}
+
+
+
+// Add a c-style variant ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddCStyleVariant {
+ Variant1,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddCStyleVariant {
+ Variant1,
+ Variant2,
+}
+
+
+
+// Remove a c-style variant ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumRemoveCStyleVariant {
+ Variant1,
+ Variant2,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumRemoveCStyleVariant {
+ Variant1,
+}
+
+
+
+// Add a tuple-style variant --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddTupleStyleVariant {
+ Variant1,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddTupleStyleVariant {
+ Variant1,
+ Variant2(u32, f32),
+}
+
+
+
+// Remove a tuple-style variant -----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumRemoveTupleStyleVariant {
+ Variant1,
+ Variant2(u32, f32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumRemoveTupleStyleVariant {
+ Variant1,
+}
+
+
+
+// Add a struct-style variant -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddStructStyleVariant {
+ Variant1,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddStructStyleVariant {
+ Variant1,
+ Variant2 { a: u32, b: f32 },
+}
+
+
+
+// Remove a struct-style variant ----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumRemoveStructStyleVariant {
+ Variant1,
+ Variant2 { a: u32, b: f32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumRemoveStructStyleVariant {
+ Variant1,
+}
+
+
+
+// Change the type of a field in a tuple-style variant ------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeFieldTypeTupleStyleVariant {
+ Variant1(u32, u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeFieldTypeTupleStyleVariant {
+ Variant1(u32,
+ u64),
+}
+
+
+
+// Change the type of a field in a struct-style variant -----------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeFieldTypeStructStyleVariant {
+ Variant1,
+ Variant2 { a: u32, b: u32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeFieldTypeStructStyleVariant {
+ Variant1,
+ Variant2 {
+ a: u32,
+ b: u64
+ },
+}
+
+
+
+// Change the name of a field in a struct-style variant -----------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeFieldNameStructStyleVariant {
+ Variant1 { a: u32, b: u32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeFieldNameStructStyleVariant {
+ Variant1 { a: u32, c: u32 },
+}
+
+
+
+// Change order of fields in a tuple-style variant ----------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeOrderTupleStyleVariant {
+ Variant1(u32, u64),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeOrderTupleStyleVariant {
+ Variant1(
+ u64,
+ u32),
+}
+
+
+
+// Change order of fields in a struct-style variant ---------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeFieldOrderStructStyleVariant {
+ Variant1 { a: u32, b: f32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeFieldOrderStructStyleVariant {
+ Variant1 { b: f32, a: u32 },
+}
+
+
+
+// Add a field to a tuple-style variant ---------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddFieldTupleStyleVariant {
+ Variant1(u32, u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddFieldTupleStyleVariant {
+ Variant1(u32, u32, u32),
+}
+
+
+
+// Add a field to a struct-style variant --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddFieldStructStyleVariant {
+ Variant1 { a: u32, b: u32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddFieldStructStyleVariant {
+ Variant1 { a: u32, b: u32, c: u32 },
+}
+
+
+
+// Add #[must_use] to the enum ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddMustUse {
+ Variant1,
+ Variant2,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[must_use]
+enum EnumAddMustUse {
+ Variant1,
+ Variant2,
+}
+
+
+
+// Add #[repr(C)] to the enum -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddReprC {
+ Variant1,
+ Variant2,
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="type_of")]
+#[rustc_clean(cfg="cfail6")]
+#[repr(C)]
+enum EnumAddReprC {
+ Variant1,
+ Variant2,
+}
+
+
+
+// Change the name of a type parameter ----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeNameOfTypeParameter<S> {
+ Variant1(S),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeNameOfTypeParameter<T> {
+ Variant1(T),
+}
+
+
+
+// Add a type parameter ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddTypeParameter<S> {
+ Variant1(S),
+ Variant2(S),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddTypeParameter<S, T> {
+ Variant1(S),
+ Variant2(T),
+}
+
+
+
+// Change the name of a lifetime parameter ------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumChangeNameOfLifetimeParameter<'a> {
+ Variant1(&'a u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumChangeNameOfLifetimeParameter<'b> {
+ Variant1(&'b u32),
+}
+
+
+
+// Add a lifetime parameter ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddLifetimeParameter<'a> {
+ Variant1(&'a u32),
+ Variant2(&'a u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddLifetimeParameter<'a, 'b> {
+ Variant1(&'a u32),
+ Variant2(&'b u32),
+}
+
+
+
+// Add a lifetime bound to a lifetime parameter -------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddLifetimeParameterBound<'a, 'b> {
+ Variant1(&'a u32),
+ Variant2(&'b u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
+ Variant1(&'a u32),
+ Variant2(&'b u32),
+}
+
+// Add a lifetime bound to a type parameter -----------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddLifetimeBoundToParameter<'a, T> {
+ Variant1(T),
+ Variant2(&'a u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
+ Variant1(T),
+ Variant2(&'a u32),
+}
+
+
+
+// Add a trait bound to a type parameter --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddTraitBound<S> {
+ Variant1(S),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddTraitBound<T: Sync> {
+ Variant1(T),
+}
+
+
+
+// Add a lifetime bound to a lifetime parameter in where clause ---------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddLifetimeParameterBoundWhere<'a, 'b> {
+ Variant1(&'a u32),
+ Variant2(&'b u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
+ Variant1(&'a u32),
+ Variant2(&'b u32),
+}
+
+
+
+// Add a lifetime bound to a type parameter in where clause -------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddLifetimeBoundToParameterWhere<'a, T> {
+ Variant1(T),
+ Variant2(&'a u32),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
+ Variant1(T),
+ Variant2(&'a u32),
+}
+
+
+
+// Add a trait bound to a type parameter in where clause ----------------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumAddTraitBoundWhere<S> {
+ Variant1(S),
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumAddTraitBoundWhere<T> where T: Sync {
+ Variant1(T),
+}
+
+
+
+// In an enum with two variants, swap usage of type parameters ----------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumSwapUsageTypeParameters<A, B> {
+ Variant1 { a: A },
+ Variant2 { a: B },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumSwapUsageTypeParameters<A, B> {
+ Variant1 {
+ a: B
+ },
+ Variant2 {
+ a: A
+ },
+}
+
+
+
+// In an enum with two variants, swap usage of lifetime parameters ------------
+#[cfg(any(cfail1,cfail4))]
+enum EnumSwapUsageLifetimeParameters<'a, 'b> {
+ Variant1 { a: &'a u32 },
+ Variant2 { b: &'b u32 },
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+enum EnumSwapUsageLifetimeParameters<'a, 'b> {
+ Variant1 {
+ a: &'b u32
+ },
+ Variant2 {
+ b: &'a u32
+ },
+}
+
+
+
+struct ReferencedType1;
+struct ReferencedType2;
+
+
+
+// Change field type in tuple-style variant indirectly by modifying a use statement
+mod change_field_type_indirectly_tuple_style {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as FieldType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as FieldType;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
+ enum TupleStyle {
+ Variant1(
+ FieldType
+ )
+ }
+}
+
+
+
+// Change field type in record-style variant indirectly by modifying a use statement
+mod change_field_type_indirectly_struct_style {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as FieldType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as FieldType;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
+ enum StructStyle {
+ Variant1 {
+ a: FieldType
+ }
+ }
+}
+
+
+
+trait ReferencedTrait1 {}
+trait ReferencedTrait2 {}
+
+
+
+// Change trait bound of type parameter indirectly by modifying a use statement
+mod change_trait_bound_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
+ enum Enum<T: Trait> {
+ Variant1(T)
+ }
+}
+
+
+
+// Change trait bound of type parameter in where clause indirectly by modifying a use statement
+mod change_trait_bound_indirectly_where {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
+ enum Enum<T> where T: Trait {
+ Variant1(T)
+ }
+}
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
new file mode 100644
index 000000000..87fd21fd1
--- /dev/null
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -0,0 +1,75 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Case 1: The function body is not exported to metadata. If the body changes,
+// the hash of the hir_owner_nodes node should change, but not the hash of
+// either the hir_owner or the Metadata node.
+
+#[cfg(any(cfail1,cfail4))]
+pub fn body_not_exported_to_metadata() -> u32 {
+ 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn body_not_exported_to_metadata() -> u32 {
+ 2
+}
+
+
+
+// Case 2: The function body *is* exported to metadata because the function is
+// marked as #[inline]. Only the hash of the hir_owner depnode should be
+// unaffected by a change to the body.
+
+#[cfg(any(cfail1,cfail4))]
+#[inline]
+pub fn body_exported_to_metadata_because_of_inline() -> u32 {
+ 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[inline]
+pub fn body_exported_to_metadata_because_of_inline() -> u32 {
+ 2
+}
+
+
+
+// Case 2: The function body *is* exported to metadata because the function is
+// generic. Only the hash of the hir_owner depnode should be
+// unaffected by a change to the body.
+
+#[cfg(any(cfail1,cfail4))]
+#[inline]
+pub fn body_exported_to_metadata_because_of_generic() -> u32 {
+ 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[inline]
+pub fn body_exported_to_metadata_because_of_generic() -> u32 {
+ 2
+}
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
new file mode 100644
index 000000000..ff79acc7f
--- /dev/null
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -0,0 +1,224 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `extern` modules.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(unboxed_closures)]
+#![crate_type = "rlib"]
+
+// Change function name --------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn change_function_name1(c: i64) -> i32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn change_function_name2(c: i64) -> i32;
+}
+
+// Change parameter name -------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn change_parameter_name(c: i64) -> i32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn change_parameter_name(d: i64) -> i32;
+}
+
+// Change parameter type -------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn change_parameter_type(c: i64) -> i32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn change_parameter_type(c: i32) -> i32;
+}
+
+// Change return type ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn change_return_type(c: i32) -> i32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn change_return_type(c: i32) -> i8 ;
+}
+
+// Add parameter ---------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn add_parameter(c: i32 ) -> i32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn add_parameter(c: i32, d: i32) -> i32;
+}
+
+// Add return type -------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn add_return_type(c: i32) ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn add_return_type(c: i32) -> i32;
+}
+
+// Make function variadic ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn make_function_variadic(c: i32 );
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn make_function_variadic(c: i32, ...);
+}
+
+// Change calling convention ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn change_calling_convention(c: i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail6")]
+extern "rust-call" {
+ pub fn change_calling_convention(c: i32);
+}
+
+// Make function public --------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ fn make_function_public(c: i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn make_function_public(c: i32);
+}
+
+// Add function ----------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+extern "C" {
+ pub fn add_function1(c: i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail6")]
+extern "C" {
+ pub fn add_function1(c: i32);
+ pub fn add_function2();
+}
+
+// Change link-name ------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+#[link(name = "foo")]
+extern "C" {
+ pub fn change_link_name(c: i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+#[link(name = "bar")]
+extern "C" {
+ pub fn change_link_name(c: i32);
+}
+
+type c_i32 = i32;
+type c_i64 = i64;
+
+// Indirectly change parameter type --------------------------------------------
+mod indirectly_change_parameter_type {
+ #[cfg(any(cfail1,cfail4))]
+ use super::c_i32 as c_int;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::c_i64 as c_int;
+
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5")]
+ #[rustc_clean(cfg = "cfail6")]
+ extern "C" {
+ pub fn indirectly_change_parameter_type(c: c_int);
+ }
+}
+
+// Indirectly change return type --------------------------------------------
+mod indirectly_change_return_type {
+ #[cfg(any(cfail1,cfail4))]
+ use super::c_i32 as c_int;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::c_i64 as c_int;
+
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5")]
+ #[rustc_clean(cfg = "cfail6")]
+ extern "C" {
+ pub fn indirectly_change_return_type() -> c_int;
+ }
+}
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
new file mode 100644
index 000000000..16d6af016
--- /dev/null
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -0,0 +1,302 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `for` loops.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change loop body ------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 2;
+ break;
+ }
+}
+
+
+
+// Change iteration variable name ----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_iteration_variable_name() {
+ let mut _x = 0;
+ for _i in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_iteration_variable_name() {
+ let mut _x = 0;
+ for _a in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Change iteration variable pattern -------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_iteration_variable_pattern() {
+ let mut _x = 0;
+ for _i in &[0, 1, 2] {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_iteration_variable_pattern() {
+ let mut _x = 0;
+ for &_i in &[0, 1, 2] {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Change iterable -------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_iterable() {
+ let mut _x = 0;
+ for _ in &[0, 1, 2] {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_iterable() {
+ let mut _x = 0;
+ for _ in &[0, 1, 3] {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add break -------------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_break() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ // ---
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_break() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label --------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ 'label: for _ in 0..1 {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label to break -----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: for _ in 0..1 {
+ _x = 1;
+ break ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: for _ in 0..1 {
+ _x = 1;
+ break 'label;
+ }
+}
+
+
+
+// Change break label ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: for _ in 0..1 {
+ 'inner: for _ in 0..1 {
+ _x = 1;
+ break 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: for _ in 0..1 {
+ 'inner: for _ in 0..1 {
+ _x = 1;
+ break 'outer;
+ }
+ }
+}
+
+
+
+// Add loop label to continue --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: for _ in 0..1 {
+ _x = 1;
+ continue ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: for _ in 0..1 {
+ _x = 1;
+ continue 'label;
+ }
+}
+
+
+
+// Change continue label ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: for _ in 0..1 {
+ 'inner: for _ in 0..1 {
+ _x = 1;
+ continue 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: for _ in 0..1 {
+ 'inner: for _ in 0..1 {
+ _x = 1;
+ continue 'outer;
+ }
+ }
+}
+
+
+
+// Change continue to break ----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ continue;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ for _ in 0..1 {
+ _x = 1;
+ break ;
+ }
+}
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
new file mode 100644
index 000000000..076eddaab
--- /dev/null
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -0,0 +1,414 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for function interfaces.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(linkage)]
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+
+// Add Parameter ---------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn add_parameter() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn add_parameter(p: i32) {}
+
+// Add Return Type -------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn add_return_type() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn add_return_type() -> () {}
+
+// Change Parameter Type -------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn type_of_parameter(p: i32) {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn type_of_parameter(p: i64) {}
+
+// Change Parameter Type Reference ---------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn type_of_parameter_ref(p: &i32) {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn type_of_parameter_ref(p: &mut i32) {}
+
+// Change Parameter Order ------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn order_of_parameters(p1: i32, p2: i64) {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn order_of_parameters(p2: i64, p1: i32) {}
+
+// Unsafe ----------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn make_unsafe() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub unsafe fn make_unsafe() {}
+
+// Extern ----------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn make_extern() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
+pub extern "C" fn make_extern() {}
+
+// Type Parameter --------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn type_parameter () {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn type_parameter<T>() {}
+
+// Lifetime Parameter ----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn lifetime_parameter () {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn lifetime_parameter<'a>() {}
+
+// Trait Bound -----------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn trait_bound<T >() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn trait_bound<T: Eq>() {}
+
+// Builtin Bound ---------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn builtin_bound<T >() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn builtin_bound<T: Send>() {}
+
+// Lifetime Bound --------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn lifetime_bound<'a, T>() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn lifetime_bound<'a, T: 'a>() {}
+
+// Second Trait Bound ----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn second_trait_bound<T: Eq >() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn second_trait_bound<T: Eq + Clone>() {}
+
+// Second Builtin Bound --------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn second_builtin_bound<T: Send >() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn second_builtin_bound<T: Send + Sized>() {}
+
+// Second Lifetime Bound -------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn second_lifetime_bound<'a, 'b, T: 'a >() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
+pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
+
+// Inline ----------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn inline() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+#[inline]
+pub fn inline() {}
+
+// Inline Never ----------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+#[inline(always)]
+pub fn inline_never() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+#[inline(never)]
+pub fn inline_never() {}
+
+// No Mangle -------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn no_mangle() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+#[no_mangle]
+pub fn no_mangle() {}
+
+// Linkage ---------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn linkage() {}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+#[linkage = "weak_odr"]
+pub fn linkage() {}
+
+// Return Impl Trait -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn return_impl_trait() -> i32 {
+ 0
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn return_impl_trait() -> impl Clone {
+ 0
+}
+
+// Change Return Impl Trait ----------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub fn change_return_impl_trait() -> impl Clone {
+ 0u32
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
+#[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn change_return_impl_trait() -> impl Copy {
+ 0u32
+}
+
+// Change Return Type Indirectly -----------------------------------------------
+
+pub struct ReferencedType1;
+pub struct ReferencedType2;
+
+pub mod change_return_type_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as ReturnType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as ReturnType;
+
+ #[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail6")]
+ pub fn indirect_return_type() -> ReturnType {
+ ReturnType {}
+ }
+}
+
+// Change Parameter Type Indirectly --------------------------------------------
+
+pub mod change_parameter_type_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as ParameterType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as ParameterType;
+
+ #[rustc_clean(
+ cfg = "cfail2",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(
+ cfg = "cfail5",
+ except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+ )]
+ #[rustc_clean(cfg = "cfail6")]
+ pub fn indirect_parameter_type(p: ParameterType) {}
+}
+
+// Change Trait Bound Indirectly -----------------------------------------------
+
+pub trait ReferencedTrait1 {}
+pub trait ReferencedTrait2 {}
+
+pub mod change_trait_bound_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail6")]
+ pub fn indirect_trait_bound<T: Trait>(p: T) {}
+}
+
+// Change Trait Bound Indirectly In Where Clause -------------------------------
+
+pub mod change_trait_bound_indirectly_in_where_clause {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail3")]
+ #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+ #[rustc_clean(cfg = "cfail6")]
+ pub fn indirect_trait_bound_where<T>(p: T)
+ where
+ T: Trait,
+ {
+ }
+}
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
new file mode 100644
index 000000000..cff557dcb
--- /dev/null
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -0,0 +1,228 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for if expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Change condition (if)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_condition(x: bool) -> u32 {
+ if x {
+ return 1
+ }
+
+ return 0
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_condition(x: bool) -> u32 {
+ if !x {
+ return 1
+ }
+
+ return 0
+}
+
+// Change then branch (if)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_then_branch(x: bool) -> u32 {
+ if x {
+ return 1
+ }
+
+ return 0
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_then_branch(x: bool) -> u32 {
+ if x {
+ return 2
+ }
+
+ return 0
+}
+
+
+
+// Change else branch (if)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_else_branch(x: bool) -> u32 {
+ if x {
+ 1
+ } else {
+ 2
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_else_branch(x: bool) -> u32 {
+ if x {
+ 1
+ } else {
+ 3
+ }
+}
+
+
+
+// Add else branch (if)
+#[cfg(any(cfail1,cfail4))]
+pub fn add_else_branch(x: bool) -> u32 {
+ let mut ret = 1;
+
+ if x {
+ ret = 2;
+ /*----*/
+ }
+
+ ret
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_else_branch(x: bool) -> u32 {
+ let mut ret = 1;
+
+ if x {
+ ret = 2;
+ } else {
+ }
+
+ ret
+}
+
+
+
+// Change condition (if let)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_condition_if_let(x: Option<u32>) -> u32 {
+ if let Some(_x) = x {
+ return 1
+ }
+
+ 0
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_condition_if_let(x: Option<u32>) -> u32 {
+ if let Some(_ ) = x {
+ return 1
+ }
+
+ 0
+}
+
+
+
+// Change then branch (if let)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
+ if let Some(x) = x {
+ return x //-
+ }
+
+ 0
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
+ if let Some(x) = x {
+ return x + 1
+ }
+
+ 0
+}
+
+
+
+// Change else branch (if let)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
+ if let Some(x) = x {
+ x
+ } else {
+ 1
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
+ if let Some(x) = x {
+ x
+ } else {
+ 2
+ }
+}
+
+
+
+// Add else branch (if let)
+#[cfg(any(cfail1,cfail4))]
+pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
+ let mut ret = 1;
+
+ if let Some(x) = x {
+ ret = x;
+ /*----*/
+ }
+
+ ret
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
+ let mut ret = 1;
+
+ if let Some(x) = x {
+ ret = x;
+ } else {
+ }
+
+ ret
+}
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
new file mode 100644
index 000000000..9ef468472
--- /dev/null
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -0,0 +1,137 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for indexing expression.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Change simple index
+#[cfg(any(cfail1,cfail4))]
+fn change_simple_index(slice: &[u32]) -> u32 {
+ slice[3]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn change_simple_index(slice: &[u32]) -> u32 {
+ slice[4]
+}
+
+
+
+// Change lower bound
+#[cfg(any(cfail1,cfail4))]
+fn change_lower_bound(slice: &[u32]) -> &[u32] {
+ &slice[3..5]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn change_lower_bound(slice: &[u32]) -> &[u32] {
+ &slice[2..5]
+}
+
+
+
+// Change upper bound
+#[cfg(any(cfail1,cfail4))]
+fn change_upper_bound(slice: &[u32]) -> &[u32] {
+ &slice[3..5]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn change_upper_bound(slice: &[u32]) -> &[u32] {
+ &slice[3..7]
+}
+
+
+
+// Add lower bound
+#[cfg(any(cfail1,cfail4))]
+fn add_lower_bound(slice: &[u32]) -> &[u32] {
+ &slice[ ..4]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn add_lower_bound(slice: &[u32]) -> &[u32] {
+ &slice[3..4]
+}
+
+
+
+// Add upper bound
+#[cfg(any(cfail1,cfail4))]
+fn add_upper_bound(slice: &[u32]) -> &[u32] {
+ &slice[3.. ]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn add_upper_bound(slice: &[u32]) -> &[u32] {
+ &slice[3..7]
+}
+
+
+
+// Change mutability
+#[cfg(any(cfail1,cfail4))]
+fn change_mutability(slice: &mut [u32]) -> u32 {
+ (&mut slice[3..5])[0]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn change_mutability(slice: &mut [u32]) -> u32 {
+ (& slice[3..5])[0]
+}
+
+
+
+// Exclusive to inclusive range
+#[cfg(any(cfail1,cfail4))]
+fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
+ &slice[3.. 7]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
+ &slice[3..=7]
+}
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
new file mode 100644
index 000000000..1abbff32c
--- /dev/null
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -0,0 +1,790 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for let expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+pub struct Foo;
+
+// Change Method Name -----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ pub fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn method_name2() { }
+}
+
+// Change Method Body -----------------------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //--------------------------------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn method_body() {
+ // -----------------------
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn method_body() {
+ println!("Hello, world!");
+ }
+}
+
+
+// Change Method Body (inlined) ------------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //------------------------------------------------------------
+ //
+ //--------------------------
+ #[inline]
+ pub fn method_body_inlined() {
+ // -----------------------
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ #[inline]
+ pub fn method_body_inlined() {
+ println!("Hello, world!");
+ }
+}
+
+
+// Change Method Privacy -------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //--------------------------
+ //--------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ pub fn method_privacy() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_privacy() { }
+}
+
+// Change Method Selfness -----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //---------------------------------------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //---------------------------------------------------------------------------------------------
+ //
+ //--------------------------
+ pub fn method_selfness() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn method_selfness(&self) { }
+}
+
+// Change Method Selfmutness ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn method_selfmutness(& self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn method_selfmutness(&mut self) { }
+}
+
+
+
+// Add Method To Impl ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ pub fn add_method_to_impl1(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_method_to_impl1(&self) { }
+
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_method_to_impl2(&self) { }
+}
+
+
+
+// Add Method Parameter --------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn add_method_parameter(&self ) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_method_parameter(&self, _: i32) { }
+}
+
+
+
+// Change Method Parameter Name ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
+ pub fn change_method_parameter_name(&self, a: i64) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_method_parameter_name(&self, b: i64) { }
+}
+
+
+
+// Change Method Return Type ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn change_method_return_type(&self) -> u16 { 0 }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_method_return_type(&self) -> u32 { 0 }
+}
+
+
+
+// Make Method #[inline] -------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //-------
+ pub fn make_method_inline(&self) -> u8 { 0 }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ #[inline]
+ pub fn make_method_inline(&self) -> u8 { 0 }
+}
+
+
+
+// Change order of parameters -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
+ pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
+}
+
+
+
+// Make method unsafe ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------------------
+ //--------------------------
+ pub fn make_method_unsafe(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+ #[rustc_clean(cfg="cfail6")]
+ pub unsafe fn make_method_unsafe(&self) { }
+}
+
+
+
+// Make method extern ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //----------------------------------------------------------------------------
+ //--------------------------
+ //----------------------------------------------------------------------------
+ //--------------------------
+ pub fn make_method_extern(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub extern "C" fn make_method_extern(&self) { }
+}
+
+
+
+// Change method calling convention --------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //----------------------------------------------------------------------------
+ //--------------------------
+ //----------------------------------------------------------------------------
+ //--------------------------
+ pub extern "C" fn change_method_calling_convention(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub extern "system" fn change_method_calling_convention(&self) { }
+}
+
+
+
+// Add Lifetime Parameter to Method --------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ---------------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------
+ // -------------------------------------------------------
+ // --------------------------------------------------------
+ // ----------------------------------------------------------
+ // -----------------------------------------------------------
+ // ----------------------------------------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ pub fn add_lifetime_parameter_to_method (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ // Warning: Note that `typeck` are coming up clean here.
+ // The addition or removal of lifetime parameters that don't
+ // appear in the arguments or fn body in any way does not, in
+ // fact, affect the `typeck` in any semantic way (at least
+ // as of this writing). **However,** altering the order of
+ // lowering **can** cause it appear to affect the `typeck`:
+ // if we lower generics before the body, then the `HirId` for
+ // things in the body will be affected. So if you start to see
+ // `typeck` appear dirty, that might be the cause. -nmatsakis
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_lifetime_parameter_to_method<'a>(&self) { }
+}
+
+
+
+// Add Type Parameter To Method ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ---------------------------------------------------------------
+ // -------------------------------------------------------------
+ // -----------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------
+ //
+ // -------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------
+ //
+ // -------------------------
+ pub fn add_type_parameter_to_method (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ // Warning: Note that `typeck` are coming up clean here.
+ // The addition or removal of type parameters that don't appear in
+ // the arguments or fn body in any way does not, in fact, affect
+ // the `typeck` in any semantic way (at least as of this
+ // writing). **However,** altering the order of lowering **can**
+ // cause it appear to affect the `typeck`: if we lower
+ // generics before the body, then the `HirId` for things in the
+ // body will be affected. So if you start to see `typeck`
+ // appear dirty, that might be the cause. -nmatsakis
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_type_parameter_to_method<T>(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Lifetime Parameter of Method --------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //------------
+ //---------------
+ //-----------------------------------------------------------------------------
+ //
+ //--------------------------
+ //------------
+ //---------------
+ //-----------------------------------------------------------------------------
+ //
+ //--------------------------
+ pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Type Parameter of Method ------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------------
+ // -------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------------
+ //
+ // -------------------------
+ // -----------
+ // --------------
+ // ----------------------------------------------------------------------------
+ //
+ // -------------------------
+ pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ // Warning: Note that `typeck` are coming up clean here.
+ // The addition or removal of bounds that don't appear in the
+ // arguments or fn body in any way does not, in fact, affect the
+ // `typeck` in any semantic way (at least as of this
+ // writing). **However,** altering the order of lowering **can**
+ // cause it appear to affect the `typeck`: if we lower
+ // generics before the body, then the `HirId` for things in the
+ // body will be affected. So if you start to see `typeck`
+ // appear dirty, that might be the cause. -nmatsakis
+ #[rustc_clean(
+ cfg="cfail2",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
+}
+
+
+
+// Add Trait Bound to Type Parameter of Method ------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ // -----------------------------------------------------
+ // ----------------------------------------------------------
+ // -------------------------------------------------------------
+ // -------------------------------------------------
+ // -------------------------------------------------------------
+ // ---------------------------------------------------
+ // ------------------------------------------------------------
+ // ------------------------------------------------------
+ // -------------------------------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ pub fn add_trait_bound_to_type_param_of_method<T >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ // Warning: Note that `typeck` are coming up clean here.
+ // The addition or removal of bounds that don't appear in the
+ // arguments or fn body in any way does not, in fact, affect the
+ // `typeck` in any semantic way (at least as of this
+ // writing). **However,** altering the order of lowering **can**
+ // cause it appear to affect the `typeck`: if we lower
+ // generics before the body, then the `HirId` for things in the
+ // body will be affected. So if you start to see `typeck`
+ // appear dirty, that might be the cause. -nmatsakis
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
+}
+
+
+
+// Add #[no_mangle] to Method --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //----------
+ pub fn add_no_mangle_to_method(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ #[no_mangle]
+ pub fn add_no_mangle_to_method(&self) { }
+}
+
+
+
+struct Bar<T>(T);
+
+// Add Type Parameter To Impl --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Bar<u32> {
+ pub fn add_type_parameter_to_impl(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")]
+#[rustc_clean(cfg="cfail6")]
+impl<T> Bar<T> {
+ #[rustc_clean(
+ cfg="cfail2",
+ except="generics_of,fn_sig,typeck,type_of,optimized_mir"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="generics_of,fn_sig,typeck,type_of,optimized_mir"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_type_parameter_to_impl(&self) { }
+}
+
+
+
+// Change Self Type of Impl ----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl Bar<u32> {
+ pub fn change_impl_self_type(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+impl Bar<u64> {
+ #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="fn_sig,optimized_mir,typeck")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn change_impl_self_type(&self) { }
+}
+
+
+
+// Add Lifetime Bound to Impl --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl<T> Bar<T> {
+ pub fn add_lifetime_bound_to_impl_parameter(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+impl<T: 'static> Bar<T> {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_lifetime_bound_to_impl_parameter(&self) { }
+}
+
+
+
+// Add Trait Bound to Impl Parameter -------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+impl<T> Bar<T> {
+ pub fn add_trait_bound_to_impl_parameter(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+impl<T: Clone> Bar<T> {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn add_trait_bound_to_impl_parameter(&self) { }
+}
+
+
+// Force instantiation of some fns so we can check their hash.
+pub fn instantiation_root() {
+ Foo::method_privacy();
+
+ #[cfg(any(cfail1,cfail4))]
+ {
+ Bar(0u32).change_impl_self_type();
+ }
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ {
+ Bar(0u64).change_impl_self_type();
+ }
+}
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
new file mode 100644
index 000000000..dc878d682
--- /dev/null
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -0,0 +1,222 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for inline asm.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// needs-asm-support
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+use std::arch::asm;
+
+// Change template
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_template(_a: i32) -> i32 {
+ let c: i32;
+ unsafe {
+ asm!("mov {0}, 1",
+ out(reg) c
+ );
+ }
+ c
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_template(_a: i32) -> i32 {
+ let c: i32;
+ unsafe {
+ asm!("mov {0}, 2",
+ out(reg) c
+ );
+ }
+ c
+}
+
+
+
+// Change output
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_output(a: i32) -> i32 {
+ let mut _out1: i32 = 0;
+ let mut _out2: i32 = 0;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out1,
+ in(reg) a
+ );
+ }
+ _out1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_output(a: i32) -> i32 {
+ let mut _out1: i32 = 0;
+ let mut _out2: i32 = 0;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out2,
+ in(reg) a
+ );
+ }
+ _out1
+}
+
+
+
+// Change input
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_input(_a: i32, _b: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a
+ );
+ }
+ _out
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_input(_a: i32, _b: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _b
+ );
+ }
+ _out
+}
+
+
+
+// Change input constraint
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ in("eax") _b);
+ }
+ _out
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ in("ecx") _b);
+ }
+ _out
+}
+
+
+// Change clobber
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_clobber(_a: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ lateout("ecx") _
+ );
+ }
+ _out
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_clobber(_a: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ lateout("edx") _
+ );
+ }
+ _out
+}
+
+
+
+// Change options
+#[cfg(any(cfail1,cfail4))]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_options(_a: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ options(readonly),
+ );
+ }
+ _out
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+pub fn change_options(_a: i32) -> i32 {
+ let _out;
+ unsafe {
+ asm!("mov {0}, {1}",
+ out(reg) _out,
+ in(reg) _a,
+ options(nomem ),
+ );
+ }
+ _out
+}
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
new file mode 100644
index 000000000..01320cd51
--- /dev/null
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -0,0 +1,222 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for let expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Change Name -----------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_name() {
+ let _x = 2u64;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_name() {
+ let _y = 2u64;
+}
+
+
+
+// Add Type --------------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_type() {
+ let _x = 2u32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_type() {
+ let _x: u32 = 2u32;
+}
+
+
+
+// Change Type -----------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_type() {
+ let _x: u64 = 2;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_type() {
+ let _x: u8 = 2;
+}
+
+
+
+// Change Mutability of Reference Type -----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_mutability_of_reference_type() {
+ let _x: & u64;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_mutability_of_reference_type() {
+ let _x: &mut u64;
+}
+
+
+
+// Change Mutability of Slot ---------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_mutability_of_slot() {
+ let mut _x: u64 = 0;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_mutability_of_slot() {
+ let _x: u64 = 0;
+}
+
+
+
+// Change Simple Binding to Pattern --------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_simple_binding_to_pattern() {
+ let _x = (0u8, 'x');
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_simple_binding_to_pattern() {
+ let (_a, _b) = (0u8, 'x');
+}
+
+
+
+// Change Name in Pattern ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_name_in_pattern() {
+ let (_a, _b) = (1u8, 'y');
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_name_in_pattern() {
+ let (_a, _c) = (1u8, 'y');
+}
+
+
+
+// Add `ref` in Pattern --------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_ref_in_pattern() {
+ let ( _a, _b) = (1u8, 'y');
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_ref_in_pattern() {
+ let (ref _a, _b) = (1u8, 'y');
+}
+
+
+
+// Add `&` in Pattern ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_amp_in_pattern() {
+ let ( _a, _b) = (&1u8, 'y');
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_amp_in_pattern() {
+ let (&_a, _b) = (&1u8, 'y');
+}
+
+
+
+// Change Mutability of Binding in Pattern -------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_mutability_of_binding_in_pattern() {
+ let ( _a, _b) = (99u8, 'q');
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_mutability_of_binding_in_pattern() {
+ let (mut _a, _b) = (99u8, 'q');
+}
+
+
+
+// Add Initializer -------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_initializer() {
+ let _x: i16 ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_initializer() {
+ let _x: i16 = 3i16;
+}
+
+
+
+// Change Initializer ----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_initializer() {
+ let _x = 4u16;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_initializer() {
+ let _x = 5u16;
+}
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
new file mode 100644
index 000000000..a12cd0d02
--- /dev/null
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -0,0 +1,227 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `loop` loops.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change loop body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ loop {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ loop {
+ _x = 2;
+ break;
+ }
+}
+
+
+
+// Add break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_break() {
+ let mut _x = 0;
+ loop {
+ _x = 1;
+ //----
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_break() {
+ let mut _x = 0;
+ loop {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ /*---*/ loop {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ 'label: loop {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label to break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: loop {
+ _x = 1;
+ break ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: loop {
+ _x = 1;
+ break 'label;
+ }
+}
+
+
+
+// Change break label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: loop {
+ 'inner: loop {
+ _x = 1;
+ break 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: loop {
+ 'inner: loop {
+ _x = 1;
+ break 'outer;
+ }
+ }
+}
+
+
+
+// Add loop label to continue
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: loop {
+ _x = 1;
+ continue ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: loop {
+ _x = 1;
+ continue 'label;
+ }
+}
+
+
+
+// Change continue label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: loop {
+ 'inner: loop {
+ _x = 1;
+ continue 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: loop {
+ 'inner: loop {
+ _x = 1;
+ continue 'outer;
+ }
+ }
+}
+
+
+
+// Change continue to break
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ loop {
+ _x = 1;
+ continue;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ loop {
+ _x = 1;
+ break ;
+ }
+}
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
new file mode 100644
index 000000000..fa054c7de
--- /dev/null
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -0,0 +1,337 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for match expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Add Arm ---------------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_arm(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ /*---*/
+ _ => 100,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_arm(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ _ => 100,
+ }
+}
+
+
+
+// Change Order Of Arms --------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_order_of_arms(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ _ => 100,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_order_of_arms(x: u32) -> u32 {
+ match x {
+ 1 => 1,
+ 0 => 0,
+ _ => 100,
+ }
+}
+
+
+
+// Add Guard Clause ------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_guard_clause(x: u32, y: bool) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ _ => 100,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_guard_clause(x: u32, y: bool) -> u32 {
+ match x {
+ 0 => 0,
+ 1 if y => 1,
+ _ => 100,
+ }
+}
+
+
+
+// Change Guard Clause ------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_guard_clause(x: u32, y: bool) -> u32 {
+ match x {
+ 0 => 0,
+ 1 if y => 1,
+ _ => 100,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_guard_clause(x: u32, y: bool) -> u32 {
+ match x {
+ 0 => 0,
+ 1 if !y => 1,
+ _ => 100,
+ }
+}
+
+
+
+// Add @-Binding ---------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_at_binding(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ _ => x,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_at_binding(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ x @ _ => x,
+ }
+}
+
+
+
+// Change Name of @-Binding ----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_name_of_at_binding(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ x @ _ => 7,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_name_of_at_binding(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ y @ _ => 7,
+ }
+}
+
+
+
+// Change Simple Binding To Pattern --------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_simple_name_to_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (0, 0) => 0,
+ a => 1,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_simple_name_to_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (0, 0) => 0,
+ (x, y) => 1,
+ }
+}
+
+
+
+// Change Name In Pattern ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_name_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (a, 0) => 0,
+ (a, 1) => a,
+ _ => 100,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_name_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (b, 0) => 0,
+ (a, 1) => a,
+ _ => 100,
+ }
+}
+
+
+
+// Change Mutability Of Binding In Pattern -------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ ( a, 0) => 0,
+ _ => 1,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (mut a, 0) => 0,
+ _ => 1,
+ }
+}
+
+
+
+// Add `ref` To Binding In Pattern -------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ ( a, 0) => 0,
+ _ => 1,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
+ match (x, x & 1) {
+ (ref a, 0) => 0,
+ _ => 1,
+ }
+}
+
+
+
+// Add `&` To Binding In Pattern -------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
+ match (&x, x & 1) {
+ ( a, 0) => 0,
+ _ => 1,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
+ match (&x, x & 1) {
+ (&a, 0) => 0,
+ _ => 1,
+ }
+}
+
+
+
+// Change RHS Of Arm -----------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn change_rhs_of_arm(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ _ => 2,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_rhs_of_arm(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 3,
+ _ => 2,
+ }
+}
+
+
+
+// Add Alternative To Arm ------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn add_alternative_to_arm(x: u32) -> u32 {
+ match x {
+ 0 => 0,
+ 1 => 1,
+ _ => 2,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_alternative_to_arm(x: u32) -> u32 {
+ match x {
+ 0 | 7 => 0,
+ 1 => 3,
+ _ => 2,
+ }
+}
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
new file mode 100644
index 000000000..37d10d922
--- /dev/null
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -0,0 +1,151 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for exprs that can panic at runtime (e.g., because of bounds checking). For
+// these expressions an error message containing their source location is
+// generated, so their hash must always depend on their location in the source
+// code, not just when debuginfo is enabled.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph -C debug-assertions -O
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Indexing expression
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn indexing(slice: &[u8]) -> u8 {
+ #[cfg(cfail1)]
+ {
+ slice[100]
+ }
+ #[cfg(not(cfail1))]
+ {
+ slice[100]
+ }
+}
+
+
+// Arithmetic overflow plus
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn arithmetic_overflow_plus(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ val + 1
+ }
+ #[cfg(not(cfail1))]
+ {
+ val + 1
+ }
+}
+
+
+// Arithmetic overflow minus
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn arithmetic_overflow_minus(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ val - 1
+ }
+ #[cfg(not(cfail1))]
+ {
+ val - 1
+ }
+}
+
+
+// Arithmetic overflow mult
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn arithmetic_overflow_mult(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ val * 2
+ }
+ #[cfg(not(cfail1))]
+ {
+ val * 2
+ }
+}
+
+
+// Arithmetic overflow negation
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn arithmetic_overflow_negation(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ -val
+ }
+ #[cfg(not(cfail1))]
+ {
+ -val
+ }
+}
+
+
+// Division by zero
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn division_by_zero(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ 2 / val
+ }
+ #[cfg(not(cfail1))]
+ {
+ 2 / val
+ }
+}
+
+// Division by zero
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn mod_by_zero(val: i32) -> i32 {
+ #[cfg(cfail1)]
+ {
+ 2 % val
+ }
+ #[cfg(not(cfail1))]
+ {
+ 2 % val
+ }
+}
+
+
+// shift left
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn shift_left(val: i32, shift: usize) -> i32 {
+ #[cfg(cfail1)]
+ {
+ val << shift
+ }
+ #[cfg(not(cfail1))]
+ {
+ val << shift
+ }
+}
+
+
+// shift right
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+pub fn shift_right(val: i32, shift: usize) -> i32 {
+ #[cfg(cfail1)]
+ {
+ val >> shift
+ }
+ #[cfg(not(cfail1))]
+ {
+ val >> shift
+ }
+}
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
new file mode 100644
index 000000000..67d87f5c4
--- /dev/null
+++ b/src/test/incremental/hashes/statics.rs
@@ -0,0 +1,186 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for statics.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(linkage)]
+#![feature(thread_local)]
+#![crate_type="rlib"]
+
+
+// Change static visibility
+#[cfg(any(cfail1,cfail4))]
+static STATIC_VISIBILITY: u8 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub static STATIC_VISIBILITY: u8 = 0;
+
+
+// Change static mutability
+#[cfg(any(cfail1,cfail4))]
+static STATIC_MUTABILITY: u8 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+static mut STATIC_MUTABILITY: u8 = 0;
+
+
+// Add linkage attribute
+#[cfg(any(cfail1,cfail4))]
+static STATIC_LINKAGE: u8 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[linkage="weak_odr"]
+static STATIC_LINKAGE: u8 = 0;
+
+
+// Add no_mangle attribute
+#[cfg(any(cfail1,cfail4))]
+static STATIC_NO_MANGLE: u8 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[no_mangle]
+static STATIC_NO_MANGLE: u8 = 0;
+
+
+// Add thread_local attribute
+#[cfg(any(cfail1,cfail4))]
+static STATIC_THREAD_LOCAL: u8 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[thread_local]
+static STATIC_THREAD_LOCAL: u8 = 0;
+
+
+// Change type from i16 to u64
+#[cfg(any(cfail1,cfail4))]
+static STATIC_CHANGE_TYPE_1: i16 = 0;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_TYPE_1: u64 = 0;
+
+
+// Change type from Option<i8> to Option<u16>
+#[cfg(any(cfail1,cfail4))]
+static STATIC_CHANGE_TYPE_2: Option<i8> = None;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_TYPE_2: Option<u16> = None;
+
+
+// Change value between simple literals
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_VALUE_1: i16 = {
+ #[cfg(any(cfail1,cfail4))]
+ { 1 }
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ { 2 }
+};
+
+
+// Change value between expressions
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_VALUE_2: i16 = {
+ #[cfg(any(cfail1,cfail4))]
+ { 1 + 1 }
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ { 1 + 2 }
+};
+
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_VALUE_3: i16 = {
+ #[cfg(any(cfail1,cfail4))]
+ { 2 + 3 }
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ { 2 * 3 }
+};
+
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+static STATIC_CHANGE_VALUE_4: i16 = {
+ #[cfg(any(cfail1,cfail4))]
+ { 1 + 2 * 3 }
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ { 1 + 2 * 4 }
+};
+
+
+// Change type indirectly
+struct ReferencedType1;
+struct ReferencedType2;
+
+mod static_change_type_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as Type;
+
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as Type;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail6")]
+ static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+ #[rustc_clean(cfg="cfail6")]
+ static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
+}
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
new file mode 100644
index 000000000..fc9671cb4
--- /dev/null
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -0,0 +1,270 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for struct constructor expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+pub struct RegularStruct {
+ x: i32,
+ y: i64,
+ z: i16,
+}
+
+// Change field value (regular struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_value_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_value_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 0,
+ y: 2,
+ z: 2,
+ }
+}
+
+
+
+// Change field order (regular struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_order_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_order_regular_struct() -> RegularStruct {
+ RegularStruct {
+ y: 4,
+ x: 3,
+ z: 5,
+ }
+}
+
+
+
+// Add field (regular struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn add_field_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ // --
+ .. struct1
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_field_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ y: 8,
+ .. struct1
+ }
+}
+
+
+
+// Change field label (regular struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_label_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ y: 9,
+ .. struct1
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_label_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ z: 9,
+ .. struct1
+ }
+}
+
+
+
+pub struct RegularStruct2 {
+ x: i8,
+ y: i8,
+ z: i8,
+}
+
+// Change constructor path (regular struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_path_regular_struct() {
+ let _ = RegularStruct {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_path_regular_struct() {
+ let _ = RegularStruct2 {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+
+
+// Change constructor path indirectly (regular struct)
+pub mod change_constructor_path_indirectly_regular_struct {
+ #[cfg(any(cfail1,cfail4))]
+ use super::RegularStruct as Struct;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::RegularStruct2 as Struct;
+
+ #[rustc_clean(
+ cfg="cfail2",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ pub fn function() -> Struct {
+ Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+ }
+}
+
+
+
+pub struct TupleStruct(i32, i64, i16);
+
+// Change field value (tuple struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_field_value_tuple_struct() -> TupleStruct {
+ TupleStruct(0, 1, 2)
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_field_value_tuple_struct() -> TupleStruct {
+ TupleStruct(0, 1, 3)
+}
+
+
+
+pub struct TupleStruct2(u16, u16, u16);
+
+// Change constructor path (tuple struct)
+#[cfg(any(cfail1,cfail4))]
+pub fn change_constructor_path_tuple_struct() {
+ let _ = TupleStruct (0, 1, 2);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_constructor_path_tuple_struct() {
+ let _ = TupleStruct2(0, 1, 2);
+}
+
+
+
+// Change constructor path indirectly (tuple struct)
+pub mod change_constructor_path_indirectly_tuple_struct {
+ #[cfg(any(cfail1,cfail4))]
+ use super::TupleStruct as Struct;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::TupleStruct2 as Struct;
+
+ #[rustc_clean(
+ cfg="cfail5",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ #[rustc_clean(
+ cfg="cfail2",
+ except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ pub fn function() -> Struct {
+ Struct(0, 1, 2)
+ }
+}
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
new file mode 100644
index 000000000..7a91722d7
--- /dev/null
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -0,0 +1,335 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for struct definitions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// We also test the ICH for struct definitions exported in metadata. Same as
+// above, we want to make sure that the change between rev1 and rev2 also
+// results in a change of the ICH for the struct's metadata, and that it stays
+// the same between rev2 and rev3.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+// Layout ----------------------------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub struct LayoutPacked;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[repr(packed)]
+pub struct LayoutPacked;
+
+#[cfg(any(cfail1,cfail4))]
+struct LayoutC;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+#[repr(C)]
+struct LayoutC;
+
+
+// Tuple Struct Change Field Type ----------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct TupleStructFieldType(i32);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+// Note that changing the type of a field does not change the type of the struct or enum, but
+// adding/removing fields or changing a fields name or visibility does.
+struct TupleStructFieldType(
+ u32
+);
+
+
+// Tuple Struct Add Field ------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct TupleStructAddField(i32);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct TupleStructAddField(
+ i32,
+ u32
+);
+
+
+// Tuple Struct Field Visibility -----------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct TupleStructFieldVisibility( char);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+struct TupleStructFieldVisibility(pub char);
+
+
+// Record Struct Field Type ----------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct RecordStructFieldType { x: f32 }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+// Note that changing the type of a field does not change the type of the struct or enum, but
+// adding/removing fields or changing a fields name or visibility does.
+struct RecordStructFieldType {
+ x: u64
+}
+
+
+// Record Struct Field Name ----------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct RecordStructFieldName { x: f32 }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct RecordStructFieldName { y: f32 }
+
+
+// Record Struct Add Field -----------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct RecordStructAddField { x: f32 }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct RecordStructAddField {
+ x: f32,
+ y: () }
+
+
+// Record Struct Field Visibility ----------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct RecordStructFieldVisibility { x: f32 }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="type_of")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
+struct RecordStructFieldVisibility { pub x: f32 }
+
+
+// Add Lifetime Parameter ------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
+
+
+// Add Lifetime Parameter Bound ------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddLifetimeParameterBound<'a, 'b: 'a>(
+ &'a f32,
+ &'b f64
+);
+
+#[cfg(any(cfail1,cfail4))]
+struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
+ &'a f32,
+ &'b f64)
+ where 'b: 'a;
+
+
+// Add Type Parameter ----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct AddTypeParameter<T1>(T1, T1);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddTypeParameter<T1, T2>(
+ // The field contains the parent's Generics, so it's dirty even though its
+ // type hasn't changed.
+ T1,
+ T2
+);
+
+
+// Add Type Parameter Bound ----------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct AddTypeParameterBound<T>(T);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddTypeParameterBound<T: Send>(
+ T
+);
+
+
+#[cfg(any(cfail1,cfail4))]
+struct AddTypeParameterBoundWhereClause<T>(T);
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+struct AddTypeParameterBoundWhereClause<T>(
+ T
+) where T: Sync;
+
+
+// Empty struct ----------------------------------------------------------------
+// Since we cannot change anything in this case, we just make sure that the
+// fingerprint is stable (i.e., that there are no random influences like memory
+// addresses taken into account by the hashing algorithm).
+// Note: there is no #[cfg(...)], so this is ALWAYS compiled
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub struct EmptyStruct;
+
+
+// Visibility ------------------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+struct Visibility;
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub struct Visibility;
+
+struct ReferencedType1;
+struct ReferencedType2;
+
+// Tuple Struct Change Field Type Indirectly -----------------------------------
+mod tuple_struct_change_field_type_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as FieldType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as FieldType;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ struct TupleStruct(
+ FieldType
+ );
+}
+
+
+// Record Struct Change Field Type Indirectly -----------------------------------
+mod record_struct_change_field_type_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedType1 as FieldType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedType2 as FieldType;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ struct RecordStruct {
+ _x: FieldType
+ }
+}
+
+
+
+
+trait ReferencedTrait1 {}
+trait ReferencedTrait2 {}
+
+// Change Trait Bound Indirectly -----------------------------------------------
+mod change_trait_bound_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ struct Struct<T: Trait>(T);
+}
+
+// Change Trait Bound Indirectly In Where Clause -------------------------------
+mod change_trait_bound_indirectly_in_where_clause {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ struct Struct<T>(T) where T : Trait;
+}
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
new file mode 100644
index 000000000..1988f3f35
--- /dev/null
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -0,0 +1,1412 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for trait definitions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// We also test the ICH for trait definitions exported in metadata. Same as
+// above, we want to make sure that the change between rev1 and rev2 also
+// results in a change of the ICH for the trait's metadata, and that it stays
+// the same between rev2 and rev3.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+#![feature(associated_type_defaults)]
+
+
+// Change trait visibility
+#[cfg(any(cfail1,cfail4))]
+trait TraitVisibility { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub trait TraitVisibility { }
+
+
+
+// Change trait unsafety
+#[cfg(any(cfail1,cfail4))]
+trait TraitUnsafety { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+unsafe trait TraitUnsafety { }
+
+
+
+// Add method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddMethod {
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub trait TraitAddMethod {
+ fn method();
+}
+
+
+
+// Change name of method
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeMethodName {
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeMethodName {
+ fn methodChanged();
+}
+
+
+
+// Add return type to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddReturnType {
+ //---------------------------------------------------------------------
+ //--------------------------
+ //---------------------------------------------------------------------
+ //--------------------------
+ fn method() ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddReturnType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method() -> u32;
+}
+
+
+
+// Change return type of method
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeReturnType {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method() -> u32;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeReturnType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method() -> u64;
+}
+
+
+
+// Add parameter to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddParameterToMethod {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method( );
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddParameterToMethod {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(a: u32);
+}
+
+
+
+// Change name of method parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeMethodParameterName {
+ //------------------------------------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ fn method(a: u32);
+
+ //------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------
+ //--------------------------
+ fn with_default(x: i32) {}
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeMethodParameterName {
+ // FIXME(#38501) This should preferably always be clean.
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(b: u32);
+
+ #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn with_default(y: i32) {}
+}
+
+
+
+// Change type of method parameter (i32 => i64)
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeMethodParameterType {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method(a: i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeMethodParameterType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(a: i64);
+}
+
+
+
+// Change type of method parameter (&i32 => &mut i32)
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeMethodParameterTypeRef {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method(a: & i32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeMethodParameterTypeRef {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(a: &mut i32);
+}
+
+
+
+// Change order of method parameters
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeMethodParametersOrder {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method(a: i32, b: i64);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeMethodParametersOrder {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(b: i64, a: i32);
+}
+
+
+
+// Add default implementation to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddMethodAutoImplementation {
+ // -------------------------------------------------------------
+ // -------------------------
+ // -------------------------------------------------------------
+ // -------------------------
+ fn method() ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddMethodAutoImplementation {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method() {}
+}
+
+
+
+// Change order of methods
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeOrderOfMethods {
+ fn method0();
+ fn method1();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeOrderOfMethods {
+ fn method1();
+ fn method0();
+}
+
+
+
+// Change mode of self parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeModeSelfRefToMut {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method(& self);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeModeSelfRefToMut {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(&mut self);
+}
+
+
+
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeModeSelfOwnToMut: Sized {
+ // ----------------------------------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------------------------------
+ // -------------------------
+ fn method( self) {}
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeModeSelfOwnToMut: Sized {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(mut self) {}
+}
+
+
+
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeModeSelfOwnToRef {
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ fn method( self);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeModeSelfOwnToRef {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(&self);
+}
+
+
+
+// Add unsafe modifier to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddUnsafeModifier {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method() ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddUnsafeModifier {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ unsafe fn method();
+}
+
+
+
+// Add extern modifier to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddExternModifier {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ fn method() ;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddExternModifier {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ extern "C" fn method();
+}
+
+
+
+// Change extern "C" to extern "stdcall"
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeExternCToRustIntrinsic {
+ // --------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------
+ // -------------------------
+ extern "C" fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeExternCToRustIntrinsic {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ extern "stdcall" fn method();
+}
+
+
+
+// Add type parameter to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTypeParameterToMethod {
+ // --------------------------------------------------------------------------------
+ // ---------------
+ // -------------------------
+ // --------------------------------------------------------------------------------
+ // ---------------
+ // -------------------------
+ fn method ();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTypeParameterToMethod {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+ cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+ cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T>();
+}
+
+
+
+// Add lifetime parameter to method
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeParameterToMethod {
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ // --------------------------------------------------------------------------------
+ // -------------------------
+ fn method ();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeParameterToMethod {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<'a>();
+}
+
+
+
+// dummy trait for bound
+trait ReferencedTrait0 { }
+trait ReferencedTrait1 { }
+
+// Add trait bound to method type parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitBoundToMethodTypeParameter {
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T >();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitBoundToMethodTypeParameter {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T: ReferencedTrait0>();
+}
+
+
+
+// Add builtin bound to method type parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltinBoundToMethodTypeParameter {
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T >();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltinBoundToMethodTypeParameter {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T: Sized>();
+}
+
+
+
+// Add lifetime bound to method lifetime parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToMethodLifetimeParameter {
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ fn method<'a, 'b >(a: &'a u32, b: &'b u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToMethodLifetimeParameter {
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail2",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
+}
+
+
+
+// Add second trait bound to method type parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondTraitBoundToMethodTypeParameter {
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T: ReferencedTrait0 >();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondTraitBoundToMethodTypeParameter {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T: ReferencedTrait0 + ReferencedTrait1>();
+}
+
+
+
+// Add second builtin bound to method type parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------------
+ // -------------------------
+ fn method<T: Sized >();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T: Sized + Sync>();
+}
+
+
+
+// Add second lifetime bound to method lifetime parameter
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ // -----------
+ // -----------------------------------------------------------------------------
+ // --------------
+ //
+ // -------------------------
+ fn method<'a, 'b, 'c: 'a >(a: &'a u32, b: &'b u32, c: &'c u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail2",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
+}
+
+
+
+// Add associated type
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddAssociatedType {
+ //--------------------------
+ //--------------------------
+ // -------------
+
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddAssociatedType {
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
+ type Associated;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method();
+}
+
+
+
+// Add trait bound to associated type
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitBoundToAssociatedType {
+ // -------------------------------------------------------------
+ // -------------------------
+ // -------------------------------------------------------------
+ // -------------------------
+ type Associated ;
+
+ fn method();
+}
+
+
+// Apparently the type bound contributes to the predicates of the trait, but
+// does not change the associated item itself.
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitBoundToAssociatedType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ type Associated: ReferencedTrait0;
+
+ fn method();
+}
+
+
+
+// Add lifetime bound to associated type
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToAssociatedType<'a> {
+ // -------------------------------------------------------------
+ // -------------------------
+ // -------------------------------------------------------------
+ // -------------------------
+ type Associated ;
+
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToAssociatedType<'a> {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ type Associated: 'a;
+
+ fn method();
+}
+
+
+
+// Add default to associated type
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddDefaultToAssociatedType {
+ //--------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ type Associated ;
+
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddDefaultToAssociatedType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ type Associated = ReferenceType0;
+
+ fn method();
+}
+
+
+
+// Add associated constant
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddAssociatedConstant {
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddAssociatedConstant {
+ const Value: u32;
+
+ fn method();
+}
+
+
+
+// Add initializer to associated constant
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddInitializerToAssociatedConstant {
+ //--------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ const Value: u32 ;
+
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ //--------------------------
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddInitializerToAssociatedConstant {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ const Value: u32 = 1;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method();
+}
+
+
+
+// Change type of associated constant
+#[cfg(any(cfail1,cfail4))]
+trait TraitChangeTypeOfAssociatedConstant {
+ // ---------------------------------------------------------------------
+ // -------------------------
+ // ---------------------------------------------------------------------
+ // -------------------------
+ const Value: u32;
+
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ fn method();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitChangeTypeOfAssociatedConstant {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ const Value: f64;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method();
+}
+
+
+
+// Add super trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSuperTrait { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSuperTrait : ReferencedTrait0 { }
+
+
+
+// Add builtin bound (Send or Copy)
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltiBound { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltiBound : Send { }
+
+
+
+// Add 'static lifetime bound to trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddStaticLifetimeBound { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddStaticLifetimeBound : 'static { }
+
+
+
+// Add super trait as second bound
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
+
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
+
+
+
+// Add builtin bound as second bound
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
+
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
+
+
+
+// Add 'static bounds as second bound
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
+
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
+
+
+
+// Add type parameter to trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTypeParameterToTrait { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTypeParameterToTrait<T> { }
+
+
+
+// Add lifetime parameter to trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeParameterToTrait { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeParameterToTrait<'a> { }
+
+
+
+// Add trait bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
+
+
+
+// Add lifetime bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
+
+
+
+// Add lifetime bound to lifetime parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
+
+
+
+// Add builtin bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
+
+
+
+// Add second type parameter to trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondTypeParameterToTrait<T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondTypeParameterToTrait<T, S> { }
+
+
+
+// Add second lifetime parameter to trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeParameterToTrait<'a> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
+
+
+
+// Add second trait bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
+
+
+
+// Add second lifetime bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
+
+
+
+// Add second lifetime bound to lifetime parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
+
+
+
+// Add second builtin bound to type parameter of trait
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
+
+
+
+struct ReferenceType0 {}
+struct ReferenceType1 {}
+
+
+
+// Add trait bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
+
+
+
+// Add lifetime bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
+
+
+
+// Add lifetime bound to lifetime parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
+
+
+
+// Add builtin bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
+
+
+
+// Add second trait bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
+ where T: ReferencedTrait0 + ReferencedTrait1 { }
+
+
+
+// Add second lifetime bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
+
+
+
+// Add second lifetime bound to lifetime parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
+
+
+
+// Add second builtin bound to type parameter of trait in where clause
+#[cfg(any(cfail1,cfail4))]
+trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
+
+
+// Change return type of method indirectly by modifying a use statement
+mod change_return_type_of_method_indirectly_use {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferenceType0 as ReturnType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferenceType1 as ReturnType;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeReturnType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method() -> ReturnType;
+ }
+}
+
+
+
+// Change type of method parameter indirectly by modifying a use statement
+mod change_method_parameter_type_indirectly_by_use {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferenceType0 as ArgType;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferenceType1 as ArgType;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeArgType {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method(a: ArgType);
+ }
+}
+
+
+
+// Change trait bound of method type parameter indirectly by modifying a use statement
+mod change_method_parameter_type_bound_indirectly_by_use {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait0 as Bound;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait1 as Bound;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeBoundOfMethodTypeParameter {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T: Bound>(a: T);
+ }
+}
+
+
+
+// Change trait bound of method type parameter in where clause indirectly
+// by modifying a use statement
+mod change_method_parameter_type_bound_indirectly_by_use_where {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait0 as Bound;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait1 as Bound;
+
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeBoundOfMethodTypeParameterWhere {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method<T>(a: T) where T: Bound;
+ }
+}
+
+
+
+// Change trait bound of trait type parameter indirectly by modifying a use statement
+mod change_method_type_parameter_bound_indirectly {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait0 as Bound;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait1 as Bound;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeTraitBound<T: Bound> {
+ fn method(a: T);
+ }
+}
+
+
+
+// Change trait bound of trait type parameter in where clause indirectly
+// by modifying a use statement
+mod change_method_type_parameter_bound_indirectly_where {
+ #[cfg(any(cfail1,cfail4))]
+ use super::ReferencedTrait0 as Bound;
+ #[cfg(not(any(cfail1,cfail4)))]
+ use super::ReferencedTrait1 as Bound;
+
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ trait TraitChangeTraitBoundWhere<T> where T: Bound {
+ fn method(a: T);
+ }
+}
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
new file mode 100644
index 000000000..f555f555f
--- /dev/null
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -0,0 +1,620 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for let expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![feature(specialization)]
+#![crate_type="rlib"]
+
+struct Foo;
+
+// Change Method Name -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeMethodNameTrait {
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeMethodNameTrait for Foo {
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub trait ChangeMethodNameTrait {
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name2();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeMethodNameTrait for Foo {
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name2() { }
+}
+
+// Change Method Body -----------------------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+
+pub trait ChangeMethodBodyTrait {
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeMethodBodyTrait for Foo {
+ // ----------------------------------------------------------
+ // -------------------------
+ // ----------------------------------------------------------
+ // -------------------------
+ fn method_name() {
+ //
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeMethodBodyTrait for Foo {
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name() {
+ ()
+ }
+}
+
+// Change Method Body (inlined fn) ---------------------------------------------
+//
+// This should affect the method itself, but not the impl.
+
+pub trait ChangeMethodBodyTraitInlined {
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeMethodBodyTraitInlined for Foo {
+ // ------------------------------------------------------------------------
+ // -------------------------
+ // ------------------------------------------------------------------------
+ // -------------------------
+ #[inline]
+ fn method_name() {
+ // -----
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeMethodBodyTraitInlined for Foo {
+ #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ #[inline]
+ fn method_name() {
+ panic!()
+ }
+}
+
+// Change Method Selfness ------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeMethodSelfnessTrait {
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeMethodSelfnessTrait for Foo {
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait ChangeMethodSelfnessTrait {
+ fn method_name(&self);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeMethodSelfnessTrait for Foo {
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail2",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name(&self) {
+ ()
+ }
+}
+
+// Change Method Selfness -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait RemoveMethodSelfnessTrait {
+ fn method_name(&self);
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl RemoveMethodSelfnessTrait for Foo {
+ fn method_name(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait RemoveMethodSelfnessTrait {
+ fn method_name();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl RemoveMethodSelfnessTrait for Foo {
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail2",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name() {}
+}
+
+// Change Method Selfmutness -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeMethodSelfmutnessTrait {
+ fn method_name(&self);
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeMethodSelfmutnessTrait for Foo {
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(& self) {}
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait ChangeMethodSelfmutnessTrait {
+ fn method_name(&mut self);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeMethodSelfmutnessTrait for Foo {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name(&mut self) {}
+}
+
+// Change item kind -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeItemKindTrait {
+ fn name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeItemKindTrait for Foo {
+ fn name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait ChangeItemKindTrait {
+ type name;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeItemKindTrait for Foo {
+ type name = ();
+}
+
+// Remove item -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait RemoveItemTrait {
+ type TypeName;
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl RemoveItemTrait for Foo {
+ type TypeName = ();
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait RemoveItemTrait {
+ type TypeName;
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl RemoveItemTrait for Foo {
+ type TypeName = ();
+}
+
+// Add item -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait AddItemTrait {
+ type TypeName;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl AddItemTrait for Foo {
+ type TypeName = ();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait AddItemTrait {
+ type TypeName;
+ fn method_name();
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl AddItemTrait for Foo {
+ type TypeName = ();
+ fn method_name() { }
+}
+
+// Change has-value -----------------------------------------------------------
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeHasValueTrait {
+ //--------------------------------------------------------------
+ //--------------------------
+ //--------------------------------------------------------------
+ //--------------------------
+ fn method_name() ;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeHasValueTrait for Foo {
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub trait ChangeHasValueTrait {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeHasValueTrait for Foo {
+ fn method_name() { }
+}
+
+// Add default
+
+pub trait AddDefaultTrait {
+ fn method_name();
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl AddDefaultTrait for Foo {
+ // -------------------------------------------------------------
+ // -------------------------
+ // -------------------------------------------------------------
+ // -------------------------
+ fn method_name() { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl AddDefaultTrait for Foo {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ default fn method_name() { }
+}
+
+// Add arguments
+
+#[cfg(any(cfail1,cfail4))]
+pub trait AddArgumentTrait {
+ fn method_name(&self);
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl AddArgumentTrait for Foo {
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(&self ) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait AddArgumentTrait {
+ fn method_name(&self, x: u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl AddArgumentTrait for Foo {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name(&self, _x: u32) { }
+}
+
+// Change argument type
+
+#[cfg(any(cfail1,cfail4))]
+pub trait ChangeArgumentTypeTrait {
+ fn method_name(&self, x: u32);
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeArgumentTypeTrait for Foo {
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ // -----------------------------------------------------------------------------------------
+ // -------------------------
+ fn method_name(&self, _x: u32 ) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+pub trait ChangeArgumentTypeTrait {
+ fn method_name(&self, x: char);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeArgumentTypeTrait for Foo {
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn method_name(&self, _x: char) { }
+}
+
+
+
+struct Bar<T>(T);
+
+// Add Type Parameter To Impl --------------------------------------------------
+trait AddTypeParameterToImpl<T> {
+ fn id(t: T) -> T;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl AddTypeParameterToImpl<u32> for Bar<u32> {
+ fn id(t: u32) -> u32 { t }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<TTT> AddTypeParameterToImpl<TTT> for Bar<TTT> {
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+ cfg="cfail2",
+ )]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(
+ except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+ cfg="cfail5",
+ )]
+ #[rustc_clean(cfg="cfail6")]
+ fn id(t: TTT) -> TTT { t }
+}
+
+
+
+// Change Self Type of Impl ----------------------------------------------------
+trait ChangeSelfTypeOfImpl {
+ fn id(self) -> Self;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl ChangeSelfTypeOfImpl for u32 {
+ fn id(self) -> Self { self }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl ChangeSelfTypeOfImpl for u64 {
+ #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn id(self) -> Self { self }
+}
+
+
+
+// Add Lifetime Bound to Impl --------------------------------------------------
+trait AddLifetimeBoundToImplParameter {
+ fn id(self) -> Self;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl<T> AddLifetimeBoundToImplParameter for T {
+ fn id(self) -> Self { self }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<T: 'static> AddLifetimeBoundToImplParameter for T {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn id(self) -> Self { self }
+}
+
+
+
+// Add Trait Bound to Impl Parameter -------------------------------------------
+trait AddTraitBoundToImplParameter {
+ fn id(self) -> Self;
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl<T> AddTraitBoundToImplParameter for T {
+ fn id(self) -> Self { self }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<T: Clone> AddTraitBoundToImplParameter for T {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ fn id(self) -> Self { self }
+}
+
+
+
+// Add #[no_mangle] to Method --------------------------------------------------
+trait AddNoMangleToMethod {
+ fn add_no_mangle_to_method(&self) { }
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl AddNoMangleToMethod for Foo {
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // ---------
+ fn add_no_mangle_to_method(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl AddNoMangleToMethod for Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ #[no_mangle]
+ fn add_no_mangle_to_method(&self) { }
+}
+
+
+// Make Method #[inline] -------------------------------------------------------
+trait MakeMethodInline {
+ fn make_method_inline(&self) -> u8 { 0 }
+}
+
+#[cfg(any(cfail1,cfail4))]
+impl MakeMethodInline for Foo {
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // -------------------------
+ // ------
+ fn make_method_inline(&self) -> u8 { 0 }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl MakeMethodInline for Foo {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ #[rustc_clean(cfg="cfail5")]
+ #[rustc_clean(cfg="cfail6")]
+ #[inline]
+ fn make_method_inline(&self) -> u8 { 0 }
+}
diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs
new file mode 100644
index 000000000..79398eb07
--- /dev/null
+++ b/src/test/incremental/hashes/type_defs.rs
@@ -0,0 +1,220 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `type` definitions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// We also test the ICH for `type` definitions exported in metadata. Same as
+// above, we want to make sure that the change between rev1 and rev2 also
+// results in a change of the ICH for the enum's metadata, and that it stays
+// the same between rev2 and rev3.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph -O
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change type (primitive) -----------------------------------------------------
+#[cfg(cfail1)]
+type ChangePrimitiveType = i32;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangePrimitiveType = i64;
+
+
+
+// Change mutability -----------------------------------------------------------
+#[cfg(cfail1)]
+type ChangeMutability = &'static i32;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeMutability = &'static mut i32;
+
+
+
+// Change mutability -----------------------------------------------------------
+#[cfg(cfail1)]
+type ChangeLifetime<'a> = (&'static i32, &'a i32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeLifetime<'a> = (&'a i32, &'a i32);
+
+
+
+// Change type (struct) -----------------------------------------------------------
+struct Struct1;
+struct Struct2;
+
+#[cfg(cfail1)]
+type ChangeTypeStruct = Struct1;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeTypeStruct = Struct2;
+
+
+
+// Change type (tuple) ---------------------------------------------------------
+#[cfg(cfail1)]
+type ChangeTypeTuple = (u32, u64);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeTypeTuple = (u32, i64);
+
+
+
+// Change type (enum) ----------------------------------------------------------
+enum Enum1 {
+ Var1,
+ Var2,
+}
+enum Enum2 {
+ Var1,
+ Var2,
+}
+
+#[cfg(cfail1)]
+type ChangeTypeEnum = Enum1;
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeTypeEnum = Enum2;
+
+
+
+// Add tuple field -------------------------------------------------------------
+#[cfg(cfail1)]
+type AddTupleField = (i32, i64);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddTupleField = (i32, i64, i16);
+
+
+
+// Change nested tuple field ---------------------------------------------------
+#[cfg(cfail1)]
+type ChangeNestedTupleField = (i32, (i64, i16));
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type ChangeNestedTupleField = (i32, (i64, i8));
+
+
+
+// Add type param --------------------------------------------------------------
+#[cfg(cfail1)]
+type AddTypeParam<T1> = (T1, T1);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddTypeParam<T1, T2> = (T1, T2);
+
+
+
+// Add type param bound --------------------------------------------------------
+#[cfg(cfail1)]
+type AddTypeParamBound<T1> = (T1, u32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddTypeParamBound<T1: Clone> = (T1, u32);
+
+
+
+// Add type param bound in where clause ----------------------------------------
+#[cfg(cfail1)]
+type AddTypeParamBoundWhereClause<T1> where T1: Clone = (T1, u32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddTypeParamBoundWhereClause<T1> where T1: Clone+Copy = (T1, u32);
+
+
+
+// Add lifetime param ----------------------------------------------------------
+#[cfg(cfail1)]
+type AddLifetimeParam<'a> = (&'a u32, &'a u32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32);
+
+
+
+// Add lifetime param bound ----------------------------------------------------
+#[cfg(cfail1)]
+type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32);
+
+
+
+// Add lifetime param bound in where clause ------------------------------------
+#[cfg(cfail1)]
+type AddLifetimeParamBoundWhereClause<'a, 'b, 'c>
+where 'b: 'a
+ = (&'a u32, &'b u32, &'c u32);
+
+#[cfg(not(cfail1))]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+type AddLifetimeParamBoundWhereClause<'a, 'b, 'c>
+where 'b: 'a,
+ 'c: 'a
+ = (&'a u32, &'b u32, &'c u32);
+
+
+
+// Change Trait Bound Indirectly -----------------------------------------------
+trait ReferencedTrait1 {}
+trait ReferencedTrait2 {}
+
+mod change_trait_bound_indirectly {
+ #[cfg(cfail1)]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(cfail1))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail3")]
+ type ChangeTraitBoundIndirectly<T: Trait> = (T, u32);
+}
+
+
+
+// Change Trait Bound Indirectly In Where Clause -------------------------------
+mod change_trait_bound_indirectly_in_where_clause {
+ #[cfg(cfail1)]
+ use super::ReferencedTrait1 as Trait;
+ #[cfg(not(cfail1))]
+ use super::ReferencedTrait2 as Trait;
+
+ #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
+ #[rustc_clean(cfg="cfail3")]
+ type ChangeTraitBoundIndirectly<T> where T : Trait = (T, u32);
+}
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
new file mode 100644
index 000000000..18fb71635
--- /dev/null
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -0,0 +1,509 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for unary and binary expressions.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change constant operand of negation -----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn const_negation() -> i32 {
+ -10
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn const_negation() -> i32 {
+ -1
+}
+
+
+
+// Change constant operand of bitwise not --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn const_bitwise_not() -> i32 {
+ !100
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn const_bitwise_not() -> i32 {
+ !99
+}
+
+
+
+// Change variable operand of negation -----------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn var_negation(x: i32, y: i32) -> i32 {
+ -x
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn var_negation(x: i32, y: i32) -> i32 {
+ -y
+}
+
+
+
+// Change variable operand of bitwise not --------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
+ !x
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
+ !y
+}
+
+
+
+// Change variable operand of deref --------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn var_deref(x: &i32, y: &i32) -> i32 {
+ *x
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn var_deref(x: &i32, y: &i32) -> i32 {
+ *y
+}
+
+
+
+// Change first constant operand of addition -----------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn first_const_add() -> i32 {
+ 1 + 3
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn first_const_add() -> i32 {
+ 2 + 3
+}
+
+
+
+// Change second constant operand of addition -----------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn second_const_add() -> i32 {
+ 1 + 2
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn second_const_add() -> i32 {
+ 1 + 3
+}
+
+
+
+// Change first variable operand of addition -----------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn first_var_add(a: i32, b: i32) -> i32 {
+ a + 2
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn first_var_add(a: i32, b: i32) -> i32 {
+ b + 2
+}
+
+
+
+// Change second variable operand of addition ----------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn second_var_add(a: i32, b: i32) -> i32 {
+ 1 + a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn second_var_add(a: i32, b: i32) -> i32 {
+ 1 + b
+}
+
+
+
+// Change operator from + to - -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn plus_to_minus(a: i32) -> i32 {
+ 1 + a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn plus_to_minus(a: i32) -> i32 {
+ 1 - a
+}
+
+
+
+// Change operator from + to * -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn plus_to_mult(a: i32) -> i32 {
+ 1 + a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn plus_to_mult(a: i32) -> i32 {
+ 1 * a
+}
+
+
+
+// Change operator from + to / -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn plus_to_div(a: i32) -> i32 {
+ 1 + a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn plus_to_div(a: i32) -> i32 {
+ 1 / a
+}
+
+
+
+// Change operator from + to % -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn plus_to_mod(a: i32) -> i32 {
+ 1 + a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn plus_to_mod(a: i32) -> i32 {
+ 1 % a
+}
+
+
+
+// Change operator from && to || -----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn and_to_or(a: bool, b: bool) -> bool {
+ a && b
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn and_to_or(a: bool, b: bool) -> bool {
+ a || b
+}
+
+
+
+// Change operator from & to | -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
+ 1 & a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
+ 1 | a
+}
+
+
+
+// Change operator from & to ^ -------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
+ 1 & a
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
+ 1 ^ a
+}
+
+
+
+// Change operator from & to << ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn bitwise_and_to_lshift(a: i32) -> i32 {
+ a & 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn bitwise_and_to_lshift(a: i32) -> i32 {
+ a << 1
+}
+
+
+
+// Change operator from & to >> ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn bitwise_and_to_rshift(a: i32) -> i32 {
+ a & 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn bitwise_and_to_rshift(a: i32) -> i32 {
+ a >> 1
+}
+
+
+
+// Change operator from == to != -----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn eq_to_uneq(a: i32) -> bool {
+ a == 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn eq_to_uneq(a: i32) -> bool {
+ a != 1
+}
+
+
+
+// Change operator from == to < ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn eq_to_lt(a: i32) -> bool {
+ a == 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn eq_to_lt(a: i32) -> bool {
+ a < 1
+}
+
+
+
+// Change operator from == to > ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn eq_to_gt(a: i32) -> bool {
+ a == 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn eq_to_gt(a: i32) -> bool {
+ a > 1
+}
+
+
+
+// Change operator from == to <= -----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn eq_to_le(a: i32) -> bool {
+ a == 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn eq_to_le(a: i32) -> bool {
+ a <= 1
+}
+
+
+
+// Change operator from == to >= -----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn eq_to_ge(a: i32) -> bool {
+ a == 1
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn eq_to_ge(a: i32) -> bool {
+ a >= 1
+}
+
+
+
+// Change type in cast expression ----------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn type_cast(a: u8) -> u64 {
+ let b = a as i32;
+ let c = b as u64;
+ c
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn type_cast(a: u8) -> u64 {
+ let b = a as u32;
+ let c = b as u64;
+ c
+}
+
+
+
+// Change value in cast expression ---------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn value_cast(a: u32) -> i32 {
+ 1 as i32
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn value_cast(a: u32) -> i32 {
+ 2 as i32
+}
+
+
+
+// Change place in assignment --------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn place() -> i32 {
+ let mut x = 10;
+ let mut y = 11;
+ x = 9;
+ x
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn place() -> i32 {
+ let mut x = 10;
+ let mut y = 11;
+ y = 9;
+ x
+}
+
+
+
+// Change r-value in assignment ------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn rvalue() -> i32 {
+ let mut x = 10;
+ x = 9;
+ x
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn rvalue() -> i32 {
+ let mut x = 10;
+ x = 8;
+ x
+}
+
+
+
+// Change index into slice -----------------------------------------------------
+#[cfg(any(cfail1,cfail4))]
+pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
+ s[i]
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
+ s[j]
+}
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
new file mode 100644
index 000000000..f81855e42
--- /dev/null
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -0,0 +1,250 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `while let` loops.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change loop body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 2;
+ break;
+ }
+}
+
+
+
+// Change loop body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_condition() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_condition() {
+ let mut _x = 0;
+ while let Some(1u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_break() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ // ---
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_break() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ 'label: while let Some(0u32) = None {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label to break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: while let Some(0u32) = None {
+ _x = 1;
+ break ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: while let Some(0u32) = None {
+ _x = 1;
+ break 'label;
+ }
+}
+
+
+
+// Change break label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: while let Some(0u32) = None {
+ 'inner: while let Some(0u32) = None {
+ _x = 1;
+ break 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: while let Some(0u32) = None {
+ 'inner: while let Some(0u32) = None {
+ _x = 1;
+ break 'outer;
+ }
+ }
+}
+
+// Add loop label to continue
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: while let Some(0u32) = None {
+ _x = 1;
+ continue ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: while let Some(0u32) = None {
+ _x = 1;
+ continue 'label;
+ }
+}
+
+
+
+// Change continue label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: while let Some(0u32) = None {
+ 'inner: while let Some(0u32) = None {
+ _x = 1;
+ continue 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: while let Some(0u32) = None {
+ 'inner: while let Some(0u32) = None {
+ _x = 1;
+ continue 'outer;
+ }
+ }
+}
+
+
+
+// Change continue to break
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ continue;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ while let Some(0u32) = None {
+ _x = 1;
+ break ;
+ }
+}
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
new file mode 100644
index 000000000..e432cf8fe
--- /dev/null
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -0,0 +1,252 @@
+// This test case tests the incremental compilation hash (ICH) implementation
+// for `while` loops.
+
+// The general pattern followed here is: Change one thing between rev1 and rev2
+// and make sure that the hash has changed, then change nothing between rev2 and
+// rev3 and make sure that the hash has not changed.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -O
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+
+// Change loop body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_body() {
+ let mut _x = 0;
+ while true {
+ _x = 2;
+ break;
+ }
+}
+
+
+
+// Change loop body
+#[cfg(any(cfail1,cfail4))]
+pub fn change_loop_condition() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_loop_condition() {
+ let mut _x = 0;
+ while false {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_break() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ // ---
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_break() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ break;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label() {
+ let mut _x = 0;
+ 'label: while true {
+ _x = 1;
+ break;
+ }
+}
+
+
+
+// Add loop label to break
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: while true {
+ _x = 1;
+ break ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_break() {
+ let mut _x = 0;
+ 'label: while true {
+ _x = 1;
+ break 'label;
+ }
+}
+
+
+
+// Change break label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: while true {
+ 'inner: while true {
+ _x = 1;
+ break 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_break_label() {
+ let mut _x = 0;
+ 'outer: while true {
+ 'inner: while true {
+ _x = 1;
+ break 'outer;
+ }
+ }
+}
+
+
+
+// Add loop label to continue
+#[cfg(any(cfail1,cfail4))]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: while true {
+ _x = 1;
+ continue ;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
+pub fn add_loop_label_to_continue() {
+ let mut _x = 0;
+ 'label: while true {
+ _x = 1;
+ continue 'label;
+ }
+}
+
+
+
+// Change continue label
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: while true {
+ 'inner: while true {
+ _x = 1;
+ continue 'inner;
+ }
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_label() {
+ let mut _x = 0;
+ 'outer: while true {
+ 'inner: while true {
+ _x = 1;
+ continue 'outer;
+ }
+ }
+}
+
+
+
+// Change continue to break
+#[cfg(any(cfail1,cfail4))]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ continue;
+ }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
+pub fn change_continue_to_break() {
+ let mut _x = 0;
+ while true {
+ _x = 1;
+ break ;
+ }
+}
diff --git a/src/test/incremental/hello_world.rs b/src/test/incremental/hello_world.rs
new file mode 100644
index 000000000..d5ec6e92b
--- /dev/null
+++ b/src/test/incremental/hello_world.rs
@@ -0,0 +1,37 @@
+// revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+fn main() { }
+
+mod x {
+ #[cfg(rpass1)]
+ pub fn xxxx() -> i32 {
+ 1
+ }
+
+ #[cfg(rpass2)]
+ pub fn xxxx() -> i32 {
+ 2
+ }
+}
+
+mod y {
+ use x;
+
+ #[rustc_clean(cfg="rpass2")]
+ pub fn yyyy() {
+ x::xxxx();
+ }
+}
+
+mod z {
+ use y;
+
+ #[rustc_clean(cfg="rpass2")]
+ pub fn z() {
+ y::yyyy();
+ }
+}
diff --git a/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs b/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
new file mode 100644
index 000000000..b31f60e97
--- /dev/null
+++ b/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
@@ -0,0 +1,36 @@
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+// We use #[inline(always)] to ensure that the downstream crate
+// will always load the MIR for these functions
+
+#![feature(rustc_attrs)]
+
+#[allow(unused)]
+macro_rules! first_macro {
+ () => {
+ println!("New call!");
+ }
+}
+
+#[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")]
+#[inline(always)]
+pub fn changed_fn() {
+ // This will cause additional hygiene to be generate,
+ // which will cause the SyntaxContext/ExpnId raw ids to be
+ // different when we write out `my_fn` to the crate metadata.
+ #[cfg(rpass2)]
+ first_macro!();
+}
+
+macro_rules! print_loc {
+ () => {
+ println!("Caller loc: {}", std::panic::Location::caller());
+ }
+}
+
+#[rustc_clean(cfg="rpass2")]
+#[inline(always)]
+pub fn unchanged_fn() {
+ print_loc!();
+}
diff --git a/src/test/incremental/hygiene/load_cached_hygiene.rs b/src/test/incremental/hygiene/load_cached_hygiene.rs
new file mode 100644
index 000000000..812414141
--- /dev/null
+++ b/src/test/incremental/hygiene/load_cached_hygiene.rs
@@ -0,0 +1,48 @@
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+// aux-build:cached_hygiene.rs
+
+// This tests the folllowing scenario
+// 1. A foreign crate is compiled with incremental compilation.
+// This causes hygiene information to be saved to the incr cache.
+// 2. One function is the foreign crate is modified. This causes the
+// optimized mir for an unmodified function to be loaded from the
+// incremental cache and written out to the crate metadata.
+// 3. In the process of loading and writing out this function's MIR,
+// we load hygiene information from the incremental cache and
+// write it to our metadata.
+// 4. This hygiene information is loaded by another crate (this file)
+
+// Previously, this situation would cause hygiene identifiers
+// (SyntaxContexts and ExpnIds) to get corrupted when we tried to
+// serialize the hygiene information loaded from the incr cache into
+// the metadata. Specifically, we were not resetting `orig_id`
+// for an `EpxnData` generate in the current crate, which would cause
+// us to serialize the `ExpnId` pointing to a garbage location in
+// the metadata.
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="load_cached_hygiene-call_unchanged_function", cfg="rpass2")]
+#![rustc_partition_codegened(module="load_cached_hygiene-call_changed_function", cfg="rpass2")]
+
+
+extern crate cached_hygiene;
+
+pub mod call_unchanged_function {
+
+ pub fn unchanged() {
+ cached_hygiene::unchanged_fn();
+ }
+}
+
+pub mod call_changed_function {
+ pub fn changed() {
+ cached_hygiene::changed_fn();
+ }
+}
+
+pub fn main() {
+ call_unchanged_function::unchanged();
+ call_changed_function::changed();
+}
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
new file mode 100644
index 000000000..5566506c0
--- /dev/null
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -0,0 +1,40 @@
+// Check that the hash for a method call is sensitive to the traits in
+// scope.
+
+// revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+fn test<T>() { }
+
+trait Trait1 {
+ fn method(&self) { }
+}
+
+impl Trait1 for () { }
+
+trait Trait2 {
+ fn method(&self) { }
+}
+
+impl Trait2 for () { }
+
+mod mod3 {
+ #[cfg(rpass1)]
+ use Trait1;
+ #[cfg(rpass2)]
+ use Trait2;
+
+ #[rustc_clean(except="typeck", cfg="rpass2")]
+ fn bar() {
+ ().method();
+ }
+
+ #[rustc_clean(cfg="rpass2")]
+ fn baz() {
+ 22; // no method call, traits in scope don't matter
+ }
+}
+
+fn main() { }
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
new file mode 100644
index 000000000..379c09575
--- /dev/null
+++ b/src/test/incremental/ich_nested_items.rs
@@ -0,0 +1,23 @@
+// Check that the hash of `foo` doesn't change just because we ordered
+// the nested items (or even added new ones).
+
+// revisions: cfail1 cfail2
+// build-pass (FIXME(62277): could be check-pass?)
+// compile-flags: -Z query-dep-graph
+
+#![crate_type = "rlib"]
+#![feature(rustc_attrs)]
+
+#[rustc_clean(except = "hir_owner_nodes", cfg = "cfail2")]
+pub fn foo() {
+ #[cfg(cfail1)]
+ pub fn baz() {} // order is different...
+
+ #[rustc_clean(cfg = "cfail2")]
+ pub fn bar() {} // but that doesn't matter.
+
+ #[cfg(cfail2)]
+ pub fn baz() {} // order is different...
+
+ pub fn bap() {} // neither does adding a new item
+}
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
new file mode 100644
index 000000000..e6ab6bceb
--- /dev/null
+++ b/src/test/incremental/ich_resolve_results.rs
@@ -0,0 +1,45 @@
+// Check that the hash for `mod3::bar` changes when we change the
+// `use` to something different.
+
+// revisions: rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+fn test<T>() { }
+
+mod mod1 {
+ pub struct Foo(pub u32);
+}
+
+mod mod2 {
+ pub struct Foo(pub i64);
+}
+
+mod mod3 {
+ #[cfg(rpass1)]
+ use mod1::Foo;
+ use test;
+
+ // In rpass2 we move the use declaration.
+ #[cfg(rpass2)]
+ use mod1::Foo;
+
+ // In rpass3 we let the declaration point to something else.
+ #[cfg(rpass3)]
+ use mod2::Foo;
+
+ #[rustc_clean(cfg="rpass2")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")]
+ fn in_expr() {
+ Foo(0);
+ }
+
+ #[rustc_clean(cfg="rpass2")]
+ #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")]
+ fn in_type() {
+ test::<Foo>();
+ }
+}
+
+fn main() { }
diff --git a/src/test/incremental/incremental_proc_macro.rs b/src/test/incremental/incremental_proc_macro.rs
new file mode 100644
index 000000000..becc1538f
--- /dev/null
+++ b/src/test/incremental/incremental_proc_macro.rs
@@ -0,0 +1,16 @@
+// aux-build:incremental_proc_macro_aux.rs
+// revisions: cfail1 cfail2
+// build-pass (FIXME(62277): could be check-pass?)
+
+// This test makes sure that we still find the proc-macro registrar function
+// when we compile proc-macros incrementally (see #47292).
+
+#![crate_type = "rlib"]
+
+#[macro_use]
+extern crate incremental_proc_macro_aux;
+
+#[derive(IncrementalMacro)]
+pub struct Foo {
+ x: u32
+}
diff --git a/src/test/incremental/inlined_hir_34991/main.rs b/src/test/incremental/inlined_hir_34991/main.rs
new file mode 100644
index 000000000..bb76a0bb8
--- /dev/null
+++ b/src/test/incremental/inlined_hir_34991/main.rs
@@ -0,0 +1,23 @@
+// Regression test for #34991: an ICE occurred here because we inline
+// some of the vector routines and give them a local def-id `X`. This
+// got hashed after codegen (`hir_owner(X)`). When we load back up, we get an
+// error because the `X` is remapped to the original def-id (in
+// libstd), and we can't hash a HIR node from std.
+
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+use std::vec::Vec;
+
+pub fn foo() -> Vec<i32> {
+ vec![1, 2, 3]
+}
+
+pub fn bar() {
+ foo();
+}
+
+pub fn main() {
+ bar();
+}
diff --git a/src/test/incremental/issue-35593.rs b/src/test/incremental/issue-35593.rs
new file mode 100644
index 000000000..009e37d17
--- /dev/null
+++ b/src/test/incremental/issue-35593.rs
@@ -0,0 +1,12 @@
+// Regression test for #35593. Check that we can reuse this trivially
+// equal example.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module="issue_35593", cfg="rpass2")]
+
+fn main() {
+ println!("hello world");
+}
diff --git a/src/test/incremental/issue-38222.rs b/src/test/incremental/issue-38222.rs
new file mode 100644
index 000000000..20d4d4200
--- /dev/null
+++ b/src/test/incremental/issue-38222.rs
@@ -0,0 +1,27 @@
+// Test that debuginfo does not introduce a dependency edge to the hir_crate
+// dep-node.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "issue_38222-mod1", cfg = "rpass2")]
+// If codegen had added a dependency edge to the hir_crate dep-node, nothing would
+// be re-used, so checking that this module was re-used is sufficient.
+#![rustc_partition_reused(module = "issue_38222", cfg = "rpass2")]
+
+//[rpass1] compile-flags: -C debuginfo=1
+//[rpass2] compile-flags: -C debuginfo=1
+
+pub fn main() {
+ mod1::some_fn();
+}
+
+mod mod1 {
+ pub fn some_fn() {
+ #[cfg(rpass2)]
+ {}
+
+ let _ = 1;
+ }
+}
diff --git a/src/test/incremental/issue-39569.rs b/src/test/incremental/issue-39569.rs
new file mode 100644
index 000000000..881ecfca7
--- /dev/null
+++ b/src/test/incremental/issue-39569.rs
@@ -0,0 +1,27 @@
+// Regression test for a weird corner case in our dep-graph reduction
+// code. When we solve `CoerceUnsized<Foo>`, we find no impls, so we
+// don't end up with an edge to any HIR nodes, but it still gets
+// preserved in the dep graph.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+use std::sync::Arc;
+
+#[cfg(rpass1)]
+struct Foo { x: usize }
+
+#[cfg(rpass1)]
+fn main() {
+ let x: Arc<Foo> = Arc::new(Foo { x: 22 });
+ let y: Arc<Foo> = x;
+}
+
+#[cfg(rpass2)]
+struct FooX { x: usize }
+
+#[cfg(rpass2)]
+fn main() {
+ let x: Arc<FooX> = Arc::new(FooX { x: 22 });
+ let y: Arc<FooX> = x;
+}
diff --git a/src/test/incremental/issue-39828/auxiliary/generic.rs b/src/test/incremental/issue-39828/auxiliary/generic.rs
new file mode 100644
index 000000000..a5bb0d65f
--- /dev/null
+++ b/src/test/incremental/issue-39828/auxiliary/generic.rs
@@ -0,0 +1,8 @@
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![rustc_partition_reused(module="generic-fallback.cgu", cfg="rpass2")]
+#![feature(rustc_attrs)]
+
+#![crate_type="rlib"]
+pub fn foo<T>() { }
diff --git a/src/test/incremental/issue-39828/issue-39828.rs b/src/test/incremental/issue-39828/issue-39828.rs
new file mode 100644
index 000000000..8cef916ff
--- /dev/null
+++ b/src/test/incremental/issue-39828/issue-39828.rs
@@ -0,0 +1,12 @@
+// Regression test for #39828. If you make use of a module that
+// consists only of generics, no code is generated, just a dummy
+// module. The reduced graph consists of a single node (for that
+// module) with no inputs. Since we only serialize edges, when we
+// reload, we would consider that node dirty since it is not recreated
+// (it is not the target of any edges).
+
+// revisions:rpass1 rpass2
+// aux-build:generic.rs
+
+extern crate generic;
+fn main() { }
diff --git a/src/test/incremental/issue-42602.rs b/src/test/incremental/issue-42602.rs
new file mode 100644
index 000000000..b8d5303fb
--- /dev/null
+++ b/src/test/incremental/issue-42602.rs
@@ -0,0 +1,44 @@
+// Regression test for #42602. It used to be that we had
+// a dep-graph like
+//
+// typeck(foo) -> FnOnce -> typeck(bar)
+//
+// This was fixed by improving the resolution of the `FnOnce` trait
+// selection node.
+
+// revisions:cfail1 cfail2 cfail3
+// compile-flags:-Zquery-dep-graph
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+fn main() {
+ a::foo();
+ b::bar();
+}
+
+mod a {
+ #[cfg(cfail1)]
+ pub fn foo() {
+ let x = vec![1, 2, 3];
+ let v = || ::std::mem::drop(x);
+ v();
+ }
+
+ #[cfg(not(cfail1))]
+ pub fn foo() {
+ let x = vec![1, 2, 3, 4];
+ let v = || ::std::mem::drop(x);
+ v();
+ }
+}
+
+mod b {
+ #[rustc_clean(cfg="cfail2")]
+ #[rustc_clean(cfg="cfail3")]
+ pub fn bar() {
+ let x = vec![1, 2, 3];
+ let v = || ::std::mem::drop(x);
+ v();
+ }
+}
diff --git a/src/test/incremental/issue-49043.rs b/src/test/incremental/issue-49043.rs
new file mode 100644
index 000000000..50d8fb869
--- /dev/null
+++ b/src/test/incremental/issue-49043.rs
@@ -0,0 +1,12 @@
+// Regression test for hashing involving canonical variables. In this
+// test -- which has an intensional error -- the type of the value
+// being dropped winds up including a type variable. Canonicalization
+// would then produce a `?0` which -- in turn -- triggered an ICE in
+// hashing.
+
+// revisions:cfail1
+
+fn main() {
+ println!("Hello, world! {}",*thread_rng().choose(&[0, 1, 2, 3]).unwrap());
+ //[cfail1]~^ ERROR cannot find function `thread_rng`
+}
diff --git a/src/test/incremental/issue-49482.rs b/src/test/incremental/issue-49482.rs
new file mode 100644
index 000000000..042ecc0f2
--- /dev/null
+++ b/src/test/incremental/issue-49482.rs
@@ -0,0 +1,30 @@
+// aux-build:issue-49482-macro-def.rs
+// aux-build:issue-49482-reexport.rs
+// revisions: rpass1
+
+extern crate issue_49482_reexport;
+
+pub trait KvStorage
+{
+ fn get(&self);
+}
+
+impl<K> KvStorage for Box<K>
+where
+ K: KvStorage + ?Sized,
+{
+ fn get(&self) {
+ (**self).get()
+ }
+}
+
+impl KvStorage for u32 {
+ fn get(&self) {}
+}
+
+fn main() {
+ /* force issue_49482_reexport to be loaded */
+ issue_49482_reexport::foo();
+
+ Box::new(2).get();
+}
diff --git a/src/test/incremental/issue-49595/auxiliary/lit_a.rs b/src/test/incremental/issue-49595/auxiliary/lit_a.rs
new file mode 100644
index 000000000..295a0b481
--- /dev/null
+++ b/src/test/incremental/issue-49595/auxiliary/lit_a.rs
@@ -0,0 +1 @@
+pub const A: &str = "hello";
diff --git a/src/test/incremental/issue-49595/auxiliary/lit_b.rs b/src/test/incremental/issue-49595/auxiliary/lit_b.rs
new file mode 100644
index 000000000..5d377edfb
--- /dev/null
+++ b/src/test/incremental/issue-49595/auxiliary/lit_b.rs
@@ -0,0 +1 @@
+pub const A: &str = "xxxxx";
diff --git a/src/test/incremental/issue-49595/issue-49595.rs b/src/test/incremental/issue-49595/issue-49595.rs
new file mode 100644
index 000000000..7b1096a64
--- /dev/null
+++ b/src/test/incremental/issue-49595/issue-49595.rs
@@ -0,0 +1,31 @@
+// revisions:cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph --test
+// build-pass
+
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+
+#![rustc_partition_codegened(module="issue_49595-tests", cfg="cfail2")]
+#![rustc_partition_codegened(module="issue_49595-lit_test", cfg="cfail3")]
+
+mod tests {
+ #[cfg_attr(not(cfail1), test)]
+ fn test() {
+ }
+}
+
+
+// Checks that changing a string literal without changing its span
+// takes effect.
+
+// replacing a module to have a stable span
+#[cfg_attr(not(cfail3), path = "auxiliary/lit_a.rs")]
+#[cfg_attr(cfail3, path = "auxiliary/lit_b.rs")]
+mod lit;
+
+pub mod lit_test {
+ #[test]
+ fn lit_test() {
+ println!("{}", ::lit::A);
+ }
+}
diff --git a/src/test/incremental/issue-51409.rs b/src/test/incremental/issue-51409.rs
new file mode 100644
index 000000000..280094ec0
--- /dev/null
+++ b/src/test/incremental/issue-51409.rs
@@ -0,0 +1,10 @@
+// revisions: rpass1
+
+// Regression test that `infer_outlives_predicates` can be
+// used with incremental without an ICE.
+
+struct Foo<'a, T> {
+ x: &'a T
+}
+
+fn main() { }
diff --git a/src/test/incremental/issue-54059.rs b/src/test/incremental/issue-54059.rs
new file mode 100644
index 000000000..0a5a54750
--- /dev/null
+++ b/src/test/incremental/issue-54059.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-54059.rs
+// ignore-wasm32-bare no libc for ffi testing
+// ignore-windows - dealing with weird symbols issues on dylibs isn't worth it
+// revisions: rpass1
+
+extern crate issue_54059;
+
+fn main() {}
diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs
new file mode 100644
index 000000000..806c84152
--- /dev/null
+++ b/src/test/incremental/issue-54242.rs
@@ -0,0 +1,20 @@
+// revisions: rpass cfail
+
+trait Tr
+where
+ (Self::Arr,): Sized,
+{
+ type Arr;
+
+ const C: usize = 0;
+}
+
+impl Tr for str {
+ #[cfg(rpass)]
+ type Arr = [u8; 8];
+ #[cfg(cfail)]
+ type Arr = [u8; Self::C];
+ //[cfail]~^ ERROR cycle detected when evaluating type-level constant
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
new file mode 100644
index 000000000..fa52ca90b
--- /dev/null
+++ b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
@@ -0,0 +1,27 @@
+// We should not see the unused_attributes lint fire for
+// rustc_on_unimplemented, but with this bug we are seeing it fire (on
+// subsequent runs) if incremental compilation is enabled.
+
+// revisions: cfail1 cfail2
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![deny(unused_attributes)]
+
+#[rustc_on_unimplemented = "invalid"]
+trait Index<Idx: ?Sized> {
+ type Output: ?Sized;
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+#[rustc_on_unimplemented = "a usize is required to index into a slice"]
+impl Index<usize> for [i32] {
+ type Output = i32;
+ fn index(&self, index: usize) -> &i32 {
+ &self[index]
+ }
+}
+
+fn main() {
+ Index::<usize>::index(&[1, 2, 3] as &[i32], 2);
+}
diff --git a/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs
new file mode 100644
index 000000000..bfb5e539c
--- /dev/null
+++ b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs
@@ -0,0 +1,19 @@
+// We should not see the unused_attributes lint fire for
+// rustc_layout_scalar_valid_range_start, but with this bug we are
+// seeing it fire (on subsequent runs) if incremental compilation is
+// enabled.
+
+// revisions: cfail1 cfail2
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![deny(unused_attributes)]
+
+#[rustc_layout_scalar_valid_range_start(10)]
+#[rustc_layout_scalar_valid_range_end(30)]
+struct RestrictedRange(u32);
+const OKAY_RANGE: RestrictedRange = unsafe { RestrictedRange(20) };
+
+fn main() {
+ OKAY_RANGE.0;
+}
diff --git a/src/test/incremental/issue-60629.rs b/src/test/incremental/issue-60629.rs
new file mode 100644
index 000000000..4807af4b3
--- /dev/null
+++ b/src/test/incremental/issue-60629.rs
@@ -0,0 +1,10 @@
+// revisions:rpass1 rpass2
+
+struct A;
+
+#[cfg(rpass2)]
+impl From<A> for () {
+ fn from(_: A) {}
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs
new file mode 100644
index 000000000..97cbfe408
--- /dev/null
+++ b/src/test/incremental/issue-61323.rs
@@ -0,0 +1,15 @@
+// revisions: rpass cfail
+
+enum A {
+ //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072]
+ B(C),
+}
+
+#[cfg(rpass)]
+struct C(Box<A>);
+
+#[cfg(cfail)]
+struct C(A);
+//[cfail]~^ ERROR 12:1: 12:9: recursive type `C` has infinite size [E0072]
+
+fn main() {}
diff --git a/src/test/incremental/issue-61530.rs b/src/test/incremental/issue-61530.rs
new file mode 100644
index 000000000..edb3d60ba
--- /dev/null
+++ b/src/test/incremental/issue-61530.rs
@@ -0,0 +1,18 @@
+#![feature(repr_simd, platform_intrinsics)]
+
+// revisions:rpass1 rpass2
+
+#[repr(simd)]
+struct I32x2(i32, i32);
+
+extern "platform-intrinsic" {
+ fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
+}
+
+fn main() {
+ unsafe {
+ const IDX: [u32; 2] = [0, 0];
+ let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
+ let _: I32x2 = simd_shuffle2(I32x2(1, 2), I32x2(3, 4), IDX);
+ }
+}
diff --git a/src/test/incremental/issue-62649-path-collisions-happen.rs b/src/test/incremental/issue-62649-path-collisions-happen.rs
new file mode 100644
index 000000000..ee81be76b
--- /dev/null
+++ b/src/test/incremental/issue-62649-path-collisions-happen.rs
@@ -0,0 +1,13 @@
+// revisions: rpass1 rpass2
+
+#[cfg(rpass1)]
+pub trait Something {
+ fn foo();
+}
+
+#[cfg(rpass2)]
+pub struct Something {
+ pub foo: u8,
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-69596.rs b/src/test/incremental/issue-69596.rs
new file mode 100644
index 000000000..dc587fdc4
--- /dev/null
+++ b/src/test/incremental/issue-69596.rs
@@ -0,0 +1,21 @@
+// revisions: rpass1 rpass2
+
+#![allow(unused_imports)]
+
+#[macro_export]
+macro_rules! a_macro {
+ () => {};
+}
+
+#[cfg(rpass1)]
+use a_macro as same_name;
+
+mod same_name {}
+
+mod needed_mod {
+ fn _crash() {
+ use super::same_name;
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-72386.rs b/src/test/incremental/issue-72386.rs
new file mode 100644
index 000000000..5917152e1
--- /dev/null
+++ b/src/test/incremental/issue-72386.rs
@@ -0,0 +1,21 @@
+// revisions: rpass1 cfail1 rpass3
+// needs-asm-support
+// only-x86_64
+// Regression test for issue #72386
+// Checks that we don't ICE when switching to an invalid register
+// and back again
+
+use std::arch::asm;
+
+#[cfg(any(rpass1, rpass3))]
+fn main() {
+ unsafe { asm!("nop") }
+}
+
+#[cfg(cfail1)]
+fn main() {
+ unsafe {
+ asm!("nop",out("invalid_reg")_)
+ //[cfail1]~^ ERROR invalid register
+ }
+}
diff --git a/src/test/incremental/issue-79661-missing-def-path-hash.rs b/src/test/incremental/issue-79661-missing-def-path-hash.rs
new file mode 100644
index 000000000..f86fb33fb
--- /dev/null
+++ b/src/test/incremental/issue-79661-missing-def-path-hash.rs
@@ -0,0 +1,14 @@
+// aux-build:issue-79661.rs
+// revisions: rpass1 rpass2 rpass3
+
+// Regression test for issue #79661
+// We were failing to copy over a DefPathHash->DefId mapping
+// from the old incremental cache to the new incremental cache
+// when we ended up forcing a query. As a result, a subsequent
+// unchanged incremental run would crash due to the missing mapping
+
+extern crate issue_79661;
+use issue_79661::Wrapper;
+
+pub struct Outer(Wrapper);
+fn main() {}
diff --git a/src/test/incremental/issue-79890-imported-crates-changed.rs b/src/test/incremental/issue-79890-imported-crates-changed.rs
new file mode 100644
index 000000000..93daa5ca9
--- /dev/null
+++ b/src/test/incremental/issue-79890-imported-crates-changed.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-79890.rs
+// revisions:rpass1 rpass2 rpass3
+// compile-flags:--extern issue_79890 --test
+// edition:2018
+
+// Tests that we don't ICE when the set of imported crates changes
+#[cfg(rpass2)] use issue_79890::MyTrait;
diff --git a/src/test/incremental/issue-80336-invalid-span.rs b/src/test/incremental/issue-80336-invalid-span.rs
new file mode 100644
index 000000000..7757d9159
--- /dev/null
+++ b/src/test/incremental/issue-80336-invalid-span.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #80336
+// Test that we properly handle encoding, decoding, and hashing
+// of spans with an invalid location and non-root `SyntaxContext`
+
+// revisions:rpass1 rpass2
+// only-x86_64
+
+pub fn main() {
+ let _ = is_x86_feature_detected!("avx2");
+}
diff --git a/src/test/incremental/issue-80691-bad-eval-cache.rs b/src/test/incremental/issue-80691-bad-eval-cache.rs
new file mode 100644
index 000000000..1a644fd88
--- /dev/null
+++ b/src/test/incremental/issue-80691-bad-eval-cache.rs
@@ -0,0 +1,184 @@
+// revisions: rfail1 rfail2
+// failure-status: 101
+// error-pattern: not implemented
+
+pub trait Interner {
+ type InternedVariableKinds;
+}
+
+trait RustIrDatabase<I: Interner> {
+ fn associated_ty_data(&self) -> AssociatedTyDatum<I>;
+ fn impl_datum(&self) -> ImplDatum<I>;
+}
+
+trait Fold<I: Interner> {
+ type Result;
+}
+impl<T, I: Interner> Fold<I> for Binders<T>
+where
+ T: HasInterner<Interner = I> + Fold<I>,
+ <T as Fold<I>>::Result: HasInterner<Interner = I>,
+ I: Interner,
+{
+ type Result = Binders<T::Result>;
+}
+impl<I: Interner> Fold<I> for WhereClause<I> {
+ type Result = Binders<WhereClause<I>>;
+}
+
+trait HasInterner {
+ type Interner: Interner;
+}
+impl<T: HasInterner> HasInterner for Vec<T> {
+ type Interner = T::Interner;
+}
+impl<T: HasInterner + ?Sized> HasInterner for &T {
+ type Interner = T::Interner;
+}
+
+pub struct VariableKind<I: Interner> {
+ _marker: std::marker::PhantomData<I>,
+}
+
+struct VariableKinds<I: Interner> {
+ _interned: I::InternedVariableKinds,
+}
+
+struct WhereClause<I: Interner> {
+ _marker: std::marker::PhantomData<I>,
+}
+impl<I: Interner> HasInterner for WhereClause<I> {
+ type Interner = I;
+}
+
+struct Binders<T> {
+ _marker: std::marker::PhantomData<T>,
+}
+impl<T: HasInterner> HasInterner for Binders<T> {
+ type Interner = T::Interner;
+}
+impl<T> Binders<&T> {
+ fn cloned(self) -> Binders<T> {
+ unimplemented!()
+ }
+}
+impl<T: HasInterner> Binders<T> {
+ fn map_ref<'a, U, OP>(&'a self, _op: OP) -> Binders<U>
+ where
+ OP: FnOnce(&'a T) -> U,
+ U: HasInterner<Interner = T::Interner>,
+ {
+ unimplemented!()
+ }
+}
+impl<T, I: Interner> Binders<T>
+where
+ T: Fold<I> + HasInterner<Interner = I>,
+ I: Interner,
+{
+ fn substitute(self) -> T::Result {
+ unimplemented!()
+ }
+}
+impl<V, U> IntoIterator for Binders<V>
+where
+ V: HasInterner + IntoIterator<Item = U>,
+ U: HasInterner<Interner = V::Interner>,
+{
+ type Item = Binders<U>;
+ type IntoIter = BindersIntoIterator<V>;
+ fn into_iter(self) -> Self::IntoIter {
+ unimplemented!()
+ }
+}
+struct BindersIntoIterator<V: HasInterner> {
+ _binders: VariableKinds<V::Interner>,
+}
+impl<V> Iterator for BindersIntoIterator<V>
+where
+ V: HasInterner + IntoIterator,
+ <V as IntoIterator>::Item: HasInterner<Interner = V::Interner>,
+{
+ type Item = Binders<<V as IntoIterator>::Item>;
+ fn next(&mut self) -> Option<Self::Item> {
+ unimplemented!()
+ }
+}
+
+struct ImplDatum<I: Interner> {
+ binders: Binders<ImplDatumBound<I>>,
+}
+struct ImplDatumBound<I: Interner> {
+ where_clauses: Vec<Binders<WhereClause<I>>>,
+}
+impl<I: Interner> HasInterner for ImplDatumBound<I> {
+ type Interner = I;
+}
+
+struct AssociatedTyDatum<I: Interner> {
+ binders: Binders<AssociatedTyDatumBound<I>>,
+}
+
+struct AssociatedTyDatumBound<I: Interner> {
+ where_clauses: Vec<Binders<WhereClause<I>>>,
+}
+impl<I: Interner> HasInterner for AssociatedTyDatumBound<I> {
+ type Interner = I;
+}
+
+struct ClauseBuilder<'me, I: Interner> {
+ db: &'me dyn RustIrDatabase<I>,
+}
+impl<'me, I: Interner> ClauseBuilder<'me, I> {
+ fn new() -> Self {
+ unimplemented!()
+ }
+ fn push_clause(&mut self, _conditions: impl Iterator<Item = Binders<Binders<WhereClause<I>>>>) {
+ unimplemented!()
+ }
+}
+
+pub(crate) struct Forest<I: Interner> {
+ _marker: std::marker::PhantomData<I>,
+}
+
+impl<I: Interner> Forest<I> {
+ fn iter_answers<'f>(&'f self) {
+ let builder = &mut ClauseBuilder::<I>::new();
+ let impl_datum = builder.db.impl_datum();
+ let impl_where_clauses = impl_datum
+ .binders
+ .map_ref(|b| &b.where_clauses)
+ .into_iter()
+ .map(|wc| wc.cloned().substitute());
+ let associated_ty = builder.db.associated_ty_data();
+ let assoc_ty_where_clauses = associated_ty
+ .binders
+ .map_ref(|b| &b.where_clauses)
+ .into_iter()
+ .map(|wc| wc.cloned().substitute());
+ builder.push_clause(impl_where_clauses.chain(assoc_ty_where_clauses));
+ }
+}
+
+pub struct SLGSolver {
+ pub(crate) forest: Forest<ChalkIr>,
+}
+impl SLGSolver {
+ fn new() -> Self {
+ unimplemented!()
+ }
+ fn solve_multiple(&self) {
+ let _answers = self.forest.iter_answers();
+ }
+}
+
+pub struct ChalkIr;
+impl Interner for ChalkIr {
+ type InternedVariableKinds = Vec<VariableKind<ChalkIr>>;
+}
+
+fn main() {
+ let solver = SLGSolver::new();
+ solver.solve_multiple();
+}
diff --git a/src/test/incremental/issue-82920-predicate-order-miscompile.rs b/src/test/incremental/issue-82920-predicate-order-miscompile.rs
new file mode 100644
index 000000000..793af679c
--- /dev/null
+++ b/src/test/incremental/issue-82920-predicate-order-miscompile.rs
@@ -0,0 +1,31 @@
+// revisions: rpass1 rpass2
+
+trait MyTrait: One + Two {}
+impl<T> One for T {
+ fn method_one(&self) -> usize {
+ 1
+ }
+}
+impl<T> Two for T {
+ fn method_two(&self) -> usize {
+ 2
+ }
+}
+impl<T: One + Two> MyTrait for T {}
+
+fn main() {
+ let a: &dyn MyTrait = &true;
+ assert_eq!(a.method_one(), 1);
+ assert_eq!(a.method_two(), 2);
+}
+
+// Re-order traits 'One' and 'Two' between compilation
+// sessions
+
+#[cfg(rpass1)]
+trait One { fn method_one(&self) -> usize; }
+
+trait Two { fn method_two(&self) -> usize; }
+
+#[cfg(rpass2)]
+trait One { fn method_one(&self) -> usize; }
diff --git a/src/test/incremental/issue-84252-global-alloc.rs b/src/test/incremental/issue-84252-global-alloc.rs
new file mode 100644
index 000000000..d2438df89
--- /dev/null
+++ b/src/test/incremental/issue-84252-global-alloc.rs
@@ -0,0 +1,12 @@
+// revisions: cfail1 cfail2
+// build-pass
+
+#![crate_type="lib"]
+#![crate_type="cdylib"]
+
+#[allow(unused_imports)]
+use std::alloc::System;
+
+#[cfg(cfail1)]
+#[global_allocator]
+static ALLOC: System = System;
diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs
new file mode 100644
index 000000000..2453af5b6
--- /dev/null
+++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs
@@ -0,0 +1,11 @@
+// revisions: rpass1 rpass2
+
+extern crate respan;
+
+#[macro_use]
+#[path = "invalid-span-helper-mod.rs"]
+mod invalid_span_helper_mod;
+
+// Invoke a macro from a different file - this
+// allows us to get tokens with spans from different files
+helper!(1);
diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs
new file mode 100644
index 000000000..747174b1e
--- /dev/null
+++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs
@@ -0,0 +1,14 @@
+#[macro_export]
+macro_rules! helper {
+ // Use `:tt` instead of `:ident` so that we don't get a `None`-delimited group
+ ($first:tt) => {
+ pub fn foo<T>() {
+ // The span of `$first` comes from another file,
+ // so the expression `1 + $first` ends up with an
+ // 'invalid' span that starts and ends in different files.
+ // We use the `respan!` macro to give all tokens the same
+ // `SyntaxContext`, so that the parser will try to merge the spans.
+ respan::respan!(let a = 1 + $first;);
+ }
+ }
+}
diff --git a/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs b/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs
new file mode 100644
index 000000000..5088eab62
--- /dev/null
+++ b/src/test/incremental/issue-85197-invalid-span/auxiliary/respan.rs
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+
+/// Copies the resolution information (the `SyntaxContext`) of the first
+/// token to all other tokens in the stream. Does not recurse into groups.
+#[proc_macro]
+pub fn respan(input: TokenStream) -> TokenStream {
+ let first_span = input.clone().into_iter().next().unwrap().span();
+ input.into_iter().map(|mut tree| {
+ tree.set_span(tree.span().resolved_at(first_span));
+ tree
+ }).collect()
+}
diff --git a/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs b/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs
new file mode 100644
index 000000000..f358460b3
--- /dev/null
+++ b/src/test/incremental/issue-85197-invalid-span/invalid_span_main.rs
@@ -0,0 +1,24 @@
+// revisions: rpass1 rpass2
+// aux-build:respan.rs
+// aux-build:invalid-span-helper-lib.rs
+
+// This issue has several different parts. The high level idea is:
+// 1. We create an 'invalid' span with the help of the `respan` proc-macro,
+// The compiler attempts to prevent the creation of invalid spans by
+// refusing to join spans with different `SyntaxContext`s. We work around
+// this by applying the same `SyntaxContext` to the span of every token,
+// using `Span::resolved_at`
+// 2. We using this invalid span in the body of a function, causing it to get
+// encoded into the `optimized_mir`
+// 3. We call the function from a different crate - since the function is generic,
+// monomorphization runs, causing `optimized_mir` to get called.
+// 4. We re-run compilation using our populated incremental cache, but without
+// making any changes. When we recompile the crate containing our generic function
+// (`invalid_span_helper_lib`), we load the span from the incremental cache, and
+// write it into the crate metadata.
+
+extern crate invalid_span_helper_lib;
+
+fn main() {
+ invalid_span_helper_lib::foo::<u8>();
+}
diff --git a/src/test/incremental/issue-85360-eval-obligation-ice.rs b/src/test/incremental/issue-85360-eval-obligation-ice.rs
new file mode 100644
index 000000000..1796c9d19
--- /dev/null
+++ b/src/test/incremental/issue-85360-eval-obligation-ice.rs
@@ -0,0 +1,118 @@
+// revisions:cfail1 cfail2
+//[cfail1] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=not-loaded
+//[cfail2] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=loaded
+// build-pass
+
+use core::any::Any;
+use core::marker::PhantomData;
+
+struct DerefWrap<T>(T);
+
+impl<T> core::ops::Deref for DerefWrap<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+struct Storage<T, D> {
+ phantom: PhantomData<(T, D)>,
+}
+
+type ReadStorage<T> = Storage<T, DerefWrap<MaskedStorage<T>>>;
+
+pub trait Component {
+ type Storage;
+}
+
+struct VecStorage;
+
+struct Pos;
+
+impl Component for Pos {
+ type Storage = VecStorage;
+}
+
+struct GenericComp<T> {
+ _t: T,
+}
+
+impl<T: 'static> Component for GenericComp<T> {
+ type Storage = VecStorage;
+}
+struct ReadData {
+ pos_interpdata: ReadStorage<GenericComp<Pos>>,
+}
+
+trait System {
+ type SystemData;
+
+ fn run(data: Self::SystemData, any: Box<dyn Any>);
+}
+
+struct Sys;
+
+impl System for Sys {
+ type SystemData = (ReadData, ReadStorage<Pos>);
+
+ fn run((data, pos): Self::SystemData, any: Box<dyn Any>) {
+ <ReadStorage<GenericComp<Pos>> as SystemData>::setup(any);
+
+ ParJoin::par_join((&pos, &data.pos_interpdata));
+ }
+}
+
+trait ParJoin {
+ fn par_join(self)
+ where
+ Self: Sized,
+ {
+ }
+}
+
+impl<'a, T, D> ParJoin for &'a Storage<T, D>
+where
+ T: Component,
+ D: core::ops::Deref<Target = MaskedStorage<T>>,
+ T::Storage: Sync,
+{
+}
+
+impl<A, B> ParJoin for (A, B)
+where
+ A: ParJoin,
+ B: ParJoin,
+{
+}
+
+pub trait SystemData {
+ fn setup(any: Box<dyn Any>);
+}
+
+impl<T: 'static> SystemData for ReadStorage<T>
+where
+ T: Component,
+{
+ fn setup(any: Box<dyn Any>) {
+ let storage: &MaskedStorage<T> = any.downcast_ref().unwrap();
+
+ <dyn Any as CastFrom<MaskedStorage<T>>>::cast(&storage);
+ }
+}
+
+pub struct MaskedStorage<T: Component> {
+ _inner: T::Storage,
+}
+
+pub unsafe trait CastFrom<T> {
+ fn cast(t: &T) -> &Self;
+}
+
+unsafe impl<T> CastFrom<T> for dyn Any
+where
+ T: Any + 'static,
+{
+ fn cast(t: &T) -> &Self {
+ t
+ }
+}
diff --git a/src/test/incremental/issue-86753.rs b/src/test/incremental/issue-86753.rs
new file mode 100644
index 000000000..4d6c4354e
--- /dev/null
+++ b/src/test/incremental/issue-86753.rs
@@ -0,0 +1,50 @@
+// edition:2018
+// revisions: rpass1
+
+
+// Regression test for #86753. The `type_implements_trait` query (since moved to a method)
+// was encountering an ICE during incremental testing when hashing its arguments.
+#![warn(rust_2021_compatibility)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Poll, Context};
+
+struct LocalSet {}
+struct RunUntil<'a, F> {
+ _local_set: &'a LocalSet,
+ _future: F,
+}
+impl<'a, F> RunUntil<'a, F> {
+ fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> {
+ unimplemented!()
+ }
+}
+
+struct Projection<'pin, 'a, F>
+where
+ RunUntil<'a, F>: 'pin,
+{
+ pub local_set: &'pin mut &'a LocalSet,
+ pub future: Pin<&'pin mut F>,
+}
+
+impl LocalSet {
+ fn with<T>(&self, _f: impl FnOnce() -> T) -> T {
+ unimplemented!()
+ }
+}
+impl<T: Future> Future for RunUntil<'_, T> {
+ type Output = T::Output;
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ let me = self.project();
+ me.local_set.with(|| {
+ let _ = cx.waker();
+ let f = me.future;
+ let _ = f.poll(cx);
+ Poll::Pending
+ })
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs b/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs
new file mode 100644
index 000000000..134afd4fb
--- /dev/null
+++ b/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs
@@ -0,0 +1,3 @@
+pub enum Foo {
+ Variant
+}
diff --git a/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs b/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs
new file mode 100644
index 000000000..ab7961f38
--- /dev/null
+++ b/src/test/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs
@@ -0,0 +1,10 @@
+// compile-flags:--extern first_crate
+
+// Note: adding `first_crate` to the extern prelude
+// (instead of using `extern_crate`) appears to be necessary to
+// trigger the original incremental compilation bug.
+// I'm not entirely sure why this is the case
+
+pub fn make_it() -> first_crate::Foo {
+ panic!()
+}
diff --git a/src/test/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs b/src/test/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs
new file mode 100644
index 000000000..e9219c6f5
--- /dev/null
+++ b/src/test/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs
@@ -0,0 +1,31 @@
+// aux-build:first_crate.rs
+// aux-build:second_crate.rs
+// revisions:rpass1 rpass2
+
+// Regression test for issue #92163
+// Under certain circumstances, we may end up trying to
+// decode a foreign `Span` from the incremental cache, without previously
+// having imported the `SourceFile`s from the owning crate. This can happen
+// if the `Span` comes from a transitive dependency (so we never try to resolve
+// items from the crate during expansion/resolution).
+//
+// Previously, this would result in an ICE, since we would not have loaded
+// the corresponding `SourceFile` for the `StableSourceFileId` we decoded.
+// This test verifies that the decoding of a foreign `Span` will always
+// try to import the `SourceFile`s from the foreign crate, instead of
+// relying on that having already happened during expansion.
+
+extern crate second_crate;
+
+pub struct Outer;
+
+impl Outer {
+ pub fn use_it() {
+ // This returns `first_crate::Foo`, causing
+ // us to encode the `AdtDef `first_crate::Foo` (along with its `Span`s)
+ // into the query cache for the `TypeckResults` for this function.
+ second_crate::make_it();
+ }
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-92987-provisional-dep-node.rs b/src/test/incremental/issue-92987-provisional-dep-node.rs
new file mode 100644
index 000000000..a48a8373c
--- /dev/null
+++ b/src/test/incremental/issue-92987-provisional-dep-node.rs
@@ -0,0 +1,24 @@
+// revisions: rpass1 rpass2
+
+// Regression test for issue #92987
+// Tests that we properly manage `DepNode`s during trait evaluation
+// involing an auto-trait cycle.
+
+#[cfg(rpass1)]
+struct CycleOne(Box<CycleTwo>);
+
+#[cfg(rpass2)]
+enum CycleOne {
+ Variant(Box<CycleTwo>)
+}
+
+struct CycleTwo(CycleOne);
+
+fn assert_send<T: Send>() {}
+
+fn bar() {
+ assert_send::<CycleOne>();
+ assert_send::<CycleTwo>();
+}
+
+fn main() {}
diff --git a/src/test/incremental/issue-96319-coinductive-cycle.rs b/src/test/incremental/issue-96319-coinductive-cycle.rs
new file mode 100644
index 000000000..b5ff9112a
--- /dev/null
+++ b/src/test/incremental/issue-96319-coinductive-cycle.rs
@@ -0,0 +1,34 @@
+// edition:2018
+// revisions: rpass1 rpass2
+
+pub struct Stmt {
+ pub stmt_type: StmtKind,
+ #[cfg(rpass1)] pub stmt_tag: Option<LintTag>,
+ #[cfg(rpass2)] pub renamed_tag: Option<LintTag>,
+}
+pub struct LintTag;
+pub enum StmtKind {
+ If(If),
+ Block(&'static str),
+ Return(Return),
+}
+pub struct If {
+ pub condition: Function,
+}
+pub struct Return {
+ pub value: Function,
+}
+pub struct Function {
+ pub parameters: Box<Stmt>,
+}
+pub fn start_late_pass(stmt_receiver: Box<Stmt>) {
+ spawn(async { stmt_receiver });
+}
+
+pub fn spawn<T>(_: T)
+where
+ T: Send,
+{
+}
+
+fn main() {}
diff --git a/src/test/incremental/krate-inherent.rs b/src/test/incremental/krate-inherent.rs
new file mode 100644
index 000000000..2c04e1105
--- /dev/null
+++ b/src/test/incremental/krate-inherent.rs
@@ -0,0 +1,23 @@
+// revisions: cfail1 cfail2
+// compile-flags: -Z query-dep-graph
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "krate_inherent-x", cfg = "cfail2")]
+#![crate_type = "rlib"]
+
+pub mod x {
+ pub struct Foo;
+ impl Foo {
+ pub fn foo(&self) {}
+ }
+
+ pub fn method() {
+ let x: Foo = Foo;
+ x.foo(); // inherent methods used to add an edge from hir_crate
+ }
+}
+
+#[cfg(cfail1)]
+pub fn bar() {} // remove this unrelated fn in cfail2, which should not affect `x::method`
diff --git a/src/test/incremental/krate-inlined.rs b/src/test/incremental/krate-inlined.rs
new file mode 100644
index 000000000..6b1db74a3
--- /dev/null
+++ b/src/test/incremental/krate-inlined.rs
@@ -0,0 +1,25 @@
+// Regr. test that using HIR inlined from another krate does *not* add
+// a dependency from the local hir_crate node. We can't easily test that
+// directly anymore, so now we test that we get reuse.
+
+// revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "krate_inlined-x", cfg = "rpass2")]
+
+fn main() {
+ x::method();
+
+ #[cfg(rpass2)]
+ ()
+}
+
+mod x {
+ pub fn method() {
+ // use some methods that require inlining HIR from another crate:
+ let mut v = vec![];
+ v.push(1);
+ }
+}
diff --git a/src/test/incremental/krate_reassign_34991/auxiliary/a.rs b/src/test/incremental/krate_reassign_34991/auxiliary/a.rs
new file mode 100644
index 000000000..69be8d3bc
--- /dev/null
+++ b/src/test/incremental/krate_reassign_34991/auxiliary/a.rs
@@ -0,0 +1,3 @@
+#![crate_type="rlib"]
+
+pub type X = u32;
diff --git a/src/test/incremental/krate_reassign_34991/main.rs b/src/test/incremental/krate_reassign_34991/main.rs
new file mode 100644
index 000000000..c4ae19ac9
--- /dev/null
+++ b/src/test/incremental/krate_reassign_34991/main.rs
@@ -0,0 +1,20 @@
+// aux-build:a.rs
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+extern crate a;
+
+#[cfg(rpass1)]
+pub fn use_X() -> u32 {
+ let x: a::X = 22;
+ x as u32
+}
+
+#[cfg(rpass2)]
+pub fn use_X() -> u32 {
+ 22
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/link_order/auxiliary/my_lib.rs b/src/test/incremental/link_order/auxiliary/my_lib.rs
new file mode 100644
index 000000000..1e7d82305
--- /dev/null
+++ b/src/test/incremental/link_order/auxiliary/my_lib.rs
@@ -0,0 +1,3 @@
+// no-prefer-dynamic
+//[cfail1] compile-flags: -lbar -lfoo --crate-type lib -Zassert-incr-state=not-loaded
+//[cfail2] compile-flags: -lfoo -lbar --crate-type lib -Zassert-incr-state=not-loaded
diff --git a/src/test/incremental/link_order/main.rs b/src/test/incremental/link_order/main.rs
new file mode 100644
index 000000000..d211c295b
--- /dev/null
+++ b/src/test/incremental/link_order/main.rs
@@ -0,0 +1,12 @@
+// aux-build:my_lib.rs
+// error-pattern: error: linking with
+// revisions:cfail1 cfail2
+// compile-flags:-Z query-dep-graph
+
+// Tests that re-ordering the `-l` arguments used
+// when compiling an external dependency does not lead to
+// an 'unstable fingerprint' error.
+
+extern crate my_lib;
+
+fn main() {}
diff --git a/src/test/incremental/lto-in-linker.rs b/src/test/incremental/lto-in-linker.rs
new file mode 100644
index 000000000..0e8c1ebb9
--- /dev/null
+++ b/src/test/incremental/lto-in-linker.rs
@@ -0,0 +1,9 @@
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph --crate-type rlib -C linker-plugin-lto -O
+// no-prefer-dynamic
+// build-pass
+
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "lto_in_linker", cfg = "cfail2")]
+
+pub fn foo() {}
diff --git a/src/test/incremental/lto.rs b/src/test/incremental/lto.rs
new file mode 100644
index 000000000..2a3e3c246
--- /dev/null
+++ b/src/test/incremental/lto.rs
@@ -0,0 +1,40 @@
+// no-prefer-dynamic
+// revisions:rpass1 rpass2
+// compile-flags: -C lto
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/macro_export.rs b/src/test/incremental/macro_export.rs
new file mode 100644
index 000000000..044d63fd2
--- /dev/null
+++ b/src/test/incremental/macro_export.rs
@@ -0,0 +1,12 @@
+// revisions: cfail1 cfail2 cfail3
+// build-pass (FIXME(62277): could be check-pass?)
+
+// This test case makes sure that we can compile with incremental compilation
+// enabled when there are macros exported from this crate. (See #37756)
+
+#![crate_type="rlib"]
+
+#[macro_export]
+macro_rules! some_macro {
+ ($e:expr) => ($e + 1)
+}
diff --git a/src/test/incremental/mir-opt.rs b/src/test/incremental/mir-opt.rs
new file mode 100644
index 000000000..5bd863439
--- /dev/null
+++ b/src/test/incremental/mir-opt.rs
@@ -0,0 +1,11 @@
+// MIR optimizations can create expansions after the TyCtxt has been created.
+// This test verifies that those expansions can be decoded correctly.
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph -Z mir-opt-level=3
+
+fn main() {
+ if std::env::var("a").is_ok() {
+ println!("b");
+ }
+}
diff --git a/src/test/incremental/no_mangle.rs b/src/test/incremental/no_mangle.rs
new file mode 100644
index 000000000..b1c9b2bc3
--- /dev/null
+++ b/src/test/incremental/no_mangle.rs
@@ -0,0 +1,10 @@
+// revisions:cfail1 cfail2
+// check-pass
+// compile-flags: --crate-type cdylib
+
+#![deny(unused_attributes)]
+
+#[no_mangle]
+pub extern "C" fn rust_no_mangle() -> i32 {
+ 42
+}
diff --git a/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs b/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs
new file mode 100644
index 000000000..627b99445
--- /dev/null
+++ b/src/test/incremental/remapped_paths_cc/auxiliary/extern_crate.rs
@@ -0,0 +1,11 @@
+//[rpass1] compile-flags: -g
+//[rpass2] compile-flags: -g
+//[rpass3] compile-flags: -g --remap-path-prefix={{src-base}}=/the/src
+
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+#[inline(always)]
+pub fn inline_fn() {
+ println!("test");
+}
diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs
new file mode 100644
index 000000000..b01f02444
--- /dev/null
+++ b/src/test/incremental/remapped_paths_cc/main.rs
@@ -0,0 +1,28 @@
+// revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph -g
+// aux-build:extern_crate.rs
+
+// ignore-asmjs wasm2js does not support source maps yet
+// This test case makes sure that we detect if paths emitted into debuginfo
+// are changed, even when the change happens in an external crate.
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="main", cfg="rpass2")]
+#![rustc_partition_reused(module="main-some_mod", cfg="rpass2")]
+#![rustc_partition_reused(module="main", cfg="rpass3")]
+#![rustc_partition_codegened(module="main-some_mod", cfg="rpass3")]
+
+extern crate extern_crate;
+
+fn main() {
+ some_mod::some_fn();
+}
+
+mod some_mod {
+ use extern_crate;
+
+ pub fn some_fn() {
+ extern_crate::inline_fn();
+ }
+}
diff --git a/src/test/incremental/remove-private-item-cross-crate/auxiliary/a.rs b/src/test/incremental/remove-private-item-cross-crate/auxiliary/a.rs
new file mode 100644
index 000000000..279a6f078
--- /dev/null
+++ b/src/test/incremental/remove-private-item-cross-crate/auxiliary/a.rs
@@ -0,0 +1,8 @@
+#![allow(warnings)]
+#![crate_name = "a"]
+#![crate_type = "rlib"]
+
+pub fn foo(b: u8) -> u32 { b as u32 }
+
+#[cfg(rpass1)]
+fn bar() { }
diff --git a/src/test/incremental/remove-private-item-cross-crate/main.rs b/src/test/incremental/remove-private-item-cross-crate/main.rs
new file mode 100644
index 000000000..c831ab6fe
--- /dev/null
+++ b/src/test/incremental/remove-private-item-cross-crate/main.rs
@@ -0,0 +1,20 @@
+// Test that we are able to reuse `main` even though a private
+// item was removed from the root module of crate`a`.
+
+// revisions:rpass1 rpass2
+// aux-build:a.rs
+// compile-flags: -Zquery-dep-graph
+
+#![feature(rustc_attrs)]
+#![crate_type = "bin"]
+
+#![rustc_partition_reused(module="main", cfg="rpass2")]
+
+extern crate a;
+
+pub fn main() {
+ let vec: Vec<u8> = vec![0, 1, 2, 3];
+ for &b in &vec {
+ println!("{}", a::foo(b));
+ }
+}
diff --git a/src/test/incremental/remove_crate/auxiliary/extern_crate.rs b/src/test/incremental/remove_crate/auxiliary/extern_crate.rs
new file mode 100644
index 000000000..1cafdf49d
--- /dev/null
+++ b/src/test/incremental/remove_crate/auxiliary/extern_crate.rs
@@ -0,0 +1,3 @@
+pub fn foo(_: u8) {
+
+}
diff --git a/src/test/incremental/remove_crate/main.rs b/src/test/incremental/remove_crate/main.rs
new file mode 100644
index 000000000..14b80df0d
--- /dev/null
+++ b/src/test/incremental/remove_crate/main.rs
@@ -0,0 +1,24 @@
+// Test that removing an upstream crate does not cause any trouble.
+
+// revisions:rpass1 rpass2
+// aux-build:extern_crate.rs
+
+#[cfg(rpass1)]
+extern crate extern_crate;
+
+pub fn main() {
+ #[cfg(rpass1)]
+ {
+ extern_crate::foo(1);
+ }
+
+ #[cfg(rpass2)]
+ {
+ foo(1);
+ }
+}
+
+#[cfg(rpass2)]
+pub fn foo(_: u8) {
+
+}
diff --git a/src/test/incremental/remove_source_file/auxiliary/mod.rs b/src/test/incremental/remove_source_file/auxiliary/mod.rs
new file mode 100644
index 000000000..96a366d96
--- /dev/null
+++ b/src/test/incremental/remove_source_file/auxiliary/mod.rs
@@ -0,0 +1,3 @@
+pub fn print_hello() {
+ println!("hello");
+}
diff --git a/src/test/incremental/remove_source_file/main.rs b/src/test/incremental/remove_source_file/main.rs
new file mode 100644
index 000000000..b2411c094
--- /dev/null
+++ b/src/test/incremental/remove_source_file/main.rs
@@ -0,0 +1,24 @@
+// This test case makes sure that the compiler doesn't crash due to a failing
+// table lookup when a source file is removed.
+
+// revisions:cfail1 cfail2
+
+// Note that we specify -g so that the SourceFiles actually get referenced by the
+// incr. comp. cache:
+// compile-flags: -Z query-dep-graph -g
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![crate_type= "rlib"]
+
+#[cfg(cfail1)]
+mod auxiliary;
+
+#[cfg(cfail1)]
+pub fn foo() {
+ auxiliary::print_hello();
+}
+
+#[cfg(cfail2)]
+pub fn foo() {
+ println!("hello");
+}
diff --git a/src/test/incremental/reorder_vtable.rs b/src/test/incremental/reorder_vtable.rs
new file mode 100644
index 000000000..8dacba633
--- /dev/null
+++ b/src/test/incremental/reorder_vtable.rs
@@ -0,0 +1,41 @@
+// revisions:rpass1 rpass2
+
+// This test case makes sure re-order the methods in a vtable will
+// trigger recompilation of codegen units that instantiate it.
+//
+// See https://github.com/rust-lang/rust/issues/89598
+
+trait Foo {
+ #[cfg(rpass1)]
+ fn method1(&self) -> u32;
+
+ fn method2(&self) -> u32;
+
+ #[cfg(rpass2)]
+ fn method1(&self) -> u32;
+}
+
+impl Foo for u32 {
+ fn method1(&self) -> u32 { 17 }
+ fn method2(&self) -> u32 { 42 }
+}
+
+fn main() {
+ // Before #89598 was fixed, the vtable allocation would be cached during
+ // a MIR optimization pass and then the codegen pass for the main object
+ // file would not register a dependency on it (because of the missing
+ // dep-tracking).
+ //
+ // In the rpass2 session, the main object file would not be re-compiled,
+ // thus the mod1::foo(x) call would pass in an outdated vtable, while the
+ // mod1 object would expect the new, re-ordered vtable, resulting in a
+ // call to the wrong method.
+ let x: &dyn Foo = &0u32;
+ assert_eq!(mod1::foo(x), 17);
+}
+
+mod mod1 {
+ pub(super) fn foo(x: &dyn super::Foo) -> u32 {
+ x.method1()
+ }
+}
diff --git a/src/test/incremental/rlib-lto.rs b/src/test/incremental/rlib-lto.rs
new file mode 100644
index 000000000..752fee5a0
--- /dev/null
+++ b/src/test/incremental/rlib-lto.rs
@@ -0,0 +1,8 @@
+// revisions:cfail1 cfail2
+// compile-flags: -Z query-dep-graph --crate-type rlib -C lto
+// build-pass
+
+#![feature(rustc_attrs)]
+#![rustc_partition_reused(module = "rlib_lto", cfg = "cfail2")]
+
+pub fn foo() {}
diff --git a/src/test/incremental/rlib_cross_crate/auxiliary/a.rs b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
new file mode 100644
index 000000000..5a26df9ae
--- /dev/null
+++ b/src/test/incremental/rlib_cross_crate/auxiliary/a.rs
@@ -0,0 +1,16 @@
+// no-prefer-dynamic
+// compile-flags: -Z query-dep-graph
+
+#![crate_type="rlib"]
+
+#[cfg(rpass1)]
+pub type X = u32;
+
+#[cfg(rpass2)]
+pub type X = i32;
+
+// this version doesn't actually change anything:
+#[cfg(rpass3)]
+pub type X = i32;
+
+pub type Y = char;
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
new file mode 100644
index 000000000..639cfc918
--- /dev/null
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -0,0 +1,28 @@
+// Same test as `type_alias_cross_crate`, but with
+// `no-prefer-dynamic`, ensuring that we test what happens when we
+// build rlibs (before we were only testing dylibs, which meant we
+// didn't realize we had to preserve a `bc` file as well).
+
+// aux-build:a.rs
+// revisions:rpass1 rpass2 rpass3
+// no-prefer-dynamic
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+#[rustc_clean(except="typeck,optimized_mir", cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
+pub fn use_X() -> u32 {
+ let x: a::X = 22;
+ x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
+pub fn use_Y() {
+ let x: a::Y = 'c';
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/rustc-rust-log.rs b/src/test/incremental/rustc-rust-log.rs
new file mode 100644
index 000000000..566f0d96d
--- /dev/null
+++ b/src/test/incremental/rustc-rust-log.rs
@@ -0,0 +1,16 @@
+// revisions: rpass1 rpass2
+// This test is just checking that we won't ICE if logging is turned
+// on; don't bother trying to compare that (copious) output.
+//
+// dont-check-compiler-stdout
+// dont-check-compiler-stderr
+// aux-build: rustc-rust-log-aux.rs
+// rustc-env:RUSTC_LOG=debug
+
+#[cfg(rpass1)]
+fn main() {}
+
+#[cfg(rpass2)]
+fn main() {
+ println!();
+}
diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs
new file mode 100644
index 000000000..e5f04e5dc
--- /dev/null
+++ b/src/test/incremental/source_loc_macros.rs
@@ -0,0 +1,55 @@
+// This test makes sure that different expansions of the file!(), line!(),
+// column!() macros get picked up by the incr. comp. hash.
+
+// revisions:rpass1 rpass2
+
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#[rustc_clean(cfg="rpass2")]
+fn line_same() {
+ let _ = line!();
+}
+
+#[rustc_clean(cfg="rpass2")]
+fn col_same() {
+ let _ = column!();
+}
+
+#[rustc_clean(cfg="rpass2")]
+fn file_same() {
+ let _ = file!();
+}
+
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")]
+fn line_different() {
+ #[cfg(rpass1)]
+ {
+ let _ = line!();
+ }
+ #[cfg(rpass2)]
+ {
+ let _ = line!();
+ }
+}
+
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")]
+fn col_different() {
+ #[cfg(rpass1)]
+ {
+ let _ = column!();
+ }
+ #[cfg(rpass2)]
+ {
+ let _ = column!();
+ }
+}
+
+fn main() {
+ line_same();
+ line_different();
+ col_same();
+ col_different();
+ file_same();
+}
diff --git a/src/test/incremental/span_hash_stable/auxiliary/mod.rs b/src/test/incremental/span_hash_stable/auxiliary/mod.rs
new file mode 100644
index 000000000..f3824db4c
--- /dev/null
+++ b/src/test/incremental/span_hash_stable/auxiliary/mod.rs
@@ -0,0 +1,7 @@
+#[cfg(rpass1)]
+pub mod sub2;
+
+pub mod sub1;
+
+#[cfg(rpass2)]
+pub mod sub2;
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
new file mode 100644
index 000000000..70e2ea06b
--- /dev/null
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
@@ -0,0 +1,5 @@
+#[rustc_clean(cfg="rpass2")]
+pub struct SomeType {
+ pub x: u32,
+ pub y: i64,
+}
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
new file mode 100644
index 000000000..1167cdb0a
--- /dev/null
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
@@ -0,0 +1,5 @@
+#[rustc_clean(cfg="rpass2")]
+pub struct SomeOtherType {
+ pub a: i32,
+ pub b: u64,
+}
diff --git a/src/test/incremental/span_hash_stable/main.rs b/src/test/incremental/span_hash_stable/main.rs
new file mode 100644
index 000000000..367416430
--- /dev/null
+++ b/src/test/incremental/span_hash_stable/main.rs
@@ -0,0 +1,24 @@
+// This test makes sure that it doesn't make a difference in which order we are
+// adding source files to the source_map. The order affects the BytePos values of
+// the spans and this test makes sure that we handle them correctly by hashing
+// file:line:column instead of raw byte offset.
+
+// ignore-asmjs wasm2js does not support source maps yet
+// revisions:rpass1 rpass2
+// compile-flags: -g -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+mod auxiliary;
+
+fn main() {
+ let _ = auxiliary::sub1::SomeType {
+ x: 0,
+ y: 1,
+ };
+
+ let _ = auxiliary::sub2::SomeOtherType {
+ a: 2,
+ b: 3,
+ };
+}
diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs
new file mode 100644
index 000000000..f5cae15a4
--- /dev/null
+++ b/src/test/incremental/spans_in_type_debuginfo.rs
@@ -0,0 +1,53 @@
+// Test that moving a type definition within a source file does not affect
+// re-compilation.
+
+// ignore-asmjs wasm2js does not support source maps yet
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph -g
+
+#![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")]
+#![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")]
+
+#![feature(rustc_attrs)]
+
+mod structs {
+ #[cfg(rpass1)]
+ pub struct X {
+ pub x: u32,
+ }
+
+ #[cfg(rpass2)]
+ pub struct X {
+ pub x: u32,
+ }
+
+ pub fn foo(x: X) -> u32 {
+ x.x
+ }
+}
+
+mod enums {
+ #[cfg(rpass1)]
+ pub enum X {
+ A { x: u32 },
+ B(u32),
+ }
+
+ #[cfg(rpass2)]
+ pub enum X {
+ A { x: u32 },
+ B(u32),
+ }
+
+ pub fn foo(x: X) -> u32 {
+ match x {
+ X::A { x } => x,
+ X::B(x) => x,
+ }
+ }
+}
+
+pub fn main() {
+ let _ = structs::foo(structs::X { x: 1 });
+ let _ = enums::foo(enums::X::A { x: 2 });
+}
diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs
new file mode 100644
index 000000000..639454cc9
--- /dev/null
+++ b/src/test/incremental/spans_significant_w_debuginfo.rs
@@ -0,0 +1,21 @@
+// This test makes sure that just changing a definition's location in the
+// source file also changes its incr. comp. hash, if debuginfo is enabled.
+
+// revisions:rpass1 rpass2 rpass3 rpass4
+
+// ignore-asmjs wasm2js does not support source maps yet
+// compile-flags: -g -Z query-dep-graph
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
+
+#![feature(rustc_attrs)]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")]
+
+#[cfg(any(rpass1, rpass3))]
+pub fn main() {}
+
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
+pub fn main() {}
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
new file mode 100644
index 000000000..e9e35791a
--- /dev/null
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -0,0 +1,29 @@
+// This test makes sure that just changing a definition's location in the
+// source file also changes its incr. comp. hash, if debuginfo is enabled.
+
+// revisions:rpass1 rpass2 rpass3 rpass4
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
+
+// compile-flags: -C overflow-checks=on -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+#![feature(bench_black_box)]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
+
+#[cfg(any(rpass1, rpass3))]
+pub fn main() {
+ if std::hint::black_box(false) {
+ panic!()
+ }
+}
+
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
+pub fn main() {
+ if std::hint::black_box(false) {
+ panic!()
+ }
+}
diff --git a/src/test/incremental/spike-neg1.rs b/src/test/incremental/spike-neg1.rs
new file mode 100644
index 000000000..97812ffe3
--- /dev/null
+++ b/src/test/incremental/spike-neg1.rs
@@ -0,0 +1,52 @@
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_codegened` tests.
+// Here we change and say that the `x` module will be reused (when in
+// fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg1", cfg="rpass2")]
+#![rustc_partition_reused(module="spike_neg1-x", cfg="rpass2")] // this is wrong!
+#![rustc_partition_reused(module="spike_neg1-y", cfg="rpass2")]
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/spike-neg2.rs b/src/test/incremental/spike-neg2.rs
new file mode 100644
index 000000000..3bb1914fd
--- /dev/null
+++ b/src/test/incremental/spike-neg2.rs
@@ -0,0 +1,52 @@
+// A variant of the first "spike" test that serves to test the
+// `rustc_partition_reused` and `rustc_partition_codegened` tests.
+// Here we change and say that the `y` module will be codegened (when
+// in fact it will not), and then indicate that the test itself
+// should-fail (because an error will be reported, and hence the
+// revision rpass2 will not compile, despite being named rpass).
+
+// revisions:rpass1 rpass2
+// should-fail
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike_neg2", cfg="rpass2")]
+#![rustc_partition_codegened(module="spike_neg2-x", cfg="rpass2")]
+#![rustc_partition_codegened(module="spike_neg2-y", cfg="rpass2")] // this is wrong!
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/spike.rs b/src/test/incremental/spike.rs
new file mode 100644
index 000000000..a6a05e7c3
--- /dev/null
+++ b/src/test/incremental/spike.rs
@@ -0,0 +1,49 @@
+// A first "spike" for incremental compilation: here, we change the
+// content of the `make` function, and we find that we can reuse the
+// `y` module entirely (but not the `x` module).
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="spike", cfg="rpass2")]
+#![rustc_partition_codegened(module="spike-x", cfg="rpass2")]
+#![rustc_partition_reused(module="spike-y", cfg="rpass2")]
+
+mod x {
+ pub struct X {
+ x: u32, y: u32,
+ }
+
+ #[cfg(rpass1)]
+ fn make() -> X {
+ X { x: 22, y: 0 }
+ }
+
+ #[cfg(rpass2)]
+ fn make() -> X {
+ X { x: 11, y: 11 }
+ }
+
+ pub fn new() -> X {
+ make()
+ }
+
+ pub fn sum(x: &X) -> u32 {
+ x.x + x.y
+ }
+}
+
+mod y {
+ use x;
+
+ pub fn assert_sum() -> bool {
+ let x = x::new();
+ x::sum(&x) == 22
+ }
+}
+
+pub fn main() {
+ y::assert_sum();
+}
diff --git a/src/test/incremental/split_debuginfo_cached.rs b/src/test/incremental/split_debuginfo_cached.rs
new file mode 100644
index 000000000..25c802d5a
--- /dev/null
+++ b/src/test/incremental/split_debuginfo_cached.rs
@@ -0,0 +1,25 @@
+// Check that compiling with packed Split DWARF twice succeeds. This should confirm that DWARF
+// objects are cached as work products and available to the incremental compilation for `thorin` to
+// pack into a DWARF package.
+
+// ignore-tidy-linelength
+// only-x86_64-unknown-linux-gnu
+// revisions:rpass1 rpass2
+
+// [rpass1]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
+// [rpass2]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
+
+#![feature(rustc_attrs)]
+// For `rpass2`, nothing has changed so everything should re-used.
+#![rustc_partition_reused(module = "split_debuginfo_cached", cfg = "rpass2")]
+#![rustc_partition_reused(module = "split_debuginfo_cached-another_module", cfg = "rpass2")]
+
+mod another_module {
+ pub fn foo() -> &'static str {
+ "hello world"
+ }
+}
+
+pub fn main() {
+ println!("{}", another_module::foo());
+}
diff --git a/src/test/incremental/split_debuginfo_mode.rs b/src/test/incremental/split_debuginfo_mode.rs
new file mode 100644
index 000000000..f2533e414
--- /dev/null
+++ b/src/test/incremental/split_debuginfo_mode.rs
@@ -0,0 +1,33 @@
+// This test case makes sure that changing split-debuginfo commandline options triggers a full re-compilation.
+// We only test on x86_64-unknown-linux-gnu because there all combinations split-debuginfo settings are valid
+// and the test is platform-independent otherwise.
+
+// ignore-tidy-linelength
+// only-x86_64-unknown-linux-gnu
+// revisions:rpass1 rpass2 rpass3 rpass4
+
+// [rpass1]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
+// [rpass2]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
+// [rpass3]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on
+// [rpass4]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off
+
+#![feature(rustc_attrs)]
+// For rpass2 we change -Csplit-debuginfo and thus expect every CGU to be recompiled
+#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass2")]
+// For rpass3 we change -Zsplit-dwarf-kind and thus also expect every CGU to be recompiled
+#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass3")]
+#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass3")]
+// For rpass4 we change -Zsplit-dwarf-inlining and thus also expect every CGU to be recompiled
+#![rustc_partition_codegened(module = "split_debuginfo_mode", cfg = "rpass4")]
+#![rustc_partition_codegened(module = "split_debuginfo_mode-another_module", cfg = "rpass4")]
+
+mod another_module {
+ pub fn foo() -> &'static str {
+ "hello world"
+ }
+}
+
+pub fn main() {
+ println!("{}", another_module::foo());
+}
diff --git a/src/test/incremental/static_cycle/b.rs b/src/test/incremental/static_cycle/b.rs
new file mode 100644
index 000000000..064213fba
--- /dev/null
+++ b/src/test/incremental/static_cycle/b.rs
@@ -0,0 +1,9 @@
+// revisions:rpass1 rpass2
+
+#![cfg_attr(rpass2, warn(dead_code))]
+
+pub static mut BAA: *const i8 = unsafe { &BOO as *const _ as *const i8 };
+
+pub static mut BOO: *const i8 = unsafe { &BAA as *const _ as *const i8 };
+
+fn main() {}
diff --git a/src/test/incremental/static_refering_to_other_static/issue-49081.rs b/src/test/incremental/static_refering_to_other_static/issue-49081.rs
new file mode 100644
index 000000000..8e3715d1d
--- /dev/null
+++ b/src/test/incremental/static_refering_to_other_static/issue-49081.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-lang/rust/issues/49081
+
+// revisions:rpass1 rpass2
+
+pub static A: i32 = 42;
+pub static B: &i32 = &A;
+
+fn main() {}
diff --git a/src/test/incremental/static_refering_to_other_static2/issue.rs b/src/test/incremental/static_refering_to_other_static2/issue.rs
new file mode 100644
index 000000000..720bb1e22
--- /dev/null
+++ b/src/test/incremental/static_refering_to_other_static2/issue.rs
@@ -0,0 +1,10 @@
+// revisions:rpass1 rpass2
+
+#[cfg(rpass1)]
+pub static A: i32 = 42;
+#[cfg(rpass2)]
+pub static A: i32 = 43;
+
+pub static B: &i32 = &A;
+
+fn main() {}
diff --git a/src/test/incremental/static_refering_to_other_static3/issue.rs b/src/test/incremental/static_refering_to_other_static3/issue.rs
new file mode 100644
index 000000000..80999813d
--- /dev/null
+++ b/src/test/incremental/static_refering_to_other_static3/issue.rs
@@ -0,0 +1,15 @@
+// revisions:rpass1 rpass2
+
+#[cfg(rpass1)]
+pub static A: u8 = 42;
+#[cfg(rpass2)]
+pub static A: u8 = 43;
+
+static B: &u8 = &C.1;
+static C: (&&u8, u8) = (&B, A);
+
+fn main() {
+ assert_eq!(*B, A);
+ assert_eq!(**C.0, A);
+ assert_eq!(C.1, A);
+}
diff --git a/src/test/incremental/static_stable_hash/issue-49301.rs b/src/test/incremental/static_stable_hash/issue-49301.rs
new file mode 100644
index 000000000..fdd05c72c
--- /dev/null
+++ b/src/test/incremental/static_stable_hash/issue-49301.rs
@@ -0,0 +1,18 @@
+// https://github.com/rust-lang/rust/issues/49081
+
+// revisions:rpass1 rpass2
+
+#[cfg(rpass1)]
+pub static A: &str = "hello";
+#[cfg(rpass2)]
+pub static A: &str = "xxxxx";
+
+#[cfg(rpass1)]
+fn main() {
+ assert_eq!(A, "hello");
+}
+
+#[cfg(rpass2)]
+fn main() {
+ assert_eq!(A, "xxxxx");
+}
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
new file mode 100644
index 000000000..cae7b4aab
--- /dev/null
+++ b/src/test/incremental/string_constant.rs
@@ -0,0 +1,47 @@
+// revisions: cfail1 cfail2 cfail3 cfail4
+// compile-flags: -Z query-dep-graph
+// [cfail3]compile-flags: -Zincremental-relative-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+
+// Here the only thing which changes is the string constant in `x`.
+// Therefore, the compiler deduces (correctly) that typeck is not
+// needed even for callers of `x`.
+
+pub mod x {
+ #[cfg(any(cfail1, cfail3))]
+ pub fn x() {
+ println!("{}", "1");
+ }
+
+ #[cfg(any(cfail2, cfail4))]
+ #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")]
+ #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")]
+ pub fn x() {
+ println!("{}", "2");
+ }
+}
+
+pub mod y {
+ use x;
+
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail4")]
+ pub fn y() {
+ x::x();
+ }
+}
+
+pub mod z {
+ use y;
+
+ #[rustc_clean(cfg = "cfail2")]
+ #[rustc_clean(cfg = "cfail4")]
+ pub fn z() {
+ y::y();
+ }
+}
diff --git a/src/test/incremental/struct_add_field.rs b/src/test/incremental/struct_add_field.rs
new file mode 100644
index 000000000..720854f16
--- /dev/null
+++ b/src/test/incremental/struct_add_field.rs
@@ -0,0 +1,39 @@
+// Test incremental compilation tracking where we change field names
+// in between revisions (hashing should be stable).
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+pub struct X {
+ pub x: u32,
+
+ #[cfg(rpass2)]
+ pub x2: u32,
+}
+
+pub struct EmbedX {
+ x: X
+}
+
+pub struct Y {
+ pub y: char
+}
+
+#[rustc_clean(except="fn_sig,typeck", cfg="rpass2")]
+pub fn use_X(x: X) -> u32 {
+ x.x as u32
+}
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_EmbedX(embed: EmbedX) -> u32 {
+ embed.x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs
new file mode 100644
index 000000000..a7c79e9d7
--- /dev/null
+++ b/src/test/incremental/struct_change_field_name.rs
@@ -0,0 +1,47 @@
+// Test incremental compilation tracking where we change field names
+// in between revisions (hashing should be stable).
+
+// revisions:rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+// [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+pub struct X {
+ pub x: u32
+}
+
+#[cfg(cfail2)]
+pub struct X {
+ pub y: u32
+}
+
+pub struct EmbedX {
+ x: X
+}
+
+pub struct Y {
+ pub y: char
+}
+
+#[rustc_clean(except="typeck", cfg="cfail2")]
+pub fn use_X() -> u32 {
+ let x: X = X { x: 22 };
+ //[cfail2]~^ ERROR struct `X` has no field named `x`
+ x.x as u32
+ //[cfail2]~^ ERROR no field `x` on type `X`
+}
+
+#[rustc_clean(except="typeck", cfg="cfail2")]
+pub fn use_EmbedX(embed: EmbedX) -> u32 {
+ embed.x.x as u32
+ //[cfail2]~^ ERROR no field `x` on type `X`
+}
+
+#[rustc_clean(cfg="cfail2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/struct_change_field_type.rs b/src/test/incremental/struct_change_field_type.rs
new file mode 100644
index 000000000..37d2fba99
--- /dev/null
+++ b/src/test/incremental/struct_change_field_type.rs
@@ -0,0 +1,44 @@
+// Test incremental compilation tracking where we change nothing
+// in between revisions (hashing should be stable).
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+pub struct X {
+ pub x: u32
+}
+
+#[cfg(rpass2)]
+pub struct X {
+ pub x: i32
+}
+
+pub struct EmbedX {
+ x: X
+}
+
+pub struct Y {
+ pub y: char
+}
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_X() -> u32 {
+ let x: X = X { x: 22 };
+ x.x as u32
+}
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_EmbedX(x: EmbedX) -> u32 {
+ let x: X = X { x: 22 };
+ x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs b/src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs
new file mode 100644
index 000000000..d3ddb32c3
--- /dev/null
+++ b/src/test/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs
@@ -0,0 +1,19 @@
+#![crate_type="rlib"]
+
+ #[cfg(rpass1)]
+pub struct X {
+ pub x: u32
+}
+
+#[cfg(rpass2)]
+pub struct X {
+ pub x: i32
+}
+
+pub struct EmbedX {
+ pub x: X
+}
+
+pub struct Y {
+ pub y: char
+}
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
new file mode 100644
index 000000000..c78207bcb
--- /dev/null
+++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
@@ -0,0 +1,27 @@
+// aux-build:a.rs
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+use a::*;
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_X() -> u32 {
+ let x: X = X { x: 22 };
+ x.x as u32
+}
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_EmbedX(embed: EmbedX) -> u32 {
+ embed.x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/struct_change_nothing.rs b/src/test/incremental/struct_change_nothing.rs
new file mode 100644
index 000000000..de30c818c
--- /dev/null
+++ b/src/test/incremental/struct_change_nothing.rs
@@ -0,0 +1,44 @@
+// Test incremental compilation tracking where we change nothing
+// in between revisions (hashing should be stable).
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+pub struct X {
+ pub x: u32
+}
+
+#[cfg(rpass2)]
+pub struct X {
+ pub x: u32
+}
+
+pub struct EmbedX {
+ x: X
+}
+
+pub struct Y {
+ pub y: char
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_X() -> u32 {
+ let x: X = X { x: 22 };
+ x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_EmbedX(x: EmbedX) -> u32 {
+ let x: X = X { x: 22 };
+ x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/struct_remove_field.rs b/src/test/incremental/struct_remove_field.rs
new file mode 100644
index 000000000..b97a87e09
--- /dev/null
+++ b/src/test/incremental/struct_remove_field.rs
@@ -0,0 +1,43 @@
+// Test incremental compilation tracking where we change field names
+// in between revisions (hashing should be stable).
+
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+pub struct X {
+ pub x: u32,
+ pub x2: u32,
+}
+
+#[cfg(rpass2)]
+pub struct X {
+ pub x: u32,
+}
+
+pub struct EmbedX {
+ x: X
+}
+
+pub struct Y {
+ pub y: char
+}
+
+#[rustc_clean(except="typeck,fn_sig", cfg="rpass2")]
+pub fn use_X(x: X) -> u32 {
+ x.x as u32
+}
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+pub fn use_EmbedX(embed: EmbedX) -> u32 {
+ embed.x.x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+pub fn use_Y() {
+ let x: Y = Y { y: 'c' };
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/thinlto/cgu_invalidated_via_import.rs b/src/test/incremental/thinlto/cgu_invalidated_via_import.rs
new file mode 100644
index 000000000..5fe435d79
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_via_import.rs
@@ -0,0 +1,48 @@
+// This test checks that the LTO phase is re-done for CGUs that import something
+// via ThinLTO and that imported thing changes while the definition of the CGU
+// stays untouched.
+
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph -O
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-foo",
+ cfg="cfail2",
+ kind="no")]
+#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-foo",
+ cfg="cfail3",
+ kind="post-lto")]
+
+#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-bar",
+ cfg="cfail2",
+ kind="pre-lto")]
+#![rustc_expected_cgu_reuse(module="cgu_invalidated_via_import-bar",
+ cfg="cfail3",
+ kind="post-lto")]
+
+mod foo {
+
+ // Trivial functions like this one are imported very reliably by ThinLTO.
+ #[cfg(cfail1)]
+ pub fn inlined_fn() -> u32 {
+ 1234
+ }
+
+ #[cfg(not(cfail1))]
+ pub fn inlined_fn() -> u32 {
+ // See `cgu_keeps_identical_fn.rs` for why this is different
+ // from the other version of this function.
+ 12345
+ }
+}
+
+pub mod bar {
+ use foo::inlined_fn;
+
+ pub fn caller() -> u32 {
+ inlined_fn()
+ }
+}
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs b/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs
new file mode 100644
index 000000000..4d48a5f0a
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_export_added.rs
@@ -0,0 +1,26 @@
+// revisions: cfail1 cfail2
+// build-pass
+
+// rust-lang/rust#69798:
+//
+// This is analgous to cgu_invalidated_when_import_added, but it covers a
+// problem uncovered where a change to the *export* set caused a link failure
+// when reusing post-LTO optimized object code.
+
+pub struct Foo {}
+impl Drop for Foo {
+ fn drop(&mut self) {
+ println!("Dropping Foo");
+ }
+}
+#[no_mangle]
+pub extern "C" fn run() {
+ thread_local! { pub static FOO : Foo = Foo { } ; }
+
+ #[cfg(cfail2)]
+ {
+ FOO.with(|_f| ())
+ }
+}
+
+pub fn main() { run() }
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs
new file mode 100644
index 000000000..e85b4856f
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_export_removed.rs
@@ -0,0 +1,26 @@
+// revisions: cfail1 cfail2
+// build-pass
+
+// rust-lang/rust#69798:
+//
+// This is analgous to cgu_invalidated_when_export_added, but it covers the
+// other direction. This is analogous to cgu_invalidated_when_import_added: we
+// include it, because it may uncover bugs in variant implementation strategies.
+
+pub struct Foo {}
+impl Drop for Foo {
+ fn drop(&mut self) {
+ println!("Dropping Foo");
+ }
+}
+#[no_mangle]
+pub extern "C" fn run() {
+ thread_local! { pub static FOO : Foo = Foo { } ; }
+
+ #[cfg(cfail1)]
+ {
+ FOO.with(|_f| ())
+ }
+}
+
+pub fn main() { run() }
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs
new file mode 100644
index 000000000..9c17c8745
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs
@@ -0,0 +1,62 @@
+// revisions: cfail1 cfail2
+// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
+// build-pass
+
+// rust-lang/rust#59535:
+//
+// This is analogous to cgu_invalidated_when_import_removed.rs, but it covers
+// the other direction:
+//
+// We start with a call-graph like `[A] -> [B -> D] [C]` (where the letters are
+// functions and the modules are enclosed in `[]`), and add a new call `D <- C`,
+// yielding the new call-graph: `[A] -> [B -> D] <- [C]`
+//
+// The effect of this is that the compiler previously classfied `D` as internal
+// and the import-set of `[A]` to be just `B`. But after adding the `D <- C` call,
+// `D` is no longer classified as internal, and the import-set of `[A]` becomes
+// both `B` and `D`.
+//
+// We check this case because an early proposed pull request included an
+// assertion that the import-sets monotonically decreased over time, a claim
+// which this test case proves to be false.
+
+fn main() {
+ foo::foo();
+ bar::baz();
+}
+
+mod foo {
+
+ // In cfail1, ThinLTO decides that foo() does not get inlined into main, and
+ // instead bar() gets inlined into foo().
+ // In cfail2, foo() gets inlined into main.
+ pub fn foo(){
+ bar()
+ }
+
+ // This function needs to be big so that it does not get inlined by ThinLTO
+ // but *does* get inlined into foo() when it is declared `internal` in
+ // cfail1 (alone).
+ pub fn bar(){
+ println!("quux1");
+ println!("quux2");
+ println!("quux3");
+ println!("quux4");
+ println!("quux5");
+ println!("quux6");
+ println!("quux7");
+ println!("quux8");
+ println!("quux9");
+ }
+}
+
+mod bar {
+
+ #[inline(never)]
+ pub fn baz() {
+ #[cfg(cfail2)]
+ {
+ crate::foo::bar();
+ }
+ }
+}
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
new file mode 100644
index 000000000..fc53acf75
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
@@ -0,0 +1,74 @@
+// revisions: cfail1 cfail2
+// compile-flags: -O -Zhuman-readable-cgu-names -Cllvm-args=-import-instr-limit=10
+// build-pass
+
+// rust-lang/rust#59535:
+//
+// Consider a call-graph like `[A] -> [B -> D] <- [C]` (where the letters are
+// functions and the modules are enclosed in `[]`)
+//
+// In our specific instance, the earlier compilations were inlining the call
+// to`B` into `A`; thus `A` ended up with an external reference to the symbol `D`
+// in its object code, to be resolved at subsequent link time. The LTO import
+// information provided by LLVM for those runs reflected that information: it
+// explicitly says during those runs, `B` definition and `D` declaration were
+// imported into `[A]`.
+//
+// The change between incremental builds was that the call `D <- C` was removed.
+//
+// That change, coupled with other decisions within `rustc`, made the compiler
+// decide to make `D` an internal symbol (since it was no longer accessed from
+// other codegen units, this makes sense locally). And then the definition of
+// `D` was inlined into `B` and `D` itself was eliminated entirely.
+//
+// The current LTO import information reported that `B` alone is imported into
+// `[A]` for the *current compilation*. So when the Rust compiler surveyed the
+// dependence graph, it determined that nothing `[A]` imports changed since the
+// last build (and `[A]` itself has not changed either), so it chooses to reuse
+// the object code generated during the previous compilation.
+//
+// But that previous object code has an unresolved reference to `D`, and that
+// causes a link time failure!
+
+fn main() {
+ foo::foo();
+ bar::baz();
+}
+
+mod foo {
+
+ // In cfail1, foo() gets inlined into main.
+ // In cfail2, ThinLTO decides that foo() does not get inlined into main, and
+ // instead bar() gets inlined into foo(). But faulty logic in our incr.
+ // ThinLTO implementation thought that `main()` is unchanged and thus reused
+ // the object file still containing a call to the now non-existent bar().
+ pub fn foo(){
+ bar()
+ }
+
+ // This function needs to be big so that it does not get inlined by ThinLTO
+ // but *does* get inlined into foo() once it is declared `internal` in
+ // cfail2.
+ pub fn bar(){
+ println!("quux1");
+ println!("quux2");
+ println!("quux3");
+ println!("quux4");
+ println!("quux5");
+ println!("quux6");
+ println!("quux7");
+ println!("quux8");
+ println!("quux9");
+ }
+}
+
+mod bar {
+
+ #[inline(never)]
+ pub fn baz() {
+ #[cfg(cfail1)]
+ {
+ crate::foo::bar();
+ }
+ }
+}
diff --git a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
new file mode 100644
index 000000000..31f329a7f
--- /dev/null
+++ b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
@@ -0,0 +1,72 @@
+// This test is almost identical to `cgu_invalided_via_import`, except that
+// the two versions of `inline_fn` are identical. Neither version of `inlined_fn`
+// ends up with any spans in its LLVM bitecode, so LLVM is able to skip
+// re-building any modules which import 'inlined_fn'
+
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
+// compile-flags: -Z query-dep-graph -O
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![crate_type = "rlib"]
+#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail3",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail5",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-foo",
+ cfg = "cfail6",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail2",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail3",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail5",
+ kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+ module = "cgu_keeps_identical_fn-bar",
+ cfg = "cfail6",
+ kind = "post-lto"
+)]
+
+mod foo {
+
+ // Trivial functions like this one are imported very reliably by ThinLTO.
+ #[cfg(any(cfail1, cfail4))]
+ pub fn inlined_fn() -> u32 {
+ 1234
+ }
+
+ #[cfg(not(any(cfail1, cfail4)))]
+ pub fn inlined_fn() -> u32 {
+ 1234
+ }
+}
+
+pub mod bar {
+ use foo::inlined_fn;
+
+ pub fn caller() -> u32 {
+ inlined_fn()
+ }
+}
diff --git a/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs b/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs
new file mode 100644
index 000000000..045f20119
--- /dev/null
+++ b/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs
@@ -0,0 +1,58 @@
+// This test checks that a change in a CGU does not invalidate an unrelated CGU
+// during incremental ThinLTO.
+
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Z query-dep-graph -O
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+#![crate_type="rlib"]
+
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-foo",
+ cfg="cfail2",
+ kind="no")]
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-foo",
+ cfg="cfail3",
+ kind="post-lto")]
+
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-bar",
+ cfg="cfail2",
+ kind="pre-lto")]
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-bar",
+ cfg="cfail3",
+ kind="post-lto")]
+
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-baz",
+ cfg="cfail2",
+ kind="post-lto")]
+#![rustc_expected_cgu_reuse(module="independent_cgus_dont_affect_each_other-baz",
+ cfg="cfail3",
+ kind="post-lto")]
+mod foo {
+
+ #[cfg(cfail1)]
+ pub fn inlined_fn() -> u32 {
+ 1234
+ }
+
+ #[cfg(not(cfail1))]
+ pub fn inlined_fn() -> u32 {
+ // See `cgu_keeps_identical_fn.rs` for why this is different
+ // from the other version of this function.
+ 12345
+ }
+}
+
+pub mod bar {
+ use foo::inlined_fn;
+
+ pub fn caller() -> u32 {
+ inlined_fn()
+ }
+}
+
+pub mod baz {
+ pub fn unrelated_to_other_fns() -> u64 {
+ 0xbeef
+ }
+}
diff --git a/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs b/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs
new file mode 100644
index 000000000..61fe297d7
--- /dev/null
+++ b/src/test/incremental/type_alias_cross_crate/auxiliary/a.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Z query-dep-graph
+
+#![crate_type="rlib"]
+
+#[cfg(rpass1)]
+pub type X = u32;
+
+#[cfg(rpass2)]
+pub type X = i32;
+
+// this version doesn't actually change anything:
+#[cfg(rpass3)]
+pub type X = i32;
+
+pub type Y = char;
diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs
new file mode 100644
index 000000000..f6c252684
--- /dev/null
+++ b/src/test/incremental/type_alias_cross_crate/b.rs
@@ -0,0 +1,22 @@
+// aux-build:a.rs
+// revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
+
+#![feature(rustc_attrs)]
+
+extern crate a;
+
+#[rustc_clean(except="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
+pub fn use_X() -> u32 {
+ let x: a::X = 22;
+ x as u32
+}
+
+#[rustc_clean(cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
+pub fn use_Y() {
+ let x: a::Y = 'c';
+}
+
+pub fn main() { }
diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs
new file mode 100644
index 000000000..3c8692a30
--- /dev/null
+++ b/src/test/incremental/unchecked_dirty_clean.rs
@@ -0,0 +1,34 @@
+// revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+// Sanity check for the dirty-clean system. We add #[rustc_clean]
+// attributes in places that are not checked and make sure that this causes an
+// error.
+
+fn main() {
+
+ #[rustc_clean(except="hir_owner", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
+ {
+ // empty block
+ }
+
+ #[rustc_clean(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
+ {
+ // empty block
+ }
+}
+
+struct _Struct {
+ #[rustc_clean(except="hir_owner", cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
+ _field1: i32,
+
+ #[rustc_clean(cfg="cfail2")]
+ //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
+ _field2: i32,
+}
diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs
new file mode 100644
index 000000000..0e6b88232
--- /dev/null
+++ b/src/test/incremental/warnings-reemitted.rs
@@ -0,0 +1,9 @@
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Coverflow-checks=on
+// build-pass
+
+#![warn(arithmetic_overflow)]
+
+fn main() {
+ let _ = 255u8 + 1; //~ WARNING operation will overflow
+}