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)