diff options
Diffstat (limited to 'tests/incremental')
193 files changed, 13563 insertions, 0 deletions
diff --git a/tests/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs b/tests/incremental/add_private_fn_at_krate_root_cc/auxiliary/point.rs new file mode 100644 index 000000000..16aaad348 --- /dev/null +++ b/tests/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/tests/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/tests/incremental/add_private_fn_at_krate_root_cc/struct_point.rs new file mode 100644 index 000000000..ea1ea1943 --- /dev/null +++ b/tests/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/tests/incremental/async-lifetimes.rs b/tests/incremental/async-lifetimes.rs new file mode 100644 index 000000000..90a0b93b9 --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/incremental_proc_macro_aux.rs b/tests/incremental/auxiliary/incremental_proc_macro_aux.rs new file mode 100644 index 000000000..6961450b4 --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/issue-49482-macro-def.rs b/tests/incremental/auxiliary/issue-49482-macro-def.rs new file mode 100644 index 000000000..bfa7abb1a --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/issue-49482-reexport.rs b/tests/incremental/auxiliary/issue-49482-reexport.rs new file mode 100644 index 000000000..39f19e3f1 --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/issue-54059.rs b/tests/incremental/auxiliary/issue-54059.rs new file mode 100644 index 000000000..fa2814a77 --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/issue-79661.rs b/tests/incremental/auxiliary/issue-79661.rs new file mode 100644 index 000000000..cd32a52eb --- /dev/null +++ b/tests/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/tests/incremental/auxiliary/issue-79890.rs b/tests/incremental/auxiliary/issue-79890.rs new file mode 100644 index 000000000..8eaeafa52 --- /dev/null +++ b/tests/incremental/auxiliary/issue-79890.rs @@ -0,0 +1 @@ +pub trait MyTrait {} diff --git a/tests/incremental/auxiliary/rustc-rust-log-aux.rs b/tests/incremental/auxiliary/rustc-rust-log-aux.rs new file mode 100644 index 000000000..a361373dc --- /dev/null +++ b/tests/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/tests/incremental/cache_file_headers.rs b/tests/incremental/cache_file_headers.rs new file mode 100644 index 000000000..9cf611c33 --- /dev/null +++ b/tests/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/tests/incremental/callee_caller_cross_crate/auxiliary/a.rs b/tests/incremental/callee_caller_cross_crate/auxiliary/a.rs new file mode 100644 index 000000000..6445f87f7 --- /dev/null +++ b/tests/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/tests/incremental/callee_caller_cross_crate/b.rs b/tests/incremental/callee_caller_cross_crate/b.rs new file mode 100644 index 000000000..084ed232a --- /dev/null +++ b/tests/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/tests/incremental/change_add_field/struct_point.rs b/tests/incremental/change_add_field/struct_point.rs new file mode 100644 index 000000000..3308ea562 --- /dev/null +++ b/tests/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/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs new file mode 100644 index 000000000..8c35f6ca0 --- /dev/null +++ b/tests/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/tests/incremental/change_crate_order/auxiliary/a.rs b/tests/incremental/change_crate_order/auxiliary/a.rs new file mode 100644 index 000000000..1bd48714a --- /dev/null +++ b/tests/incremental/change_crate_order/auxiliary/a.rs @@ -0,0 +1,3 @@ +#![crate_type="rlib"] + +pub static A : u32 = 32; diff --git a/tests/incremental/change_crate_order/auxiliary/b.rs b/tests/incremental/change_crate_order/auxiliary/b.rs new file mode 100644 index 000000000..001b88912 --- /dev/null +++ b/tests/incremental/change_crate_order/auxiliary/b.rs @@ -0,0 +1,3 @@ +#![crate_type="rlib"] + +pub static B: u32 = 32; diff --git a/tests/incremental/change_crate_order/main.rs b/tests/incremental/change_crate_order/main.rs new file mode 100644 index 000000000..7448b54dd --- /dev/null +++ b/tests/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/tests/incremental/change_implementation_cross_crate/auxiliary/a.rs b/tests/incremental/change_implementation_cross_crate/auxiliary/a.rs new file mode 100644 index 000000000..7320a97b9 --- /dev/null +++ b/tests/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/tests/incremental/change_implementation_cross_crate/main.rs b/tests/incremental/change_implementation_cross_crate/main.rs new file mode 100644 index 000000000..dee9ebd74 --- /dev/null +++ b/tests/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/tests/incremental/change_name_of_static_in_fn.rs b/tests/incremental/change_name_of_static_in_fn.rs new file mode 100644 index 000000000..fd16ad2dc --- /dev/null +++ b/tests/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/tests/incremental/change_private_fn/struct_point.rs b/tests/incremental/change_private_fn/struct_point.rs new file mode 100644 index 000000000..d57267adc --- /dev/null +++ b/tests/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/tests/incremental/change_private_fn_cc/auxiliary/point.rs b/tests/incremental/change_private_fn_cc/auxiliary/point.rs new file mode 100644 index 000000000..483f20572 --- /dev/null +++ b/tests/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/tests/incremental/change_private_fn_cc/struct_point.rs b/tests/incremental/change_private_fn_cc/struct_point.rs new file mode 100644 index 000000000..1c27ec3a3 --- /dev/null +++ b/tests/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/tests/incremental/change_private_impl_method/struct_point.rs b/tests/incremental/change_private_impl_method/struct_point.rs new file mode 100644 index 000000000..cf43e4757 --- /dev/null +++ b/tests/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/tests/incremental/change_private_impl_method_cc/auxiliary/point.rs b/tests/incremental/change_private_impl_method_cc/auxiliary/point.rs new file mode 100644 index 000000000..2441da06b --- /dev/null +++ b/tests/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/tests/incremental/change_private_impl_method_cc/struct_point.rs b/tests/incremental/change_private_impl_method_cc/struct_point.rs new file mode 100644 index 000000000..9fe8b5df9 --- /dev/null +++ b/tests/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/tests/incremental/change_pub_inherent_method_body/struct_point.rs b/tests/incremental/change_pub_inherent_method_body/struct_point.rs new file mode 100644 index 000000000..1b87b18fc --- /dev/null +++ b/tests/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/tests/incremental/change_pub_inherent_method_sig/struct_point.rs b/tests/incremental/change_pub_inherent_method_sig/struct_point.rs new file mode 100644 index 000000000..0a6729567 --- /dev/null +++ b/tests/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/tests/incremental/change_symbol_export_status.rs b/tests/incremental/change_symbol_export_status.rs new file mode 100644 index 000000000..83737a022 --- /dev/null +++ b/tests/incremental/change_symbol_export_status.rs @@ -0,0 +1,39 @@ +// revisions: rpass1 rpass2 rpass3 rpass4 +// compile-flags: -Zquery-dep-graph +// [rpass1]compile-flags: -Zincremental-ignore-spans +// [rpass2]compile-flags: -Zincremental-ignore-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/tests/incremental/commandline-args.rs b/tests/incremental/commandline-args.rs new file mode 100644 index 000000000..35b7183db --- /dev/null +++ b/tests/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/tests/incremental/const-generics/hash-tyvid-regression-1.rs b/tests/incremental/const-generics/hash-tyvid-regression-1.rs new file mode 100644 index 000000000..5ff7b19d8 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/hash-tyvid-regression-2.rs b/tests/incremental/const-generics/hash-tyvid-regression-2.rs new file mode 100644 index 000000000..5cdd43cd7 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/hash-tyvid-regression-3.rs b/tests/incremental/const-generics/hash-tyvid-regression-3.rs new file mode 100644 index 000000000..61f568f79 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/hash-tyvid-regression-4.rs b/tests/incremental/const-generics/hash-tyvid-regression-4.rs new file mode 100644 index 000000000..12e8ac7ab --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-61338.rs b/tests/incremental/const-generics/issue-61338.rs new file mode 100644 index 000000000..e9d67fee2 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-61516.rs b/tests/incremental/const-generics/issue-61516.rs new file mode 100644 index 000000000..c781484d1 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-62536.rs b/tests/incremental/const-generics/issue-62536.rs new file mode 100644 index 000000000..93c1dbf44 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-64087.rs b/tests/incremental/const-generics/issue-64087.rs new file mode 100644 index 000000000..81c813531 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-65623.rs b/tests/incremental/const-generics/issue-65623.rs new file mode 100644 index 000000000..22bbcbcab --- /dev/null +++ b/tests/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/tests/incremental/const-generics/issue-68477.rs b/tests/incremental/const-generics/issue-68477.rs new file mode 100644 index 000000000..9e35cf93d --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs new file mode 100644 index 000000000..8262a2a21 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs new file mode 100644 index 000000000..92bbcba4b --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs new file mode 100644 index 000000000..fc114f224 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs new file mode 100644 index 000000000..c05d8355c --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs new file mode 100644 index 000000000..8886a556d --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs new file mode 100644 index 000000000..5b2f5edc8 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs new file mode 100644 index 000000000..d659c5676 --- /dev/null +++ b/tests/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/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs new file mode 100644 index 000000000..5f5435ba9 --- /dev/null +++ b/tests/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/tests/incremental/crate_hash_reorder.rs b/tests/incremental/crate_hash_reorder.rs new file mode 100644 index 000000000..ca476b4d2 --- /dev/null +++ b/tests/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/tests/incremental/cyclic-trait-hierarchy.rs b/tests/incremental/cyclic-trait-hierarchy.rs new file mode 100644 index 000000000..b502e7207 --- /dev/null +++ b/tests/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/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs new file mode 100644 index 000000000..2529e531e --- /dev/null +++ b/tests/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/tests/incremental/dirty_clean.rs b/tests/incremental/dirty_clean.rs new file mode 100644 index 000000000..11d999ab3 --- /dev/null +++ b/tests/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/tests/incremental/extern_static/issue-49153.rs b/tests/incremental/extern_static/issue-49153.rs new file mode 100644 index 000000000..f1dbac288 --- /dev/null +++ b/tests/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/tests/incremental/feature_gate.rs b/tests/incremental/feature_gate.rs new file mode 100644 index 000000000..5317a9962 --- /dev/null +++ b/tests/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/tests/incremental/foreign.rs b/tests/incremental/foreign.rs new file mode 100644 index 000000000..f46f92eb5 --- /dev/null +++ b/tests/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/tests/incremental/hash-module-order.rs b/tests/incremental/hash-module-order.rs new file mode 100644 index 000000000..fe9af9eeb --- /dev/null +++ b/tests/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/tests/incremental/hashes/call_expressions.rs b/tests/incremental/hashes/call_expressions.rs new file mode 100644 index 000000000..65df2e829 --- /dev/null +++ b/tests/incremental/hashes/call_expressions.rs @@ -0,0 +1,197 @@ +// 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 + + +#![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/tests/incremental/hashes/closure_expressions.rs b/tests/incremental/hashes/closure_expressions.rs new file mode 100644 index 000000000..927bcd96e --- /dev/null +++ b/tests/incremental/hashes/closure_expressions.rs @@ -0,0 +1,124 @@ +// 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 + +#![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, typeck")] +#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, 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/tests/incremental/hashes/consts.rs b/tests/incremental/hashes/consts.rs new file mode 100644 index 000000000..eaef63386 --- /dev/null +++ b/tests/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/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs new file mode 100644 index 000000000..db367d070 --- /dev/null +++ b/tests/incremental/hashes/enum_constructors.rs @@ -0,0 +1,387 @@ +// 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 + +#![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/tests/incremental/hashes/enum_defs.rs b/tests/incremental/hashes/enum_defs.rs new file mode 100644 index 000000000..bc83723a9 --- /dev/null +++ b/tests/incremental/hashes/enum_defs.rs @@ -0,0 +1,715 @@ +// 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 + +#![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,predicates_of")] +#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,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,predicates_of")] +#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,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/tests/incremental/hashes/exported_vs_not.rs b/tests/incremental/hashes/exported_vs_not.rs new file mode 100644 index 000000000..9ac9ae24f --- /dev/null +++ b/tests/incremental/hashes/exported_vs_not.rs @@ -0,0 +1,72 @@ +// 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 + +#![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/tests/incremental/hashes/extern_mods.rs b/tests/incremental/hashes/extern_mods.rs new file mode 100644 index 000000000..1906843c7 --- /dev/null +++ b/tests/incremental/hashes/extern_mods.rs @@ -0,0 +1,221 @@ +// 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 + +#![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/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs new file mode 100644 index 000000000..193e792c8 --- /dev/null +++ b/tests/incremental/hashes/for_loops.rs @@ -0,0 +1,299 @@ +// 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 + +#![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/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs new file mode 100644 index 000000000..182ca7d92 --- /dev/null +++ b/tests/incremental/hashes/function_interfaces.rs @@ -0,0 +1,411 @@ +// 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 + +#![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", except = "typeck")] +#[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/tests/incremental/hashes/if_expressions.rs b/tests/incremental/hashes/if_expressions.rs new file mode 100644 index 000000000..937fd3ac8 --- /dev/null +++ b/tests/incremental/hashes/if_expressions.rs @@ -0,0 +1,225 @@ +// 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 + +#![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/tests/incremental/hashes/indexing_expressions.rs b/tests/incremental/hashes/indexing_expressions.rs new file mode 100644 index 000000000..b1ac6f6fa --- /dev/null +++ b/tests/incremental/hashes/indexing_expressions.rs @@ -0,0 +1,134 @@ +// 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 + +#![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/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs new file mode 100644 index 000000000..285f857c9 --- /dev/null +++ b/tests/incremental/hashes/inherent_impls.rs @@ -0,0 +1,787 @@ +// 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 + + +#![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/tests/incremental/hashes/inline_asm.rs b/tests/incremental/hashes/inline_asm.rs new file mode 100644 index 000000000..3118aa135 --- /dev/null +++ b/tests/incremental/hashes/inline_asm.rs @@ -0,0 +1,219 @@ +// 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 + +#![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/tests/incremental/hashes/let_expressions.rs b/tests/incremental/hashes/let_expressions.rs new file mode 100644 index 000000000..180bf6fec --- /dev/null +++ b/tests/incremental/hashes/let_expressions.rs @@ -0,0 +1,219 @@ +// 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 + +#![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/tests/incremental/hashes/loop_expressions.rs b/tests/incremental/hashes/loop_expressions.rs new file mode 100644 index 000000000..87b86479d --- /dev/null +++ b/tests/incremental/hashes/loop_expressions.rs @@ -0,0 +1,224 @@ +// 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 + +#![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")] +#[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: 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/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs new file mode 100644 index 000000000..4429df683 --- /dev/null +++ b/tests/incremental/hashes/match_expressions.rs @@ -0,0 +1,334 @@ +// 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 + +#![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/tests/incremental/hashes/panic_exprs.rs b/tests/incremental/hashes/panic_exprs.rs new file mode 100644 index 000000000..37d10d922 --- /dev/null +++ b/tests/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/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs new file mode 100644 index 000000000..bb83f8300 --- /dev/null +++ b/tests/incremental/hashes/statics.rs @@ -0,0 +1,183 @@ +// 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 + +#![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/tests/incremental/hashes/struct_constructors.rs b/tests/incremental/hashes/struct_constructors.rs new file mode 100644 index 000000000..e50e5674c --- /dev/null +++ b/tests/incremental/hashes/struct_constructors.rs @@ -0,0 +1,267 @@ +// 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 + +#![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/tests/incremental/hashes/struct_defs.rs b/tests/incremental/hashes/struct_defs.rs new file mode 100644 index 000000000..4a2706b4f --- /dev/null +++ b/tests/incremental/hashes/struct_defs.rs @@ -0,0 +1,332 @@ +// 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 + +#![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/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs new file mode 100644 index 000000000..b583bee2f --- /dev/null +++ b/tests/incremental/hashes/trait_defs.rs @@ -0,0 +1,1409 @@ +// 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 + +#![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,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 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,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 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,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 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,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 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/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs new file mode 100644 index 000000000..3b2e18d17 --- /dev/null +++ b/tests/incremental/hashes/trait_impls.rs @@ -0,0 +1,617 @@ +// 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 + +#![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/tests/incremental/hashes/type_defs.rs b/tests/incremental/hashes/type_defs.rs new file mode 100644 index 000000000..79398eb07 --- /dev/null +++ b/tests/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/tests/incremental/hashes/unary_and_binary_exprs.rs b/tests/incremental/hashes/unary_and_binary_exprs.rs new file mode 100644 index 000000000..58af51eef --- /dev/null +++ b/tests/incremental/hashes/unary_and_binary_exprs.rs @@ -0,0 +1,506 @@ +// 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 + +#![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/tests/incremental/hashes/while_let_loops.rs b/tests/incremental/hashes/while_let_loops.rs new file mode 100644 index 000000000..c81b0d0af --- /dev/null +++ b/tests/incremental/hashes/while_let_loops.rs @@ -0,0 +1,247 @@ +// 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 + +#![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")] +#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[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")] +#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[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/tests/incremental/hashes/while_loops.rs b/tests/incremental/hashes/while_loops.rs new file mode 100644 index 000000000..c1cc0b62b --- /dev/null +++ b/tests/incremental/hashes/while_loops.rs @@ -0,0 +1,249 @@ +// 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 + +#![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")] +#[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: 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")] +#[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: 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/tests/incremental/hello_world.rs b/tests/incremental/hello_world.rs new file mode 100644 index 000000000..d5ec6e92b --- /dev/null +++ b/tests/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/tests/incremental/hygiene/auxiliary/cached_hygiene.rs b/tests/incremental/hygiene/auxiliary/cached_hygiene.rs new file mode 100644 index 000000000..b31f60e97 --- /dev/null +++ b/tests/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/tests/incremental/hygiene/load_cached_hygiene.rs b/tests/incremental/hygiene/load_cached_hygiene.rs new file mode 100644 index 000000000..355d33458 --- /dev/null +++ b/tests/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 following 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/tests/incremental/ich_method_call_trait_scope.rs b/tests/incremental/ich_method_call_trait_scope.rs new file mode 100644 index 000000000..5566506c0 --- /dev/null +++ b/tests/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/tests/incremental/ich_nested_items.rs b/tests/incremental/ich_nested_items.rs new file mode 100644 index 000000000..379c09575 --- /dev/null +++ b/tests/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/tests/incremental/ich_resolve_results.rs b/tests/incremental/ich_resolve_results.rs new file mode 100644 index 000000000..e6ab6bceb --- /dev/null +++ b/tests/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/tests/incremental/incremental_proc_macro.rs b/tests/incremental/incremental_proc_macro.rs new file mode 100644 index 000000000..becc1538f --- /dev/null +++ b/tests/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/tests/incremental/inlined_hir_34991/main.rs b/tests/incremental/inlined_hir_34991/main.rs new file mode 100644 index 000000000..bb76a0bb8 --- /dev/null +++ b/tests/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/tests/incremental/issue-100521-change-struct-name-assocty.rs b/tests/incremental/issue-100521-change-struct-name-assocty.rs new file mode 100644 index 000000000..7f8d1e608 --- /dev/null +++ b/tests/incremental/issue-100521-change-struct-name-assocty.rs @@ -0,0 +1,65 @@ +// revisions: rpass1 rpass2 + +pub fn foo() { + bar(); + baz::<()>(); +} + +fn bar() +where + <() as Table>::AllColumns:, +{ +} + +fn baz<W>() +where + W: AsQuery, + <W as AsQuery>::Query:, +{ +} + +trait AsQuery { + type Query; +} + +trait UnimplementedTrait {} + +impl<T> AsQuery for T +where + T: UnimplementedTrait, +{ + type Query = (); +} + +struct Wrapper<Expr>(Expr); + +impl<Ret> AsQuery for Wrapper<Ret> { + type Query = (); +} + +impl AsQuery for () +where + Wrapper<<() as Table>::AllColumns>: AsQuery, +{ + type Query = (); +} + +trait Table { + type AllColumns; +} + +#[cfg(rpass1)] +impl Table for () { + type AllColumns = Checksum1; +} +#[cfg(rpass1)] +struct Checksum1; + +#[cfg(rpass2)] +impl Table for () { + type AllColumns = Checksum2; +} +#[cfg(rpass2)] +struct Checksum2; + +fn main() {} diff --git a/tests/incremental/issue-101518.rs b/tests/incremental/issue-101518.rs new file mode 100644 index 000000000..501be175f --- /dev/null +++ b/tests/incremental/issue-101518.rs @@ -0,0 +1,31 @@ +// revisions: cfail1 +// should-ice +// error-pattern: forcing query +// known-bug: #101518 + +#[derive(PartialEq, Eq)] +struct Id<'a> { + ns: &'a str, +} +fn visit_struct() { + let id = Id { ns: "random1" }; + const FLAG: Id<'static> = Id { + ns: "needs_to_be_the_same", + }; + match id { + FLAG => {} + _ => {} + } +} +fn visit_struct2() { + let id = Id { ns: "random2" }; + const FLAG: Id<'static> = Id { + ns: "needs_to_be_the_same", + }; + match id { + FLAG => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/incremental/issue-35593.rs b/tests/incremental/issue-35593.rs new file mode 100644 index 000000000..009e37d17 --- /dev/null +++ b/tests/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/tests/incremental/issue-38222.rs b/tests/incremental/issue-38222.rs new file mode 100644 index 000000000..20d4d4200 --- /dev/null +++ b/tests/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/tests/incremental/issue-39569.rs b/tests/incremental/issue-39569.rs new file mode 100644 index 000000000..881ecfca7 --- /dev/null +++ b/tests/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/tests/incremental/issue-39828/auxiliary/generic.rs b/tests/incremental/issue-39828/auxiliary/generic.rs new file mode 100644 index 000000000..a5bb0d65f --- /dev/null +++ b/tests/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/tests/incremental/issue-39828/issue-39828.rs b/tests/incremental/issue-39828/issue-39828.rs new file mode 100644 index 000000000..8cef916ff --- /dev/null +++ b/tests/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/tests/incremental/issue-42602.rs b/tests/incremental/issue-42602.rs new file mode 100644 index 000000000..b8d5303fb --- /dev/null +++ b/tests/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/tests/incremental/issue-49043.rs b/tests/incremental/issue-49043.rs new file mode 100644 index 000000000..8d13718b8 --- /dev/null +++ b/tests/incremental/issue-49043.rs @@ -0,0 +1,12 @@ +// Regression test for hashing involving canonical variables. In this +// test -- which has an intentional 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/tests/incremental/issue-49482.rs b/tests/incremental/issue-49482.rs new file mode 100644 index 000000000..042ecc0f2 --- /dev/null +++ b/tests/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/tests/incremental/issue-49595/auxiliary/lit_a.rs b/tests/incremental/issue-49595/auxiliary/lit_a.rs new file mode 100644 index 000000000..295a0b481 --- /dev/null +++ b/tests/incremental/issue-49595/auxiliary/lit_a.rs @@ -0,0 +1 @@ +pub const A: &str = "hello"; diff --git a/tests/incremental/issue-49595/auxiliary/lit_b.rs b/tests/incremental/issue-49595/auxiliary/lit_b.rs new file mode 100644 index 000000000..5d377edfb --- /dev/null +++ b/tests/incremental/issue-49595/auxiliary/lit_b.rs @@ -0,0 +1 @@ +pub const A: &str = "xxxxx"; diff --git a/tests/incremental/issue-49595/issue-49595.rs b/tests/incremental/issue-49595/issue-49595.rs new file mode 100644 index 000000000..7b1096a64 --- /dev/null +++ b/tests/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/tests/incremental/issue-51409.rs b/tests/incremental/issue-51409.rs new file mode 100644 index 000000000..280094ec0 --- /dev/null +++ b/tests/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/tests/incremental/issue-54059.rs b/tests/incremental/issue-54059.rs new file mode 100644 index 000000000..0a5a54750 --- /dev/null +++ b/tests/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/tests/incremental/issue-54242.rs b/tests/incremental/issue-54242.rs new file mode 100644 index 000000000..806c84152 --- /dev/null +++ b/tests/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/tests/incremental/issue-59523-on-implemented-is-not-unused.rs b/tests/incremental/issue-59523-on-implemented-is-not-unused.rs new file mode 100644 index 000000000..fa52ca90b --- /dev/null +++ b/tests/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/tests/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs b/tests/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs new file mode 100644 index 000000000..bfb5e539c --- /dev/null +++ b/tests/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/tests/incremental/issue-60629.rs b/tests/incremental/issue-60629.rs new file mode 100644 index 000000000..4807af4b3 --- /dev/null +++ b/tests/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/tests/incremental/issue-61323.rs b/tests/incremental/issue-61323.rs new file mode 100644 index 000000000..7ce47947c --- /dev/null +++ b/tests/incremental/issue-61323.rs @@ -0,0 +1,14 @@ +// revisions: rpass cfail + +enum A { + //[cfail]~^ ERROR 3:1: 3:7: recursive types `A` and `C` have infinite size [E0072] + B(C), +} + +#[cfg(rpass)] +struct C(Box<A>); + +#[cfg(cfail)] +struct C(A); + +fn main() {} diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs new file mode 100644 index 000000000..edb3d60ba --- /dev/null +++ b/tests/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/tests/incremental/issue-62649-path-collisions-happen.rs b/tests/incremental/issue-62649-path-collisions-happen.rs new file mode 100644 index 000000000..ee81be76b --- /dev/null +++ b/tests/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/tests/incremental/issue-69596.rs b/tests/incremental/issue-69596.rs new file mode 100644 index 000000000..dc587fdc4 --- /dev/null +++ b/tests/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/tests/incremental/issue-72386.rs b/tests/incremental/issue-72386.rs new file mode 100644 index 000000000..5917152e1 --- /dev/null +++ b/tests/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/tests/incremental/issue-79661-missing-def-path-hash.rs b/tests/incremental/issue-79661-missing-def-path-hash.rs new file mode 100644 index 000000000..f86fb33fb --- /dev/null +++ b/tests/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/tests/incremental/issue-79890-imported-crates-changed.rs b/tests/incremental/issue-79890-imported-crates-changed.rs new file mode 100644 index 000000000..93daa5ca9 --- /dev/null +++ b/tests/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/tests/incremental/issue-80336-invalid-span.rs b/tests/incremental/issue-80336-invalid-span.rs new file mode 100644 index 000000000..7757d9159 --- /dev/null +++ b/tests/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/tests/incremental/issue-80691-bad-eval-cache.rs b/tests/incremental/issue-80691-bad-eval-cache.rs new file mode 100644 index 000000000..1a644fd88 --- /dev/null +++ b/tests/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/tests/incremental/issue-82920-predicate-order-miscompile.rs b/tests/incremental/issue-82920-predicate-order-miscompile.rs new file mode 100644 index 000000000..793af679c --- /dev/null +++ b/tests/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/tests/incremental/issue-84252-global-alloc.rs b/tests/incremental/issue-84252-global-alloc.rs new file mode 100644 index 000000000..d2438df89 --- /dev/null +++ b/tests/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/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-lib.rs new file mode 100644 index 000000000..2453af5b6 --- /dev/null +++ b/tests/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/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/invalid-span-helper-mod.rs new file mode 100644 index 000000000..747174b1e --- /dev/null +++ b/tests/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/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs b/tests/incremental/issue-85197-invalid-span/auxiliary/respan.rs new file mode 100644 index 000000000..5088eab62 --- /dev/null +++ b/tests/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/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs b/tests/incremental/issue-85197-invalid-span/invalid_span_main.rs new file mode 100644 index 000000000..f358460b3 --- /dev/null +++ b/tests/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/tests/incremental/issue-85360-eval-obligation-ice.rs b/tests/incremental/issue-85360-eval-obligation-ice.rs new file mode 100644 index 000000000..1796c9d19 --- /dev/null +++ b/tests/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/tests/incremental/issue-86753.rs b/tests/incremental/issue-86753.rs new file mode 100644 index 000000000..4d6c4354e --- /dev/null +++ b/tests/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/tests/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs b/tests/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs new file mode 100644 index 000000000..134afd4fb --- /dev/null +++ b/tests/incremental/issue-92163-missing-sourcefile/auxiliary/first_crate.rs @@ -0,0 +1,3 @@ +pub enum Foo { + Variant +} diff --git a/tests/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs b/tests/incremental/issue-92163-missing-sourcefile/auxiliary/second_crate.rs new file mode 100644 index 000000000..ab7961f38 --- /dev/null +++ b/tests/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/tests/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs b/tests/incremental/issue-92163-missing-sourcefile/issue_92163_main.rs new file mode 100644 index 000000000..e9219c6f5 --- /dev/null +++ b/tests/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/tests/incremental/issue-92987-provisional-dep-node.rs b/tests/incremental/issue-92987-provisional-dep-node.rs new file mode 100644 index 000000000..a48a8373c --- /dev/null +++ b/tests/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/tests/incremental/issue-96319-coinductive-cycle.rs b/tests/incremental/issue-96319-coinductive-cycle.rs new file mode 100644 index 000000000..b5ff9112a --- /dev/null +++ b/tests/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/tests/incremental/krate-inherent.rs b/tests/incremental/krate-inherent.rs new file mode 100644 index 000000000..2c04e1105 --- /dev/null +++ b/tests/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/tests/incremental/krate-inlined.rs b/tests/incremental/krate-inlined.rs new file mode 100644 index 000000000..6b1db74a3 --- /dev/null +++ b/tests/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/tests/incremental/krate_reassign_34991/auxiliary/a.rs b/tests/incremental/krate_reassign_34991/auxiliary/a.rs new file mode 100644 index 000000000..69be8d3bc --- /dev/null +++ b/tests/incremental/krate_reassign_34991/auxiliary/a.rs @@ -0,0 +1,3 @@ +#![crate_type="rlib"] + +pub type X = u32; diff --git a/tests/incremental/krate_reassign_34991/main.rs b/tests/incremental/krate_reassign_34991/main.rs new file mode 100644 index 000000000..c4ae19ac9 --- /dev/null +++ b/tests/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/tests/incremental/link_order/auxiliary/my_lib.rs b/tests/incremental/link_order/auxiliary/my_lib.rs new file mode 100644 index 000000000..1e7d82305 --- /dev/null +++ b/tests/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/tests/incremental/link_order/main.rs b/tests/incremental/link_order/main.rs new file mode 100644 index 000000000..d211c295b --- /dev/null +++ b/tests/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/tests/incremental/lto-in-linker.rs b/tests/incremental/lto-in-linker.rs new file mode 100644 index 000000000..0e8c1ebb9 --- /dev/null +++ b/tests/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/tests/incremental/lto.rs b/tests/incremental/lto.rs new file mode 100644 index 000000000..2a3e3c246 --- /dev/null +++ b/tests/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/tests/incremental/macro_export.rs b/tests/incremental/macro_export.rs new file mode 100644 index 000000000..044d63fd2 --- /dev/null +++ b/tests/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/tests/incremental/mir-opt.rs b/tests/incremental/mir-opt.rs new file mode 100644 index 000000000..5bd863439 --- /dev/null +++ b/tests/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/tests/incremental/no_mangle.rs b/tests/incremental/no_mangle.rs new file mode 100644 index 000000000..b1c9b2bc3 --- /dev/null +++ b/tests/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/tests/incremental/remapped_paths_cc/auxiliary/extern_crate.rs b/tests/incremental/remapped_paths_cc/auxiliary/extern_crate.rs new file mode 100644 index 000000000..627b99445 --- /dev/null +++ b/tests/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/tests/incremental/remapped_paths_cc/main.rs b/tests/incremental/remapped_paths_cc/main.rs new file mode 100644 index 000000000..b01f02444 --- /dev/null +++ b/tests/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/tests/incremental/remove-private-item-cross-crate/auxiliary/a.rs b/tests/incremental/remove-private-item-cross-crate/auxiliary/a.rs new file mode 100644 index 000000000..279a6f078 --- /dev/null +++ b/tests/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/tests/incremental/remove-private-item-cross-crate/main.rs b/tests/incremental/remove-private-item-cross-crate/main.rs new file mode 100644 index 000000000..c831ab6fe --- /dev/null +++ b/tests/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/tests/incremental/remove_crate/auxiliary/extern_crate.rs b/tests/incremental/remove_crate/auxiliary/extern_crate.rs new file mode 100644 index 000000000..1cafdf49d --- /dev/null +++ b/tests/incremental/remove_crate/auxiliary/extern_crate.rs @@ -0,0 +1,3 @@ +pub fn foo(_: u8) { + +} diff --git a/tests/incremental/remove_crate/main.rs b/tests/incremental/remove_crate/main.rs new file mode 100644 index 000000000..14b80df0d --- /dev/null +++ b/tests/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/tests/incremental/remove_source_file/auxiliary/mod.rs b/tests/incremental/remove_source_file/auxiliary/mod.rs new file mode 100644 index 000000000..96a366d96 --- /dev/null +++ b/tests/incremental/remove_source_file/auxiliary/mod.rs @@ -0,0 +1,3 @@ +pub fn print_hello() { + println!("hello"); +} diff --git a/tests/incremental/remove_source_file/main.rs b/tests/incremental/remove_source_file/main.rs new file mode 100644 index 000000000..b2411c094 --- /dev/null +++ b/tests/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/tests/incremental/reorder_vtable.rs b/tests/incremental/reorder_vtable.rs new file mode 100644 index 000000000..8dacba633 --- /dev/null +++ b/tests/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/tests/incremental/rlib-lto.rs b/tests/incremental/rlib-lto.rs new file mode 100644 index 000000000..752fee5a0 --- /dev/null +++ b/tests/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/tests/incremental/rlib_cross_crate/auxiliary/a.rs b/tests/incremental/rlib_cross_crate/auxiliary/a.rs new file mode 100644 index 000000000..5a26df9ae --- /dev/null +++ b/tests/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/tests/incremental/rlib_cross_crate/b.rs b/tests/incremental/rlib_cross_crate/b.rs new file mode 100644 index 000000000..639cfc918 --- /dev/null +++ b/tests/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/tests/incremental/rustc-rust-log.rs b/tests/incremental/rustc-rust-log.rs new file mode 100644 index 000000000..566f0d96d --- /dev/null +++ b/tests/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/tests/incremental/source_loc_macros.rs b/tests/incremental/source_loc_macros.rs new file mode 100644 index 000000000..e5f04e5dc --- /dev/null +++ b/tests/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/tests/incremental/span_hash_stable/auxiliary/mod.rs b/tests/incremental/span_hash_stable/auxiliary/mod.rs new file mode 100644 index 000000000..f3824db4c --- /dev/null +++ b/tests/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/tests/incremental/span_hash_stable/auxiliary/sub1.rs b/tests/incremental/span_hash_stable/auxiliary/sub1.rs new file mode 100644 index 000000000..70e2ea06b --- /dev/null +++ b/tests/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/tests/incremental/span_hash_stable/auxiliary/sub2.rs b/tests/incremental/span_hash_stable/auxiliary/sub2.rs new file mode 100644 index 000000000..1167cdb0a --- /dev/null +++ b/tests/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/tests/incremental/span_hash_stable/main.rs b/tests/incremental/span_hash_stable/main.rs new file mode 100644 index 000000000..367416430 --- /dev/null +++ b/tests/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/tests/incremental/spans_in_type_debuginfo.rs b/tests/incremental/spans_in_type_debuginfo.rs new file mode 100644 index 000000000..f5cae15a4 --- /dev/null +++ b/tests/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/tests/incremental/spans_significant_w_debuginfo.rs b/tests/incremental/spans_significant_w_debuginfo.rs new file mode 100644 index 000000000..38ab28461 --- /dev/null +++ b/tests/incremental/spans_significant_w_debuginfo.rs @@ -0,0 +1,17 @@ +// 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 + +// ignore-asmjs wasm2js does not support source maps yet +// compile-flags: -g -Z query-dep-graph + +#![feature(rustc_attrs)] +#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")] + +#[cfg(rpass1)] +pub fn main() {} + +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] +pub fn main() {} diff --git a/tests/incremental/spans_significant_w_panic.rs b/tests/incremental/spans_significant_w_panic.rs new file mode 100644 index 000000000..085e4cd78 --- /dev/null +++ b/tests/incremental/spans_significant_w_panic.rs @@ -0,0 +1,24 @@ +// 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 + +// compile-flags: -C overflow-checks=on -Z query-dep-graph + +#![feature(rustc_attrs)] +#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")] + +#[cfg(rpass1)] +pub fn main() { + if std::hint::black_box(false) { + panic!() + } +} + +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] +pub fn main() { + if std::hint::black_box(false) { + panic!() + } +} diff --git a/tests/incremental/spike-neg1.rs b/tests/incremental/spike-neg1.rs new file mode 100644 index 000000000..97812ffe3 --- /dev/null +++ b/tests/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/tests/incremental/spike-neg2.rs b/tests/incremental/spike-neg2.rs new file mode 100644 index 000000000..3bb1914fd --- /dev/null +++ b/tests/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/tests/incremental/spike.rs b/tests/incremental/spike.rs new file mode 100644 index 000000000..a6a05e7c3 --- /dev/null +++ b/tests/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/tests/incremental/split_debuginfo_cached.rs b/tests/incremental/split_debuginfo_cached.rs new file mode 100644 index 000000000..ba8385f89 --- /dev/null +++ b/tests/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 -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split +// [rpass2]compile-flags: -g -Zquery-dep-graph -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/tests/incremental/split_debuginfo_mode.rs b/tests/incremental/split_debuginfo_mode.rs new file mode 100644 index 000000000..edc1a80d3 --- /dev/null +++ b/tests/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 -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass2]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on +// [rpass3]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on +// [rpass4]compile-flags: -Zquery-dep-graph -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/tests/incremental/static_cycle/b.rs b/tests/incremental/static_cycle/b.rs new file mode 100644 index 000000000..064213fba --- /dev/null +++ b/tests/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/tests/incremental/static_refering_to_other_static/issue-49081.rs b/tests/incremental/static_refering_to_other_static/issue-49081.rs new file mode 100644 index 000000000..8e3715d1d --- /dev/null +++ b/tests/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/tests/incremental/static_refering_to_other_static2/issue.rs b/tests/incremental/static_refering_to_other_static2/issue.rs new file mode 100644 index 000000000..720bb1e22 --- /dev/null +++ b/tests/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/tests/incremental/static_refering_to_other_static3/issue.rs b/tests/incremental/static_refering_to_other_static3/issue.rs new file mode 100644 index 000000000..80999813d --- /dev/null +++ b/tests/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/tests/incremental/static_stable_hash/issue-49301.rs b/tests/incremental/static_stable_hash/issue-49301.rs new file mode 100644 index 000000000..fdd05c72c --- /dev/null +++ b/tests/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/tests/incremental/string_constant.rs b/tests/incremental/string_constant.rs new file mode 100644 index 000000000..e15a8d18f --- /dev/null +++ b/tests/incremental/string_constant.rs @@ -0,0 +1,42 @@ +// revisions: cfail1 cfail2 +// compile-flags: -Z query-dep-graph +// 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(cfail1)] + pub fn x() { + println!("{}", "1"); + } + + #[cfg(cfail2)] + #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail2")] + pub fn x() { + println!("{}", "2"); + } +} + +pub mod y { + use x; + + #[rustc_clean(cfg = "cfail2")] + pub fn y() { + x::x(); + } +} + +pub mod z { + use y; + + #[rustc_clean(cfg = "cfail2")] + pub fn z() { + y::y(); + } +} diff --git a/tests/incremental/struct_add_field.rs b/tests/incremental/struct_add_field.rs new file mode 100644 index 000000000..720854f16 --- /dev/null +++ b/tests/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/tests/incremental/struct_change_field_name.rs b/tests/incremental/struct_change_field_name.rs new file mode 100644 index 000000000..a7c79e9d7 --- /dev/null +++ b/tests/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/tests/incremental/struct_change_field_type.rs b/tests/incremental/struct_change_field_type.rs new file mode 100644 index 000000000..37d2fba99 --- /dev/null +++ b/tests/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/tests/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs b/tests/incremental/struct_change_field_type_cross_crate/auxiliary/a.rs new file mode 100644 index 000000000..d3ddb32c3 --- /dev/null +++ b/tests/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/tests/incremental/struct_change_field_type_cross_crate/b.rs b/tests/incremental/struct_change_field_type_cross_crate/b.rs new file mode 100644 index 000000000..c78207bcb --- /dev/null +++ b/tests/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/tests/incremental/struct_change_nothing.rs b/tests/incremental/struct_change_nothing.rs new file mode 100644 index 000000000..de30c818c --- /dev/null +++ b/tests/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/tests/incremental/struct_remove_field.rs b/tests/incremental/struct_remove_field.rs new file mode 100644 index 000000000..b97a87e09 --- /dev/null +++ b/tests/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/tests/incremental/thinlto/cgu_invalidated_via_import.rs b/tests/incremental/thinlto/cgu_invalidated_via_import.rs new file mode 100644 index 000000000..5fe435d79 --- /dev/null +++ b/tests/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/tests/incremental/thinlto/cgu_invalidated_when_export_added.rs b/tests/incremental/thinlto/cgu_invalidated_when_export_added.rs new file mode 100644 index 000000000..95f3b8ae4 --- /dev/null +++ b/tests/incremental/thinlto/cgu_invalidated_when_export_added.rs @@ -0,0 +1,26 @@ +// revisions: cfail1 cfail2 +// build-pass + +// rust-lang/rust#69798: +// +// This is analogous 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/tests/incremental/thinlto/cgu_invalidated_when_export_removed.rs b/tests/incremental/thinlto/cgu_invalidated_when_export_removed.rs new file mode 100644 index 000000000..e86ebd354 --- /dev/null +++ b/tests/incremental/thinlto/cgu_invalidated_when_export_removed.rs @@ -0,0 +1,26 @@ +// revisions: cfail1 cfail2 +// build-pass + +// rust-lang/rust#69798: +// +// This is analogous 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/tests/incremental/thinlto/cgu_invalidated_when_import_added.rs b/tests/incremental/thinlto/cgu_invalidated_when_import_added.rs new file mode 100644 index 000000000..9c17c8745 --- /dev/null +++ b/tests/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/tests/incremental/thinlto/cgu_invalidated_when_import_removed.rs b/tests/incremental/thinlto/cgu_invalidated_when_import_removed.rs new file mode 100644 index 000000000..fc53acf75 --- /dev/null +++ b/tests/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/tests/incremental/thinlto/cgu_keeps_identical_fn.rs b/tests/incremental/thinlto/cgu_keeps_identical_fn.rs new file mode 100644 index 000000000..368a726ea --- /dev/null +++ b/tests/incremental/thinlto/cgu_keeps_identical_fn.rs @@ -0,0 +1,49 @@ +// 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 +// 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-bar", + cfg = "cfail2", + kind = "post-lto" +)] +#![rustc_expected_cgu_reuse( + module = "cgu_keeps_identical_fn-bar", + cfg = "cfail3", + 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/tests/incremental/thinlto/independent_cgus_dont_affect_each_other.rs b/tests/incremental/thinlto/independent_cgus_dont_affect_each_other.rs new file mode 100644 index 000000000..045f20119 --- /dev/null +++ b/tests/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/tests/incremental/type_alias_cross_crate/auxiliary/a.rs b/tests/incremental/type_alias_cross_crate/auxiliary/a.rs new file mode 100644 index 000000000..61fe297d7 --- /dev/null +++ b/tests/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/tests/incremental/type_alias_cross_crate/b.rs b/tests/incremental/type_alias_cross_crate/b.rs new file mode 100644 index 000000000..f6c252684 --- /dev/null +++ b/tests/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/tests/incremental/unchecked_dirty_clean.rs b/tests/incremental/unchecked_dirty_clean.rs new file mode 100644 index 000000000..3c8692a30 --- /dev/null +++ b/tests/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/tests/incremental/warnings-reemitted.rs b/tests/incremental/warnings-reemitted.rs new file mode 100644 index 000000000..0e6b88232 --- /dev/null +++ b/tests/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 +} |