diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 40e801d03885c..f71e6f3e6f3a6 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -1,14 +1,18 @@ use std::io; +use rustc_data_structures::fx::FxHashSet; +use rustc_index::IndexVec; use rustc_middle::mir::pretty::{ PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, }; use rustc_middle::mir::{Body, ClosureRegionRequirements}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; +use crate::constraints::OutlivesConstraint; use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSet}; +use crate::type_check::Locations; use crate::{BorrowckInferCtxt, RegionInferenceContext}; /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. @@ -50,6 +54,8 @@ pub(crate) fn dump_polonius_mir<'tcx>( /// - the NLL MIR /// - the list of polonius localized constraints /// - a mermaid graph of the CFG +/// - a mermaid graph of the NLL regions and the constraints between them +/// - a mermaid graph of the NLL SCCs and the constraints between them fn emit_polonius_dump<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -68,7 +74,7 @@ fn emit_polonius_dump<'tcx>( // Section 1: the NLL + Polonius MIR. writeln!(out, "
")?; writeln!(out, "Raw MIR dump")?; - writeln!(out, "
")?;
+    writeln!(out, "
")?;
     emit_html_mir(
         tcx,
         body,
@@ -78,15 +84,31 @@ fn emit_polonius_dump<'tcx>(
         closure_region_requirements,
         out,
     )?;
-    writeln!(out, "
")?; + writeln!(out, "
")?; writeln!(out, "
")?; // Section 2: mermaid visualization of the CFG. writeln!(out, "
")?; writeln!(out, "Control-flow graph")?; - writeln!(out, "
")?;
+    writeln!(out, "
")?;
     emit_mermaid_cfg(body, out)?;
-    writeln!(out, "
")?; + writeln!(out, "
")?; + writeln!(out, "
")?; + + // Section 3: mermaid visualization of the NLL region graph. + writeln!(out, "
")?; + writeln!(out, "NLL regions")?; + writeln!(out, "
")?;
+    emit_mermaid_nll_regions(regioncx, out)?;
+    writeln!(out, "
")?; + writeln!(out, "
")?; + + // Section 4: mermaid visualization of the NLL SCC graph. + writeln!(out, "
")?; + writeln!(out, "NLL SCCs")?; + writeln!(out, "
")?;
+    emit_mermaid_nll_sccs(regioncx, out)?;
+    writeln!(out, "
")?; writeln!(out, "
")?; // Finalize the dump with the HTML epilogue. @@ -261,3 +283,112 @@ fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()> Ok(()) } + +/// Emits a region's label: index, universe, external name. +fn render_region( + region: RegionVid, + regioncx: &RegionInferenceContext<'_>, + out: &mut dyn io::Write, +) -> io::Result<()> { + let def = regioncx.region_definition(region); + let universe = def.universe; + + write!(out, "'{}", region.as_usize())?; + if !universe.is_root() { + write!(out, "/{universe:?}")?; + } + if let Some(name) = def.external_name.and_then(|e| e.get_name()) { + write!(out, " ({name})")?; + } + Ok(()) +} + +/// Emits a mermaid flowchart of the NLL regions and the outlives constraints between them, similar +/// to the graphviz version. +fn emit_mermaid_nll_regions<'tcx>( + regioncx: &RegionInferenceContext<'tcx>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // The mermaid chart type: a top-down flowchart. + writeln!(out, "flowchart TD")?; + + // Emit the region nodes. + for region in regioncx.var_infos.indices() { + write!(out, "{}[\"", region.as_usize())?; + render_region(region, regioncx, out)?; + writeln!(out, "\"]")?; + } + + // Get a set of edges to check for the reverse edge being present. + let edges: FxHashSet<_> = regioncx.outlives_constraints().map(|c| (c.sup, c.sub)).collect(); + + // Order (and deduplicate) edges for traversal, to display them in a generally increasing order. + let constraint_key = |c: &OutlivesConstraint<'_>| { + let min = c.sup.min(c.sub); + let max = c.sup.max(c.sub); + (min, max) + }; + let mut ordered_edges: Vec<_> = regioncx.outlives_constraints().collect(); + ordered_edges.sort_by_key(|c| constraint_key(c)); + ordered_edges.dedup_by_key(|c| constraint_key(c)); + + for outlives in ordered_edges { + // Source node. + write!(out, "{} ", outlives.sup.as_usize())?; + + // The kind of arrow: bidirectional if the opposite edge exists in the set. + if edges.contains(&(outlives.sub, outlives.sup)) { + write!(out, "<")?; + } + write!(out, "-- ")?; + + // Edge label from its `Locations`. + match outlives.locations { + Locations::All(_) => write!(out, "All")?, + Locations::Single(location) => write!(out, "{:?}", location)?, + } + + // Target node. + writeln!(out, " --> {}", outlives.sub.as_usize())?; + } + Ok(()) +} + +/// Emits a mermaid flowchart of the NLL SCCs and the outlives constraints between them, similar +/// to the graphviz version. +fn emit_mermaid_nll_sccs<'tcx>( + regioncx: &RegionInferenceContext<'tcx>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // The mermaid chart type: a top-down flowchart. + writeln!(out, "flowchart TD")?; + + // Gather and emit the SCC nodes. + let mut nodes_per_scc: IndexVec<_, _> = + regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect(); + for region in regioncx.var_infos.indices() { + let scc = regioncx.constraint_sccs().scc(region); + nodes_per_scc[scc].push(region); + } + for (scc, regions) in nodes_per_scc.iter_enumerated() { + // The node label: the regions contained in the SCC. + write!(out, "{scc}[\"SCC({scc}) = {{", scc = scc.as_usize())?; + for (idx, ®ion) in regions.iter().enumerate() { + render_region(region, regioncx, out)?; + if idx < regions.len() - 1 { + write!(out, ",")?; + } + } + writeln!(out, "}}\"]")?; + } + + // Emit the edges between SCCs. + let edges = regioncx.constraint_sccs().all_sccs().flat_map(|source| { + regioncx.constraint_sccs().successors(source).iter().map(move |&target| (source, target)) + }); + for (source, target) in edges { + writeln!(out, "{} --> {}", source.as_usize(), target.as_usize())?; + } + + Ok(()) +} diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 74d02ac22276c..9495030f124b5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -797,7 +797,6 @@ fn test_unstable_options_tracking_hash() { tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); tracked!(incremental_ignore_spans, true); - tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); tracked!(inline_mir_threshold, Some(123)); diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 3eccf56d8c4dd..6fa3fa2432de5 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -91,13 +91,8 @@ impl<'tcx> MonoItem<'tcx> { } pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode { - let generate_cgu_internal_copies = tcx - .sess - .opts - .unstable_opts - .inline_in_all_cgus - .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No) - && !tcx.sess.link_dead_code(); + let generate_cgu_internal_copies = + (tcx.sess.opts.optimize != OptLevel::No) && !tcx.sess.link_dead_code(); match *self { MonoItem::Fn(ref instance) => { @@ -121,8 +116,8 @@ impl<'tcx> MonoItem<'tcx> { } // At this point we don't have explicit linkage and we're an - // inlined function. If we're inlining into all CGUs then we'll - // be creating a local copy per CGU. + // inlined function. If this crate's build settings permit, + // we'll be creating a local copy per CGU. if generate_cgu_internal_copies { return InstantiationMode::LocalCopy; } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 50287b706ce83..2373ab67d42ed 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2830,9 +2830,10 @@ pub(crate) struct DynAfterMut { pub(crate) struct FnPointerCannotBeConst { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] #[label] pub qualifier: Span, + #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] @@ -2840,9 +2841,10 @@ pub(crate) struct FnPointerCannotBeConst { pub(crate) struct FnPointerCannotBeAsync { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] #[label] pub qualifier: Span, + #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6497d19a173ca..dc5919b3630ce 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -609,16 +609,58 @@ impl<'a> Parser<'a> { let span_start = self.token.span; let ast::FnHeader { ext, safety, constness, coroutine_kind } = self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?; + let fn_start_lo = self.prev_token.span.lo(); if self.may_recover() && self.token == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; } let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); - if let ast::Const::Yes(span) = constness { - self.dcx().emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span }); + + // Order/parsing of "front matter" follows: + // ` fn()` + // ^ ^ ^ ^ ^ + // | | | | fn_start_lo + // | | | ext_sp.lo + // | | safety_sp.lo + // | coroutine_sp.lo + // const_sp.lo + if let ast::Const::Yes(const_span) = constness { + let next_token_lo = if let Some( + ast::CoroutineKind::Async { span, .. } + | ast::CoroutineKind::Gen { span, .. } + | ast::CoroutineKind::AsyncGen { span, .. }, + ) = coroutine_kind + { + span.lo() + } else if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety { + span.lo() + } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext { + span.lo() + } else { + fn_start_lo + }; + let sugg_span = const_span.with_hi(next_token_lo); + self.dcx().emit_err(FnPointerCannotBeConst { + span: whole_span, + qualifier: const_span, + suggestion: sugg_span, + }); } - if let Some(ast::CoroutineKind::Async { span, .. }) = coroutine_kind { - self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span }); + if let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind { + let next_token_lo = if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety + { + span.lo() + } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext { + span.lo() + } else { + fn_start_lo + }; + let sugg_span = async_span.with_hi(next_token_lo); + self.dcx().emit_err(FnPointerCannotBeAsync { + span: whole_span, + qualifier: async_span, + suggestion: sugg_span, + }); } // FIXME(gen_blocks): emit a similar error for `gen fn()` let decl_span = span_start.to(self.prev_token.span); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 63aaa3abc8e56..4ce6382512978 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1870,8 +1870,6 @@ options! { "verify extended properties for incr. comp. (default: no): - hashes of green query instances - hash collisions of query keys"), - inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], - "control whether `#[inline]` functions are in all CGUs"), inline_llvm: bool = (true, parse_bool, [TRACKED], "enable LLVM inlining (default: yes)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED], diff --git a/library/core/src/iter/sources/from_fn.rs b/library/core/src/iter/sources/from_fn.rs index 5f3d404d7dca2..75cc0ffe3c77c 100644 --- a/library/core/src/iter/sources/from_fn.rs +++ b/library/core/src/iter/sources/from_fn.rs @@ -1,7 +1,7 @@ use crate::fmt; -/// Creates a new iterator where each iteration calls the provided closure -/// `F: FnMut() -> Option`. +/// Creates an iterator with the provided closure +/// `F: FnMut() -> Option` as its `[next](Iterator::next)` method. /// /// The iterator will yield the `T`s returned from the closure. /// diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile index 6f33c63218182..2b8a3f829c608 100644 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -20,6 +20,7 @@ RUN yum upgrade -y && \ gcc-c++ \ git \ glibc-devel \ + glibc-static \ libedit-devel \ libstdc++-devel \ make \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 3a39623058255..0b4682ac32ba0 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -21,6 +21,8 @@ RUN yum upgrade -y && \ git \ glibc-devel.i686 \ glibc-devel.x86_64 \ + glibc-static.i686 \ + glibc-static.x86_64 \ libedit-devel \ libstdc++-devel.i686 \ libstdc++-devel.x86_64 \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7730d29d28f68..4c4863e2b4b3e 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -86,7 +86,7 @@ envs: # builds) # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain # - # If you *want* these to happen however, temporarily uncomment it before triggering a try build. + # If you *want* these to happen however, temporarily comment it before triggering a try build. DIST_TRY_BUILD: 1 auto: diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index aa05b5f0e76ca..04de3493ea29c 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -148,18 +148,15 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> let is_aarch64 = target_triple.starts_with("aarch64"); - let mut skip_tests = vec![ - // Fails because of linker errors, as of June 2023. - "tests/ui/process/nofile-limit.rs".to_string(), - ]; - - if is_aarch64 { - skip_tests.extend([ + let skip_tests = if is_aarch64 { + vec![ // Those tests fail only inside of Docker on aarch64, as of December 2024 "tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs".to_string(), "tests/ui/consts/large_const_alloc.rs".to_string(), - ]); - } + ] + } else { + vec![] + }; let checkout_dir = Utf8PathBuf::from("/checkout"); let env = EnvironmentBuilder::default() @@ -191,10 +188,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .build_dir(checkout_dir) .shared_llvm(false) .use_bolt(false) - .skipped_tests(vec![ - // Fails as of June 2023. - "tests\\codegen\\vec-shrink-panik.rs".to_string(), - ]) + .skipped_tests(vec![]) .build()?; (env, shared.build_args) diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs index e1887b93b93a0..a57b102a5fd21 100644 --- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -1,7 +1,6 @@ -// //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus //@ compile-flags:-Zinline-mir=no +//@ compile-flags: -O #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs index 6ecf98a032f52..c0d2e899bbc86 100644 --- a/tests/codegen-units/item-collection/generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/generic-drop-glue.rs @@ -1,6 +1,5 @@ -// //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus +//@ compile-flags: -O #![deny(dead_code)] #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index 9087fc6410ab5..ee0b5dc1dd2cb 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -1,5 +1,4 @@ -// -//@ compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0 +//@ compile-flags:-Zprint-mono-items=eager -Zmir-opt-level=0 #![deny(dead_code)] #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs index c4d7942ba1ed9..2eeccd2e99f2d 100644 --- a/tests/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs @@ -1,6 +1,5 @@ -// //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus +//@ compile-flags: -O #![deny(dead_code)] #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/transitive-drop-glue.rs b/tests/codegen-units/item-collection/transitive-drop-glue.rs index 18954fab86f66..b999e466d54b7 100644 --- a/tests/codegen-units/item-collection/transitive-drop-glue.rs +++ b/tests/codegen-units/item-collection/transitive-drop-glue.rs @@ -1,6 +1,5 @@ -// //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus +//@ compile-flags: -O #![deny(dead_code)] #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/tuple-drop-glue.rs b/tests/codegen-units/item-collection/tuple-drop-glue.rs index 2e70d0151eb7c..5e97fbb43368a 100644 --- a/tests/codegen-units/item-collection/tuple-drop-glue.rs +++ b/tests/codegen-units/item-collection/tuple-drop-glue.rs @@ -1,6 +1,5 @@ -// //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus +//@ compile-flags: -O #![deny(dead_code)] #![crate_type = "lib"] diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 23e6003dc19fd..97adf72ce2c9b 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -1,5 +1,4 @@ //@ compile-flags:-Zprint-mono-items=eager -//@ compile-flags:-Zinline-in-all-cgus //@ compile-flags:-Zmir-opt-level=0 #![deny(dead_code)] diff --git a/tests/codegen-units/partitioning/README.md b/tests/codegen-units/partitioning/README.md new file mode 100644 index 0000000000000..5dd6b1281fd9d --- /dev/null +++ b/tests/codegen-units/partitioning/README.md @@ -0,0 +1,14 @@ +# codegen-units/partitioning tests + +This test suite is designed to test that codegen unit partitioning works as intended. +Note that it does not evaluate whether CGU partitioning is *good*. That is the job of the compiler benchmark suite. + +All tests in this suite use the flag `-Zprint-mono-items=lazy`, which makes the compiler print a machine-readable summary of all MonoItems that were collected, which CGUs they were assigned to, and the linkage in each CGU. The output looks like: +``` +MONO_ITEM @@ [] [] +``` +DO NOT add tests to this suite that use `-Zprint-mono-items=eager`. That flag changes the way that MonoItem collection works in rather fundamental ways that are otherwise only used by `-Clink-dead-code`, and thus the MonoItems collected and their linkage under `-Zprint-mono-items=eager` does not correlate very well with normal compilation behavior. + +The current CGU partitioning algorithm essentially groups MonoItems by which module they are defined in, then merges small CGUs. There are a lot of inline modules in this test suite because that's the only way to observe the partitioning. + +Currently, the test suite is very heavily biased towards incremental builds with -Copt-level=0. This is mostly an accident of history; the entire test suite was added as part of supporting incremental compilation in #32779. But also CGU partitioning is *mostly* valuable because the CGU is the unit of incrementality to the codegen backend (cached queries are the unit of incrementality for the rest of the compiler). diff --git a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs index b6c568ed387a1..d3517df03763e 100644 --- a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs +++ b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs @@ -1,7 +1,6 @@ // 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 +//@ compile-flags: -Zshare-generics=yes -Copt-level=0 #![crate_type = "rlib"] diff --git a/tests/codegen-units/partitioning/extern-drop-glue.rs b/tests/codegen-units/partitioning/extern-drop-glue.rs index d3bce7b4223cc..ca78c175dbf34 100644 --- a/tests/codegen-units/partitioning/extern-drop-glue.rs +++ b/tests/codegen-units/partitioning/extern-drop-glue.rs @@ -1,15 +1,14 @@ -// 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 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![allow(dead_code)] #![crate_type = "rlib"] //@ aux-build:cgu_extern_drop_glue.rs extern crate cgu_extern_drop_glue; +// This test checks that drop glue is generated, even for types not defined in this crate, and all +// drop glue is put in the fallback CGU. + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(cgu_extern_drop_glue::Struct)) @@ extern_drop_glue-fallback.cgu[External] struct LocalStruct(cgu_extern_drop_glue::Struct); diff --git a/tests/codegen-units/partitioning/extern-generic.rs b/tests/codegen-units/partitioning/extern-generic.rs index 602a5240283bc..875ebb3098e56 100644 --- a/tests/codegen-units/partitioning/extern-generic.rs +++ b/tests/codegen-units/partitioning/extern-generic.rs @@ -1,51 +1,36 @@ -// We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental -//@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=y +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![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() { +// This test checks that, in an unoptimized build, a generic function and its callees are only +// instantiated once in this crate. + +//~ MONO_ITEM fn user @@ extern_generic[External] +pub fn user() { let _ = cgu_generic_function::foo("abc"); } -mod mod1 { +pub mod mod1 { use cgu_generic_function; - //~ MONO_ITEM fn mod1::user @@ extern_generic-mod1[Internal] - fn user() { + //~ MONO_ITEM fn mod1::user @@ extern_generic-mod1[External] + pub fn user() { let _ = cgu_generic_function::foo("abc"); } - mod mod1 { + pub mod mod1 { use cgu_generic_function; - //~ MONO_ITEM fn mod1::mod1::user @@ extern_generic-mod1-mod1[Internal] - fn user() { + //~ MONO_ITEM fn mod1::mod1::user @@ extern_generic-mod1-mod1[External] + pub 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 index 6834bb2bebf5c..68eee803e5f22 100644 --- a/tests/codegen-units/partitioning/incremental-merging.rs +++ b/tests/codegen-units/partitioning/incremental-merging.rs @@ -1,7 +1,5 @@ -// 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 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -Ccodegen-units=3 #![crate_type = "rlib"] @@ -9,8 +7,9 @@ // 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. +// CGU partitioning creates one CGU per module, so with 4 modules and codegen-units=3, +// two of the modules should be merged. We expect CGUs `aaa` and `bbb` to be merged +// (because they are the smallest), while `ccc` and `ddd` should stay untouched. pub mod aaa { //~ MONO_ITEM fn aaa::foo @@ incremental_merging-aaa--incremental_merging-bbb[External] diff --git a/tests/codegen-units/partitioning/inline-always.rs b/tests/codegen-units/partitioning/inline-always.rs new file mode 100644 index 0000000000000..5e8cce0ac337b --- /dev/null +++ b/tests/codegen-units/partitioning/inline-always.rs @@ -0,0 +1,38 @@ +//@ incremental +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 + +#![crate_type = "lib"] + +// This test checks that a monomorphic inline(always) function is instantiated in every CGU that +// references it, even though this is an unoptimized incremental build. +// It also checks that an inline(always) function is only placed in CGUs that reference it. + +mod inline { + //~ MONO_ITEM fn inline::inlined_function @@ inline_always-user1[Internal] inline_always-user2[Internal] + #[inline(always)] + pub fn inlined_function() {} +} + +pub mod user1 { + use super::inline; + + //~ MONO_ITEM fn user1::foo @@ inline_always-user1[External] + pub fn foo() { + inline::inlined_function(); + } +} + +pub mod user2 { + use super::inline; + + //~ MONO_ITEM fn user2::bar @@ inline_always-user2[External] + pub fn bar() { + inline::inlined_function(); + } +} + +pub mod non_user { + + //~ MONO_ITEM fn non_user::baz @@ inline_always-non_user[External] + pub fn baz() {} +} diff --git a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs index b007ffe1cb510..d321c88d03a6e 100644 --- a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -1,7 +1,5 @@ -// 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 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=1 #![crate_type = "lib"] diff --git a/tests/codegen-units/partitioning/local-drop-glue.rs b/tests/codegen-units/partitioning/local-drop-glue.rs index 5fa1df95cbc82..240f64e4f7021 100644 --- a/tests/codegen-units/partitioning/local-drop-glue.rs +++ b/tests/codegen-units/partitioning/local-drop-glue.rs @@ -1,14 +1,14 @@ -// 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 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![allow(dead_code)] #![crate_type = "rlib"] +// This test checks that drop glue is generated for types defined in this crate, and that all drop +// glue is put in the fallback CGU. +// This is rather similar to extern-drop-glue.rs. + //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(Struct)) @@ local_drop_glue-fallback.cgu[External] -struct Struct { +pub struct Struct { _a: u32, } @@ -18,7 +18,7 @@ impl Drop for Struct { } //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(Outer)) @@ local_drop_glue-fallback.cgu[External] -struct Outer { +pub struct Outer { _a: Struct, } @@ -33,7 +33,7 @@ pub mod mod1 { //~ MONO_ITEM fn std::ptr::drop_in_place:: - 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] + //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Struct)> - shim(Some((u32, Struct))) @@ local_drop_glue-fallback.cgu[External] _b: (u32, Struct), } diff --git a/tests/codegen-units/partitioning/local-generic.rs b/tests/codegen-units/partitioning/local-generic.rs index 0cfc572650c1f..177eb2632f640 100644 --- a/tests/codegen-units/partitioning/local-generic.rs +++ b/tests/codegen-units/partitioning/local-generic.rs @@ -1,10 +1,11 @@ -// We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental -//@ compile-flags:-Zprint-mono-items=eager +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![allow(dead_code)] #![crate_type = "lib"] +// This test checks that all the instantiations of a local generic fn are placed in the same CGU, +// regardless of where it is called. + //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] @@ -13,34 +14,34 @@ pub fn generic(x: T) -> T { x } -//~ MONO_ITEM fn user @@ local_generic[Internal] -fn user() { +//~ MONO_ITEM fn user @@ local_generic[External] +pub fn user() { let _ = generic(0u32); } -mod mod1 { +pub mod mod1 { pub use super::generic; - //~ MONO_ITEM fn mod1::user @@ local_generic-mod1[Internal] - fn user() { + //~ MONO_ITEM fn mod1::user @@ local_generic-mod1[External] + pub fn user() { let _ = generic(0u64); } - mod mod1 { + pub mod mod1 { use super::generic; - //~ MONO_ITEM fn mod1::mod1::user @@ local_generic-mod1-mod1[Internal] - fn user() { + //~ MONO_ITEM fn mod1::mod1::user @@ local_generic-mod1-mod1[External] + pub fn user() { let _ = generic('c'); } } } -mod mod2 { +pub mod mod2 { use super::generic; - //~ MONO_ITEM fn mod2::user @@ local_generic-mod2[Internal] - fn user() { + //~ MONO_ITEM fn mod2::user @@ local_generic-mod2[External] + pub 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 deleted file mode 100644 index 454de255254a4..0000000000000 --- a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs +++ /dev/null @@ -1,38 +0,0 @@ -// 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 deleted file mode 100644 index 42c68b5c62186..0000000000000 --- a/tests/codegen-units/partitioning/local-inlining.rs +++ /dev/null @@ -1,39 +0,0 @@ -// 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 index 0d279ebe74041..bcd32bd2e264e 100644 --- a/tests/codegen-units/partitioning/local-transitive-inlining.rs +++ b/tests/codegen-units/partitioning/local-transitive-inlining.rs @@ -1,11 +1,13 @@ -// 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 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![allow(dead_code)] #![crate_type = "rlib"] +// This test checks that a monomorphic inline(always) function is instantiated in every CGU that +// references it, even if it is only referenced via another module. +// The modules `inline` and `direct_user` do not get CGUs because they only define inline(always) +// functions, which always get lazy codegen. + mod inline { //~ MONO_ITEM fn inline::inlined_function @@ local_transitive_inlining-indirect_user[Internal] @@ -13,7 +15,7 @@ mod inline { pub fn inlined_function() {} } -mod direct_user { +pub mod direct_user { use super::inline; //~ MONO_ITEM fn direct_user::foo @@ local_transitive_inlining-indirect_user[Internal] diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs index 94d06829c6c35..4d3f946fd9538 100644 --- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs @@ -1,9 +1,11 @@ -// We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental -//@ compile-flags:-Zprint-mono-items=lazy +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 #![crate_type = "lib"] +// This test ensures that methods are assigned to the module where their self-type is defined, not +// where the method is defined. + pub struct SomeType; struct SomeGenericType(T1, T2); diff --git a/tests/codegen-units/partitioning/regular-modules.rs b/tests/codegen-units/partitioning/regular-modules.rs index 2949714641557..d59074e7e3471 100644 --- a/tests/codegen-units/partitioning/regular-modules.rs +++ b/tests/codegen-units/partitioning/regular-modules.rs @@ -1,71 +1,71 @@ -// We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental -//@ compile-flags:-Zprint-mono-items=eager +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -#![allow(dead_code)] #![crate_type = "lib"] -//~ MONO_ITEM fn foo @@ regular_modules[Internal] -fn foo() {} +// This test ensures that regular fn items and statics are assigned to the CGU of their module. -//~ MONO_ITEM fn bar @@ regular_modules[Internal] -fn bar() {} +//~ MONO_ITEM fn foo @@ regular_modules[External] +pub fn foo() {} -//~ MONO_ITEM static BAZ @@ regular_modules[Internal] -static BAZ: u64 = 0; +//~ MONO_ITEM fn bar @@ regular_modules[External] +pub fn bar() {} -mod mod1 { +//~ MONO_ITEM static BAZ @@ regular_modules[External] +pub static BAZ: u64 = 0; - //~ 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; +pub mod mod1 { - 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; + //~ MONO_ITEM fn mod1::foo @@ regular_modules-mod1[External] + pub fn foo() {} + //~ MONO_ITEM fn mod1::bar @@ regular_modules-mod1[External] + pub fn bar() {} + //~ MONO_ITEM static mod1::BAZ @@ regular_modules-mod1[External] + pub static BAZ: u64 = 0; + + pub mod mod1 { + //~ MONO_ITEM fn mod1::mod1::foo @@ regular_modules-mod1-mod1[External] + pub fn foo() {} + //~ MONO_ITEM fn mod1::mod1::bar @@ regular_modules-mod1-mod1[External] + pub fn bar() {} + //~ MONO_ITEM static mod1::mod1::BAZ @@ regular_modules-mod1-mod1[External] + pub 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; + pub mod mod2 { + //~ MONO_ITEM fn mod1::mod2::foo @@ regular_modules-mod1-mod2[External] + pub fn foo() {} + //~ MONO_ITEM fn mod1::mod2::bar @@ regular_modules-mod1-mod2[External] + pub fn bar() {} + //~ MONO_ITEM static mod1::mod2::BAZ @@ regular_modules-mod1-mod2[External] + pub static BAZ: u64 = 0; } } -mod mod2 { +pub 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; + //~ MONO_ITEM fn mod2::foo @@ regular_modules-mod2[External] + pub fn foo() {} + //~ MONO_ITEM fn mod2::bar @@ regular_modules-mod2[External] + pub fn bar() {} + //~ MONO_ITEM static mod2::BAZ @@ regular_modules-mod2[External] + pub 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; + pub mod mod1 { + //~ MONO_ITEM fn mod2::mod1::foo @@ regular_modules-mod2-mod1[External] + pub fn foo() {} + //~ MONO_ITEM fn mod2::mod1::bar @@ regular_modules-mod2-mod1[External] + pub fn bar() {} + //~ MONO_ITEM static mod2::mod1::BAZ @@ regular_modules-mod2-mod1[External] + pub 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; + pub mod mod2 { + //~ MONO_ITEM fn mod2::mod2::foo @@ regular_modules-mod2-mod2[External] + pub fn foo() {} + //~ MONO_ITEM fn mod2::mod2::bar @@ regular_modules-mod2-mod2[External] + pub fn bar() {} + //~ MONO_ITEM static mod2::mod2::BAZ @@ regular_modules-mod2-mod2[External] + pub static BAZ: u64 = 0; } } diff --git a/tests/codegen-units/partitioning/shared-generics.rs b/tests/codegen-units/partitioning/shared-generics.rs index ea312719ac918..b5bf376a6134a 100644 --- a/tests/codegen-units/partitioning/shared-generics.rs +++ b/tests/codegen-units/partitioning/shared-generics.rs @@ -2,13 +2,19 @@ // 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 +//@ compile-flags: -Zprint-mono-items=lazy -Zshare-generics=yes -Copt-level=0 #![crate_type = "rlib"] //@ aux-build:shared_generics_aux.rs extern crate shared_generics_aux; +// This test ensures that when a crate and a dependency are compiled with -Zshare-generics, the +// downstream crate reuses generic instantiations from the dependency, but will still instantiate +// its own copy when instantiating with arguments that the dependency did not. +// Drop glue has a lot of special handling in the compiler, so we check that drop glue is also +// shared. + //~ MONO_ITEM fn foo pub fn foo() { //~ MONO_ITEM fn shared_generics_aux::generic_fn:: @@ shared_generics_aux-in-shared_generics.volatile[External] diff --git a/tests/codegen-units/partitioning/statics.rs b/tests/codegen-units/partitioning/statics.rs index 00dd6d877e1e2..72bca4c5ed36a 100644 --- a/tests/codegen-units/partitioning/statics.rs +++ b/tests/codegen-units/partitioning/statics.rs @@ -1,9 +1,11 @@ -// We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental -//@ compile-flags:-Zprint-mono-items=lazy +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 #![crate_type = "rlib"] +// This test ensures that statics are assigned to the correct module when they are defined inside +// of a function. + //~ MONO_ITEM static FOO @@ statics[Internal] static FOO: u32 = 0; diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs index 3880bba6f6b32..fd73e3fe9238d 100644 --- a/tests/codegen-units/partitioning/vtable-through-const.rs +++ b/tests/codegen-units/partitioning/vtable-through-const.rs @@ -1,14 +1,11 @@ -// 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 // Need to disable optimizations to ensure consistent output across all CI runners. -//@ compile-flags:-Copt-level=0 +//@ compile-flags: -Zprint-mono-items=lazy -Copt-level=0 -// This test case makes sure, that references made through constants are -// recorded properly in the InliningMap. +#![crate_type = "rlib"] -#![crate_type = "lib"] +// This test case makes sure that references made through constants cause trait associated methods +// to be monomorphized when required. mod mod1 { struct NeedsDrop; @@ -43,7 +40,7 @@ mod mod1 { x } - // These are referenced, so they produce mono-items (see start()) + // These are referenced, so they produce mono-items (see main) pub const TRAIT1_REF: &'static Trait1 = &NeedsDrop as &Trait1; pub const TRAIT1_GEN_REF: &'static Trait1Gen = &NeedsDrop as &Trait1Gen; pub const ID_CHAR: fn(char) -> char = id::; @@ -77,9 +74,8 @@ mod mod1 { pub const ID_I64: fn(i64) -> i64 = id::; } -//~ MONO_ITEM fn start -#[no_mangle] -pub fn start(_: isize, _: *const *const u8) -> isize { +//~ MONO_ITEM fn main @@ vtable_through_const[External] +pub fn main() { //~ MONO_ITEM fn ::drop @@ vtable_through_const-fallback.cgu[External] //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(mod1::NeedsDrop)) @@ vtable_through_const-fallback.cgu[External] @@ -103,6 +99,4 @@ pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn mod1::id:: @@ vtable_through_const-mod1.volatile[External] mod1::ID_CHAR('x'); - - 0 } diff --git a/tests/run-make/sepcomp-cci-copies/cci_lib.rs b/tests/run-make/sepcomp-cci-copies/cci_lib.rs deleted file mode 100644 index 869d4a6cd3e4e..0000000000000 --- a/tests/run-make/sepcomp-cci-copies/cci_lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![crate_type = "rlib"] - -#[inline] -pub fn cci_fn() -> usize { - 1234 -} diff --git a/tests/run-make/sepcomp-cci-copies/foo.rs b/tests/run-make/sepcomp-cci-copies/foo.rs deleted file mode 100644 index ba251fcb0ac24..0000000000000 --- a/tests/run-make/sepcomp-cci-copies/foo.rs +++ /dev/null @@ -1,25 +0,0 @@ -extern crate cci_lib; -use cci_lib::cci_fn; - -fn call1() -> usize { - cci_fn() -} - -mod a { - use cci_lib::cci_fn; - pub fn call2() -> usize { - cci_fn() - } -} - -mod b { - pub fn call3() -> usize { - 0 - } -} - -fn main() { - call1(); - a::call2(); - b::call3(); -} diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs deleted file mode 100644 index a66cc2872b434..0000000000000 --- a/tests/run-make/sepcomp-cci-copies/rmake.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Check that cross-crate inlined items are inlined in all compilation units -// that refer to them, and not in any other compilation units. -// Note that we have to pass `-C codegen-units=6` because up to two CGUs may be -// created for each source module (see `rustc_const_eval::monomorphize::partitioning`). -// See https://github.com/rust-lang/rust/pull/16367 - -use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; - -fn main() { - rustc().input("cci_lib.rs").run(); - rustc().input("foo.rs").emit("llvm-ir").codegen_units(6).arg("-Zinline-in-all-cgus").run(); - let re = regex::Regex::new(r#"define\ .*cci_fn"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); -} diff --git a/tests/run-make/sepcomp-inlining/foo.rs b/tests/run-make/sepcomp-inlining/foo.rs deleted file mode 100644 index 9101ee691a4e0..0000000000000 --- a/tests/run-make/sepcomp-inlining/foo.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![crate_type = "lib"] - -#[inline] -fn inlined() -> u32 { - 1234 -} - -fn normal() -> u32 { - 2345 -} - -mod a { - pub fn f() -> u32 { - ::inlined() + ::normal() - } -} - -mod b { - pub fn f() -> u32 { - ::inlined() + ::normal() - } -} - -pub fn start(_: isize, _: *const *const u8) -> isize { - a::f(); - b::f(); - - 0 -} diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs deleted file mode 100644 index ea4a4d210cc3e..0000000000000 --- a/tests/run-make/sepcomp-inlining/rmake.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Test that #[inline] functions still get inlined across compilation unit -// boundaries. Compilation should produce three IR files, but only the two -// compilation units that have a usage of the #[inline] function should -// contain a definition. Also, the non-#[inline] function should be defined -// in only one compilation unit. -// See https://github.com/rust-lang/rust/pull/16367 - -use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; - -fn main() { - rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).arg("-Zinline-in-all-cgus").run(); - let re = regex::Regex::new(r#"define\ i32\ .*inlined"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 0); - let re = regex::Regex::new(r#"define\ internal\ .*inlined"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); - let re = regex::Regex::new(r#"define\ hidden\ i32\ .*normal"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 1); - let re = regex::Regex::new(r#"declare\ hidden\ i32\ .*normal"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); -} diff --git a/tests/run-make/sepcomp-separate/foo.rs b/tests/run-make/sepcomp-separate/foo.rs deleted file mode 100644 index 169bafa9b3a50..0000000000000 --- a/tests/run-make/sepcomp-separate/foo.rs +++ /dev/null @@ -1,21 +0,0 @@ -fn magic_fn() -> usize { - 1234 -} - -mod a { - pub fn magic_fn() -> usize { - 2345 - } -} - -mod b { - pub fn magic_fn() -> usize { - 3456 - } -} - -fn main() { - magic_fn(); - a::magic_fn(); - b::magic_fn(); -} diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs deleted file mode 100644 index 49958044a612a..0000000000000 --- a/tests/run-make/sepcomp-separate/rmake.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Test that separate compilation actually puts code into separate compilation -// units. `foo.rs` defines `magic_fn` in three different modules, which should -// wind up in three different compilation units. -// See https://github.com/rust-lang/rust/pull/16367 - -use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; - -fn main() { - rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run(); - let re = regex::Regex::new(r#"define\ .*magic_fn"#).unwrap(); - assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 3); -} diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.fixed b/tests/ui/parser/bad-fn-ptr-qualifier.fixed index e2a2f9486b785..8a97a2f09ccab 100644 --- a/tests/ui/parser/bad-fn-ptr-qualifier.fixed +++ b/tests/ui/parser/bad-fn-ptr-qualifier.fixed @@ -2,24 +2,24 @@ //@ edition:2018 // Most of items are taken from ./recover-const-async-fn-ptr.rs but this is able to apply rustfix. -pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T6 = unsafe extern "C" fn(); +pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T6 = unsafe extern "C" fn(); //~^ ERROR an `fn` pointer type cannot be `const` //~| ERROR an `fn` pointer type cannot be `async` -pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type FTT5 = for<'a> unsafe extern "C" fn(); +pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT5 = for<'a> unsafe extern "C" fn(); //~^ ERROR an `fn` pointer type cannot be `async` -pub type FTT6 = for<'a> unsafe extern "C" fn(); +pub type FTT6 = for<'a> unsafe extern "C" fn(); //~^ ERROR an `fn` pointer type cannot be `const` //~| ERROR an `fn` pointer type cannot be `async` diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.stderr b/tests/ui/parser/bad-fn-ptr-qualifier.stderr index ddc8bac678cfb..b9d2625d9f4be 100644 --- a/tests/ui/parser/bad-fn-ptr-qualifier.stderr +++ b/tests/ui/parser/bad-fn-ptr-qualifier.stderr @@ -9,7 +9,7 @@ LL | pub type T0 = const fn(); help: remove the `const` qualifier | LL - pub type T0 = const fn(); -LL + pub type T0 = fn(); +LL + pub type T0 = fn(); | error: an `fn` pointer type cannot be `const` @@ -23,7 +23,7 @@ LL | pub type T1 = const extern "C" fn(); help: remove the `const` qualifier | LL - pub type T1 = const extern "C" fn(); -LL + pub type T1 = extern "C" fn(); +LL + pub type T1 = extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -37,7 +37,7 @@ LL | pub type T2 = const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type T2 = const unsafe extern "C" fn(); -LL + pub type T2 = unsafe extern "C" fn(); +LL + pub type T2 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -51,7 +51,7 @@ LL | pub type T3 = async fn(); help: remove the `async` qualifier | LL - pub type T3 = async fn(); -LL + pub type T3 = fn(); +LL + pub type T3 = fn(); | error: an `fn` pointer type cannot be `async` @@ -65,7 +65,7 @@ LL | pub type T4 = async extern "C" fn(); help: remove the `async` qualifier | LL - pub type T4 = async extern "C" fn(); -LL + pub type T4 = extern "C" fn(); +LL + pub type T4 = extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -79,7 +79,7 @@ LL | pub type T5 = async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type T5 = async unsafe extern "C" fn(); -LL + pub type T5 = unsafe extern "C" fn(); +LL + pub type T5 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -93,7 +93,7 @@ LL | pub type T6 = const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type T6 = const async unsafe extern "C" fn(); -LL + pub type T6 = async unsafe extern "C" fn(); +LL + pub type T6 = async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -107,7 +107,7 @@ LL | pub type T6 = const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type T6 = const async unsafe extern "C" fn(); -LL + pub type T6 = const unsafe extern "C" fn(); +LL + pub type T6 = const unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -121,7 +121,7 @@ LL | pub type FTT0 = for<'a> const fn(); help: remove the `const` qualifier | LL - pub type FTT0 = for<'a> const fn(); -LL + pub type FTT0 = for<'a> fn(); +LL + pub type FTT0 = for<'a> fn(); | error: an `fn` pointer type cannot be `const` @@ -135,7 +135,7 @@ LL | pub type FTT1 = for<'a> const extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT1 = for<'a> const extern "C" fn(); -LL + pub type FTT1 = for<'a> extern "C" fn(); +LL + pub type FTT1 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -149,7 +149,7 @@ LL | pub type FTT2 = for<'a> const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT2 = for<'a> const unsafe extern "C" fn(); -LL + pub type FTT2 = for<'a> unsafe extern "C" fn(); +LL + pub type FTT2 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -163,7 +163,7 @@ LL | pub type FTT3 = for<'a> async fn(); help: remove the `async` qualifier | LL - pub type FTT3 = for<'a> async fn(); -LL + pub type FTT3 = for<'a> fn(); +LL + pub type FTT3 = for<'a> fn(); | error: an `fn` pointer type cannot be `async` @@ -177,7 +177,7 @@ LL | pub type FTT4 = for<'a> async extern "C" fn(); help: remove the `async` qualifier | LL - pub type FTT4 = for<'a> async extern "C" fn(); -LL + pub type FTT4 = for<'a> extern "C" fn(); +LL + pub type FTT4 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -191,7 +191,7 @@ LL | pub type FTT5 = for<'a> async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type FTT5 = for<'a> async unsafe extern "C" fn(); -LL + pub type FTT5 = for<'a> unsafe extern "C" fn(); +LL + pub type FTT5 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -205,7 +205,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn(); -LL + pub type FTT6 = for<'a> async unsafe extern "C" fn(); +LL + pub type FTT6 = for<'a> async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -219,7 +219,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn(); -LL + pub type FTT6 = for<'a> const unsafe extern "C" fn(); +LL + pub type FTT6 = for<'a> const unsafe extern "C" fn(); | error: aborting due to 16 previous errors diff --git a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr index 9112a0e135a50..4e5927914ccb5 100644 --- a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr +++ b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr @@ -9,7 +9,7 @@ LL | type T0 = const fn(); help: remove the `const` qualifier | LL - type T0 = const fn(); -LL + type T0 = fn(); +LL + type T0 = fn(); | error: an `fn` pointer type cannot be `const` @@ -23,7 +23,7 @@ LL | type T1 = const extern "C" fn(); help: remove the `const` qualifier | LL - type T1 = const extern "C" fn(); -LL + type T1 = extern "C" fn(); +LL + type T1 = extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -37,7 +37,7 @@ LL | type T2 = const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type T2 = const unsafe extern "C" fn(); -LL + type T2 = unsafe extern "C" fn(); +LL + type T2 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -51,7 +51,7 @@ LL | type T3 = async fn(); help: remove the `async` qualifier | LL - type T3 = async fn(); -LL + type T3 = fn(); +LL + type T3 = fn(); | error: an `fn` pointer type cannot be `async` @@ -65,7 +65,7 @@ LL | type T4 = async extern "C" fn(); help: remove the `async` qualifier | LL - type T4 = async extern "C" fn(); -LL + type T4 = extern "C" fn(); +LL + type T4 = extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -79,7 +79,7 @@ LL | type T5 = async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type T5 = async unsafe extern "C" fn(); -LL + type T5 = unsafe extern "C" fn(); +LL + type T5 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -93,7 +93,7 @@ LL | type T6 = const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type T6 = const async unsafe extern "C" fn(); -LL + type T6 = async unsafe extern "C" fn(); +LL + type T6 = async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -107,7 +107,7 @@ LL | type T6 = const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type T6 = const async unsafe extern "C" fn(); -LL + type T6 = const unsafe extern "C" fn(); +LL + type T6 = const unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -121,7 +121,7 @@ LL | type FT0 = for<'a> const fn(); help: remove the `const` qualifier | LL - type FT0 = for<'a> const fn(); -LL + type FT0 = for<'a> fn(); +LL + type FT0 = for<'a> fn(); | error: an `fn` pointer type cannot be `const` @@ -135,7 +135,7 @@ LL | type FT1 = for<'a> const extern "C" fn(); help: remove the `const` qualifier | LL - type FT1 = for<'a> const extern "C" fn(); -LL + type FT1 = for<'a> extern "C" fn(); +LL + type FT1 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -149,7 +149,7 @@ LL | type FT2 = for<'a> const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type FT2 = for<'a> const unsafe extern "C" fn(); -LL + type FT2 = for<'a> unsafe extern "C" fn(); +LL + type FT2 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -163,7 +163,7 @@ LL | type FT3 = for<'a> async fn(); help: remove the `async` qualifier | LL - type FT3 = for<'a> async fn(); -LL + type FT3 = for<'a> fn(); +LL + type FT3 = for<'a> fn(); | error: an `fn` pointer type cannot be `async` @@ -177,7 +177,7 @@ LL | type FT4 = for<'a> async extern "C" fn(); help: remove the `async` qualifier | LL - type FT4 = for<'a> async extern "C" fn(); -LL + type FT4 = for<'a> extern "C" fn(); +LL + type FT4 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -191,7 +191,7 @@ LL | type FT5 = for<'a> async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type FT5 = for<'a> async unsafe extern "C" fn(); -LL + type FT5 = for<'a> unsafe extern "C" fn(); +LL + type FT5 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -205,7 +205,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type FT6 = for<'a> const async unsafe extern "C" fn(); -LL + type FT6 = for<'a> async unsafe extern "C" fn(); +LL + type FT6 = for<'a> async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -219,7 +219,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type FT6 = for<'a> const async unsafe extern "C" fn(); -LL + type FT6 = for<'a> const unsafe extern "C" fn(); +LL + type FT6 = for<'a> const unsafe extern "C" fn(); | error[E0308]: mismatched types diff --git a/tests/ui/asan-odr-win/asan_odr_windows.rs b/tests/ui/sanitizer/asan_odr_windows.rs similarity index 100% rename from tests/ui/asan-odr-win/asan_odr_windows.rs rename to tests/ui/sanitizer/asan_odr_windows.rs diff --git a/tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs b/tests/ui/sanitizer/auxiliary/asan_odr_win-2.rs similarity index 100% rename from tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs rename to tests/ui/sanitizer/auxiliary/asan_odr_win-2.rs diff --git a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs index f3e7f96d7c4de..8b1b6a8a105f3 100644 --- a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs +++ b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs @@ -1,6 +1,22 @@ //@ run-pass #![feature(arbitrary_self_types)] +// When probing for methods, we step forward through a chain of types. The first +// few of those steps can be reached by jumping through the chain of Derefs or the +// chain of Receivers. Later steps can only be reached by following the chain of +// Receivers. For instance, supposing A and B implement both Receiver and Deref, +// while C and D implement only Receiver: +// +// Type A>>> +// +// Deref chain: A -> B -> C +// Receiver chain: A -> B -> C -> D -> E +// +// We report bad type errors from the end of the chain. But at the end of which +// chain? We never morph the type as far as E so the correct behavior is to +// report errors from point C, i.e. the end of the Deref chain. This test case +// ensures we do that. + struct MyNonNull(*const T); impl std::ops::Receiver for MyNonNull { @@ -10,7 +26,13 @@ impl std::ops::Receiver for MyNonNull { #[allow(dead_code)] impl MyNonNull { fn foo(&self) -> *const U { - self.cast::().bar() + let mnn = self.cast::(); + // The following method call is the point of this test. + // If probe.rs reported errors from the last type discovered + // in the Receiver chain, it would be sad here because U is just + // a type variable. But this is a valid call so it ensures + // probe.rs doesn't make that mistake. + mnn.bar() } fn cast(&self) -> MyNonNull { MyNonNull(self.0 as *const U)