diff options
Diffstat (limited to 'tests/codegen-units')
50 files changed, 2518 insertions, 0 deletions
diff --git a/tests/codegen-units/item-collection/asm-sym.rs b/tests/codegen-units/item-collection/asm-sym.rs new file mode 100644 index 000000000..8bafb95bc --- /dev/null +++ b/tests/codegen-units/item-collection/asm-sym.rs @@ -0,0 +1,20 @@ +// needs-asm-support +// compile-flags: -Ccodegen-units=1 -Zprint-mono-items=lazy --crate-type=lib + +#[inline(always)] +pub unsafe fn f() { + //~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External] + static S: usize = 1; + //~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External] + fn fun() {} + core::arch::asm!("/* {0} {1} */", sym S, sym fun); +} + +//~ MONO_ITEM fn g @@ asm_sym-cgu.0[External] +pub unsafe fn g() { + //~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal] + static S: usize = 2; + //~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal] + fn fun() {} + core::arch::asm!("/* {0} {1} */", sym S, sym fun); +} diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs new file mode 100644 index 000000000..ecea26dc4 --- /dev/null +++ b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs @@ -0,0 +1,24 @@ +#![crate_type = "lib"] + +pub trait Trait : Sized { + fn without_self() -> u32; + fn without_self_default() -> u32 { 0 } + + fn with_default_impl(self) -> Self { self } + fn with_default_impl_generic<T>(self, x: T) -> (Self, T) { (self, x) } + + fn without_default_impl(x: u32) -> (Self, u32); + fn without_default_impl_generic<T>(x: T) -> (Self, T); +} + +impl Trait for char { + fn without_self() -> u32 { 2 } + fn without_default_impl(x: u32) -> (Self, u32) { ('c', x) } + fn without_default_impl_generic<T>(x: T) -> (Self, T) { ('c', x) } +} + +impl Trait for u32 { + fn without_self() -> u32 { 1 } + fn without_default_impl(x: u32) -> (Self, u32) { (0, x) } + fn without_default_impl_generic<T>(x: T) -> (Self, T) { (0, x) } +} diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs new file mode 100644 index 000000000..05ea0a89f --- /dev/null +++ b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs @@ -0,0 +1,23 @@ +#![crate_type = "lib"] + +#[inline] +pub fn inlined_fn(x: i32, y: i32) -> i32 { + + let closure = |a, b| { a + b }; + + closure(x, y) +} + +pub fn inlined_fn_generic<T>(x: i32, y: i32, z: T) -> (i32, T) { + + let closure = |a, b| { a + b }; + + (closure(x, y), z) +} + +pub fn non_inlined_fn(x: i32, y: i32) -> i32 { + + let closure = |a, b| { a + b }; + + closure(x, y) +} diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_generic_function.rs b/tests/codegen-units/item-collection/auxiliary/cgu_generic_function.rs new file mode 100644 index 000000000..3926f2957 --- /dev/null +++ b/tests/codegen-units/item-collection/auxiliary/cgu_generic_function.rs @@ -0,0 +1,26 @@ +#![crate_type = "lib"] + +struct Struct(u32); + +#[inline(never)] +pub fn foo<T>(x: T) -> (T, u32, i8) { + let (x, Struct(y)) = bar(x); + (x, y, 2) +} + +#[inline(never)] +fn bar<T>(x: T) -> (T, Struct) { + let _ = not_exported_and_not_generic(0); + (x, Struct(1)) +} + +// These should not contribute to the codegen items of other crates. +#[inline(never)] +pub fn exported_but_not_generic(x: i32) -> i64 { + x as i64 +} + +#[inline(never)] +fn not_exported_and_not_generic(x: u32) -> u64 { + x as u64 +} diff --git a/tests/codegen-units/item-collection/cross-crate-closures.rs b/tests/codegen-units/item-collection/cross-crate-closures.rs new file mode 100644 index 000000000..6af344fab --- /dev/null +++ b/tests/codegen-units/item-collection/cross-crate-closures.rs @@ -0,0 +1,33 @@ +// In the current version of the collector that still has to support +// legacy-codegen, closures do not generate their own MonoItems, so we are +// ignoring this test until MIR codegen has taken over completely +// ignore-test + +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +// aux-build:cgu_extern_closures.rs +extern crate cgu_extern_closures; + +//~ MONO_ITEM fn cross_crate_closures::start[0] +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0] + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[0] + let _ = cgu_extern_closures::inlined_fn(1, 2); + + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0]<i32> + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0]::{{closure}}[0]<i32> + let _ = cgu_extern_closures::inlined_fn_generic(3, 4, 5i32); + + // Nothing should be generated for this call, we just link to the instance + // in the extern crate. + let _ = cgu_extern_closures::non_inlined_fn(6, 7); + + 0 +} + +//~ MONO_ITEM drop-glue i8 diff --git a/tests/codegen-units/item-collection/cross-crate-generic-functions.rs b/tests/codegen-units/item-collection/cross-crate-generic-functions.rs new file mode 100644 index 000000000..7289ceee9 --- /dev/null +++ b/tests/codegen-units/item-collection/cross-crate-generic-functions.rs @@ -0,0 +1,24 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +// aux-build:cgu_generic_function.rs +extern crate cgu_generic_function; + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn cgu_generic_function::bar::<u32> + //~ MONO_ITEM fn cgu_generic_function::foo::<u32> + let _ = cgu_generic_function::foo(1u32); + + //~ MONO_ITEM fn cgu_generic_function::bar::<u64> + //~ MONO_ITEM fn cgu_generic_function::foo::<u64> + let _ = cgu_generic_function::foo(2u64); + + // This should not introduce a codegen item + let _ = cgu_generic_function::exported_but_not_generic(3); + + 0 +} diff --git a/tests/codegen-units/item-collection/cross-crate-trait-method.rs b/tests/codegen-units/item-collection/cross-crate-trait-method.rs new file mode 100644 index 000000000..dc0984c8a --- /dev/null +++ b/tests/codegen-units/item-collection/cross-crate-trait-method.rs @@ -0,0 +1,50 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +// aux-build:cgu_export_trait_method.rs +extern crate cgu_export_trait_method; + +use cgu_export_trait_method::Trait; + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + // The object code of these methods is contained in the external crate, so + // calling them should *not* introduce codegen items in the current crate. + let _: (u32, u32) = Trait::without_default_impl(0); + let _: (char, u32) = Trait::without_default_impl(0); + + // Currently, no object code is generated for trait methods with default + // implementations, unless they are actually called from somewhere. Therefore + // we cannot import the implementations and have to create our own inline. + //~ MONO_ITEM fn <u32 as cgu_export_trait_method::Trait>::with_default_impl + let _ = Trait::with_default_impl(0u32); + //~ MONO_ITEM fn <char as cgu_export_trait_method::Trait>::with_default_impl + let _ = Trait::with_default_impl('c'); + + + + //~ MONO_ITEM fn <u32 as cgu_export_trait_method::Trait>::with_default_impl_generic::<&str> + let _ = Trait::with_default_impl_generic(0u32, "abc"); + //~ MONO_ITEM fn <u32 as cgu_export_trait_method::Trait>::with_default_impl_generic::<bool> + let _ = Trait::with_default_impl_generic(0u32, false); + + //~ MONO_ITEM fn <char as cgu_export_trait_method::Trait>::with_default_impl_generic::<i16> + let _ = Trait::with_default_impl_generic('x', 1i16); + //~ MONO_ITEM fn <char as cgu_export_trait_method::Trait>::with_default_impl_generic::<i32> + let _ = Trait::with_default_impl_generic('y', 0i32); + + //~ MONO_ITEM fn <u32 as cgu_export_trait_method::Trait>::without_default_impl_generic::<char> + let _: (u32, char) = Trait::without_default_impl_generic('c'); + //~ MONO_ITEM fn <u32 as cgu_export_trait_method::Trait>::without_default_impl_generic::<bool> + let _: (u32, bool) = Trait::without_default_impl_generic(false); + + //~ MONO_ITEM fn <char as cgu_export_trait_method::Trait>::without_default_impl_generic::<char> + let _: (char, char) = Trait::without_default_impl_generic('c'); + //~ MONO_ITEM fn <char as cgu_export_trait_method::Trait>::without_default_impl_generic::<bool> + let _: (char, bool) = Trait::without_default_impl_generic(false); + + 0 +} diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs new file mode 100644 index 000000000..a3f1fb5e7 --- /dev/null +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -0,0 +1,36 @@ +// +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus + +#![feature(start)] + +//~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDtor> - shim(Some(StructWithDtor)) @@ drop_in_place_intrinsic-cgu.0[Internal] +struct StructWithDtor(u32); + +impl Drop for StructWithDtor { + //~ MONO_ITEM fn <StructWithDtor as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + + //~ MONO_ITEM fn std::ptr::drop_in_place::<[StructWithDtor; 2]> - shim(Some([StructWithDtor; 2])) @@ drop_in_place_intrinsic-cgu.0[Internal] + let x = [StructWithDtor(0), StructWithDtor(1)]; + + drop_slice_in_place(&x); + + 0 +} + +//~ MONO_ITEM fn drop_slice_in_place +fn drop_slice_in_place(x: &[StructWithDtor]) { + unsafe { + // This is the interesting thing in this test case: Normally we would + // not have drop-glue for the unsized [StructWithDtor]. This has to be + // generated though when the drop_in_place() intrinsic is used. + //~ MONO_ITEM fn std::ptr::drop_in_place::<[StructWithDtor]> - shim(Some([StructWithDtor])) @@ drop_in_place_intrinsic-cgu.0[Internal] + ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); + } +} diff --git a/tests/codegen-units/item-collection/function-as-argument.rs b/tests/codegen-units/item-collection/function-as-argument.rs new file mode 100644 index 000000000..ea500c311 --- /dev/null +++ b/tests/codegen-units/item-collection/function-as-argument.rs @@ -0,0 +1,40 @@ +// +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) { + (f)(x, y) +} + +fn function<T1, T2>(_: T1, _: T2) {} + +fn take_fn_pointer<T1, T2>(f: fn(T1, T2), x: T1, y: T2) { + (f)(x, y) +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + + //~ MONO_ITEM fn take_fn_once::<u32, &str, fn(u32, &str) {function::<u32, &str>}> + //~ MONO_ITEM fn function::<u32, &str> + //~ MONO_ITEM fn <fn(u32, &str) {function::<u32, &str>} as std::ops::FnOnce<(u32, &str)>>::call_once - shim(fn(u32, &str) {function::<u32, &str>}) + take_fn_once(function, 0u32, "abc"); + + //~ MONO_ITEM fn take_fn_once::<char, f64, fn(char, f64) {function::<char, f64>}> + //~ MONO_ITEM fn function::<char, f64> + //~ MONO_ITEM fn <fn(char, f64) {function::<char, f64>} as std::ops::FnOnce<(char, f64)>>::call_once - shim(fn(char, f64) {function::<char, f64>}) + take_fn_once(function, 'c', 0f64); + + //~ MONO_ITEM fn take_fn_pointer::<i32, ()> + //~ MONO_ITEM fn function::<i32, ()> + take_fn_pointer(function, 0i32, ()); + + //~ MONO_ITEM fn take_fn_pointer::<f32, i64> + //~ MONO_ITEM fn function::<f32, i64> + take_fn_pointer(function, 0f32, 0i64); + + 0 +} diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs new file mode 100644 index 000000000..6df4ff7e5 --- /dev/null +++ b/tests/codegen-units/item-collection/generic-drop-glue.rs @@ -0,0 +1,91 @@ +// +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus + +#![deny(dead_code)] +#![feature(start)] + +struct StructWithDrop<T1, T2> { + x: T1, + y: T2, +} + +impl<T1, T2> Drop for StructWithDrop<T1, T2> { + fn drop(&mut self) {} +} + +struct StructNoDrop<T1, T2> { + x: T1, + y: T2, +} + +enum EnumWithDrop<T1, T2> { + A(T1), + B(T2) +} + +impl<T1, T2> Drop for EnumWithDrop<T1, T2> { + fn drop(&mut self) {} +} + +enum EnumNoDrop<T1, T2> { + A(T1), + B(T2) +} + + +struct NonGenericNoDrop(#[allow(unused_tuple_struct_fields)] i32); + +struct NonGenericWithDrop(#[allow(unused_tuple_struct_fields)] i32); +//~ MONO_ITEM fn std::ptr::drop_in_place::<NonGenericWithDrop> - shim(Some(NonGenericWithDrop)) @@ generic_drop_glue-cgu.0[Internal] + +impl Drop for NonGenericWithDrop { + //~ MONO_ITEM fn <NonGenericWithDrop as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDrop<i8, char>> - shim(Some(StructWithDrop<i8, char>)) @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <StructWithDrop<i8, char> as std::ops::Drop>::drop + let _ = StructWithDrop { x: 0i8, y: 'a' }.x; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDrop<&str, NonGenericNoDrop>> - shim(Some(StructWithDrop<&str, NonGenericNoDrop>)) @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <StructWithDrop<&str, NonGenericNoDrop> as std::ops::Drop>::drop + let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; + + // Should produce no drop glue + let _ = StructNoDrop { x: 'a', y: 0u32 }.x; + + // This is supposed to generate drop-glue because it contains a field that + // needs to be dropped. + //~ MONO_ITEM fn std::ptr::drop_in_place::<StructNoDrop<NonGenericWithDrop, f64>> - shim(Some(StructNoDrop<NonGenericWithDrop, f64>)) @@ generic_drop_glue-cgu.0[Internal] + let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<EnumWithDrop<i32, i64>> - shim(Some(EnumWithDrop<i32, i64>)) @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <EnumWithDrop<i32, i64> as std::ops::Drop>::drop + let _ = match EnumWithDrop::A::<i32, i64>(0) { + EnumWithDrop::A(x) => x, + EnumWithDrop::B(x) => x as i32 + }; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<EnumWithDrop<f64, f32>> - shim(Some(EnumWithDrop<f64, f32>)) @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <EnumWithDrop<f64, f32> as std::ops::Drop>::drop + let _ = match EnumWithDrop::B::<f64, f32>(1.0) { + EnumWithDrop::A(x) => x, + EnumWithDrop::B(x) => x as f64 + }; + + let _ = match EnumNoDrop::A::<i32, i64>(0) { + EnumNoDrop::A(x) => x, + EnumNoDrop::B(x) => x as i32 + }; + + let _ = match EnumNoDrop::B::<f64, f32>(1.0) { + EnumNoDrop::A(x) => x, + EnumNoDrop::B(x) => x as f64 + }; + + 0 +} diff --git a/tests/codegen-units/item-collection/generic-functions.rs b/tests/codegen-units/item-collection/generic-functions.rs new file mode 100644 index 000000000..04383bb8e --- /dev/null +++ b/tests/codegen-units/item-collection/generic-functions.rs @@ -0,0 +1,55 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +fn foo1<T1>(a: T1) -> (T1, u32) { + (a, 1) +} + +fn foo2<T1, T2>(a: T1, b: T2) -> (T1, T2) { + (a, b) +} + +fn foo3<T1, T2, T3>(a: T1, b: T2, c: T3) -> (T1, T2, T3) { + (a, b, c) +} + +// This function should be instantiated even if no used +//~ MONO_ITEM fn lifetime_only +pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 { + a +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn foo1::<i32> + let _ = foo1(2i32); + //~ MONO_ITEM fn foo1::<i64> + let _ = foo1(2i64); + //~ MONO_ITEM fn foo1::<&str> + let _ = foo1("abc"); + //~ MONO_ITEM fn foo1::<char> + let _ = foo1('v'); + + //~ MONO_ITEM fn foo2::<i32, i32> + let _ = foo2(2i32, 2i32); + //~ MONO_ITEM fn foo2::<i64, &str> + let _ = foo2(2i64, "abc"); + //~ MONO_ITEM fn foo2::<&str, usize> + let _ = foo2("a", 2usize); + //~ MONO_ITEM fn foo2::<char, ()> + let _ = foo2('v', ()); + + //~ MONO_ITEM fn foo3::<i32, i32, i32> + let _ = foo3(2i32, 2i32, 2i32); + //~ MONO_ITEM fn foo3::<i64, &str, char> + let _ = foo3(2i64, "abc", 'c'); + //~ MONO_ITEM fn foo3::<i16, &str, usize> + let _ = foo3(0i16, "a", 2usize); + //~ MONO_ITEM fn foo3::<char, (), ()> + let _ = foo3('v', (), ()); + + 0 +} diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs new file mode 100644 index 000000000..4260230c2 --- /dev/null +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -0,0 +1,71 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +struct Struct<T> { + x: T, + f: fn(x: T) -> T, +} + +fn id<T>(x: T) -> T { x } + +impl<T> Struct<T> { + + fn new(x: T) -> Struct<T> { + Struct { + x: x, + f: id + } + } + + fn get<T2>(self, x: T2) -> (T, T2) { + (self.x, x) + } +} + +pub struct LifeTimeOnly<'a> { + _a: &'a u32 +} + +impl<'a> LifeTimeOnly<'a> { + + //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo + pub fn foo(&self) {} + //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar + pub fn bar(&'a self) {} + //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz + pub fn baz<'b>(&'b self) {} + + pub fn non_instantiated<T>(&self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn Struct::<i32>::new + //~ MONO_ITEM fn id::<i32> + //~ MONO_ITEM fn Struct::<i32>::get::<i16> + let _ = Struct::new(0i32).get(0i16); + + //~ MONO_ITEM fn Struct::<i64>::new + //~ MONO_ITEM fn id::<i64> + //~ MONO_ITEM fn Struct::<i64>::get::<i16> + let _ = Struct::new(0i64).get(0i16); + + //~ MONO_ITEM fn Struct::<char>::new + //~ MONO_ITEM fn id::<char> + //~ MONO_ITEM fn Struct::<char>::get::<i16> + let _ = Struct::new('c').get(0i16); + + //~ MONO_ITEM fn Struct::<&str>::new + //~ MONO_ITEM fn id::<&str> + //~ MONO_ITEM fn Struct::<Struct<&str>>::get::<i16> + let _ = Struct::new(Struct::new("str")).get(0i16); + + //~ MONO_ITEM fn Struct::<Struct<&str>>::new + //~ MONO_ITEM fn id::<Struct<&str>> + let _ = (Struct::new(Struct::new("str")).f)(Struct::new("str")); + + 0 +} diff --git a/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs b/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs new file mode 100644 index 000000000..c01398eb2 --- /dev/null +++ b/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs @@ -0,0 +1,27 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +trait SomeTrait { + fn foo(&self); +} + +// This function is never instantiated but the contained impl must still be +// discovered. +pub fn generic_function<T>(x: T) -> (T, i32) { + impl SomeTrait for i64 { + //~ MONO_ITEM fn generic_function::<impl SomeTrait for i64>::foo + fn foo(&self) {} + } + + (x, 0) +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 0i64.foo(); + + 0 +} diff --git a/tests/codegen-units/item-collection/implicit-panic-call.rs b/tests/codegen-units/item-collection/implicit-panic-call.rs new file mode 100644 index 000000000..abec7ad50 --- /dev/null +++ b/tests/codegen-units/item-collection/implicit-panic-call.rs @@ -0,0 +1,58 @@ +// compile-flags:-Zprint-mono-items=lazy + +// rust-lang/rust#90405 +// Ensure implicit panic calls are collected + +#![feature(lang_items)] +#![feature(no_core)] +#![crate_type = "lib"] +#![no_core] +#![no_std] + +#[lang = "panic_location"] +struct Location<'a> { + _file: &'a str, + _line: u32, + _col: u32, +} + +#[lang = "panic"] +#[inline] +#[track_caller] +fn panic(_: &'static str) -> ! { + loop {} +} + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "freeze"] +trait Freeze {} + +impl Copy for i32 {} + +#[lang = "div"] +trait Div<Rhs = Self> { + type Output; + fn div(self, rhs: Rhs) -> Self::Output; +} + +impl Div for i32 { + type Output = i32; + fn div(self, rhs: i32) -> i32 { + self / rhs + } +} + +#[allow(unconditional_panic)] +pub fn foo() { + // This implicitly generates a panic call. + let _ = 1 / 0; +} + +//~ MONO_ITEM fn foo +//~ MONO_ITEM fn <i32 as Div>::div +//~ MONO_ITEM fn panic diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs new file mode 100644 index 000000000..e78226d40 --- /dev/null +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -0,0 +1,38 @@ +// +// compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0 + +#![deny(dead_code)] +#![feature(start)] + +trait Trait { + fn foo(&self) -> u32; + fn bar(&self); +} + +struct Struct<T> { + _a: T +} + +impl<T> Trait for Struct<T> { + fn foo(&self) -> u32 { 0 } + fn bar(&self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let s1 = Struct { _a: 0u32 }; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u32>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn <Struct<u32> as Trait>::foo + //~ MONO_ITEM fn <Struct<u32> as Trait>::bar + let _ = &s1 as &Trait; + + let s1 = Struct { _a: 0u64 }; + //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u64>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn <Struct<u64> as Trait>::foo + //~ MONO_ITEM fn <Struct<u64> as Trait>::bar + let _ = &s1 as &Trait; + + 0 +} diff --git a/tests/codegen-units/item-collection/items-within-generic-items.rs b/tests/codegen-units/item-collection/items-within-generic-items.rs new file mode 100644 index 000000000..d37d7f7d9 --- /dev/null +++ b/tests/codegen-units/item-collection/items-within-generic-items.rs @@ -0,0 +1,35 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +fn generic_fn<T>(a: T) -> (T, i32) { + //~ MONO_ITEM fn generic_fn::nested_fn + fn nested_fn(a: i32) -> i32 { + a + 1 + } + + let x = { + //~ MONO_ITEM fn generic_fn::nested_fn + fn nested_fn(a: i32) -> i32 { + a + 2 + } + + 1 + nested_fn(1) + }; + + return (a, x + nested_fn(0)); +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn generic_fn::<i64> + let _ = generic_fn(0i64); + //~ MONO_ITEM fn generic_fn::<u16> + let _ = generic_fn(0u16); + //~ MONO_ITEM fn generic_fn::<i8> + let _ = generic_fn(0i8); + + 0 +} diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs new file mode 100644 index 000000000..379fbcf26 --- /dev/null +++ b/tests/codegen-units/item-collection/non-generic-closures.rs @@ -0,0 +1,60 @@ +// In the current version of the collector that still has to support +// legacy-codegen, closures do not generate their own MonoItems, so we are +// ignoring this test until MIR codegen has taken over completely +// ignore-test + +// +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +//~ MONO_ITEM fn non_generic_closures::temporary[0] +fn temporary() { + //~ MONO_ITEM fn non_generic_closures::temporary[0]::{{closure}}[0] + (|a: u32| { + let _ = a; + })(4); +} + +//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0] +fn assigned_to_variable_but_not_executed() { + //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]::{{closure}}[0] + let _x = |a: i16| { + let _ = a + 1; + }; +} + +//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0] +fn assigned_to_variable_executed_indirectly() { + //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]::{{closure}}[0] + let f = |a: i32| { + let _ = a + 2; + }; + run_closure(&f); +} + +//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0] +fn assigned_to_variable_executed_directly() { + //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]::{{closure}}[0] + let f = |a: i64| { + let _ = a + 3; + }; + f(4); +} + +//~ MONO_ITEM fn non_generic_closures::start[0] +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + temporary(); + assigned_to_variable_but_not_executed(); + assigned_to_variable_executed_directly(); + assigned_to_variable_executed_indirectly(); + + 0 +} + +//~ MONO_ITEM fn non_generic_closures::run_closure[0] +fn run_closure(f: &Fn(i32)) { + f(3); +} diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs new file mode 100644 index 000000000..06f76f7db --- /dev/null +++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs @@ -0,0 +1,49 @@ +// +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus + +#![deny(dead_code)] +#![feature(start)] + +//~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDrop> - shim(Some(StructWithDrop)) @@ non_generic_drop_glue-cgu.0[Internal] +struct StructWithDrop { + x: i32 +} + +impl Drop for StructWithDrop { + //~ MONO_ITEM fn <StructWithDrop as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +struct StructNoDrop { + x: i32 +} + +//~ MONO_ITEM fn std::ptr::drop_in_place::<EnumWithDrop> - shim(Some(EnumWithDrop)) @@ non_generic_drop_glue-cgu.0[Internal] +enum EnumWithDrop { + A(i32) +} + +impl Drop for EnumWithDrop { + //~ MONO_ITEM fn <EnumWithDrop as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +enum EnumNoDrop { + A(i32) +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _ = StructWithDrop { x: 0 }.x; + let _ = StructNoDrop { x: 0 }.x; + let _ = match EnumWithDrop::A(0) { + EnumWithDrop::A(x) => x + }; + let _ = match EnumNoDrop::A(0) { + EnumNoDrop::A(x) => x + }; + + 0 +} diff --git a/tests/codegen-units/item-collection/non-generic-functions.rs b/tests/codegen-units/item-collection/non-generic-functions.rs new file mode 100644 index 000000000..092e64562 --- /dev/null +++ b/tests/codegen-units/item-collection/non-generic-functions.rs @@ -0,0 +1,72 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +//~ MONO_ITEM fn foo +fn foo() { + { + //~ MONO_ITEM fn foo::foo + fn foo() {} + foo(); + } + + { + //~ MONO_ITEM fn foo::foo + fn foo() {} + foo(); + } +} + +//~ MONO_ITEM fn bar +fn bar() { + //~ MONO_ITEM fn bar::baz + fn baz() {} + baz(); +} + +struct Struct { _x: i32 } + +impl Struct { + //~ MONO_ITEM fn Struct::foo + fn foo() { + { + //~ MONO_ITEM fn Struct::foo::foo + fn foo() {} + foo(); + } + + { + //~ MONO_ITEM fn Struct::foo::foo + fn foo() {} + foo(); + } + } + + //~ MONO_ITEM fn Struct::bar + fn bar(&self) { + { + //~ MONO_ITEM fn Struct::bar::foo + fn foo() {} + foo(); + } + + { + //~ MONO_ITEM fn Struct::bar::foo + fn foo() {} + foo(); + } + } +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + foo(); + bar(); + Struct::foo(); + let x = Struct { _x: 0 }; + x.bar(); + + 0 +} diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs new file mode 100644 index 000000000..2be7eba1d --- /dev/null +++ b/tests/codegen-units/item-collection/overloaded-operators.rs @@ -0,0 +1,59 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![crate_type="lib"] + +use std::ops::{Index, IndexMut, Add, Deref}; + +pub struct Indexable { + data: [u8; 3] +} + +impl Index<usize> for Indexable { + type Output = u8; + + //~ MONO_ITEM fn <Indexable as std::ops::Index<usize>>::index + fn index(&self, index: usize) -> &Self::Output { + if index >= 3 { + &self.data[0] + } else { + &self.data[index] + } + } +} + +impl IndexMut<usize> for Indexable { + //~ MONO_ITEM fn <Indexable as std::ops::IndexMut<usize>>::index_mut + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + if index >= 3 { + &mut self.data[0] + } else { + &mut self.data[index] + } + } +} + + +//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::eq +//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::ne +#[derive(PartialEq)] +pub struct Equatable(u32); + + +impl Add<u32> for Equatable { + type Output = u32; + + //~ MONO_ITEM fn <Equatable as std::ops::Add<u32>>::add + fn add(self, rhs: u32) -> u32 { + self.0 + rhs + } +} + +impl Deref for Equatable { + type Target = u32; + + //~ MONO_ITEM fn <Equatable as std::ops::Deref>::deref + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/tests/codegen-units/item-collection/static-init.rs b/tests/codegen-units/item-collection/static-init.rs new file mode 100644 index 000000000..287ec8f24 --- /dev/null +++ b/tests/codegen-units/item-collection/static-init.rs @@ -0,0 +1,16 @@ +// compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on + +#![feature(start)] + +pub static FN : fn() = foo::<i32>; + +pub fn foo<T>() { } + +//~ MONO_ITEM fn foo::<T> +//~ MONO_ITEM static FN + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 0 +} diff --git a/tests/codegen-units/item-collection/statics-and-consts.rs b/tests/codegen-units/item-collection/statics-and-consts.rs new file mode 100644 index 000000000..49a8d3dff --- /dev/null +++ b/tests/codegen-units/item-collection/statics-and-consts.rs @@ -0,0 +1,54 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +static STATIC1: i64 = { + const STATIC1_CONST1: i64 = 2; + 1 + CONST1 as i64 + STATIC1_CONST1 +}; + +const CONST1: i64 = { + const CONST1_1: i64 = { + const CONST1_1_1: i64 = 2; + CONST1_1_1 + 1 + }; + 1 + CONST1_1 as i64 +}; + +fn foo() { + let _ = { + const CONST2: i64 = 0; + static STATIC2: i64 = CONST2; + + let x = { + const CONST2: i64 = 1; + static STATIC2: i64 = CONST2; + STATIC2 + }; + + x + STATIC2 + }; + + let _ = { + const CONST2: i64 = 0; + static STATIC2: i64 = CONST2; + STATIC2 + }; +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + foo(); + let _ = STATIC1; + + 0 +} + +//~ MONO_ITEM static STATIC1 + +//~ MONO_ITEM fn foo +//~ MONO_ITEM static foo::STATIC2 +//~ MONO_ITEM static foo::STATIC2 +//~ MONO_ITEM static foo::STATIC2 diff --git a/tests/codegen-units/item-collection/trait-implementations.rs b/tests/codegen-units/item-collection/trait-implementations.rs new file mode 100644 index 000000000..a816cb032 --- /dev/null +++ b/tests/codegen-units/item-collection/trait-implementations.rs @@ -0,0 +1,73 @@ +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +pub trait SomeTrait { + fn foo(&self); + fn bar<T>(&self, x: T); +} + +impl SomeTrait for i64 { + + //~ MONO_ITEM fn <i64 as SomeTrait>::foo + fn foo(&self) {} + + fn bar<T>(&self, _: T) {} +} + +impl SomeTrait for i32 { + + //~ MONO_ITEM fn <i32 as SomeTrait>::foo + fn foo(&self) {} + + fn bar<T>(&self, _: T) {} +} + +pub trait SomeGenericTrait<T> { + fn foo(&self, x: T); + fn bar<T2>(&self, x: T, y: T2); +} + +// Concrete impl of generic trait +impl SomeGenericTrait<u32> for f64 { + + //~ MONO_ITEM fn <f64 as SomeGenericTrait<u32>>::foo + fn foo(&self, _: u32) {} + + fn bar<T2>(&self, _: u32, _: T2) {} +} + +// Generic impl of generic trait +impl<T> SomeGenericTrait<T> for f32 { + + fn foo(&self, _: T) {} + fn bar<T2>(&self, _: T, _: T2) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn <i32 as SomeTrait>::bar::<char> + 0i32.bar('x'); + + //~ MONO_ITEM fn <f64 as SomeGenericTrait<u32>>::bar::<&str> + 0f64.bar(0u32, "&str"); + + //~ MONO_ITEM fn <f64 as SomeGenericTrait<u32>>::bar::<()> + 0f64.bar(0u32, ()); + + //~ MONO_ITEM fn <f32 as SomeGenericTrait<char>>::foo + 0f32.foo('x'); + + //~ MONO_ITEM fn <f32 as SomeGenericTrait<i64>>::foo + 0f32.foo(-1i64); + + //~ MONO_ITEM fn <f32 as SomeGenericTrait<u32>>::bar::<()> + 0f32.bar(0u32, ()); + + //~ MONO_ITEM fn <f32 as SomeGenericTrait<&str>>::bar::<&str> + 0f32.bar("&str", "&str"); + + 0 +} diff --git a/tests/codegen-units/item-collection/trait-method-as-argument.rs b/tests/codegen-units/item-collection/trait-method-as-argument.rs new file mode 100644 index 000000000..235569728 --- /dev/null +++ b/tests/codegen-units/item-collection/trait-method-as-argument.rs @@ -0,0 +1,60 @@ +// +// compile-flags:-Zprint-mono-items=eager + +#![deny(dead_code)] +#![feature(start)] + +trait Trait : Sized { + fn foo(self) -> Self { self } +} + +impl Trait for u32 { + fn foo(self) -> u32 { self } +} + +impl Trait for char { +} + +fn take_foo_once<T, F: FnOnce(T) -> T>(f: F, arg: T) -> T { + (f)(arg) +} + +fn take_foo<T, F: Fn(T) -> T>(f: F, arg: T) -> T { + (f)(arg) +} + +fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T { + (f)(arg) +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn take_foo_once::<u32, fn(u32) -> u32 {<u32 as Trait>::foo}> + //~ MONO_ITEM fn <u32 as Trait>::foo + //~ MONO_ITEM fn <fn(u32) -> u32 {<u32 as Trait>::foo} as std::ops::FnOnce<(u32,)>>::call_once - shim(fn(u32) -> u32 {<u32 as Trait>::foo}) + take_foo_once(Trait::foo, 0u32); + + //~ MONO_ITEM fn take_foo_once::<char, fn(char) -> char {<char as Trait>::foo}> + //~ MONO_ITEM fn <char as Trait>::foo + //~ MONO_ITEM fn <fn(char) -> char {<char as Trait>::foo} as std::ops::FnOnce<(char,)>>::call_once - shim(fn(char) -> char {<char as Trait>::foo}) + take_foo_once(Trait::foo, 'c'); + + //~ MONO_ITEM fn take_foo::<u32, fn(u32) -> u32 {<u32 as Trait>::foo}> + //~ MONO_ITEM fn <fn(u32) -> u32 {<u32 as Trait>::foo} as std::ops::Fn<(u32,)>>::call - shim(fn(u32) -> u32 {<u32 as Trait>::foo}) + take_foo(Trait::foo, 0u32); + + //~ MONO_ITEM fn take_foo::<char, fn(char) -> char {<char as Trait>::foo}> + //~ MONO_ITEM fn <fn(char) -> char {<char as Trait>::foo} as std::ops::Fn<(char,)>>::call - shim(fn(char) -> char {<char as Trait>::foo}) + take_foo(Trait::foo, 'c'); + + //~ MONO_ITEM fn take_foo_mut::<u32, fn(u32) -> u32 {<u32 as Trait>::foo}> + //~ MONO_ITEM fn <fn(u32) -> u32 {<u32 as Trait>::foo} as std::ops::FnMut<(u32,)>>::call_mut - shim(fn(u32) -> u32 {<u32 as Trait>::foo}) + take_foo_mut(Trait::foo, 0u32); + + //~ MONO_ITEM fn take_foo_mut::<char, fn(char) -> char {<char as Trait>::foo}> + //~ MONO_ITEM fn <fn(char) -> char {<char as Trait>::foo} as std::ops::FnMut<(char,)>>::call_mut - shim(fn(char) -> char {<char as Trait>::foo}) + take_foo_mut(Trait::foo, 'c'); + + 0 +} diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs new file mode 100644 index 000000000..bfcdb6fa1 --- /dev/null +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -0,0 +1,61 @@ +// compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on + +#![deny(dead_code)] +#![feature(start)] + +trait SomeTrait { + fn foo(&self) { } + fn bar<T>(&self, x: T) -> T { x } +} + +impl SomeTrait for i8 { + // take the default implementations + + // For the non-generic foo(), we should generate a codegen-item even if it + // is not called anywhere + //~ MONO_ITEM fn <i8 as SomeTrait>::foo +} + +trait SomeGenericTrait<T1> { + fn foo(&self) { } + fn bar<T2>(&self, x: T1, y: T2) {} +} + +// Non-generic impl of generic trait +impl SomeGenericTrait<u64> for i32 { + // take the default implementations + + // For the non-generic foo(), we should generate a codegen-item even if it + // is not called anywhere + //~ MONO_ITEM fn <i32 as SomeGenericTrait<T1>>::foo +} + +// Non-generic impl of generic trait +impl<T1> SomeGenericTrait<T1> for u32 { + // take the default implementations + // since nothing is monomorphic here, nothing should be generated unless used somewhere. +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn <i8 as SomeTrait>::bar::<char> + let _ = 1i8.bar('c'); + + //~ MONO_ITEM fn <i8 as SomeTrait>::bar::<&str> + let _ = 2i8.bar("&str"); + + //~ MONO_ITEM fn <i32 as SomeGenericTrait<u64>>::bar::<char> + 0i32.bar(0u64, 'c'); + + //~ MONO_ITEM fn <i32 as SomeGenericTrait<u64>>::bar::<&str> + 0i32.bar(0u64, "&str"); + + //~ MONO_ITEM fn <u32 as SomeGenericTrait<i8>>::bar::<&[char; 1]> + 0u32.bar(0i8, &['c']); + + //~ MONO_ITEM fn <u32 as SomeGenericTrait<i16>>::bar::<()> + 0u32.bar(0i16, ()); + + 0 +} diff --git a/tests/codegen-units/item-collection/transitive-drop-glue.rs b/tests/codegen-units/item-collection/transitive-drop-glue.rs new file mode 100644 index 000000000..e286c800b --- /dev/null +++ b/tests/codegen-units/item-collection/transitive-drop-glue.rs @@ -0,0 +1,46 @@ +// +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus + +#![deny(dead_code)] +#![feature(start)] + +//~ MONO_ITEM fn std::ptr::drop_in_place::<Root> - shim(Some(Root)) @@ transitive_drop_glue-cgu.0[Internal] +struct Root(#[allow(unused_tuple_struct_fields)] Intermediate); +//~ MONO_ITEM fn std::ptr::drop_in_place::<Intermediate> - shim(Some(Intermediate)) @@ transitive_drop_glue-cgu.0[Internal] +struct Intermediate(#[allow(unused_tuple_struct_fields)] Leaf); +//~ MONO_ITEM fn std::ptr::drop_in_place::<Leaf> - shim(Some(Leaf)) @@ transitive_drop_glue-cgu.0[Internal] +struct Leaf; + +impl Drop for Leaf { + //~ MONO_ITEM fn <Leaf as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +struct RootGen<T>(#[allow(unused_tuple_struct_fields)] IntermediateGen<T>); +struct IntermediateGen<T>(#[allow(unused_tuple_struct_fields)] LeafGen<T>); +struct LeafGen<T>(#[allow(unused_tuple_struct_fields)] T); + +impl<T> Drop for LeafGen<T> { + fn drop(&mut self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + let _ = Root(Intermediate(Leaf)); + + //~ MONO_ITEM fn std::ptr::drop_in_place::<RootGen<u32>> - shim(Some(RootGen<u32>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<IntermediateGen<u32>> - shim(Some(IntermediateGen<u32>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<LeafGen<u32>> - shim(Some(LeafGen<u32>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <LeafGen<u32> as std::ops::Drop>::drop + let _ = RootGen(IntermediateGen(LeafGen(0u32))); + + //~ MONO_ITEM fn std::ptr::drop_in_place::<RootGen<i16>> - shim(Some(RootGen<i16>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<IntermediateGen<i16>> - shim(Some(IntermediateGen<i16>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<LeafGen<i16>> - shim(Some(LeafGen<i16>)) @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn <LeafGen<i16> as std::ops::Drop>::drop + let _ = RootGen(IntermediateGen(LeafGen(0i16))); + + 0 +} diff --git a/tests/codegen-units/item-collection/tuple-drop-glue.rs b/tests/codegen-units/item-collection/tuple-drop-glue.rs new file mode 100644 index 000000000..ae3b2e081 --- /dev/null +++ b/tests/codegen-units/item-collection/tuple-drop-glue.rs @@ -0,0 +1,27 @@ +// +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus + +#![deny(dead_code)] +#![feature(start)] + +//~ MONO_ITEM fn std::ptr::drop_in_place::<Dropped> - shim(Some(Dropped)) @@ tuple_drop_glue-cgu.0[Internal] +struct Dropped; + +impl Drop for Dropped { + //~ MONO_ITEM fn <Dropped as std::ops::Drop>::drop + fn drop(&mut self) {} +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Dropped)> - shim(Some((u32, Dropped))) @@ tuple_drop_glue-cgu.0[Internal] + let x = (0u32, Dropped); + + //~ MONO_ITEM fn std::ptr::drop_in_place::<(i16, (Dropped, bool))> - shim(Some((i16, (Dropped, bool)))) @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<(Dropped, bool)> - shim(Some((Dropped, bool))) @@ tuple_drop_glue-cgu.0[Internal] + let x = (0i16, (Dropped, true)); + + 0 +} diff --git a/tests/codegen-units/item-collection/unreferenced-const-fn.rs b/tests/codegen-units/item-collection/unreferenced-const-fn.rs new file mode 100644 index 000000000..17b92eae0 --- /dev/null +++ b/tests/codegen-units/item-collection/unreferenced-const-fn.rs @@ -0,0 +1,9 @@ +// compile-flags:-Zprint-mono-items=lazy + +#![deny(dead_code)] +#![crate_type = "rlib"] + +//~ MONO_ITEM fn foo @@ unreferenced_const_fn-cgu.0[External] +pub const fn foo(x: u32) -> u32 { + x + 0xf00 +} diff --git a/tests/codegen-units/item-collection/unreferenced-inline-function.rs b/tests/codegen-units/item-collection/unreferenced-inline-function.rs new file mode 100644 index 000000000..4d095e4d6 --- /dev/null +++ b/tests/codegen-units/item-collection/unreferenced-inline-function.rs @@ -0,0 +1,11 @@ +// compile-flags:-Zprint-mono-items=lazy + +// N.B., we do not expect *any* monomorphization to be generated here. + +#![deny(dead_code)] +#![crate_type = "rlib"] + +#[inline] +pub fn foo() -> bool { + [1, 2] == [3, 4] +} diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs new file mode 100644 index 000000000..111a72312 --- /dev/null +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -0,0 +1,79 @@ +// compile-flags:-Zprint-mono-items=eager +// compile-flags:-Zinline-in-all-cgus +// compile-flags:-Zmir-opt-level=0 + +#![deny(dead_code)] +#![feature(coerce_unsized)] +#![feature(unsize)] +#![feature(start)] + +use std::marker::Unsize; +use std::ops::CoerceUnsized; + +trait Trait { + fn foo(&self); +} + +// Simple Case +impl Trait for bool { + fn foo(&self) {} +} + +impl Trait for char { + fn foo(&self) {} +} + +// Struct Field Case +struct Struct<T: ?Sized> { + _a: u32, + _b: i32, + _c: T +} + +impl Trait for f64 { + fn foo(&self) {} +} + +// Custom Coercion Case +impl Trait for u32 { + fn foo(&self) {} +} + +#[derive(Clone, Copy)] +struct Wrapper<T: ?Sized>(#[allow(unused_tuple_struct_fields)] *const T); + +impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + // simple case + let bool_sized = &true; + //~ MONO_ITEM fn std::ptr::drop_in_place::<bool> - shim(None) @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn <bool as Trait>::foo + let _bool_unsized = bool_sized as &Trait; + + let char_sized = &'a'; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<char> - shim(None) @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn <char as Trait>::foo + let _char_unsized = char_sized as &Trait; + + // struct field + let struct_sized = &Struct { + _a: 1, + _b: 2, + _c: 3.0f64 + }; + //~ MONO_ITEM fn std::ptr::drop_in_place::<f64> - shim(None) @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn <f64 as Trait>::foo + let _struct_unsized = struct_sized as &Struct<Trait>; + + // custom coercion + let wrapper_sized = Wrapper(&0u32); + //~ MONO_ITEM fn std::ptr::drop_in_place::<u32> - shim(None) @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn <u32 as Trait>::foo + let _wrapper_sized = wrapper_sized as Wrapper<Trait>; + + 0 +} diff --git a/tests/codegen-units/item-collection/unused-traits-and-generics.rs b/tests/codegen-units/item-collection/unused-traits-and-generics.rs new file mode 100644 index 000000000..561dc1a5c --- /dev/null +++ b/tests/codegen-units/item-collection/unused-traits-and-generics.rs @@ -0,0 +1,77 @@ +// compile-flags:-Zprint-mono-items=eager + +#![crate_type="lib"] +#![deny(dead_code)] + +// This test asserts that no codegen items are generated for generic items that +// are never instantiated in the local crate. + +pub trait Trait { + fn foo() {} + fn bar(&self) {} +} + +pub fn foo<T: Copy>(x: T) -> (T, T) { + (x, x) +} + +pub struct Struct<T> { + x: T +} + +impl<T> Struct<T> { + pub fn foo(self) -> T { + self.x + } + + pub fn bar() {} +} + +pub enum Enum<T> { + A(T), + B { x: T } +} + +impl<T> Enum<T> { + pub fn foo(self) -> T { + match self { + Enum::A(x) => x, + Enum::B { x } => x, + } + } + + pub fn bar() {} +} + +pub struct TupleStruct<T>(T); + +impl<T> TupleStruct<T> { + pub fn foo(self) -> T { + self.0 + } + + pub fn bar() {} +} + +pub type Pair<T> = (T, T); + +pub struct NonGeneric { + x: i32 +} + +impl NonGeneric { + pub fn foo(self) -> i32 { + self.x + } + + pub fn generic_foo<T>(&self, x: T) -> (T, i32) { + (x, self.x) + } + + pub fn generic_bar<T: Copy>(x: T) -> (T, T) { + (x, x) + } +} + +// Only the non-generic methods should be instantiated: +//~ MONO_ITEM fn NonGeneric::foo diff --git a/tests/codegen-units/partitioning/auxiliary/cgu_explicit_inlining.rs b/tests/codegen-units/partitioning/auxiliary/cgu_explicit_inlining.rs new file mode 100644 index 000000000..4a3a63cc1 --- /dev/null +++ b/tests/codegen-units/partitioning/auxiliary/cgu_explicit_inlining.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +#[inline] +pub fn inlined() {} + +#[inline(always)] +pub fn always_inlined() {} + +#[inline(never)] +pub fn never_inlined() {} diff --git a/tests/codegen-units/partitioning/auxiliary/cgu_extern_drop_glue.rs b/tests/codegen-units/partitioning/auxiliary/cgu_extern_drop_glue.rs new file mode 100644 index 000000000..b5fec2337 --- /dev/null +++ b/tests/codegen-units/partitioning/auxiliary/cgu_extern_drop_glue.rs @@ -0,0 +1,7 @@ +#![crate_type = "lib"] + +pub struct Struct(pub u32); + +impl Drop for Struct { + fn drop(&mut self) {} +} diff --git a/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs new file mode 100644 index 000000000..3926f2957 --- /dev/null +++ b/tests/codegen-units/partitioning/auxiliary/cgu_generic_function.rs @@ -0,0 +1,26 @@ +#![crate_type = "lib"] + +struct Struct(u32); + +#[inline(never)] +pub fn foo<T>(x: T) -> (T, u32, i8) { + let (x, Struct(y)) = bar(x); + (x, y, 2) +} + +#[inline(never)] +fn bar<T>(x: T) -> (T, Struct) { + let _ = not_exported_and_not_generic(0); + (x, Struct(1)) +} + +// These should not contribute to the codegen items of other crates. +#[inline(never)] +pub fn exported_but_not_generic(x: i32) -> i64 { + x as i64 +} + +#[inline(never)] +fn not_exported_and_not_generic(x: u32) -> u64 { + x as u64 +} diff --git a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs new file mode 100644 index 000000000..ffbd0dc54 --- /dev/null +++ b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs @@ -0,0 +1,26 @@ +// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels +// prevent drop-glue from participating in share-generics. +// compile-flags:-Zshare-generics=yes -Copt-level=0 +// no-prefer-dynamic + +#![crate_type="rlib"] + +pub fn generic_fn<T>(x: T, y: T) -> (T, T) { + (x, y) +} + +pub fn use_generic_fn_f32() -> (f32, f32) { + // This line causes drop glue for Foo to be instantiated. We want to make + // sure that this crate exports an instance to be re-used by share-generics. + let _ = Foo(0); + + generic_fn(0.0f32, 1.0f32) +} + +pub struct Foo(pub u32); + +impl Drop for Foo { + fn drop(&mut self) { + println!("foo"); + } +} diff --git a/tests/codegen-units/partitioning/extern-drop-glue.rs b/tests/codegen-units/partitioning/extern-drop-glue.rs new file mode 100644 index 000000000..c73d2a10a --- /dev/null +++ b/tests/codegen-units/partitioning/extern-drop-glue.rs @@ -0,0 +1,36 @@ +// + +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus -Copt-level=0 + +#![allow(dead_code)] +#![crate_type = "rlib"] + +// aux-build:cgu_extern_drop_glue.rs +extern crate cgu_extern_drop_glue; + +//~ MONO_ITEM fn std::ptr::drop_in_place::<cgu_extern_drop_glue::Struct> - shim(Some(cgu_extern_drop_glue::Struct)) @@ extern_drop_glue-fallback.cgu[External] + +struct LocalStruct(cgu_extern_drop_glue::Struct); + +//~ MONO_ITEM fn user @@ extern_drop_glue[External] +pub fn user() { + //~ MONO_ITEM fn std::ptr::drop_in_place::<LocalStruct> - shim(Some(LocalStruct)) @@ extern_drop_glue-fallback.cgu[External] + let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); +} + +pub mod mod1 { + use cgu_extern_drop_glue; + + struct LocalStruct(cgu_extern_drop_glue::Struct); + + //~ MONO_ITEM fn mod1::user @@ extern_drop_glue-mod1[External] + pub fn user() { + //~ MONO_ITEM fn std::ptr::drop_in_place::<mod1::LocalStruct> - shim(Some(mod1::LocalStruct)) @@ extern_drop_glue-fallback.cgu[External] + let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); + } +} diff --git a/tests/codegen-units/partitioning/extern-generic.rs b/tests/codegen-units/partitioning/extern-generic.rs new file mode 100644 index 000000000..638ec079a --- /dev/null +++ b/tests/codegen-units/partitioning/extern-generic.rs @@ -0,0 +1,53 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=eager -Zshare-generics=y + +#![allow(dead_code)] +#![crate_type="lib"] + +// aux-build:cgu_generic_function.rs +extern crate cgu_generic_function; + +//~ MONO_ITEM fn user @@ extern_generic[Internal] +fn user() { + let _ = cgu_generic_function::foo("abc"); +} + +mod mod1 { + use cgu_generic_function; + + //~ MONO_ITEM fn mod1::user @@ extern_generic-mod1[Internal] + fn user() { + let _ = cgu_generic_function::foo("abc"); + } + + mod mod1 { + use cgu_generic_function; + + //~ MONO_ITEM fn mod1::mod1::user @@ extern_generic-mod1-mod1[Internal] + fn user() { + let _ = cgu_generic_function::foo("abc"); + } + } +} + +mod mod2 { + use cgu_generic_function; + + //~ MONO_ITEM fn mod2::user @@ extern_generic-mod2[Internal] + fn user() { + let _ = cgu_generic_function::foo("abc"); + } +} + +mod mod3 { + //~ MONO_ITEM fn mod3::non_user @@ extern_generic-mod3[Internal] + fn non_user() {} +} + +// Make sure the two generic functions from the extern crate get instantiated +// once for the current crate +//~ MONO_ITEM fn cgu_generic_function::foo::<&str> @@ cgu_generic_function-in-extern_generic.volatile[External] +//~ MONO_ITEM fn cgu_generic_function::bar::<&str> @@ cgu_generic_function-in-extern_generic.volatile[External] diff --git a/tests/codegen-units/partitioning/incremental-merging.rs b/tests/codegen-units/partitioning/incremental-merging.rs new file mode 100644 index 000000000..118b7bdf4 --- /dev/null +++ b/tests/codegen-units/partitioning/incremental-merging.rs @@ -0,0 +1,42 @@ +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Ccodegen-units=3 + +#![crate_type = "rlib"] + +// This test makes sure that merging of CGUs works together with incremental +// compilation but at the same time does not modify names of CGUs that were not +// affected by merging. +// +// We expect CGUs `aaa` and `bbb` to be merged (because they are the smallest), +// while `ccc` and `ddd` are supposed to stay untouched. + +pub mod aaa { + //~ MONO_ITEM fn aaa::foo @@ incremental_merging-aaa--incremental_merging-bbb[External] + pub fn foo(a: u64) -> u64 { + a + 1 + } +} + +pub mod bbb { + //~ MONO_ITEM fn bbb::foo @@ incremental_merging-aaa--incremental_merging-bbb[External] + pub fn foo(a: u64, b: u64) -> u64 { + a + b + 1 + } +} + +pub mod ccc { + //~ MONO_ITEM fn ccc::foo @@ incremental_merging-ccc[External] + pub fn foo(a: u64, b: u64, c: u64) -> u64 { + a + b + c + 1 + } +} + +pub mod ddd { + //~ MONO_ITEM fn ddd::foo @@ incremental_merging-ddd[External] + pub fn foo(a: u64, b: u64, c: u64, d: u64) -> u64 { + a + b + c + d + 1 + } +} diff --git a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs new file mode 100644 index 000000000..1cc21632e --- /dev/null +++ b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -0,0 +1,53 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus + +#![crate_type="lib"] + +// aux-build:cgu_explicit_inlining.rs +extern crate cgu_explicit_inlining; + +// This test makes sure that items inlined from external crates are privately +// instantiated in every codegen unit they are used in. + +//~ MONO_ITEM fn cgu_explicit_inlining::inlined @@ inlining_from_extern_crate[Internal] inlining_from_extern_crate-mod1[Internal] +//~ MONO_ITEM fn cgu_explicit_inlining::always_inlined @@ inlining_from_extern_crate[Internal] inlining_from_extern_crate-mod2[Internal] + +//~ MONO_ITEM fn user @@ inlining_from_extern_crate[External] +pub fn user() +{ + cgu_explicit_inlining::inlined(); + cgu_explicit_inlining::always_inlined(); + + // does not generate a monomorphization in this crate + cgu_explicit_inlining::never_inlined(); +} + +pub mod mod1 { + use cgu_explicit_inlining; + + //~ MONO_ITEM fn mod1::user @@ inlining_from_extern_crate-mod1[External] + pub fn user() + { + cgu_explicit_inlining::inlined(); + + // does not generate a monomorphization in this crate + cgu_explicit_inlining::never_inlined(); + } +} + +pub mod mod2 { + use cgu_explicit_inlining; + + //~ MONO_ITEM fn mod2::user @@ inlining_from_extern_crate-mod2[External] + pub fn user() + { + cgu_explicit_inlining::always_inlined(); + + // does not generate a monomorphization in this crate + cgu_explicit_inlining::never_inlined(); + } +} diff --git a/tests/codegen-units/partitioning/local-drop-glue.rs b/tests/codegen-units/partitioning/local-drop-glue.rs new file mode 100644 index 000000000..2fd853a44 --- /dev/null +++ b/tests/codegen-units/partitioning/local-drop-glue.rs @@ -0,0 +1,46 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus -Copt-level=0 + +#![allow(dead_code)] +#![crate_type = "rlib"] + +//~ MONO_ITEM fn std::ptr::drop_in_place::<Struct> - shim(Some(Struct)) @@ local_drop_glue-fallback.cgu[External] +struct Struct { + _a: u32, +} + +impl Drop for Struct { + //~ MONO_ITEM fn <Struct as std::ops::Drop>::drop @@ local_drop_glue-fallback.cgu[External] + fn drop(&mut self) {} +} + +//~ MONO_ITEM fn std::ptr::drop_in_place::<Outer> - shim(Some(Outer)) @@ local_drop_glue-fallback.cgu[External] +struct Outer { + _a: Struct, +} + +//~ MONO_ITEM fn user @@ local_drop_glue[External] +pub fn user() { + let _ = Outer { _a: Struct { _a: 0 } }; +} + +pub mod mod1 { + use super::Struct; + + //~ MONO_ITEM fn std::ptr::drop_in_place::<mod1::Struct2> - shim(Some(mod1::Struct2)) @@ local_drop_glue-fallback.cgu[External] + struct Struct2 { + _a: Struct, + //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Struct)> - shim(Some((u32, Struct))) @@ local_drop_glue-fallback.cgu[Internal] + _b: (u32, Struct), + } + + //~ MONO_ITEM fn mod1::user @@ local_drop_glue-mod1[External] + pub fn user() { + let _ = Struct2 { _a: Struct { _a: 0 }, _b: (0, Struct { _a: 0 }) }; + } +} diff --git a/tests/codegen-units/partitioning/local-generic.rs b/tests/codegen-units/partitioning/local-generic.rs new file mode 100644 index 000000000..38aec7291 --- /dev/null +++ b/tests/codegen-units/partitioning/local-generic.rs @@ -0,0 +1,45 @@ +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=eager + +#![allow(dead_code)] +#![crate_type="lib"] + +//~ MONO_ITEM fn generic::<u32> @@ local_generic.volatile[External] +//~ MONO_ITEM fn generic::<u64> @@ local_generic.volatile[External] +//~ MONO_ITEM fn generic::<char> @@ local_generic.volatile[External] +//~ MONO_ITEM fn generic::<&str> @@ local_generic.volatile[External] +pub fn generic<T>(x: T) -> T { x } + +//~ MONO_ITEM fn user @@ local_generic[Internal] +fn user() { + let _ = generic(0u32); +} + +mod mod1 { + pub use super::generic; + + //~ MONO_ITEM fn mod1::user @@ local_generic-mod1[Internal] + fn user() { + let _ = generic(0u64); + } + + mod mod1 { + use super::generic; + + //~ MONO_ITEM fn mod1::mod1::user @@ local_generic-mod1-mod1[Internal] + fn user() { + let _ = generic('c'); + } + } +} + +mod mod2 { + use super::generic; + + //~ MONO_ITEM fn mod2::user @@ local_generic-mod2[Internal] + fn user() { + let _ = generic("abc"); + } +} diff --git a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs new file mode 100644 index 000000000..318f0c28a --- /dev/null +++ b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -0,0 +1,45 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus=no + +#![allow(dead_code)] +#![crate_type="lib"] + +mod inline { + + //~ MONO_ITEM fn inline::inlined_function @@ local_inlining_but_not_all-inline[External] + #[inline] + pub fn inlined_function() + { + + } +} + +pub mod user1 { + use super::inline; + + //~ MONO_ITEM fn user1::foo @@ local_inlining_but_not_all-user1[External] + pub fn foo() { + inline::inlined_function(); + } +} + +pub mod user2 { + use super::inline; + + //~ MONO_ITEM fn user2::bar @@ local_inlining_but_not_all-user2[External] + pub fn bar() { + inline::inlined_function(); + } +} + +pub mod non_user { + + //~ MONO_ITEM fn non_user::baz @@ local_inlining_but_not_all-non_user[External] + pub fn baz() { + + } +} diff --git a/tests/codegen-units/partitioning/local-inlining.rs b/tests/codegen-units/partitioning/local-inlining.rs new file mode 100644 index 000000000..841a428e9 --- /dev/null +++ b/tests/codegen-units/partitioning/local-inlining.rs @@ -0,0 +1,46 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus + +#![allow(dead_code)] +#![crate_type="lib"] + +mod inline { + + // Important: This function should show up in all codegen units where it is inlined + //~ MONO_ITEM fn inline::inlined_function @@ local_inlining-user1[Internal] local_inlining-user2[Internal] + #[inline(always)] + pub fn inlined_function() + { + + } +} + +pub mod user1 { + use super::inline; + + //~ MONO_ITEM fn user1::foo @@ local_inlining-user1[External] + pub fn foo() { + inline::inlined_function(); + } +} + +pub mod user2 { + use super::inline; + + //~ MONO_ITEM fn user2::bar @@ local_inlining-user2[External] + pub fn bar() { + inline::inlined_function(); + } +} + +pub mod non_user { + + //~ MONO_ITEM fn non_user::baz @@ local_inlining-non_user[External] + pub fn baz() { + + } +} diff --git a/tests/codegen-units/partitioning/local-transitive-inlining.rs b/tests/codegen-units/partitioning/local-transitive-inlining.rs new file mode 100644 index 000000000..03c37954d --- /dev/null +++ b/tests/codegen-units/partitioning/local-transitive-inlining.rs @@ -0,0 +1,46 @@ +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus + +#![allow(dead_code)] +#![crate_type="rlib"] + +mod inline { + + //~ MONO_ITEM fn inline::inlined_function @@ local_transitive_inlining-indirect_user[Internal] + #[inline(always)] + pub fn inlined_function() + { + + } +} + +mod direct_user { + use super::inline; + + //~ MONO_ITEM fn direct_user::foo @@ local_transitive_inlining-indirect_user[Internal] + #[inline(always)] + pub fn foo() { + inline::inlined_function(); + } +} + +pub mod indirect_user { + use super::direct_user; + + //~ MONO_ITEM fn indirect_user::bar @@ local_transitive_inlining-indirect_user[External] + pub fn bar() { + direct_user::foo(); + } +} + +pub mod non_user { + + //~ MONO_ITEM fn non_user::baz @@ local_transitive_inlining-non_user[External] + pub fn baz() { + + } +} diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs new file mode 100644 index 000000000..8220dc12e --- /dev/null +++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs @@ -0,0 +1,79 @@ +// Currently, all generic functions are instantiated in each codegen unit that +// uses them, even those not marked with #[inline], so this test does not make +// much sense at the moment. +// ignore-test + +// +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy + +#![allow(dead_code)] +#![feature(start)] + +struct SomeType; + +struct SomeGenericType<T1, T2>(T1, T2); + +mod mod1 { + use super::{SomeType, SomeGenericType}; + + // Even though the impl is in `mod1`, the methods should end up in the + // parent module, since that is where their self-type is. + impl SomeType { + //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::method[0] @@ methods_are_with_self_type[External] + fn method(&self) {} + + //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::associated_fn[0] @@ methods_are_with_self_type[External] + fn associated_fn() {} + } + + impl<T1, T2> SomeGenericType<T1, T2> { + pub fn method(&self) {} + pub fn associated_fn(_: T1, _: T2) {} + } +} + +trait Trait { + fn foo(&self); + fn default(&self) {} +} + +// We provide an implementation of `Trait` for all types. The corresponding +// monomorphizations should end up in whichever module the concrete `T` is. +impl<T> Trait for T +{ + fn foo(&self) {} +} + +mod type1 { + pub struct Struct; +} + +mod type2 { + pub struct Struct; +} + +//~ MONO_ITEM fn methods_are_with_self_type::start[0] +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0]<u32, u64> @@ methods_are_with_self_type.volatile[WeakODR] + SomeGenericType(0u32, 0u64).method(); + //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0]<char, &str> @@ methods_are_with_self_type.volatile[WeakODR] + SomeGenericType::associated_fn('c', "&str"); + + //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0]<methods_are_with_self_type::type1[0]::Struct[0]> @@ methods_are_with_self_type-type1.volatile[WeakODR] + type1::Struct.foo(); + //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR] + type2::Struct.foo(); + + //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type1[0]::Struct[0]> @@ methods_are_with_self_type-type1.volatile[WeakODR] + type1::Struct.default(); + //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR] + type2::Struct.default(); + + 0 +} + +//~ MONO_ITEM drop-glue i8 diff --git a/tests/codegen-units/partitioning/regular-modules.rs b/tests/codegen-units/partitioning/regular-modules.rs new file mode 100644 index 000000000..ce7fe9c3a --- /dev/null +++ b/tests/codegen-units/partitioning/regular-modules.rs @@ -0,0 +1,72 @@ +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=eager + +#![allow(dead_code)] +#![crate_type="lib"] + +//~ MONO_ITEM fn foo @@ regular_modules[Internal] +fn foo() {} + +//~ MONO_ITEM fn bar @@ regular_modules[Internal] +fn bar() {} + +//~ MONO_ITEM static BAZ @@ regular_modules[Internal] +static BAZ: u64 = 0; + +mod mod1 { + + //~ MONO_ITEM fn mod1::foo @@ regular_modules-mod1[Internal] + fn foo() {} + //~ MONO_ITEM fn mod1::bar @@ regular_modules-mod1[Internal] + fn bar() {} + //~ MONO_ITEM static mod1::BAZ @@ regular_modules-mod1[Internal] + static BAZ: u64 = 0; + + mod mod1 { + //~ MONO_ITEM fn mod1::mod1::foo @@ regular_modules-mod1-mod1[Internal] + fn foo() {} + //~ MONO_ITEM fn mod1::mod1::bar @@ regular_modules-mod1-mod1[Internal] + fn bar() {} + //~ MONO_ITEM static mod1::mod1::BAZ @@ regular_modules-mod1-mod1[Internal] + static BAZ: u64 = 0; + } + + mod mod2 { + //~ MONO_ITEM fn mod1::mod2::foo @@ regular_modules-mod1-mod2[Internal] + fn foo() {} + //~ MONO_ITEM fn mod1::mod2::bar @@ regular_modules-mod1-mod2[Internal] + fn bar() {} + //~ MONO_ITEM static mod1::mod2::BAZ @@ regular_modules-mod1-mod2[Internal] + static BAZ: u64 = 0; + } +} + +mod mod2 { + + //~ MONO_ITEM fn mod2::foo @@ regular_modules-mod2[Internal] + fn foo() {} + //~ MONO_ITEM fn mod2::bar @@ regular_modules-mod2[Internal] + fn bar() {} + //~ MONO_ITEM static mod2::BAZ @@ regular_modules-mod2[Internal] + static BAZ: u64 = 0; + + mod mod1 { + //~ MONO_ITEM fn mod2::mod1::foo @@ regular_modules-mod2-mod1[Internal] + fn foo() {} + //~ MONO_ITEM fn mod2::mod1::bar @@ regular_modules-mod2-mod1[Internal] + fn bar() {} + //~ MONO_ITEM static mod2::mod1::BAZ @@ regular_modules-mod2-mod1[Internal] + static BAZ: u64 = 0; + } + + mod mod2 { + //~ MONO_ITEM fn mod2::mod2::foo @@ regular_modules-mod2-mod2[Internal] + fn foo() {} + //~ MONO_ITEM fn mod2::mod2::bar @@ regular_modules-mod2-mod2[Internal] + fn bar() {} + //~ MONO_ITEM static mod2::mod2::BAZ @@ regular_modules-mod2-mod2[Internal] + static BAZ: u64 = 0; + } +} diff --git a/tests/codegen-units/partitioning/shared-generics.rs b/tests/codegen-units/partitioning/shared-generics.rs new file mode 100644 index 000000000..ebe96bfb7 --- /dev/null +++ b/tests/codegen-units/partitioning/shared-generics.rs @@ -0,0 +1,28 @@ +// +// no-prefer-dynamic +// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels +// prevent drop-glue from participating in share-generics. +// incremental +// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Copt-level=0 + +#![crate_type="rlib"] + +// aux-build:shared_generics_aux.rs +extern crate shared_generics_aux; + +//~ MONO_ITEM fn foo +pub fn foo() { + + //~ MONO_ITEM fn shared_generics_aux::generic_fn::<u16> @@ shared_generics_aux-in-shared_generics.volatile[External] + let _ = shared_generics_aux::generic_fn(0u16, 1u16); + + // This should not generate a monomorphization because it's already + // available in `shared_generics_aux`. + let _ = shared_generics_aux::generic_fn(0.0f32, 3.0f32); + + // The following line will drop an instance of `Foo`, generating a call to + // Foo's drop-glue function. However, share-generics should take care of + // reusing the drop-glue from the upstream crate, so we do not expect a + // mono item for the drop-glue + let _ = shared_generics_aux::Foo(1); +} diff --git a/tests/codegen-units/partitioning/statics.rs b/tests/codegen-units/partitioning/statics.rs new file mode 100644 index 000000000..b11d6696d --- /dev/null +++ b/tests/codegen-units/partitioning/statics.rs @@ -0,0 +1,38 @@ +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy + +#![crate_type="rlib"] + +//~ MONO_ITEM static FOO @@ statics[Internal] +static FOO: u32 = 0; + +//~ MONO_ITEM static BAR @@ statics[Internal] +static BAR: u32 = 0; + +//~ MONO_ITEM fn function @@ statics[External] +pub fn function() { + //~ MONO_ITEM static function::FOO @@ statics[Internal] + static FOO: u32 = 0; + + //~ MONO_ITEM static function::BAR @@ statics[Internal] + static BAR: u32 = 0; +} + +pub mod mod1 { + //~ MONO_ITEM static mod1::FOO @@ statics-mod1[Internal] + static FOO: u32 = 0; + + //~ MONO_ITEM static mod1::BAR @@ statics-mod1[Internal] + static BAR: u32 = 0; + + //~ MONO_ITEM fn mod1::function @@ statics-mod1[External] + pub fn function() { + //~ MONO_ITEM static mod1::function::FOO @@ statics-mod1[Internal] + static FOO: u32 = 0; + + //~ MONO_ITEM static mod1::function::BAR @@ statics-mod1[Internal] + static BAR: u32 = 0; + } +} diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs new file mode 100644 index 000000000..cedcca804 --- /dev/null +++ b/tests/codegen-units/partitioning/vtable-through-const.rs @@ -0,0 +1,94 @@ +// + +// We specify incremental here because we want to test the partitioning for +// incremental compilation +// incremental +// compile-flags:-Zprint-mono-items=lazy +// compile-flags:-Zinline-in-all-cgus + +// This test case makes sure, that references made through constants are +// recorded properly in the InliningMap. + +#![feature(start)] + +mod mod1 { + pub trait Trait1 { + fn do_something(&self) {} + fn do_something_else(&self) {} + } + + impl Trait1 for u32 {} + + pub trait Trait1Gen<T> { + fn do_something(&self, x: T) -> T; + fn do_something_else(&self, x: T) -> T; + } + + impl<T> Trait1Gen<T> for u32 { + fn do_something(&self, x: T) -> T { x } + fn do_something_else(&self, x: T) -> T { x } + } + + //~ MONO_ITEM fn mod1::id::<i64> @@ vtable_through_const-mod1.volatile[Internal] + fn id<T>(x: T) -> T { x } + + // These are referenced, so they produce mono-items (see start()) + pub const TRAIT1_REF: &'static Trait1 = &0u32 as &Trait1; + pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>; + pub const ID_CHAR: fn(char) -> char = id::<char>; + + + + pub trait Trait2 { + fn do_something(&self) {} + fn do_something_else(&self) {} + } + + //~ MONO_ITEM fn <u32 as mod1::Trait2>::do_something @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn <u32 as mod1::Trait2>::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + impl Trait2 for u32 {} + + pub trait Trait2Gen<T> { + fn do_something(&self, x: T) -> T; + fn do_something_else(&self, x: T) -> T; + } + + impl<T> Trait2Gen<T> for u32 { + fn do_something(&self, x: T) -> T { x } + fn do_something_else(&self, x: T) -> T { x } + } + + // These are not referenced, so they do not produce mono-items + pub const TRAIT2_REF: &'static Trait2 = &0u32 as &Trait2; + pub const TRAIT2_GEN_REF: &'static Trait2Gen<u8> = &0u32 as &Trait2Gen<u8>; + pub const ID_I64: fn(i64) -> i64 = id::<i64>; +} + +//~ MONO_ITEM fn start +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn std::ptr::drop_in_place::<u32> - shim(None) @@ vtable_through_const[Internal] + + // Since Trait1::do_something() is instantiated via its default implementation, + // it is considered a generic and is instantiated here only because it is + // referenced in this module. + //~ MONO_ITEM fn <u32 as mod1::Trait1>::do_something_else @@ vtable_through_const-mod1.volatile[External] + + // Although it is never used, Trait1::do_something_else() has to be + // instantiated locally here too, otherwise the <&u32 as &Trait1> vtable + // could not be fully constructed. + //~ MONO_ITEM fn <u32 as mod1::Trait1>::do_something @@ vtable_through_const-mod1.volatile[External] + mod1::TRAIT1_REF.do_something(); + + // Same as above + //~ MONO_ITEM fn <u32 as mod1::Trait1Gen<u8>>::do_something @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn <u32 as mod1::Trait1Gen<u8>>::do_something_else @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn <u32 as mod1::Trait2Gen<u8>>::do_something @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn <u32 as mod1::Trait2Gen<u8>>::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + mod1::TRAIT1_GEN_REF.do_something(0u8); + + //~ MONO_ITEM fn mod1::id::<char> @@ vtable_through_const-mod1.volatile[External] + mod1::ID_CHAR('x'); + + 0 +} diff --git a/tests/codegen-units/polymorphization/unused_type_parameters.rs b/tests/codegen-units/polymorphization/unused_type_parameters.rs new file mode 100644 index 000000000..c2e06d067 --- /dev/null +++ b/tests/codegen-units/polymorphization/unused_type_parameters.rs @@ -0,0 +1,322 @@ +// compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1 + +#![crate_type = "rlib"] + +// This test checks that the polymorphization analysis correctly reduces the +// generated mono items. + +mod functions { + // Function doesn't have any type parameters to be unused. + pub fn no_parameters() {} + +//~ MONO_ITEM fn functions::no_parameters + + // Function has an unused type parameter. + pub fn unused<T>() { + } + +//~ MONO_ITEM fn functions::unused::<T> + + // Function uses type parameter in value of a binding. + pub fn used_binding_value<T: Default>() { + let _: T = Default::default(); + } + +//~ MONO_ITEM fn functions::used_binding_value::<u32> +//~ MONO_ITEM fn functions::used_binding_value::<u64> + + // Function uses type parameter in type of a binding. + pub fn used_binding_type<T>() { + let _: Option<T> = None; + } + +//~ MONO_ITEM fn functions::used_binding_type::<u32> +//~ MONO_ITEM fn functions::used_binding_type::<u64> + + // Function uses type parameter in argument. + pub fn used_argument<T>(_: T) { + } + +//~ MONO_ITEM fn functions::used_argument::<u32> +//~ MONO_ITEM fn functions::used_argument::<u64> +// + // Function uses type parameter in substitutions to another function. + pub fn used_substs<T>() { + unused::<T>() + } + +//~ MONO_ITEM fn functions::used_substs::<u32> +//~ MONO_ITEM fn functions::used_substs::<u64> +} + + +mod closures { + // Function doesn't have any type parameters to be unused. + pub fn no_parameters() { + let _ = || {}; + } + +//~ MONO_ITEM fn closures::no_parameters + + // Function has an unused type parameter in parent and closure. + pub fn unused<T>() -> u32 { + let add_one = |x: u32| x + 1; + add_one(3) + } + +//~ MONO_ITEM fn closures::unused::<T>::{closure#0} +//~ MONO_ITEM fn closures::unused::<T> + + // Function has an unused type parameter in closure, but not in parent. + pub fn used_parent<T: Default>() -> u32 { + let _: T = Default::default(); + let add_one = |x: u32| x + 1; + add_one(3) + } + +//~ MONO_ITEM fn closures::used_parent::<T>::{closure#0} +//~ MONO_ITEM fn closures::used_parent::<u32> +//~ MONO_ITEM fn closures::used_parent::<u64> + + // Function uses type parameter in value of a binding in closure. + pub fn used_binding_value<T: Default>() -> T { + let x = || { + let y: T = Default::default(); + y + }; + + x() + } + +//~ MONO_ITEM fn closures::used_binding_value::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_binding_value::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_binding_value::<u32> +//~ MONO_ITEM fn closures::used_binding_value::<u64> + + // Function uses type parameter in type of a binding in closure. + pub fn used_binding_type<T>() -> Option<T> { + let x = || { + let y: Option<T> = None; + y + }; + + x() + } + +//~ MONO_ITEM fn closures::used_binding_type::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_binding_type::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_binding_type::<u32> +//~ MONO_ITEM fn closures::used_binding_type::<u64> + + // Function and closure uses type parameter in argument. + pub fn used_argument<T>(t: T) -> u32 { + let x = |_: T| 3; + x(t) + } + +//~ MONO_ITEM fn closures::used_argument::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_argument::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_argument::<u32> +//~ MONO_ITEM fn closures::used_argument::<u64> + + // Closure uses type parameter in argument. + pub fn used_argument_closure<T: Default>() -> u32 { + let t: T = Default::default(); + let x = |_: T| 3; + x(t) + } + +//~ MONO_ITEM fn closures::used_argument_closure::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_argument_closure::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_argument_closure::<u32> +//~ MONO_ITEM fn closures::used_argument_closure::<u64> + + // Closure uses type parameter as upvar. + pub fn used_upvar<T: Default>() -> T { + let x: T = Default::default(); + let y = || x; + y() + } + +//~ MONO_ITEM fn closures::used_upvar::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_upvar::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_upvar::<u32> +//~ MONO_ITEM fn closures::used_upvar::<u64> + + // Closure uses type parameter in substitutions to another function. + pub fn used_substs<T>() { + let x = || super::functions::unused::<T>(); + x() + } + +//~ MONO_ITEM fn closures::used_substs::<u32>::{closure#0} +//~ MONO_ITEM fn closures::used_substs::<u64>::{closure#0} +//~ MONO_ITEM fn closures::used_substs::<u32> +//~ MONO_ITEM fn closures::used_substs::<u64> +} + +mod methods { + pub struct Foo<F>(F); + + impl<F: Default> Foo<F> { + // Function has an unused type parameter from impl. + pub fn unused_impl() { + } + +//~ MONO_ITEM fn methods::Foo::<F>::unused_impl + + // Function has an unused type parameter from impl and fn. + pub fn unused_both<G: Default>() { + } + +//~ MONO_ITEM fn methods::Foo::<F>::unused_both::<G> + + // Function uses type parameter from impl. + pub fn used_impl() { + let _: F = Default::default(); + } + +//~ MONO_ITEM fn methods::Foo::<u32>::used_impl +//~ MONO_ITEM fn methods::Foo::<u64>::used_impl + + // Function uses type parameter from impl. + pub fn used_fn<G: Default>() { + let _: G = Default::default(); + } + +//~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u32> +//~ MONO_ITEM fn methods::Foo::<F>::used_fn::<u64> + + // Function uses type parameter from impl. + pub fn used_both<G: Default>() { + let _: F = Default::default(); + let _: G = Default::default(); + } + +//~ MONO_ITEM fn methods::Foo::<u32>::used_both::<u32> +//~ MONO_ITEM fn methods::Foo::<u64>::used_both::<u64> + + // Function uses type parameter in substitutions to another function. + pub fn used_substs() { + super::functions::unused::<F>() + } + +//~ MONO_ITEM fn methods::Foo::<u32>::used_substs +//~ MONO_ITEM fn methods::Foo::<u64>::used_substs + + // Function has an unused type parameter from impl and fn. + pub fn closure_unused_all<G: Default>() -> u32 { + let add_one = |x: u32| x + 1; + add_one(3) + } + +//~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<F>::closure_unused_all::<G> + + // Function uses type parameter from impl and fn in closure. + pub fn closure_used_both<G: Default>() -> u32 { + let add_one = |x: u32| { + let _: F = Default::default(); + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_both::<u32> +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_both::<u64> + + // Function uses type parameter from fn in closure. + pub fn closure_used_fn<G: Default>() -> u32 { + let add_one = |x: u32| { + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + +//~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u32> +//~ MONO_ITEM fn methods::Foo::<F>::closure_used_fn::<u64> + + // Function uses type parameter from impl in closure. + pub fn closure_used_impl<G: Default>() -> u32 { + let add_one = |x: u32| { + let _: F = Default::default(); + x + 1 + }; + + add_one(3) + } + +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G>::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_impl::<G> +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_impl::<G> + + // Closure uses type parameter in substitutions to another function. + pub fn closure_used_substs() { + let x = || super::functions::unused::<F>(); + x() + } + +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs::{closure#0} +//~ MONO_ITEM fn methods::Foo::<u32>::closure_used_substs +//~ MONO_ITEM fn methods::Foo::<u64>::closure_used_substs + } +} + + + +fn dispatch<T: Default>() { + functions::no_parameters(); + functions::unused::<T>(); + functions::used_binding_value::<T>(); + functions::used_binding_type::<T>(); + functions::used_argument::<T>(Default::default()); + functions::used_substs::<T>(); + + closures::no_parameters(); + let _ = closures::unused::<T>(); + let _ = closures::used_parent::<T>(); + let _ = closures::used_binding_value::<T>(); + let _ = closures::used_binding_type::<T>(); + let _ = closures::used_argument::<T>(Default::default()); + let _ = closures::used_argument_closure::<T>(); + let _ = closures::used_upvar::<T>(); + let _ = closures::used_substs::<T>(); + + methods::Foo::<T>::unused_impl(); + methods::Foo::<T>::unused_both::<T>(); + methods::Foo::<T>::used_impl(); + methods::Foo::<T>::used_fn::<T>(); + methods::Foo::<T>::used_both::<T>(); + methods::Foo::<T>::used_substs(); + let _ = methods::Foo::<T>::closure_unused_all::<T>(); + let _ = methods::Foo::<T>::closure_used_both::<T>(); + let _ = methods::Foo::<T>::closure_used_impl::<T>(); + let _ = methods::Foo::<T>::closure_used_fn::<T>(); + let _ = methods::Foo::<T>::closure_used_substs(); +} + +//~ MONO_ITEM fn dispatch::<u32> +//~ MONO_ITEM fn dispatch::<u64> + +pub fn foo() { + // Generate two copies of each function to check that where the type parameter is unused, + // there is only a single copy. + dispatch::<u32>(); + dispatch::<u64>(); +} + +//~ MONO_ITEM fn foo @@ unused_type_parameters-cgu.0[External] + +// These are all the items that aren't relevant to the test. +//~ MONO_ITEM fn <u32 as std::default::Default>::default +//~ MONO_ITEM fn <u64 as std::default::Default>::default |