commit
6963ecd371
519 changed files with 3396 additions and 5419 deletions
|
|
@ -100,7 +100,7 @@ pub struct Path {
|
|||
impl PartialEq<Symbol> for Path {
|
||||
#[inline]
|
||||
fn eq(&self, symbol: &Symbol) -> bool {
|
||||
self.segments.len() == 1 && { self.segments[0].ident.name == *symbol }
|
||||
matches!(&self.segments[..], [segment] if segment.ident.name == *symbol)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,13 +121,13 @@ impl Path {
|
|||
}
|
||||
|
||||
pub fn is_global(&self) -> bool {
|
||||
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
|
||||
self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
|
||||
}
|
||||
|
||||
/// If this path is a single identifier with no arguments, does not ensure
|
||||
/// that the path resolves to a const param, the caller should check this.
|
||||
pub fn is_potential_trivial_const_arg(&self) -> bool {
|
||||
self.segments.len() == 1 && self.segments[0].args.is_none()
|
||||
matches!(self.segments[..], [PathSegment { args: None, .. }])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ impl AttrItem {
|
|||
impl MetaItem {
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
|
||||
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
|
||||
}
|
||||
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
|
|
|
|||
|
|
@ -1813,10 +1813,10 @@ pub fn walk_flat_map_stmt<T: MutVisitor>(
|
|||
.into_iter()
|
||||
.map(|kind| Stmt { id, kind, span })
|
||||
.collect();
|
||||
match stmts.len() {
|
||||
0 => {}
|
||||
1 => vis.visit_span(&mut stmts[0].span),
|
||||
2.. => panic!(
|
||||
match &mut stmts[..] {
|
||||
[] => {}
|
||||
[stmt] => vis.visit_span(&mut stmt.span),
|
||||
_ => panic!(
|
||||
"cloning statement `NodeId`s is prohibited by default, \
|
||||
the visitor should implement custom statement visiting"
|
||||
),
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
|||
let mut i = 0;
|
||||
let mut j = lines.len();
|
||||
// first line of all-stars should be omitted
|
||||
if !lines.is_empty() && lines[0].chars().all(|c| c == '*') {
|
||||
if lines.first().is_some_and(|line| line.chars().all(|c| c == '*')) {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
|
|||
return None;
|
||||
}
|
||||
}
|
||||
if lines.is_empty() { None } else { Some(lines[0][..i].into()) }
|
||||
Some(lines.first()?[..i].to_string())
|
||||
}
|
||||
|
||||
let data_s = data.as_str();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use std::io;
|
||||
|
||||
use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options};
|
||||
use rustc_middle::mir::{Body, ClosureRegionRequirements, PassWhere};
|
||||
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_session::config::MirIncludeSpans;
|
||||
|
||||
|
|
@ -10,9 +12,6 @@ use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSe
|
|||
use crate::{BorrowckInferCtxt, RegionInferenceContext};
|
||||
|
||||
/// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
|
||||
// Note: this currently duplicates most of NLL MIR, with some additions for the localized outlives
|
||||
// constraints. This is ok for now as this dump will change in the near future to an HTML file to
|
||||
// become more useful.
|
||||
pub(crate) fn dump_polonius_mir<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
|
|
@ -26,12 +25,100 @@ pub(crate) fn dump_polonius_mir<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if !dump_enabled(tcx, "polonius", body.source.def_id()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let localized_outlives_constraints = localized_outlives_constraints
|
||||
.expect("missing localized constraints with `-Zpolonius=next`");
|
||||
|
||||
// We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in
|
||||
// #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example,
|
||||
// they're always disabled in mir-opt tests to make working with blessed dumps easier.
|
||||
let _: io::Result<()> = try {
|
||||
let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?;
|
||||
emit_polonius_dump(
|
||||
tcx,
|
||||
body,
|
||||
regioncx,
|
||||
borrow_set,
|
||||
localized_outlives_constraints,
|
||||
closure_region_requirements,
|
||||
&mut file,
|
||||
)?;
|
||||
};
|
||||
}
|
||||
|
||||
/// The polonius dump consists of:
|
||||
/// - the NLL MIR
|
||||
/// - the list of polonius localized constraints
|
||||
/// - a mermaid graph of the CFG
|
||||
fn emit_polonius_dump<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
localized_outlives_constraints: LocalizedOutlivesConstraintSet,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
||||
out: &mut dyn io::Write,
|
||||
) -> io::Result<()> {
|
||||
// Prepare the HTML dump file prologue.
|
||||
writeln!(out, "<!DOCTYPE html>")?;
|
||||
writeln!(out, "<html>")?;
|
||||
writeln!(out, "<head><title>Polonius MIR dump</title></head>")?;
|
||||
writeln!(out, "<body>")?;
|
||||
|
||||
// Section 1: the NLL + Polonius MIR.
|
||||
writeln!(out, "<div>")?;
|
||||
writeln!(out, "Raw MIR dump")?;
|
||||
writeln!(out, "<code><pre>")?;
|
||||
emit_html_mir(
|
||||
tcx,
|
||||
body,
|
||||
regioncx,
|
||||
borrow_set,
|
||||
localized_outlives_constraints,
|
||||
closure_region_requirements,
|
||||
out,
|
||||
)?;
|
||||
writeln!(out, "</pre></code>")?;
|
||||
writeln!(out, "</div>")?;
|
||||
|
||||
// Section 2: mermaid visualization of the CFG.
|
||||
writeln!(out, "<div>")?;
|
||||
writeln!(out, "Control-flow graph")?;
|
||||
writeln!(out, "<code><pre class='mermaid'>")?;
|
||||
emit_mermaid_cfg(body, out)?;
|
||||
writeln!(out, "</pre></code>")?;
|
||||
writeln!(out, "</div>")?;
|
||||
|
||||
// Finalize the dump with the HTML epilogue.
|
||||
writeln!(
|
||||
out,
|
||||
"<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>"
|
||||
)?;
|
||||
writeln!(out, "<script>")?;
|
||||
writeln!(out, "mermaid.initialize({{ startOnLoad: false, maxEdges: 100 }});")?;
|
||||
writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?;
|
||||
writeln!(out, "</script>")?;
|
||||
writeln!(out, "</body>")?;
|
||||
writeln!(out, "</html>")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Emits the polonius MIR, as escaped HTML.
|
||||
fn emit_html_mir<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
regioncx: &RegionInferenceContext<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
localized_outlives_constraints: LocalizedOutlivesConstraintSet,
|
||||
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
|
||||
out: &mut dyn io::Write,
|
||||
) -> io::Result<()> {
|
||||
// Buffer the regular MIR dump to be able to escape it.
|
||||
let mut buffer = Vec::new();
|
||||
|
||||
// We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z
|
||||
// mir-include-spans` on the CLI still has priority.
|
||||
let options = PrettyPrintMirOptions {
|
||||
include_extra_comments: matches!(
|
||||
tcx.sess.opts.unstable_opts.mir_include_spans,
|
||||
|
|
@ -39,12 +126,12 @@ pub(crate) fn dump_polonius_mir<'tcx>(
|
|||
),
|
||||
};
|
||||
|
||||
dump_mir_with_options(
|
||||
dump_mir_to_writer(
|
||||
tcx,
|
||||
false,
|
||||
"polonius",
|
||||
&0,
|
||||
body,
|
||||
&mut buffer,
|
||||
|pass_where, out| {
|
||||
emit_polonius_mir(
|
||||
tcx,
|
||||
|
|
@ -57,7 +144,27 @@ pub(crate) fn dump_polonius_mir<'tcx>(
|
|||
)
|
||||
},
|
||||
options,
|
||||
);
|
||||
)?;
|
||||
|
||||
// Escape the handful of characters that need it. We don't need to be particularly efficient:
|
||||
// we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8.
|
||||
let buffer = String::from_utf8_lossy(&buffer);
|
||||
for ch in buffer.chars() {
|
||||
let escaped = match ch {
|
||||
'>' => ">",
|
||||
'<' => "<",
|
||||
'&' => "&",
|
||||
'\'' => "'",
|
||||
'"' => """,
|
||||
_ => {
|
||||
// The common case, no escaping needed.
|
||||
write!(out, "{}", ch)?;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
write!(out, "{}", escaped)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Produces the actual NLL + Polonius MIR sections to emit during the dumping process.
|
||||
|
|
@ -102,3 +209,55 @@ fn emit_polonius_mir<'tcx>(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Emits a mermaid flowchart of the CFG blocks and edges, similar to the graphviz version.
|
||||
fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()> {
|
||||
use rustc_middle::mir::{TerminatorEdges, TerminatorKind};
|
||||
|
||||
// The mermaid chart type: a top-down flowchart.
|
||||
writeln!(out, "flowchart TD")?;
|
||||
|
||||
// Emit the block nodes.
|
||||
for (block_idx, block) in body.basic_blocks.iter_enumerated() {
|
||||
let block_idx = block_idx.as_usize();
|
||||
let cleanup = if block.is_cleanup { " (cleanup)" } else { "" };
|
||||
writeln!(out, "{block_idx}[\"bb{block_idx}{cleanup}\"]")?;
|
||||
}
|
||||
|
||||
// Emit the edges between blocks, from the terminator edges.
|
||||
for (block_idx, block) in body.basic_blocks.iter_enumerated() {
|
||||
let block_idx = block_idx.as_usize();
|
||||
let terminator = block.terminator();
|
||||
match terminator.edges() {
|
||||
TerminatorEdges::None => {}
|
||||
TerminatorEdges::Single(bb) => {
|
||||
writeln!(out, "{block_idx} --> {}", bb.as_usize())?;
|
||||
}
|
||||
TerminatorEdges::Double(bb1, bb2) => {
|
||||
if matches!(terminator.kind, TerminatorKind::FalseEdge { .. }) {
|
||||
writeln!(out, "{block_idx} --> {}", bb1.as_usize())?;
|
||||
writeln!(out, "{block_idx} -- imaginary --> {}", bb2.as_usize())?;
|
||||
} else {
|
||||
writeln!(out, "{block_idx} --> {}", bb1.as_usize())?;
|
||||
writeln!(out, "{block_idx} -- unwind --> {}", bb2.as_usize())?;
|
||||
}
|
||||
}
|
||||
TerminatorEdges::AssignOnReturn { return_, cleanup, .. } => {
|
||||
for to_idx in return_ {
|
||||
writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?;
|
||||
}
|
||||
|
||||
if let Some(to_idx) = cleanup {
|
||||
writeln!(out, "{block_idx} -- unwind --> {}", to_idx.as_usize())?;
|
||||
}
|
||||
}
|
||||
TerminatorEdges::SwitchInt { targets, .. } => {
|
||||
for to_idx in targets.all_targets() {
|
||||
writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
|
|||
{
|
||||
cx.dcx().emit_err(RequiresMaybeSized {
|
||||
span: pointee_ty_ident.span,
|
||||
name: pointee_ty_ident.name.to_ident_string(),
|
||||
name: pointee_ty_ident,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
|
@ -471,5 +471,5 @@ struct TooManyPointees {
|
|||
struct RequiresMaybeSized {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: String,
|
||||
name: Ident,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
|||
apply_patches(
|
||||
&runner.dirs,
|
||||
"coretests",
|
||||
&runner.stdlib_source.join("library/core/tests"),
|
||||
&runner.stdlib_source.join("library/coretests"),
|
||||
&LIBCORE_TESTS_SRC.to_path(&runner.dirs),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Sun, 24 Nov 2019 15:10:23 +0100
|
||||
Subject: [PATCH] [core] Disable not compiling tests
|
||||
|
||||
---
|
||||
library/core/tests/Cargo.toml | 8 ++++++++
|
||||
library/core/tests/num/flt2dec/mod.rs | 1 -
|
||||
library/core/tests/num/int_macros.rs | 2 ++
|
||||
library/core/tests/num/uint_macros.rs | 2 ++
|
||||
library/core/tests/ptr.rs | 2 ++
|
||||
library/core/tests/slice.rs | 2 ++
|
||||
6 files changed, 16 insertions(+), 1 deletion(-)
|
||||
create mode 100644 library/core/tests/Cargo.toml
|
||||
|
||||
diff --git a/Cargo.toml b/Cargo.toml
|
||||
new file mode 100644
|
||||
index 0000000..46fd999
|
||||
--- /dev/null
|
||||
+++ b/Cargo.toml
|
||||
@@ -0,0 +1,12 @@
|
||||
+[package]
|
||||
+name = "coretests"
|
||||
+version = "0.0.0"
|
||||
+edition = "2021"
|
||||
+
|
||||
+[lib]
|
||||
+name = "coretests"
|
||||
+path = "lib.rs"
|
||||
+
|
||||
+[dependencies]
|
||||
+rand = { version = "0.8.5", default-features = false }
|
||||
+rand_xorshift = { version = "0.3.0", default-features = false }
|
||||
diff --git a/lib.rs b/lib.rs
|
||||
index 42a26ae..5ac1042 100644
|
||||
--- a/lib.rs
|
||||
+++ b/lib.rs
|
||||
@@ -1,3 +1,4 @@
|
||||
+#![cfg(test)]
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_match))]
|
||||
--
|
||||
2.21.0 (Apple Git-122)
|
||||
|
|
@ -10,21 +10,20 @@ Cranelift doesn't support them yet
|
|||
library/core/tests/atomic.rs | 4 ---
|
||||
4 files changed, 4 insertions(+), 50 deletions(-)
|
||||
|
||||
diff --git a/lib.rs b/lib.rs
|
||||
diff --git a/tests/lib.rs b/tests/lib.rs
|
||||
index 1e336bf..35e6f54 100644
|
||||
--- a/lib.rs
|
||||
+++ b/lib.rs
|
||||
@@ -2,6 +2,5 @@
|
||||
#![cfg(test)]
|
||||
--- a/tests/lib.rs
|
||||
+++ b/tests/lib.rs
|
||||
@@ -2,5 +2,4 @@
|
||||
// tidy-alphabetical-start
|
||||
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_match))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_chunks)]
|
||||
diff --git a/atomic.rs b/atomic.rs
|
||||
diff --git a/tests/atomic.rs b/tests/atomic.rs
|
||||
index b735957..ea728b6 100644
|
||||
--- a/atomic.rs
|
||||
+++ b/atomic.rs
|
||||
--- a/tests/atomic.rs
|
||||
+++ b/tests/atomic.rs
|
||||
@@ -185,10 +185,6 @@ fn atomic_alignment() {
|
||||
assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>());
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ Subject: [PATCH] Disable long running tests
|
|||
library/core/tests/slice.rs | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/slice.rs b/slice.rs
|
||||
diff --git a/tests/slice.rs b/tests/slice.rs
|
||||
index 8402833..84592e0 100644
|
||||
--- a/slice.rs
|
||||
+++ b/slice.rs
|
||||
--- a/tests/slice.rs
|
||||
+++ b/tests/slice.rs
|
||||
@@ -1809,6 +1809,7 @@ fn sort_unstable() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ pub(crate) fn run_aot(
|
|||
.to_owned();
|
||||
|
||||
let cgus = if tcx.sess.opts.output_types.should_codegen() {
|
||||
tcx.collect_and_partition_mono_items(()).1
|
||||
tcx.collect_and_partition_mono_items(()).codegen_units
|
||||
} else {
|
||||
// If only `--emit metadata` is used, we shouldn't perform any codegen.
|
||||
// Also `tcx.collect_and_partition_mono_items` may panic in that case.
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
libgccjit_version:
|
||||
- { gcc: "gcc-13.deb" }
|
||||
- { gcc: "gcc-13-without-int128.deb" }
|
||||
- { gcc: "gcc-15.deb" }
|
||||
- { gcc: "gcc-15-without-int128.deb" }
|
||||
commands: [
|
||||
"--std-tests",
|
||||
# FIXME: re-enable asm tests when GCC can emit in the right syntax.
|
||||
|
|
@ -108,13 +108,13 @@ jobs:
|
|||
cargo clippy --all-targets --features master -- -D warnings
|
||||
|
||||
duplicates:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: python tools/check_intrinsics_duplicates.py
|
||||
|
||||
build_system:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Test build system
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -56,12 +56,12 @@ jobs:
|
|||
|
||||
- name: Download artifact
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13.deb
|
||||
sudo dpkg --force-overwrite -i gcc-15.deb
|
||||
echo 'gcc-path = "/usr/lib"' > config.toml
|
||||
echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
|
||||
echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -47,17 +47,17 @@ jobs:
|
|||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install qemu qemu-user-static
|
||||
sudo apt-get install qemu-system qemu-user-static
|
||||
|
||||
- name: Download artifact
|
||||
run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb
|
||||
run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-15.deb
|
||||
|
||||
- name: Download VM artifact
|
||||
run: curl -LO https://github.com/cross-cg-gcc-tools/vms/releases/latest/download/debian-m68k.img
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-13.deb
|
||||
sudo dpkg -i gcc-m68k-15.deb
|
||||
echo 'gcc-path = "/usr/lib/"' > config.toml
|
||||
|
||||
- name: Set env
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ env:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -37,11 +37,11 @@ jobs:
|
|||
run: sudo apt-get install ninja-build ripgrep
|
||||
|
||||
- name: Download artifact
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb
|
||||
run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb
|
||||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg --force-overwrite -i gcc-13.deb
|
||||
sudo dpkg --force-overwrite -i gcc-15.deb
|
||||
echo 'gcc-path = "/usr/lib/"' > config.toml
|
||||
|
||||
- name: Set env
|
||||
|
|
@ -76,4 +76,9 @@ jobs:
|
|||
- name: Run y.sh cargo build
|
||||
run: |
|
||||
EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml
|
||||
# TODO: grep the asm output for "call my_func" and fail if it is found.
|
||||
call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||:
|
||||
if [ $call_found -gt 0 ]; then
|
||||
echo "ERROR: call my_func found in asm"
|
||||
echo "Test is done with LTO enabled, hence inlining should occur across crates"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
"debug"
|
||||
};
|
||||
|
||||
// We have a different environment variable than RUSTFLAGS to make sure those flags are only
|
||||
// sent to rustc_codegen_gcc and not the LLVM backend.
|
||||
if let Ok(cg_rustflags) = std::env::var("CG_RUSTFLAGS") {
|
||||
rustflags.push(' ');
|
||||
rustflags.push_str(&cg_rustflags);
|
||||
|
|
@ -184,8 +186,12 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
|
||||
let mut env = HashMap::new();
|
||||
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone());
|
||||
env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone());
|
||||
let gcc_path =
|
||||
args.config_info.gcc_path.clone().expect(
|
||||
"The config module should have emitted an error if the GCC path wasn't provided",
|
||||
);
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), gcc_path.clone());
|
||||
env.insert("LIBRARY_PATH".to_string(), gcc_path);
|
||||
|
||||
if args.config_info.no_default_features {
|
||||
env.insert("RUSTFLAGS".to_string(), "-Csymbol-mangling-version=v0".to_string());
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ pub struct ConfigInfo {
|
|||
pub sysroot_panic_abort: bool,
|
||||
pub cg_backend_path: String,
|
||||
pub sysroot_path: String,
|
||||
pub gcc_path: String,
|
||||
pub gcc_path: Option<String>,
|
||||
config_file: Option<String>,
|
||||
// This is used in particular in rust compiler bootstrap because it doesn't run at the root
|
||||
// of the `cg_gcc` folder, making it complicated for us to get access to local files we need
|
||||
|
|
@ -173,6 +173,14 @@ impl ConfigInfo {
|
|||
"--release-sysroot" => self.sysroot_release_channel = true,
|
||||
"--release" => self.channel = Channel::Release,
|
||||
"--sysroot-panic-abort" => self.sysroot_panic_abort = true,
|
||||
"--gcc-path" => match args.next() {
|
||||
Some(arg) if !arg.is_empty() => {
|
||||
self.gcc_path = Some(arg.into());
|
||||
}
|
||||
_ => {
|
||||
return Err("Expected a value after `--gcc-path`, found nothing".to_string());
|
||||
}
|
||||
},
|
||||
"--cg_gcc-path" => match args.next() {
|
||||
Some(arg) if !arg.is_empty() => {
|
||||
self.cg_gcc_path = Some(arg.into());
|
||||
|
|
@ -260,8 +268,9 @@ impl ConfigInfo {
|
|||
create_symlink(&libgccjit_so, output_dir.join(&format!("{}.0", libgccjit_so_name)))?;
|
||||
}
|
||||
|
||||
self.gcc_path = output_dir.display().to_string();
|
||||
println!("Using `{}` as path for libgccjit", self.gcc_path);
|
||||
let gcc_path = output_dir.display().to_string();
|
||||
println!("Using `{}` as path for libgccjit", gcc_path);
|
||||
self.gcc_path = Some(gcc_path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -273,6 +282,15 @@ impl ConfigInfo {
|
|||
}
|
||||
|
||||
pub fn setup_gcc_path(&mut self) -> Result<(), String> {
|
||||
// If the user used the `--gcc-path` option, no need to look at `config.toml` content
|
||||
// since we already have everything we need.
|
||||
if let Some(gcc_path) = &self.gcc_path {
|
||||
println!(
|
||||
"`--gcc-path` was provided, ignoring config file. Using `{}` as path for libgccjit",
|
||||
gcc_path
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
let config_file = match self.config_file.as_deref() {
|
||||
Some(config_file) => config_file.into(),
|
||||
None => self.compute_path("config.toml"),
|
||||
|
|
@ -283,12 +301,15 @@ impl ConfigInfo {
|
|||
self.download_gccjit_if_needed()?;
|
||||
return Ok(());
|
||||
}
|
||||
self.gcc_path = match gcc_path {
|
||||
Some(path) => path,
|
||||
None => {
|
||||
return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),));
|
||||
}
|
||||
let Some(gcc_path) = gcc_path else {
|
||||
return Err(format!("missing `gcc-path` value from `{}`", config_file.display()));
|
||||
};
|
||||
println!(
|
||||
"GCC path retrieved from `{}`. Using `{}` as path for libgccjit",
|
||||
config_file.display(),
|
||||
gcc_path
|
||||
);
|
||||
self.gcc_path = Some(gcc_path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -299,10 +320,17 @@ impl ConfigInfo {
|
|||
) -> Result<(), String> {
|
||||
env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
|
||||
|
||||
if self.gcc_path.is_empty() && !use_system_gcc {
|
||||
self.setup_gcc_path()?;
|
||||
}
|
||||
env.insert("GCC_PATH".to_string(), self.gcc_path.clone());
|
||||
let gcc_path = if !use_system_gcc {
|
||||
if self.gcc_path.is_none() {
|
||||
self.setup_gcc_path()?;
|
||||
}
|
||||
self.gcc_path.clone().expect(
|
||||
"The config module should have emitted an error if the GCC path wasn't provided",
|
||||
)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
env.insert("GCC_PATH".to_string(), gcc_path.clone());
|
||||
|
||||
if self.cargo_target_dir.is_empty() {
|
||||
match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) {
|
||||
|
|
@ -381,6 +409,8 @@ impl ConfigInfo {
|
|||
}
|
||||
|
||||
// This environment variable is useful in case we want to change options of rustc commands.
|
||||
// We have a different environment variable than RUSTFLAGS to make sure those flags are
|
||||
// only sent to rustc_codegen_gcc and not the LLVM backend.
|
||||
if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") {
|
||||
rustflags.extend_from_slice(&split_args(&cg_rustflags)?);
|
||||
}
|
||||
|
|
@ -414,7 +444,7 @@ impl ConfigInfo {
|
|||
"{target}:{sysroot}:{gcc_path}",
|
||||
target = self.cargo_target_dir,
|
||||
sysroot = sysroot.display(),
|
||||
gcc_path = self.gcc_path,
|
||||
gcc_path = gcc_path,
|
||||
);
|
||||
env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
|
||||
|
|
@ -459,6 +489,7 @@ impl ConfigInfo {
|
|||
--release-sysroot : Build sysroot in release mode
|
||||
--sysroot-panic-abort : Build the sysroot without unwinding support
|
||||
--config-file : Location of the config file to be used
|
||||
--gcc-path : Location of the GCC root folder
|
||||
--cg_gcc-path : Location of the rustc_codegen_gcc root folder (used
|
||||
when ran from another directory)
|
||||
--no-default-features : Add `--no-default-features` flag to cargo commands
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ pub fn run() -> Result<(), String> {
|
|||
}
|
||||
config.no_download = true;
|
||||
config.setup_gcc_path()?;
|
||||
println!("{}", config.gcc_path);
|
||||
if let Some(gcc_path) = config.gcc_path {
|
||||
println!("{}", gcc_path);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ Options:
|
|||
--help : Displays this help message.
|
||||
|
||||
Commands:
|
||||
cargo : Executes a cargo command.
|
||||
cargo : Executes a cargo command.
|
||||
rustc : Compiles the program using the GCC compiler.
|
||||
clean : Cleans the build directory, removing all compiled files and artifacts.
|
||||
prepare : Prepares the environment for building, including fetching dependencies and setting up configurations.
|
||||
build : Compiles the project.
|
||||
build : Compiles the project.
|
||||
test : Runs tests for the project.
|
||||
info : Displays information about the build environment and project configuration.
|
||||
clone-gcc : Clones the GCC compiler from a specified source.
|
||||
|
|
|
|||
|
|
@ -1229,8 +1229,11 @@ pub fn run() -> Result<(), String> {
|
|||
|
||||
if !args.use_system_gcc {
|
||||
args.config_info.setup_gcc_path()?;
|
||||
env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone());
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone());
|
||||
let gcc_path = args.config_info.gcc_path.clone().expect(
|
||||
"The config module should have emitted an error if the GCC path wasn't provided",
|
||||
);
|
||||
env.insert("LIBRARY_PATH".to_string(), gcc_path.clone());
|
||||
env.insert("LD_LIBRARY_PATH".to_string(), gcc_path);
|
||||
}
|
||||
|
||||
build_if_no_backend(&env, &args)?;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
45648c2edd4ecd862d9f08196d3d6c6ccba79f07
|
||||
e607be166673a8de9fc07f6f02c60426e556c5f2
|
||||
|
|
|
|||
|
|
@ -5,9 +5,6 @@ codegen_gcc_unknown_ctarget_feature_prefix =
|
|||
codegen_gcc_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_gcc_lto_not_supported =
|
||||
LTO is not supported. You may get a linker error.
|
||||
|
||||
codegen_gcc_forbidden_ctarget_feature =
|
||||
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
|||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::mono::MonoItemPartitions;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
|
|
@ -297,12 +298,13 @@ struct UsageSets<'tcx> {
|
|||
/// Prepare sets of definitions that are relevant to deciding whether something
|
||||
/// is an "unused function" for coverage purposes.
|
||||
fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
|
||||
let (all_mono_items, cgus) = tcx.collect_and_partition_mono_items(());
|
||||
let MonoItemPartitions { all_mono_items, codegen_units } =
|
||||
tcx.collect_and_partition_mono_items(());
|
||||
|
||||
// Obtain a MIR body for each function participating in codegen, via an
|
||||
// arbitrary instance.
|
||||
let mut def_ids_seen = FxHashSet::default();
|
||||
let def_and_mir_for_all_mono_fns = cgus
|
||||
let def_and_mir_for_all_mono_fns = codegen_units
|
||||
.iter()
|
||||
.flat_map(|cgu| cgu.items().keys())
|
||||
.filter_map(|item| match item {
|
||||
|
|
|
|||
|
|
@ -1182,6 +1182,60 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}};
|
||||
}
|
||||
|
||||
/// Returns the bitwidth of the `$ty` argument if it is an `Int` type.
|
||||
macro_rules! require_int_ty {
|
||||
($ty: expr, $diag: expr) => {
|
||||
match $ty {
|
||||
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
|
||||
_ => {
|
||||
return_error!($diag);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the bitwidth of the `$ty` argument if it is an `Int` or `Uint` type.
|
||||
macro_rules! require_int_or_uint_ty {
|
||||
($ty: expr, $diag: expr) => {
|
||||
match $ty {
|
||||
ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
|
||||
ty::Uint(i) => {
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
|
||||
}
|
||||
_ => {
|
||||
return_error!($diag);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts a vector mask, where each element has a bit width equal to the data elements it is used with,
|
||||
/// down to an i1 based mask that can be used by llvm intrinsics.
|
||||
///
|
||||
/// The rust simd semantics are that each element should either consist of all ones or all zeroes,
|
||||
/// but this information is not available to llvm. Truncating the vector effectively uses the lowest bit,
|
||||
/// but codegen for several targets is better if we consider the highest bit by shifting.
|
||||
///
|
||||
/// For x86 SSE/AVX targets this is beneficial since most instructions with mask parameters only consider the highest bit.
|
||||
/// So even though on llvm level we have an additional shift, in the final assembly there is no shift or truncate and
|
||||
/// instead the mask can be used as is.
|
||||
///
|
||||
/// For aarch64 and other targets there is a benefit because a mask from the sign bit can be more
|
||||
/// efficiently converted to an all ones / all zeroes mask by comparing whether each element is negative.
|
||||
fn vector_mask_to_bitmask<'a, 'll, 'tcx>(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
i_xn: &'ll Value,
|
||||
in_elem_bitwidth: u64,
|
||||
in_len: u64,
|
||||
) -> &'ll Value {
|
||||
// Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position.
|
||||
let shift_idx = bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _);
|
||||
let shift_indices = vec![shift_idx; in_len as _];
|
||||
let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
|
||||
// Truncate vector to an <i1 x N>
|
||||
bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len))
|
||||
}
|
||||
|
||||
let tcx = bx.tcx();
|
||||
let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx));
|
||||
let arg_tys = sig.inputs();
|
||||
|
|
@ -1433,14 +1487,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
m_len,
|
||||
v_len
|
||||
});
|
||||
match m_elem_ty.kind() {
|
||||
ty::Int(_) => {}
|
||||
_ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
|
||||
}
|
||||
// truncate the mask to a vector of i1s
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, m_len as u64);
|
||||
let m_i1s = bx.trunc(args[0].immediate(), i1xn);
|
||||
let in_elem_bitwidth =
|
||||
require_int_ty!(m_elem_ty.kind(), InvalidMonomorphization::MaskType {
|
||||
span,
|
||||
name,
|
||||
ty: m_elem_ty
|
||||
});
|
||||
let m_i1s = vector_mask_to_bitmask(bx, args[0].immediate(), in_elem_bitwidth, m_len);
|
||||
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
|
||||
|
|
@ -1457,33 +1510,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let expected_bytes = in_len.div_ceil(8);
|
||||
|
||||
// Integer vector <i{in_bitwidth} x in_len>:
|
||||
let (i_xn, in_elem_bitwidth) = match in_elem.kind() {
|
||||
ty::Int(i) => (
|
||||
args[0].immediate(),
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
|
||||
),
|
||||
ty::Uint(i) => (
|
||||
args[0].immediate(),
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()),
|
||||
),
|
||||
_ => return_error!(InvalidMonomorphization::VectorArgument {
|
||||
let in_elem_bitwidth =
|
||||
require_int_or_uint_ty!(in_elem.kind(), InvalidMonomorphization::VectorArgument {
|
||||
span,
|
||||
name,
|
||||
in_ty,
|
||||
in_elem
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
// LLVM doesn't always know the inputs are `0` or `!0`, so we shift here so it optimizes to
|
||||
// `pmovmskb` and similar on x86.
|
||||
let shift_indices =
|
||||
vec![
|
||||
bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _);
|
||||
in_len as _
|
||||
];
|
||||
let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice()));
|
||||
// Truncate vector to an <i1 x N>
|
||||
let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len));
|
||||
let i1xn = vector_mask_to_bitmask(bx, args[0].immediate(), in_elem_bitwidth, in_len);
|
||||
// Bitcast <i1 x N> to iN:
|
||||
let i_ = bx.bitcast(i1xn, bx.type_ix(in_len));
|
||||
|
||||
|
|
@ -1704,28 +1739,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
);
|
||||
|
||||
match element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
}
|
||||
}
|
||||
let mask_elem_bitwidth =
|
||||
require_int_ty!(element_ty2.kind(), InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, in_len);
|
||||
(bx.trunc(args[2].immediate(), i1xn), i1xn)
|
||||
};
|
||||
let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len);
|
||||
let mask_ty = bx.type_vector(bx.type_i1(), in_len);
|
||||
|
||||
// Type of the vector of pointers:
|
||||
let llvm_pointer_vec_ty = llvm_vector_ty(bx, element_ty1, in_len);
|
||||
|
|
@ -1810,27 +1838,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
);
|
||||
|
||||
require!(
|
||||
matches!(mask_elem.kind(), ty::Int(_)),
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
let m_elem_bitwidth =
|
||||
require_int_ty!(mask_elem.kind(), InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
third_arg: mask_ty,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
let mask = vector_mask_to_bitmask(bx, args[0].immediate(), m_elem_bitwidth, mask_len);
|
||||
let mask_ty = bx.type_vector(bx.type_i1(), mask_len);
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(values_elem).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, mask_len);
|
||||
(bx.trunc(args[0].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
let llvm_pointer = bx.type_ptr();
|
||||
|
||||
// Type of the vector of elements:
|
||||
|
|
@ -1901,27 +1923,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
}
|
||||
);
|
||||
|
||||
require!(
|
||||
matches!(mask_elem.kind(), ty::Int(_)),
|
||||
InvalidMonomorphization::ThirdArgElementType {
|
||||
let m_elem_bitwidth =
|
||||
require_int_ty!(mask_elem.kind(), InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: values_elem,
|
||||
third_arg: mask_ty,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
let mask = vector_mask_to_bitmask(bx, args[0].immediate(), m_elem_bitwidth, mask_len);
|
||||
let mask_ty = bx.type_vector(bx.type_i1(), mask_len);
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(values_elem).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, in_len);
|
||||
(bx.trunc(args[0].immediate(), i1xn), i1xn)
|
||||
};
|
||||
|
||||
let ret_t = bx.type_void();
|
||||
|
||||
let llvm_pointer = bx.type_ptr();
|
||||
|
|
@ -1995,28 +2011,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
);
|
||||
|
||||
// The element type of the third argument must be a signed integer type of any width:
|
||||
match element_ty2.kind() {
|
||||
ty::Int(_) => (),
|
||||
_ => {
|
||||
return_error!(InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
}
|
||||
}
|
||||
let mask_elem_bitwidth =
|
||||
require_int_ty!(element_ty2.kind(), InvalidMonomorphization::ThirdArgElementType {
|
||||
span,
|
||||
name,
|
||||
expected_element: element_ty2,
|
||||
third_arg: arg_tys[2]
|
||||
});
|
||||
|
||||
// Alignment of T, must be a constant integer value:
|
||||
let alignment_ty = bx.type_i32();
|
||||
let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32);
|
||||
|
||||
// Truncate the mask vector to a vector of i1s:
|
||||
let (mask, mask_ty) = {
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, in_len);
|
||||
(bx.trunc(args[2].immediate(), i1xn), i1xn)
|
||||
};
|
||||
let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len);
|
||||
let mask_ty = bx.type_vector(bx.type_i1(), in_len);
|
||||
|
||||
let ret_t = bx.type_void();
|
||||
|
||||
|
|
@ -2164,8 +2173,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
});
|
||||
args[0].immediate()
|
||||
} else {
|
||||
match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {}
|
||||
let bitwidth = match in_elem.kind() {
|
||||
ty::Int(i) => {
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
|
||||
}
|
||||
ty::Uint(i) => {
|
||||
i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits())
|
||||
}
|
||||
_ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
|
||||
span,
|
||||
name,
|
||||
|
|
@ -2174,12 +2188,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
in_elem,
|
||||
ret_ty
|
||||
}),
|
||||
}
|
||||
};
|
||||
|
||||
// boolean reductions operate on vectors of i1s:
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, in_len as u64);
|
||||
bx.trunc(args[0].immediate(), i1xn)
|
||||
vector_mask_to_bitmask(bx, args[0].immediate(), bitwidth, in_len as _)
|
||||
};
|
||||
return match in_elem.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => {
|
||||
|
|
|
|||
|
|
@ -46,8 +46,12 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr
|
|||
return;
|
||||
}
|
||||
|
||||
let available_cgus =
|
||||
tcx.collect_and_partition_mono_items(()).1.iter().map(|cgu| cgu.name()).collect();
|
||||
let available_cgus = tcx
|
||||
.collect_and_partition_mono_items(())
|
||||
.codegen_units
|
||||
.iter()
|
||||
.map(|cgu| cgu.name())
|
||||
.collect();
|
||||
|
||||
let mut ams = AssertModuleSource {
|
||||
tcx,
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ fn exported_symbols_provider_local(
|
|||
// external linkage is enough for monomorphization to be linked to.
|
||||
let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib;
|
||||
|
||||
let (_, cgus) = tcx.collect_and_partition_mono_items(());
|
||||
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
|
||||
|
||||
// The symbols created in this loop are sorted below it
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
|
|
|
|||
|
|
@ -619,7 +619,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
|
||||
// Run the monomorphization collector and partition the collected items into
|
||||
// codegen units.
|
||||
let codegen_units = tcx.collect_and_partition_mono_items(()).1;
|
||||
let codegen_units = tcx.collect_and_partition_mono_items(()).codegen_units;
|
||||
|
||||
// Force all codegen_unit queries so they are already either red or green
|
||||
// when compile_codegen_unit accesses them. We are not able to re-execute
|
||||
|
|
@ -1051,7 +1051,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
config::OptLevel::SizeMin => config::OptLevel::Default,
|
||||
};
|
||||
|
||||
let (defids, _) = tcx.collect_and_partition_mono_items(cratenum);
|
||||
let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items;
|
||||
|
||||
let any_for_speed = defids.items().any(|id| {
|
||||
let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ where
|
|||
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
|
||||
// should remain silent.
|
||||
err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
|
||||
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
|
||||
err_inval!(Layout(LayoutError::TooGeneric(_))) | err_inval!(TooGeneric) => {
|
||||
ErrorHandled::TooGeneric(span)
|
||||
}
|
||||
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,23 @@ mod tests;
|
|||
pub trait DirectedGraph {
|
||||
type Node: Idx;
|
||||
|
||||
/// Returns the total number of nodes in this graph.
|
||||
///
|
||||
/// Several graph algorithm implementations assume that every node ID is
|
||||
/// strictly less than the number of nodes, i.e. nodes are densely numbered.
|
||||
/// That assumption allows them to use `num_nodes` to allocate per-node
|
||||
/// data structures, indexed by node.
|
||||
fn num_nodes(&self) -> usize;
|
||||
|
||||
/// Iterates over all nodes of a graph in ascending numeric order.
|
||||
///
|
||||
/// Assumes that nodes are densely numbered, i.e. every index in
|
||||
/// `0..num_nodes` is a valid node.
|
||||
fn iter_nodes(
|
||||
&self,
|
||||
) -> impl Iterator<Item = Self::Node> + DoubleEndedIterator + ExactSizeIterator {
|
||||
(0..self.num_nodes()).map(<Self::Node as Idx>::new)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NumEdges: DirectedGraph {
|
||||
|
|
|
|||
|
|
@ -333,8 +333,8 @@ where
|
|||
to_annotation,
|
||||
};
|
||||
|
||||
let scc_indices = (0..num_nodes)
|
||||
.map(G::Node::new)
|
||||
let scc_indices = graph
|
||||
.iter_nodes()
|
||||
.map(|node| match this.start_walk_from(node) {
|
||||
WalkReturn::Complete { scc_index, .. } => scc_index,
|
||||
WalkReturn::Cycle { min_depth, .. } => {
|
||||
|
|
|
|||
|
|
@ -1285,13 +1285,13 @@ impl fmt::Debug for OwnerNodes<'_> {
|
|||
.field("node", &self.nodes[ItemLocalId::ZERO])
|
||||
.field(
|
||||
"parents",
|
||||
&self
|
||||
.nodes
|
||||
.iter_enumerated()
|
||||
.map(|(id, parented_node)| {
|
||||
debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
&fmt::from_fn(|f| {
|
||||
f.debug_list()
|
||||
.entries(self.nodes.iter_enumerated().map(|(id, parented_node)| {
|
||||
fmt::from_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
|
||||
}))
|
||||
.finish()
|
||||
}),
|
||||
)
|
||||
.field("bodies", &self.bodies)
|
||||
.field("opt_hash_including_bodies", &self.opt_hash_including_bodies)
|
||||
|
|
@ -4638,15 +4638,5 @@ mod size_asserts {
|
|||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
|
||||
struct DebugFn<F>(F);
|
||||
impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(self.0)(fmt)
|
||||
}
|
||||
}
|
||||
DebugFn(f)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
|
|
|
|||
|
|
@ -2362,7 +2362,7 @@ fn try_report_async_mismatch<'tcx>(
|
|||
// the right span is a bit difficult.
|
||||
return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture {
|
||||
span: tcx.def_span(impl_m.def_id),
|
||||
method_name: trait_m.name,
|
||||
method_name: tcx.item_ident(impl_m.def_id),
|
||||
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
|
|||
|
||||
fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
|
||||
let span = tcx.def_span(impl_item);
|
||||
let ident = tcx.item_name(impl_item);
|
||||
let ident = tcx.item_ident(impl_item);
|
||||
|
||||
let err = match tcx.span_of_impl(parent_impl) {
|
||||
Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp },
|
||||
|
|
@ -297,7 +297,7 @@ fn default_body_is_unstable(
|
|||
reason: Option<Symbol>,
|
||||
issue: Option<NonZero<u32>>,
|
||||
) {
|
||||
let missing_item_name = tcx.associated_item(item_did).name;
|
||||
let missing_item_name = tcx.item_ident(item_did);
|
||||
let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new());
|
||||
match reason {
|
||||
Some(r) => {
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
|
||||
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
|
||||
span,
|
||||
name: field.name,
|
||||
name: field.ident(tcx),
|
||||
ty: ty_a,
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -465,8 +465,8 @@ fn emit_orphan_check_error<'tcx>(
|
|||
traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => {
|
||||
let mut reported = None;
|
||||
for param_def_id in uncovered {
|
||||
let span = tcx.def_ident_span(param_def_id).unwrap();
|
||||
let name = tcx.item_name(param_def_id);
|
||||
let name = tcx.item_ident(param_def_id);
|
||||
let span = name.span;
|
||||
|
||||
reported.get_or_insert(match local_ty {
|
||||
Some(local_type) => tcx.dcx().emit_err(errors::TyParamFirstLocal {
|
||||
|
|
@ -492,7 +492,7 @@ fn lint_uncovered_ty_params<'tcx>(
|
|||
|
||||
for param_def_id in uncovered {
|
||||
let span = tcx.def_ident_span(param_def_id).unwrap();
|
||||
let name = tcx.item_name(param_def_id);
|
||||
let name = tcx.item_ident(param_def_id);
|
||||
|
||||
match local_ty {
|
||||
Some(local_type) => tcx.emit_node_span_lint(
|
||||
|
|
|
|||
|
|
@ -928,7 +928,7 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
|
|||
tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
|
||||
span,
|
||||
discr: prev_discr.unwrap().to_string(),
|
||||
item_name: tcx.item_name(variant.def_id),
|
||||
item_name: tcx.item_ident(variant.def_id),
|
||||
wrapped_discr: wrapped_discr.to_string(),
|
||||
});
|
||||
None
|
||||
|
|
@ -990,11 +990,10 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> {
|
|||
}
|
||||
|
||||
/// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
|
||||
fn check_field_decl(&mut self, ident: Ident, field_decl: FieldDeclSpan) {
|
||||
fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
|
||||
use FieldDeclSpan::*;
|
||||
let field_name = ident.name;
|
||||
let ident = ident.normalize_to_macros_2_0();
|
||||
match (field_decl, self.seen_fields.get(&ident).copied()) {
|
||||
let field_name = field_name.normalize_to_macros_2_0();
|
||||
match (field_decl, self.seen_fields.get(&field_name).copied()) {
|
||||
(NotNested(span), Some(NotNested(prev_span))) => {
|
||||
self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
|
||||
field_name,
|
||||
|
|
@ -1035,7 +1034,7 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> {
|
|||
});
|
||||
}
|
||||
(field_decl, None) => {
|
||||
self.seen_fields.insert(ident, field_decl);
|
||||
self.seen_fields.insert(field_name, field_decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,6 +184,50 @@ enum Scope<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
// A helper for debugging scopes without printing parent scopes
|
||||
fn debug_truncated(&'a self) -> impl fmt::Debug + 'a {
|
||||
fmt::from_fn(move |f| match self {
|
||||
Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
|
||||
.debug_struct("Binder")
|
||||
.field("bound_vars", bound_vars)
|
||||
.field("scope_type", scope_type)
|
||||
.field("hir_id", hir_id)
|
||||
.field("where_bound_origin", where_bound_origin)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Self::Opaque { captures, def_id, s: _ } => f
|
||||
.debug_struct("Opaque")
|
||||
.field("def_id", def_id)
|
||||
.field("captures", &captures.borrow())
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Self::Body { id, s: _ } => {
|
||||
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
|
||||
}
|
||||
Self::ObjectLifetimeDefault { lifetime, s: _ } => f
|
||||
.debug_struct("ObjectLifetimeDefault")
|
||||
.field("lifetime", lifetime)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Self::Supertrait { bound_vars, s: _ } => f
|
||||
.debug_struct("Supertrait")
|
||||
.field("bound_vars", bound_vars)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
||||
Self::LateBoundary { s: _, what, deny_late_regions } => f
|
||||
.debug_struct("LateBoundary")
|
||||
.field("what", what)
|
||||
.field("deny_late_regions", deny_late_regions)
|
||||
.finish(),
|
||||
Self::Root { opt_parent_item } => {
|
||||
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum BinderScopeType {
|
||||
/// Any non-concatenating binder scopes.
|
||||
|
|
@ -200,52 +244,6 @@ enum BinderScopeType {
|
|||
Concatenating,
|
||||
}
|
||||
|
||||
// A helper struct for debugging scopes without printing parent scopes
|
||||
struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
|
||||
|
||||
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {
|
||||
Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
|
||||
.debug_struct("Binder")
|
||||
.field("bound_vars", bound_vars)
|
||||
.field("scope_type", scope_type)
|
||||
.field("hir_id", hir_id)
|
||||
.field("where_bound_origin", where_bound_origin)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Scope::Opaque { captures, def_id, s: _ } => f
|
||||
.debug_struct("Opaque")
|
||||
.field("def_id", def_id)
|
||||
.field("captures", &captures.borrow())
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Scope::Body { id, s: _ } => {
|
||||
f.debug_struct("Body").field("id", id).field("s", &"..").finish()
|
||||
}
|
||||
Scope::ObjectLifetimeDefault { lifetime, s: _ } => f
|
||||
.debug_struct("ObjectLifetimeDefault")
|
||||
.field("lifetime", lifetime)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Scope::Supertrait { bound_vars, s: _ } => f
|
||||
.debug_struct("Supertrait")
|
||||
.field("bound_vars", bound_vars)
|
||||
.field("s", &"..")
|
||||
.finish(),
|
||||
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
|
||||
Scope::LateBoundary { s: _, what, deny_late_regions } => f
|
||||
.debug_struct("LateBoundary")
|
||||
.field("what", what)
|
||||
.field("deny_late_regions", deny_late_regions)
|
||||
.finish(),
|
||||
Scope::Root { opt_parent_item } => {
|
||||
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ScopeRef<'a> = &'a Scope<'a>;
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
|
|
@ -1144,7 +1142,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
{
|
||||
let BoundVarContext { tcx, map, .. } = self;
|
||||
let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
|
||||
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(this.scope));
|
||||
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
|
||||
{
|
||||
let _enter = span.enter();
|
||||
f(&mut this);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
|
|||
} else {
|
||||
let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
|
||||
span: tcx.def_span(def_id),
|
||||
name: tcx.item_name(parent_def_id.to_def_id()),
|
||||
name: tcx.item_ident(parent_def_id.to_def_id()),
|
||||
what: "impl",
|
||||
});
|
||||
Ty::new_error(tcx, reported)
|
||||
|
|
@ -136,7 +136,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
|
|||
}
|
||||
let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
|
||||
span: tcx.def_span(def_id),
|
||||
name: tcx.item_name(parent_def_id.to_def_id()),
|
||||
name: tcx.item_ident(parent_def_id.to_def_id()),
|
||||
what: match tcx.hir_node(scope) {
|
||||
_ if scope == hir::CRATE_HIR_ID => "module",
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ pub(crate) struct DropImplOnWrongItem {
|
|||
pub(crate) enum FieldAlreadyDeclared {
|
||||
#[diag(hir_analysis_field_already_declared, code = E0124)]
|
||||
NotNested {
|
||||
field_name: Symbol,
|
||||
field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
|
|
@ -226,7 +226,7 @@ pub(crate) enum FieldAlreadyDeclared {
|
|||
},
|
||||
#[diag(hir_analysis_field_already_declared_current_nested)]
|
||||
CurrentNested {
|
||||
field_name: Symbol,
|
||||
field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
|
|
@ -239,7 +239,7 @@ pub(crate) enum FieldAlreadyDeclared {
|
|||
},
|
||||
#[diag(hir_analysis_field_already_declared_previous_nested)]
|
||||
PreviousNested {
|
||||
field_name: Symbol,
|
||||
field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
|
|
@ -252,7 +252,7 @@ pub(crate) enum FieldAlreadyDeclared {
|
|||
},
|
||||
#[diag(hir_analysis_field_already_declared_both_nested)]
|
||||
BothNested {
|
||||
field_name: Symbol,
|
||||
field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
span: Span,
|
||||
|
|
@ -418,7 +418,7 @@ pub(crate) struct ValueOfAssociatedStructAlreadySpecified {
|
|||
pub(crate) struct UnconstrainedOpaqueType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
pub name: Ident,
|
||||
pub what: &'static str,
|
||||
}
|
||||
|
||||
|
|
@ -802,7 +802,7 @@ pub(crate) struct EnumDiscriminantOverflowed {
|
|||
#[label]
|
||||
pub span: Span,
|
||||
pub discr: String,
|
||||
pub item_name: Symbol,
|
||||
pub item_name: Ident,
|
||||
pub wrapped_discr: String,
|
||||
}
|
||||
|
||||
|
|
@ -893,7 +893,7 @@ pub(crate) enum ImplNotMarkedDefault {
|
|||
span: Span,
|
||||
#[label(hir_analysis_ok_label)]
|
||||
ok_label: Span,
|
||||
ident: Symbol,
|
||||
ident: Ident,
|
||||
},
|
||||
#[diag(hir_analysis_impl_not_marked_default_err, code = E0520)]
|
||||
#[note]
|
||||
|
|
@ -901,7 +901,7 @@ pub(crate) enum ImplNotMarkedDefault {
|
|||
#[primary_span]
|
||||
span: Span,
|
||||
cname: Symbol,
|
||||
ident: Symbol,
|
||||
ident: Ident,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +977,7 @@ pub(crate) struct MissingTraitItemUnstable {
|
|||
pub some_note: bool,
|
||||
#[note(hir_analysis_none_note)]
|
||||
pub none_note: bool,
|
||||
pub missing_item_name: Symbol,
|
||||
pub missing_item_name: Ident,
|
||||
pub feature: Symbol,
|
||||
pub reason: String,
|
||||
}
|
||||
|
|
@ -1249,7 +1249,7 @@ pub(crate) struct InherentNominal {
|
|||
pub(crate) struct DispatchFromDynZST<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
pub name: Ident,
|
||||
pub ty: Ty<'a>,
|
||||
}
|
||||
|
||||
|
|
@ -1389,7 +1389,7 @@ pub(crate) struct TyParamFirstLocal<'tcx> {
|
|||
pub span: Span,
|
||||
#[note(hir_analysis_case_note)]
|
||||
pub note: (),
|
||||
pub param: Symbol,
|
||||
pub param: Ident,
|
||||
pub local_type: Ty<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -1401,7 +1401,7 @@ pub(crate) struct TyParamFirstLocalLint<'tcx> {
|
|||
pub span: Span,
|
||||
#[note(hir_analysis_case_note)]
|
||||
pub note: (),
|
||||
pub param: Symbol,
|
||||
pub param: Ident,
|
||||
pub local_type: Ty<'tcx>,
|
||||
}
|
||||
|
||||
|
|
@ -1414,7 +1414,7 @@ pub(crate) struct TyParamSome {
|
|||
pub span: Span,
|
||||
#[note(hir_analysis_only_note)]
|
||||
pub note: (),
|
||||
pub param: Symbol,
|
||||
pub param: Ident,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -1425,7 +1425,7 @@ pub(crate) struct TyParamSomeLint {
|
|||
pub span: Span,
|
||||
#[note(hir_analysis_only_note)]
|
||||
pub note: (),
|
||||
pub param: Symbol,
|
||||
pub param: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -1533,7 +1533,7 @@ pub(crate) struct UnsupportedDelegation<'a> {
|
|||
pub(crate) struct MethodShouldReturnFuture {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub method_name: Symbol,
|
||||
pub method_name: Ident,
|
||||
#[note]
|
||||
pub trait_item_span: Option<Span>,
|
||||
}
|
||||
|
|
@ -1585,7 +1585,7 @@ pub(crate) struct UnconstrainedGenericParameter {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub param_name: Symbol,
|
||||
pub param_name: Ident,
|
||||
pub param_def_kind: &'static str,
|
||||
#[note(hir_analysis_const_param_note)]
|
||||
pub const_param_note: bool,
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||
.iter()
|
||||
.any(|constraint| constraint.ident.name == item.name)
|
||||
})
|
||||
.map(|item| item.name.to_ident_string())
|
||||
.map(|item| self.tcx.item_ident(item.def_id).to_string())
|
||||
.collect()
|
||||
} else {
|
||||
Vec::default()
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
|
|||
use LayoutError::*;
|
||||
|
||||
match layout_err {
|
||||
Unknown(ty) => {
|
||||
TooGeneric(ty) => {
|
||||
match abi {
|
||||
ExternAbi::CCmseNonSecureCall => {
|
||||
// prevent double reporting of this error
|
||||
|
|
@ -211,7 +211,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
|
|||
_ => bug!("invalid ABI: {abi}"),
|
||||
}
|
||||
}
|
||||
SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
|
||||
Unknown(..)
|
||||
| SizeOverflow(..)
|
||||
| NormalizationFailure(..)
|
||||
| ReferencesError(..)
|
||||
| Cycle(..) => {
|
||||
false // not our job to report these
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
|
|||
{
|
||||
let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
|
||||
span: tcx.def_span(param.def_id),
|
||||
param_name: param.name,
|
||||
param_name: tcx.item_ident(param.def_id),
|
||||
param_def_kind: tcx.def_descr(param.def_id),
|
||||
const_param_note: false,
|
||||
const_param_note2: false,
|
||||
|
|
@ -223,7 +223,7 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
|
|||
let const_param_note = matches!(param.kind, ty::GenericParamDefKind::Const { .. });
|
||||
let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
|
||||
span: tcx.def_span(param.def_id),
|
||||
param_name: param.name,
|
||||
param_name: tcx.item_ident(param.def_id),
|
||||
param_def_kind: tcx.def_descr(param.def_id),
|
||||
const_param_note,
|
||||
const_param_note2: const_param_note,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
|
|||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_from_coroutine)]
|
||||
#![feature(iter_intersperse)]
|
||||
|
|
|
|||
|
|
@ -851,32 +851,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
||||
|
||||
// Look for the type corresponding to the argument pattern we have in the argument list.
|
||||
&& let Some(ty_sugg) = fn_decl
|
||||
&& let Some(ty_ref) = fn_decl
|
||||
.inputs
|
||||
.iter()
|
||||
.filter_map(|ty| {
|
||||
if ty.span == *ty_span
|
||||
&& let hir::TyKind::Ref(lt, x) = ty.kind
|
||||
{
|
||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||
Some((
|
||||
x.ty.span.shrink_to_lo(),
|
||||
format!(
|
||||
"{}mut ",
|
||||
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }
|
||||
),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.filter_map(|ty| match ty.kind {
|
||||
hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
{
|
||||
let sugg = vec![
|
||||
ty_sugg,
|
||||
let mut sugg = if ty_ref.1.mutbl.is_mut() {
|
||||
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
|
||||
vec![]
|
||||
} else {
|
||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||
vec![(
|
||||
ty_ref.1.ty.span.shrink_to_lo(),
|
||||
format!(
|
||||
"{}mut ",
|
||||
if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " },
|
||||
),
|
||||
)]
|
||||
};
|
||||
sugg.extend([
|
||||
(pat.span.until(ident.span), String::new()),
|
||||
(lhs.span.shrink_to_lo(), "*".to_string()),
|
||||
];
|
||||
]);
|
||||
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
|
||||
// assignment from `ident = val;` to `*ident = val;`.
|
||||
err.multipart_suggestion_verbose(
|
||||
|
|
|
|||
|
|
@ -3337,10 +3337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
})
|
||||
.map(|mut field_path| {
|
||||
field_path.pop();
|
||||
field_path
|
||||
.iter()
|
||||
.map(|id| format!("{}.", id.name.to_ident_string()))
|
||||
.collect::<String>()
|
||||
field_path.iter().map(|id| format!("{}.", id)).collect::<String>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
candidate_fields.sort();
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
format!("generic size {size}")
|
||||
}
|
||||
}
|
||||
Err(LayoutError::Unknown(bad)) => {
|
||||
Err(LayoutError::TooGeneric(bad)) => {
|
||||
if *bad == ty {
|
||||
"this type does not have a fixed size".to_owned()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ fn report_unexpected_variant_res(
|
|||
);
|
||||
let fields = fields
|
||||
.iter()
|
||||
.map(|field| format!("{}: _", field.name.to_ident_string()))
|
||||
.map(|field| format!("{}: _", field.ident(tcx)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
let sugg = format!(" {{ {} }}", fields);
|
||||
|
|
|
|||
|
|
@ -2714,7 +2714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.map(|field_path| {
|
||||
field_path
|
||||
.iter()
|
||||
.map(|id| id.name.to_ident_string())
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(".")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -76,6 +76,11 @@ lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$rea
|
|||
lint_builtin_deref_nullptr = dereferencing a null pointer
|
||||
.label = this code causes undefined behavior when executed
|
||||
|
||||
lint_builtin_double_negations = use of a double negation
|
||||
.note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages
|
||||
.note_decrement = use `-= 1` if you meant to decrement the value
|
||||
.add_parens_suggestion = add parentheses for clarity
|
||||
|
||||
lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated
|
||||
.suggestion = use `..=` for an inclusive range
|
||||
|
||||
|
|
@ -974,6 +979,3 @@ lint_uses_power_alignment = repr(C) does not follow the power alignment rule. Th
|
|||
|
||||
lint_variant_size_differences =
|
||||
enum variant is more than three times larger ({$largest} bytes) than the next largest
|
||||
|
||||
lint_wasm_c_abi =
|
||||
older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88
|
||||
|
|
|
|||
|
|
@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self};
|
|||
use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
|
||||
use crate::lints::{
|
||||
BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
|
||||
BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr,
|
||||
BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
|
||||
BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
|
||||
BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
|
||||
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
|
||||
BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed,
|
||||
BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
|
||||
BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
|
||||
BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
|
||||
BuiltinWhileTrue, InvalidAsmLabel,
|
||||
BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, BuiltinDoubleNegations,
|
||||
BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint,
|
||||
BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote,
|
||||
BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures,
|
||||
BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
|
||||
BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
|
||||
BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
|
||||
BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub,
|
||||
BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment,
|
||||
BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
|
||||
};
|
||||
use crate::nonstandard_style::{MethodLateContext, method_context};
|
||||
use crate::{
|
||||
|
|
@ -90,19 +90,11 @@ declare_lint! {
|
|||
|
||||
declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
|
||||
|
||||
/// Traverse through any amount of parenthesis and return the first non-parens expression.
|
||||
fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
|
||||
while let ast::ExprKind::Paren(sub) = &expr.kind {
|
||||
expr = sub;
|
||||
}
|
||||
expr
|
||||
}
|
||||
|
||||
impl EarlyLintPass for WhileTrue {
|
||||
#[inline]
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
if let ast::ExprKind::While(cond, _, label) = &e.kind
|
||||
&& let ast::ExprKind::Lit(token_lit) = pierce_parens(cond).kind
|
||||
&& let ast::ExprKind::Lit(token_lit) = cond.peel_parens().kind
|
||||
&& let token::Lit { kind: token::Bool, symbol: kw::True, .. } = token_lit
|
||||
&& !cond.span.from_expansion()
|
||||
{
|
||||
|
|
@ -1576,6 +1568,58 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
|||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `double_negations` lint detects expressions of the form `--x`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// fn main() {
|
||||
/// let x = 1;
|
||||
/// let _b = --x;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Negating something twice is usually the same as not negating it at all.
|
||||
/// However, a double negation in Rust can easily be confused with the
|
||||
/// prefix decrement operator that exists in many languages derived from C.
|
||||
/// Use `-(-x)` if you really wanted to negate the value twice.
|
||||
///
|
||||
/// To decrement a value, use `x -= 1` instead.
|
||||
pub DOUBLE_NEGATIONS,
|
||||
Warn,
|
||||
"detects expressions of the form `--x`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
/// Lint for expressions of the form `--x` that can be confused with C's
|
||||
/// prefix decrement operator.
|
||||
DoubleNegations => [DOUBLE_NEGATIONS]
|
||||
);
|
||||
|
||||
impl EarlyLintPass for DoubleNegations {
|
||||
#[inline]
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
// only lint on the innermost `--` in a chain of `-` operators,
|
||||
// even if there are 3 or more negations
|
||||
if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind
|
||||
&& let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind
|
||||
&& !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _))
|
||||
{
|
||||
cx.emit_span_lint(DOUBLE_NEGATIONS, expr.span, BuiltinDoubleNegations {
|
||||
add_parens: BuiltinDoubleNegationsAddParens {
|
||||
start_span: inner.span.shrink_to_lo(),
|
||||
end_span: inner.span.shrink_to_hi(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// which are used by other parts of the compiler.
|
||||
|
|
@ -1594,7 +1638,8 @@ declare_lint_pass!(
|
|||
UNSTABLE_FEATURES,
|
||||
UNREACHABLE_PUB,
|
||||
TYPE_ALIAS_BOUNDS,
|
||||
TRIVIAL_BOUNDS
|
||||
TRIVIAL_BOUNDS,
|
||||
DOUBLE_NEGATIONS
|
||||
]
|
||||
);
|
||||
|
||||
|
|
@ -2651,7 +2696,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `deref_nullptr` lint detects when an null pointer is dereferenced,
|
||||
/// The `deref_nullptr` lint detects when a null pointer is dereferenced,
|
||||
/// which causes [undefined behavior].
|
||||
///
|
||||
/// ### Example
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
expr.hir_id,
|
||||
method.ident.span,
|
||||
DanglingPointersFromTemporaries {
|
||||
callee: method.ident.name,
|
||||
callee: method.ident,
|
||||
ty,
|
||||
ptr_span: method.ident.span,
|
||||
temporary_span: receiver.span,
|
||||
|
|
|
|||
|
|
@ -430,7 +430,6 @@ pub(super) fn decorate_lint(
|
|||
BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => {
|
||||
lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag),
|
||||
BuiltinLintDiag::IllFormedAttributeInput { suggestions } => {
|
||||
lints::IllFormedAttributeInput {
|
||||
num_suggestions: suggestions.len(),
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ early_lint_methods!(
|
|||
UnusedDocComment: UnusedDocComment,
|
||||
Expr2024: Expr2024,
|
||||
Precedence: Precedence,
|
||||
DoubleNegations: DoubleNegations,
|
||||
]
|
||||
]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -331,6 +331,24 @@ pub(crate) struct BuiltinTrivialBounds<'a> {
|
|||
pub predicate: Clause<'a>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_builtin_double_negations)]
|
||||
#[note(lint_note)]
|
||||
#[note(lint_note_decrement)]
|
||||
pub(crate) struct BuiltinDoubleNegations {
|
||||
#[subdiagnostic]
|
||||
pub add_parens: BuiltinDoubleNegationsAddParens,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")]
|
||||
pub(crate) struct BuiltinDoubleNegationsAddParens {
|
||||
#[suggestion_part(code = "(")]
|
||||
pub start_span: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
pub end_span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
|
||||
#[diag(lint_builtin_ellipsis_inclusive_range_patterns)]
|
||||
|
|
@ -1132,7 +1150,7 @@ pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
|
|||
#[help(lint_help_visit)]
|
||||
// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts
|
||||
pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
|
||||
pub callee: Symbol,
|
||||
pub callee: Ident,
|
||||
pub ty: Ty<'tcx>,
|
||||
#[label(lint_label_ptr)]
|
||||
pub ptr_span: Span,
|
||||
|
|
@ -1333,7 +1351,7 @@ pub(crate) enum NonUpperCaseGlobalSub {
|
|||
#[diag(lint_noop_method_call)]
|
||||
#[note]
|
||||
pub(crate) struct NoopMethodCallDiag<'a> {
|
||||
pub method: Symbol,
|
||||
pub method: Ident,
|
||||
pub orig_ty: Ty<'a>,
|
||||
pub trait_: Symbol,
|
||||
#[suggestion(code = "", applicability = "machine-applicable")]
|
||||
|
|
@ -2553,10 +2571,6 @@ pub(crate) struct UnusedCrateDependency {
|
|||
pub local_crate: Symbol,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_wasm_c_abi)]
|
||||
pub(crate) struct WasmCAbi;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_ill_formed_attribute_input)]
|
||||
pub(crate) struct IllFormedAttributeInput {
|
||||
|
|
|
|||
|
|
@ -343,5 +343,5 @@ fn path_span_without_args(path: &Path<'_>) -> Span {
|
|||
|
||||
/// Return a "error message-able" ident for the last segment of the `Path`
|
||||
fn path_name_to_string(path: &Path<'_>) -> String {
|
||||
path.segments.last().unwrap().ident.name.to_ident_string()
|
||||
path.segments.last().unwrap().ident.to_string()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
|||
_ => None,
|
||||
};
|
||||
cx.emit_span_lint(NOOP_METHOD_CALL, span, NoopMethodCallDiag {
|
||||
method: call.ident.name,
|
||||
method: call.ident,
|
||||
orig_ty,
|
||||
trait_,
|
||||
label: span,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
|
|||
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||
match path.res {
|
||||
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
|
||||
let name = cx.tcx.item_name(def_id).to_ident_string();
|
||||
let name = cx.tcx.item_ident(def_id);
|
||||
let path_segment = path.segments.last().unwrap();
|
||||
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ declare_lint_pass! {
|
|||
UNUSED_VARIABLES,
|
||||
USELESS_DEPRECATED,
|
||||
WARNINGS,
|
||||
WASM_C_ABI,
|
||||
// tidy-alphabetical-end
|
||||
]
|
||||
}
|
||||
|
|
@ -4092,6 +4091,7 @@ declare_lint! {
|
|||
/// ### Example
|
||||
///
|
||||
/// ```rust,ignore (needs CLI args, platform-specific)
|
||||
/// #[warn(linker_messages)]
|
||||
/// extern "C" {
|
||||
/// fn foo();
|
||||
/// }
|
||||
|
|
@ -4105,17 +4105,24 @@ declare_lint! {
|
|||
/// >>> referenced by rust_out.69edbd30df4ae57d-cgu.0
|
||||
/// >>> rust_out.rust_out.69edbd30df4ae57d-cgu.0.rcgu.o:(rust_out::main::h3a90094b06757803)
|
||||
/// |
|
||||
/// = note: `#[warn(linker_messages)]` on by default
|
||||
///
|
||||
/// note: the lint level is defined here
|
||||
/// --> warn.rs:1:9
|
||||
/// |
|
||||
/// 1 | #![warn(linker_messages)]
|
||||
/// | ^^^^^^^^^^^^^^^
|
||||
/// warning: 1 warning emitted
|
||||
/// ```
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Linkers emit platform-specific and program-specific warnings that cannot be predicted in advance by the rust compiler.
|
||||
/// They are forwarded by default, but can be disabled by adding `#![allow(linker_messages)]` at the crate root.
|
||||
/// Linkers emit platform-specific and program-specific warnings that cannot be predicted in
|
||||
/// advance by the Rust compiler. Such messages are ignored by default for now. While linker
|
||||
/// warnings could be very useful they have been ignored for many years by essentially all
|
||||
/// users, so we need to do a bit more work than just surfacing their text to produce a clear
|
||||
/// and actionable warning of similar quality to our other diagnostics. See this tracking
|
||||
/// issue for more details: <https://github.com/rust-lang/rust/issues/136096>.
|
||||
pub LINKER_MESSAGES,
|
||||
Warn,
|
||||
Allow,
|
||||
"warnings emitted at runtime by the target-specific linker program"
|
||||
}
|
||||
|
||||
|
|
@ -4681,44 +4688,6 @@ declare_lint! {
|
|||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `wasm_c_abi` lint detects crate dependencies that are incompatible
|
||||
/// with future versions of Rust that will emit spec-compliant C ABI.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,ignore (needs extern crate)
|
||||
/// #![deny(wasm_c_abi)]
|
||||
/// ```
|
||||
///
|
||||
/// This will produce:
|
||||
///
|
||||
/// ```text
|
||||
/// error: the following packages contain code that will be rejected by a future version of Rust: wasm-bindgen v0.2.87
|
||||
/// |
|
||||
/// note: the lint level is defined here
|
||||
/// --> src/lib.rs:1:9
|
||||
/// |
|
||||
/// 1 | #![deny(wasm_c_abi)]
|
||||
/// | ^^^^^^^^^^
|
||||
/// ```
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Rust has historically emitted non-spec-compliant C ABI. This has caused
|
||||
/// incompatibilities between other compilers and Wasm targets. In a future
|
||||
/// version of Rust this will be fixed and therefore dependencies relying
|
||||
/// on the non-spec-compliant C ABI will stop functioning.
|
||||
pub WASM_C_ABI,
|
||||
Deny,
|
||||
"detects dependencies that are incompatible with the Wasm C ABI",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
|
||||
reference: "issue #71871 <https://github.com/rust-lang/rust/issues/71871>",
|
||||
};
|
||||
crate_level_only
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `uncovered_param_in_projection` lint detects a violation of one of Rust's orphan rules for
|
||||
/// foreign trait implementations that concerns the use of type parameters inside trait associated
|
||||
|
|
|
|||
|
|
@ -795,7 +795,6 @@ pub enum BuiltinLintDiag {
|
|||
extern_crate: Symbol,
|
||||
local_crate: Symbol,
|
||||
},
|
||||
WasmCAbi,
|
||||
IllFormedAttributeInput {
|
||||
suggestions: Vec<String>,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -290,6 +290,9 @@ metadata_unsupported_abi =
|
|||
metadata_unsupported_abi_i686 =
|
||||
ABI not supported by `#[link(kind = "raw-dylib")]` on i686
|
||||
|
||||
metadata_wasm_c_abi =
|
||||
older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88
|
||||
|
||||
metadata_wasm_import_form =
|
||||
wasm import module must be of the form `wasm_import_module = "string"`
|
||||
|
||||
|
|
|
|||
|
|
@ -1076,12 +1076,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
// Make a point span rather than covering the whole file
|
||||
let span = krate.spans.inner_span.shrink_to_lo();
|
||||
|
||||
self.sess.psess.buffer_lint(
|
||||
lint::builtin::WASM_C_ABI,
|
||||
span,
|
||||
ast::CRATE_NODE_ID,
|
||||
BuiltinLintDiag::WasmCAbi,
|
||||
);
|
||||
self.sess.dcx().emit_err(errors::WasmCAbi { span });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -732,3 +732,10 @@ pub struct ImportNameTypeRaw {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_wasm_c_abi)]
|
||||
pub(crate) struct WasmCAbi {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ middle_strict_coherence_needs_negative_coherence =
|
|||
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
|
||||
.label = due to this attribute
|
||||
|
||||
middle_too_generic = `{$ty}` does not have a fixed size
|
||||
|
||||
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
|
||||
|
||||
middle_unknown_layout =
|
||||
|
|
@ -107,4 +109,5 @@ middle_unknown_layout =
|
|||
|
||||
middle_values_too_big =
|
||||
values of the type `{$ty}` are too big for the target architecture
|
||||
|
||||
middle_written_to_path = the full type name has been written to '{$path}'
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@ pub enum LayoutError<'tcx> {
|
|||
#[diag(middle_unknown_layout)]
|
||||
Unknown { ty: Ty<'tcx> },
|
||||
|
||||
#[diag(middle_too_generic)]
|
||||
TooGeneric { ty: Ty<'tcx> },
|
||||
|
||||
#[diag(middle_values_too_big)]
|
||||
Overflow { ty: Ty<'tcx> },
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#![feature(const_type_name)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(discriminant_kind)]
|
||||
#![feature(extern_types)]
|
||||
|
|
|
|||
|
|
@ -460,17 +460,6 @@ impl<'tcx> Const<'tcx> {
|
|||
Self::Val(val, ty)
|
||||
}
|
||||
|
||||
pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Value(ty, valtree) => {
|
||||
// Make sure that if `c` is normalized, then the return value is normalized.
|
||||
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
||||
Self::Val(const_val, ty)
|
||||
}
|
||||
_ => Self::Ty(ty, c),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if any evaluation of this constant always returns the same value,
|
||||
/// taking into account even pointer identity tests.
|
||||
pub fn is_deterministic(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexMap;
|
|||
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::ItemId;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
|
||||
use rustc_index::Idx;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
|
@ -247,6 +247,12 @@ impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable, Copy, Clone)]
|
||||
pub struct MonoItemPartitions<'tcx> {
|
||||
pub codegen_units: &'tcx [CodegenUnit<'tcx>],
|
||||
pub all_mono_items: &'tcx DefIdSet,
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable)]
|
||||
pub struct CodegenUnit<'tcx> {
|
||||
/// A name for this CGU. Incremental compilation requires that
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::fmt::{Display, Write as _};
|
||||
use std::fs;
|
||||
use std::io::{self, Write as _};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
||||
use rustc_abi::Size;
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
|
|
@ -149,37 +148,59 @@ pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool {
|
|||
// `def_path_str()` would otherwise trigger `type_of`, and this can
|
||||
// run while we are already attempting to evaluate `type_of`.
|
||||
|
||||
/// Most use-cases of dumping MIR should use the [dump_mir] entrypoint instead, which will also
|
||||
/// check if dumping MIR is enabled, and if this body matches the filters passed on the CLI.
|
||||
///
|
||||
/// That being said, if the above requirements have been validated already, this function is where
|
||||
/// most of the MIR dumping occurs, if one needs to export it to a file they have created with
|
||||
/// [create_dump_file], rather than to a new file created as part of [dump_mir], or to stdout/stderr
|
||||
/// for debugging purposes.
|
||||
pub fn dump_mir_to_writer<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pass_name: &str,
|
||||
disambiguator: &dyn Display,
|
||||
body: &Body<'tcx>,
|
||||
w: &mut dyn io::Write,
|
||||
mut extra_data: F,
|
||||
options: PrettyPrintMirOptions,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>,
|
||||
{
|
||||
// see notes on #41697 above
|
||||
let def_path =
|
||||
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
|
||||
// ignore-tidy-odd-backticks the literal below is fine
|
||||
write!(w, "// MIR for `{def_path}")?;
|
||||
match body.source.promoted {
|
||||
None => write!(w, "`")?,
|
||||
Some(promoted) => write!(w, "::{promoted:?}`")?,
|
||||
}
|
||||
writeln!(w, " {disambiguator} {pass_name}")?;
|
||||
if let Some(ref layout) = body.coroutine_layout_raw() {
|
||||
writeln!(w, "/* coroutine_layout = {layout:#?} */")?;
|
||||
}
|
||||
writeln!(w)?;
|
||||
extra_data(PassWhere::BeforeCFG, w)?;
|
||||
write_user_type_annotations(tcx, body, w)?;
|
||||
write_mir_fn(tcx, body, &mut extra_data, w, options)?;
|
||||
extra_data(PassWhere::AfterCFG, w)
|
||||
}
|
||||
|
||||
fn dump_matched_mir_node<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pass_num: bool,
|
||||
pass_name: &str,
|
||||
disambiguator: &dyn Display,
|
||||
body: &Body<'tcx>,
|
||||
mut extra_data: F,
|
||||
extra_data: F,
|
||||
options: PrettyPrintMirOptions,
|
||||
) where
|
||||
F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>,
|
||||
{
|
||||
let _: io::Result<()> = try {
|
||||
let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body)?;
|
||||
// see notes on #41697 above
|
||||
let def_path =
|
||||
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
|
||||
// ignore-tidy-odd-backticks the literal below is fine
|
||||
write!(file, "// MIR for `{def_path}")?;
|
||||
match body.source.promoted {
|
||||
None => write!(file, "`")?,
|
||||
Some(promoted) => write!(file, "::{promoted:?}`")?,
|
||||
}
|
||||
writeln!(file, " {disambiguator} {pass_name}")?;
|
||||
if let Some(ref layout) = body.coroutine_layout_raw() {
|
||||
writeln!(file, "/* coroutine_layout = {layout:#?} */")?;
|
||||
}
|
||||
writeln!(file)?;
|
||||
extra_data(PassWhere::BeforeCFG, &mut file)?;
|
||||
write_user_type_annotations(tcx, body, &mut file)?;
|
||||
write_mir_fn(tcx, body, &mut extra_data, &mut file, options)?;
|
||||
extra_data(PassWhere::AfterCFG, &mut file)?;
|
||||
dump_mir_to_writer(tcx, pass_name, disambiguator, body, &mut file, extra_data, options)?;
|
||||
};
|
||||
|
||||
if tcx.sess.opts.unstable_opts.dump_mir_graphviz {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
//! Values computed by queries that use MIR.
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
use rustc_abi::{FieldIdx, VariantIdx};
|
||||
|
|
@ -62,55 +61,26 @@ pub struct CoroutineLayout<'tcx> {
|
|||
|
||||
impl Debug for CoroutineLayout<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// Prints an iterator of (key, value) tuples as a map.
|
||||
struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>);
|
||||
impl<'a, K, V> MapPrinter<'a, K, V> {
|
||||
fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self {
|
||||
Self(Cell::new(Some(Box::new(iter))))
|
||||
}
|
||||
}
|
||||
impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_map().entries(self.0.take().unwrap()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints the coroutine variant name.
|
||||
struct GenVariantPrinter(VariantIdx);
|
||||
impl From<VariantIdx> for GenVariantPrinter {
|
||||
fn from(idx: VariantIdx) -> Self {
|
||||
GenVariantPrinter(idx)
|
||||
}
|
||||
}
|
||||
impl Debug for GenVariantPrinter {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let variant_name = ty::CoroutineArgs::variant_name(self.0);
|
||||
if fmt.alternate() {
|
||||
write!(fmt, "{:9}({:?})", variant_name, self.0)
|
||||
} else {
|
||||
write!(fmt, "{variant_name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Forces its contents to print in regular mode instead of alternate mode.
|
||||
struct OneLinePrinter<T>(T);
|
||||
impl<T: Debug> Debug for OneLinePrinter<T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.debug_struct("CoroutineLayout")
|
||||
.field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated()))
|
||||
.field(
|
||||
"variant_fields",
|
||||
&MapPrinter::new(
|
||||
self.variant_fields
|
||||
.iter_enumerated()
|
||||
.map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))),
|
||||
),
|
||||
)
|
||||
.field_with("field_tys", |fmt| {
|
||||
fmt.debug_map().entries(self.field_tys.iter_enumerated()).finish()
|
||||
})
|
||||
.field_with("variant_fields", |fmt| {
|
||||
let mut map = fmt.debug_map();
|
||||
for (idx, fields) in self.variant_fields.iter_enumerated() {
|
||||
map.key_with(|fmt| {
|
||||
let variant_name = ty::CoroutineArgs::variant_name(idx);
|
||||
if fmt.alternate() {
|
||||
write!(fmt, "{variant_name:9}({idx:?})")
|
||||
} else {
|
||||
write!(fmt, "{variant_name}")
|
||||
}
|
||||
});
|
||||
// Force variant fields to print in regular mode instead of alternate mode.
|
||||
map.value_with(|fmt| write!(fmt, "{fields:?}"));
|
||||
}
|
||||
map.finish()
|
||||
})
|
||||
.field("storage_conflicts", &self.storage_conflicts)
|
||||
.finish()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -581,9 +581,11 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||
pub enum TerminatorEdges<'mir, 'tcx> {
|
||||
/// For terminators that have no successor, like `return`.
|
||||
None,
|
||||
/// For terminators that a single successor, like `goto`, and `assert` without cleanup block.
|
||||
/// For terminators that have a single successor, like `goto`, and `assert` without a cleanup
|
||||
/// block.
|
||||
Single(BasicBlock),
|
||||
/// For terminators that two successors, `assert` with cleanup block and `falseEdge`.
|
||||
/// For terminators that have two successors, like `assert` with a cleanup block, and
|
||||
/// `falseEdge`.
|
||||
Double(BasicBlock, BasicBlock),
|
||||
/// Special action for `Yield`, `Call` and `InlineAsm` terminators.
|
||||
AssignOnReturn {
|
||||
|
|
|
|||
|
|
@ -349,6 +349,7 @@ tcx_lifetime! {
|
|||
rustc_middle::mir::interpret::GlobalId,
|
||||
rustc_middle::mir::interpret::LitToConstInput,
|
||||
rustc_middle::mir::interpret::EvalStaticInitializerRawResult,
|
||||
rustc_middle::mir::mono::MonoItemPartitions,
|
||||
rustc_middle::traits::query::MethodAutoderefStepsResult,
|
||||
rustc_middle::traits::query::type_op::AscribeUserType,
|
||||
rustc_middle::traits::query::type_op::Eq,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet};
|
|||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
use rustc_hir::def_id::{
|
||||
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
|
||||
CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
|
||||
};
|
||||
use rustc_hir::lang_items::{LangItem, LanguageItems};
|
||||
use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate};
|
||||
|
|
@ -58,7 +58,7 @@ use crate::mir::interpret::{
|
|||
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
|
||||
EvalToValTreeResult, GlobalId, LitToConstInput,
|
||||
};
|
||||
use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem};
|
||||
use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions};
|
||||
use crate::query::erase::{Erase, erase, restore};
|
||||
use crate::query::plumbing::{
|
||||
CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at,
|
||||
|
|
@ -2166,7 +2166,7 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) {
|
||||
query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> {
|
||||
eval_always
|
||||
desc { "collect_and_partition_mono_items" }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1349,6 +1349,33 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
/// Stores memory for globals (statics/consts).
|
||||
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
||||
|
||||
current_gcx: CurrentGcx,
|
||||
}
|
||||
|
||||
impl<'tcx> GlobalCtxt<'tcx> {
|
||||
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
|
||||
/// `f`.
|
||||
pub fn enter<F, R>(&'tcx self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(TyCtxt<'tcx>) -> R,
|
||||
{
|
||||
let icx = tls::ImplicitCtxt::new(self);
|
||||
|
||||
// Reset `current_gcx` to `None` when we exit.
|
||||
let _on_drop = defer(move || {
|
||||
*self.current_gcx.value.write() = None;
|
||||
});
|
||||
|
||||
// Set this `GlobalCtxt` as the current one.
|
||||
{
|
||||
let mut guard = self.current_gcx.value.write();
|
||||
assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
|
||||
*guard = Some(self as *const _ as *const ());
|
||||
}
|
||||
|
||||
tls::enter_context(&icx, || f(icx.tcx))
|
||||
}
|
||||
}
|
||||
|
||||
/// This is used to get a reference to a `GlobalCtxt` if one is available.
|
||||
|
|
@ -1539,23 +1566,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
canonical_param_env_cache: Default::default(),
|
||||
data_layout,
|
||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||
current_gcx,
|
||||
});
|
||||
|
||||
let icx = tls::ImplicitCtxt::new(&gcx);
|
||||
|
||||
// Reset `current_gcx` to `None` when we exit.
|
||||
let _on_drop = defer(|| {
|
||||
*current_gcx.value.write() = None;
|
||||
});
|
||||
|
||||
// Set this `GlobalCtxt` as the current one.
|
||||
{
|
||||
let mut guard = current_gcx.value.write();
|
||||
assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
|
||||
*guard = Some(&gcx as *const _ as *const ());
|
||||
}
|
||||
|
||||
tls::enter_context(&icx, || f(icx.tcx))
|
||||
// This is a separate function to work around a crash with parallel rustc (#135870)
|
||||
gcx.enter(f)
|
||||
}
|
||||
|
||||
/// Obtain all lang items of this crate and all dependencies (recursively)
|
||||
|
|
@ -2325,51 +2340,41 @@ macro_rules! sty_debug_print {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx {
|
||||
struct DebugStats<'tcx>(TyCtxt<'tcx>);
|
||||
pub fn debug_stats(self) -> impl fmt::Debug + 'tcx {
|
||||
fmt::from_fn(move |fmt| {
|
||||
sty_debug_print!(
|
||||
fmt,
|
||||
self,
|
||||
Adt,
|
||||
Array,
|
||||
Slice,
|
||||
RawPtr,
|
||||
Ref,
|
||||
FnDef,
|
||||
FnPtr,
|
||||
UnsafeBinder,
|
||||
Placeholder,
|
||||
Coroutine,
|
||||
CoroutineWitness,
|
||||
Dynamic,
|
||||
Closure,
|
||||
CoroutineClosure,
|
||||
Tuple,
|
||||
Bound,
|
||||
Param,
|
||||
Infer,
|
||||
Alias,
|
||||
Pat,
|
||||
Foreign
|
||||
)?;
|
||||
|
||||
impl<'tcx> std::fmt::Debug for DebugStats<'tcx> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
sty_debug_print!(
|
||||
fmt,
|
||||
self.0,
|
||||
Adt,
|
||||
Array,
|
||||
Slice,
|
||||
RawPtr,
|
||||
Ref,
|
||||
FnDef,
|
||||
FnPtr,
|
||||
UnsafeBinder,
|
||||
Placeholder,
|
||||
Coroutine,
|
||||
CoroutineWitness,
|
||||
Dynamic,
|
||||
Closure,
|
||||
CoroutineClosure,
|
||||
Tuple,
|
||||
Bound,
|
||||
Param,
|
||||
Infer,
|
||||
Alias,
|
||||
Pat,
|
||||
Foreign
|
||||
)?;
|
||||
writeln!(fmt, "GenericArgs interner: #{}", self.interners.args.len())?;
|
||||
writeln!(fmt, "Region interner: #{}", self.interners.region.len())?;
|
||||
writeln!(fmt, "Const Allocation interner: #{}", self.interners.const_allocation.len())?;
|
||||
writeln!(fmt, "Layout interner: #{}", self.interners.layout.len())?;
|
||||
|
||||
writeln!(fmt, "GenericArgs interner: #{}", self.0.interners.args.len())?;
|
||||
writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
|
||||
writeln!(
|
||||
fmt,
|
||||
"Const Allocation interner: #{}",
|
||||
self.0.interners.const_allocation.len()
|
||||
)?;
|
||||
writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
DebugStats(self)
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ impl fmt::Display for ValidityRequirement {
|
|||
pub enum LayoutError<'tcx> {
|
||||
Unknown(Ty<'tcx>),
|
||||
SizeOverflow(Ty<'tcx>),
|
||||
TooGeneric(Ty<'tcx>),
|
||||
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
|
||||
ReferencesError(ErrorGuaranteed),
|
||||
Cycle(ErrorGuaranteed),
|
||||
|
|
@ -244,6 +245,7 @@ impl<'tcx> LayoutError<'tcx> {
|
|||
match self {
|
||||
Unknown(_) => middle_unknown_layout,
|
||||
SizeOverflow(_) => middle_values_too_big,
|
||||
TooGeneric(_) => middle_too_generic,
|
||||
NormalizationFailure(_, _) => middle_cannot_be_normalized,
|
||||
Cycle(_) => middle_cycle,
|
||||
ReferencesError(_) => middle_layout_references_error,
|
||||
|
|
@ -257,6 +259,7 @@ impl<'tcx> LayoutError<'tcx> {
|
|||
match self {
|
||||
Unknown(ty) => E::Unknown { ty },
|
||||
SizeOverflow(ty) => E::Overflow { ty },
|
||||
TooGeneric(ty) => E::TooGeneric { ty },
|
||||
NormalizationFailure(ty, e) => {
|
||||
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
|
||||
}
|
||||
|
|
@ -272,6 +275,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
|
||||
LayoutError::TooGeneric(ty) => {
|
||||
write!(f, "`{ty}` does not have a fixed size")
|
||||
}
|
||||
LayoutError::SizeOverflow(ty) => {
|
||||
write!(f, "values of the type `{ty}` are too big for the target architecture")
|
||||
}
|
||||
|
|
@ -350,10 +356,11 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
|
||||
}
|
||||
}
|
||||
Err(err @ LayoutError::Unknown(_)) => err,
|
||||
Err(err @ LayoutError::TooGeneric(_)) => err,
|
||||
// We can't extract SizeSkeleton info from other layout errors
|
||||
Err(
|
||||
e @ LayoutError::Cycle(_)
|
||||
| e @ LayoutError::Unknown(_)
|
||||
| e @ LayoutError::SizeOverflow(_)
|
||||
| e @ LayoutError::NormalizationFailure(..)
|
||||
| e @ LayoutError::ReferencesError(_),
|
||||
|
|
@ -413,10 +420,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
// Alignment is unchanged by arrays.
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
|
||||
}
|
||||
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
|
||||
Err(err)
|
||||
}
|
||||
SizeSkeleton::Pointer { .. } => Err(err),
|
||||
SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
|
||||
SizeSkeleton::Pointer { .. } | SizeSkeleton::Generic(_) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1596,6 +1596,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
Some(Ident::new(def, span))
|
||||
}
|
||||
|
||||
/// Look up the name and span of a definition.
|
||||
///
|
||||
/// See [`item_name`][Self::item_name] for more information.
|
||||
pub fn item_ident(self, def_id: DefId) -> Ident {
|
||||
self.opt_item_ident(def_id).unwrap_or_else(|| {
|
||||
bug!("item_ident: no name for {:?}", self.def_path(def_id));
|
||||
})
|
||||
}
|
||||
|
||||
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
|
||||
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
|
||||
Some(self.associated_item(def_id))
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use tracing::{debug, instrument};
|
|||
|
||||
use super::TypingEnv;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::mir;
|
||||
use crate::query::Providers;
|
||||
use crate::ty::fold::fold_regions;
|
||||
use crate::ty::layout::{FloatExt, IntegerExt};
|
||||
|
|
@ -1183,18 +1184,18 @@ impl<'tcx> Ty<'tcx> {
|
|||
|
||||
/// Returns the maximum value for the given numeric type (including `char`s)
|
||||
/// or returns `None` if the type is not numeric.
|
||||
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
|
||||
pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<mir::Const<'tcx>> {
|
||||
let typing_env = TypingEnv::fully_monomorphized();
|
||||
self.numeric_min_and_max_as_bits(tcx)
|
||||
.map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self))
|
||||
.map(|(_, max)| mir::Const::from_bits(tcx, max, typing_env, self))
|
||||
}
|
||||
|
||||
/// Returns the minimum value for the given numeric type (including `char`s)
|
||||
/// or returns `None` if the type is not numeric.
|
||||
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
|
||||
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<mir::Const<'tcx>> {
|
||||
let typing_env = TypingEnv::fully_monomorphized();
|
||||
self.numeric_min_and_max_as_bits(tcx)
|
||||
.map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self))
|
||||
.map(|(min, _)| mir::Const::from_bits(tcx, min, typing_env, self))
|
||||
}
|
||||
|
||||
/// Checks whether values of this type `T` have a size known at
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
|||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_pattern_analysis::errors::Uncovered;
|
||||
use rustc_pattern_analysis::rustc::RustcPatCtxt;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
|
|
@ -753,7 +753,7 @@ pub(crate) struct BindingsWithVariantName {
|
|||
#[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")]
|
||||
pub(crate) suggestion: Option<Span>,
|
||||
pub(crate) ty_path: String,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
@ -797,7 +797,7 @@ pub(crate) struct BorrowOfMovedValue {
|
|||
pub(crate) binding_span: Span,
|
||||
#[label(mir_build_value_borrowed_label)]
|
||||
pub(crate) conflicts_ref: Vec<Span>,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
pub(crate) ty: String,
|
||||
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
||||
pub(crate) suggest_borrowing: Option<Span>,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rustc_session::lint::builtin::{
|
|||
};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::instrument;
|
||||
|
||||
|
|
@ -800,7 +800,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
sess.dcx().emit_err(BorrowOfMovedValue {
|
||||
binding_span: pat.span,
|
||||
conflicts_ref,
|
||||
name,
|
||||
name: Ident::new(name, pat.span),
|
||||
ty,
|
||||
suggest_borrowing: Some(pat.span.shrink_to_lo()),
|
||||
has_path: path.is_some(),
|
||||
|
|
@ -908,7 +908,7 @@ fn check_for_bindings_named_same_as_variants(
|
|||
None
|
||||
},
|
||||
ty_path,
|
||||
name,
|
||||
name: Ident::new(name, pat.span),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,12 @@ use rustc_index::bit_set::DenseBitSet;
|
|||
use rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, Op};
|
||||
|
||||
use crate::coverage::counters::balanced_flow::BalancedFlowGraph;
|
||||
use crate::coverage::counters::iter_nodes::IterNodes;
|
||||
use crate::coverage::counters::node_flow::{
|
||||
CounterTerm, NodeCounters, make_node_counters, node_flow_data_for_balanced_graph,
|
||||
};
|
||||
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
||||
|
||||
mod balanced_flow;
|
||||
mod iter_nodes;
|
||||
mod node_flow;
|
||||
mod union_find;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ use rustc_data_structures::graph::reversed::ReversedGraph;
|
|||
use rustc_index::Idx;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
|
||||
use crate::coverage::counters::iter_nodes::IterNodes;
|
||||
|
||||
/// A view of an underlying graph that has been augmented to have “balanced flow”.
|
||||
/// This means that the flow (execution count) of each node is equal to the
|
||||
/// sum of its in-edge flows, and also equal to the sum of its out-edge flows.
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
use rustc_data_structures::graph;
|
||||
use rustc_index::Idx;
|
||||
|
||||
pub(crate) trait IterNodes: graph::DirectedGraph {
|
||||
/// Iterates over all nodes of a graph in ascending numeric order.
|
||||
/// Assumes that nodes are densely numbered, i.e. every index in
|
||||
/// `0..num_nodes` is a valid node.
|
||||
///
|
||||
/// FIXME: Can this just be part of [`graph::DirectedGraph`]?
|
||||
fn iter_nodes(
|
||||
&self,
|
||||
) -> impl Iterator<Item = Self::Node> + DoubleEndedIterator + ExactSizeIterator {
|
||||
(0..self.num_nodes()).map(<Self::Node as Idx>::new)
|
||||
}
|
||||
}
|
||||
impl<G: graph::DirectedGraph> IterNodes for G {}
|
||||
|
|
@ -11,7 +11,6 @@ use rustc_index::bit_set::DenseBitSet;
|
|||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_middle::mir::coverage::Op;
|
||||
|
||||
use crate::coverage::counters::iter_nodes::IterNodes;
|
||||
use crate::coverage::counters::union_find::UnionFind;
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_middle::mir::AssertKind;
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::{self, Lint};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ pub(crate) struct FnItemRef {
|
|||
#[suggestion(code = "{sugg}", applicability = "unspecified")]
|
||||
pub span: Span,
|
||||
pub sugg: String,
|
||||
pub ident: String,
|
||||
pub ident: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||
s
|
||||
}
|
||||
};
|
||||
let ident = self.tcx.item_name(fn_id).to_ident_string();
|
||||
let ident = self.tcx.item_ident(fn_id);
|
||||
let ty_params = fn_args.types().map(|ty| format!("{ty}"));
|
||||
let const_params = fn_args.consts().map(|c| format!("{c}"));
|
||||
let params = ty_params.chain(const_params).join(", ");
|
||||
|
|
@ -177,7 +177,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
|
|||
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
|
||||
let sugg = format!(
|
||||
"{} as {}{}fn({}{}){}",
|
||||
if params.is_empty() { ident.clone() } else { format!("{ident}::<{params}>") },
|
||||
if params.is_empty() { ident.to_string() } else { format!("{ident}::<{params}>") },
|
||||
unsafety,
|
||||
abi,
|
||||
vec!["_"; num_args].join(", "),
|
||||
|
|
|
|||
|
|
@ -1178,11 +1178,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
) if let ty::Slice(..) = to.builtin_deref(true).unwrap().kind()
|
||||
&& let ty::Array(_, len) = from.builtin_deref(true).unwrap().kind() =>
|
||||
{
|
||||
return self.insert_constant(Const::from_ty_const(
|
||||
*len,
|
||||
self.tcx.types.usize,
|
||||
self.tcx,
|
||||
));
|
||||
return self.insert_constant(Const::Ty(self.tcx.types.usize, *len));
|
||||
}
|
||||
_ => Value::UnaryOp(op, arg_index),
|
||||
};
|
||||
|
|
@ -1492,11 +1488,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
// Trivial case: we are fetching a statically known length.
|
||||
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
||||
if let ty::Array(_, len) = place_ty.kind() {
|
||||
return self.insert_constant(Const::from_ty_const(
|
||||
*len,
|
||||
self.tcx.types.usize,
|
||||
self.tcx,
|
||||
));
|
||||
return self.insert_constant(Const::Ty(self.tcx.types.usize, *len));
|
||||
}
|
||||
|
||||
let mut inner = self.simplify_place_value(place, location)?;
|
||||
|
|
@ -1518,11 +1510,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
&& let Some(to) = to.builtin_deref(true)
|
||||
&& let ty::Slice(..) = to.kind()
|
||||
{
|
||||
return self.insert_constant(Const::from_ty_const(
|
||||
*len,
|
||||
self.tcx.types.usize,
|
||||
self.tcx,
|
||||
));
|
||||
return self.insert_constant(Const::Ty(self.tcx.types.usize, *len));
|
||||
}
|
||||
|
||||
// Fallback: a symbolic `Len`.
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
|
|||
if let Rvalue::Len(ref place) = *rvalue {
|
||||
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
||||
if let ty::Array(_, len) = *place_ty.kind() {
|
||||
let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx);
|
||||
let const_ = Const::Ty(self.tcx.types.usize, len);
|
||||
let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
|
||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
|||
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
|
||||
use rustc_middle::mir::mono::{
|
||||
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
|
||||
Visibility,
|
||||
MonoItemPartitions, Visibility,
|
||||
};
|
||||
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{self, InstanceKind, TyCtxt};
|
||||
|
|
@ -1114,7 +1114,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
|
||||
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitions<'_> {
|
||||
let collection_strategy = match tcx.sess.opts.unstable_opts.print_mono_items {
|
||||
Some(ref s) => {
|
||||
let mode = s.to_lowercase();
|
||||
|
|
@ -1236,7 +1236,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
|
|||
}
|
||||
}
|
||||
|
||||
(tcx.arena.alloc(mono_items), codegen_units)
|
||||
MonoItemPartitions { all_mono_items: tcx.arena.alloc(mono_items), codegen_units }
|
||||
}
|
||||
|
||||
/// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s
|
||||
|
|
@ -1319,14 +1319,13 @@ fn dump_mono_items_stats<'tcx>(
|
|||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
|
||||
|
||||
providers.is_codegened_item = |tcx, def_id| {
|
||||
let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());
|
||||
all_mono_items.contains(&def_id)
|
||||
};
|
||||
providers.is_codegened_item =
|
||||
|tcx, def_id| tcx.collect_and_partition_mono_items(()).all_mono_items.contains(&def_id);
|
||||
|
||||
providers.codegen_unit = |tcx, name| {
|
||||
let (_, all) = tcx.collect_and_partition_mono_items(());
|
||||
all.iter()
|
||||
tcx.collect_and_partition_mono_items(())
|
||||
.codegen_units
|
||||
.iter()
|
||||
.find(|cgu| cgu.name() == name)
|
||||
.unwrap_or_else(|| panic!("failed to find cgu with name {name:?}"))
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3233,7 +3233,7 @@ pub(crate) struct MalformedCfgAttr {
|
|||
pub(crate) struct UnknownBuiltinConstruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
pub name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -1958,7 +1958,7 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
let err = self.dcx().create_err(errors::UnknownBuiltinConstruct {
|
||||
span: lo.to(ident.span),
|
||||
name: ident.name,
|
||||
name: ident,
|
||||
});
|
||||
return Err(err);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1598,45 +1598,35 @@ impl<'a> Parser<'a> {
|
|||
// Only used when debugging.
|
||||
#[allow(unused)]
|
||||
pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ {
|
||||
struct DebugParser<'dbg> {
|
||||
parser: &'dbg Parser<'dbg>,
|
||||
lookahead: usize,
|
||||
}
|
||||
fmt::from_fn(move |f| {
|
||||
let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of
|
||||
|
||||
impl fmt::Debug for DebugParser<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { parser, lookahead } = self;
|
||||
let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of
|
||||
|
||||
// we don't need N spans, but we want at least one, so print all of prev_token
|
||||
dbg_fmt.field("prev_token", &parser.prev_token);
|
||||
let mut tokens = vec![];
|
||||
for i in 0..*lookahead {
|
||||
let tok = parser.look_ahead(i, |tok| tok.kind.clone());
|
||||
let is_eof = tok == TokenKind::Eof;
|
||||
tokens.push(tok);
|
||||
if is_eof {
|
||||
// Don't look ahead past EOF.
|
||||
break;
|
||||
}
|
||||
// we don't need N spans, but we want at least one, so print all of prev_token
|
||||
dbg_fmt.field("prev_token", &self.prev_token);
|
||||
let mut tokens = vec![];
|
||||
for i in 0..lookahead {
|
||||
let tok = self.look_ahead(i, |tok| tok.kind.clone());
|
||||
let is_eof = tok == TokenKind::Eof;
|
||||
tokens.push(tok);
|
||||
if is_eof {
|
||||
// Don't look ahead past EOF.
|
||||
break;
|
||||
}
|
||||
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
|
||||
dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls);
|
||||
|
||||
// some fields are interesting for certain values, as they relate to macro parsing
|
||||
if let Some(subparser) = parser.subparser_name {
|
||||
dbg_fmt.field("subparser_name", &subparser);
|
||||
}
|
||||
if let Recovery::Forbidden = parser.recovery {
|
||||
dbg_fmt.field("recovery", &parser.recovery);
|
||||
}
|
||||
|
||||
// imply there's "more to know" than this view
|
||||
dbg_fmt.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish());
|
||||
dbg_fmt.field("approx_token_stream_pos", &self.num_bump_calls);
|
||||
|
||||
DebugParser { parser: self, lookahead }
|
||||
// some fields are interesting for certain values, as they relate to macro parsing
|
||||
if let Some(subparser) = self.subparser_name {
|
||||
dbg_fmt.field("subparser_name", &subparser);
|
||||
}
|
||||
if let Recovery::Forbidden = self.recovery {
|
||||
dbg_fmt.field("recovery", &self.recovery);
|
||||
}
|
||||
|
||||
// imply there's "more to know" than this view
|
||||
dbg_fmt.finish_non_exhaustive()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clear_expected_token_types(&mut self) {
|
||||
|
|
|
|||
|
|
@ -1791,7 +1791,7 @@ pub(crate) struct UnusedAssign {
|
|||
pub(crate) struct UnusedAssignSuggestion {
|
||||
pub pre: &'static str,
|
||||
#[suggestion_part(code = "{pre}mut ")]
|
||||
pub ty_span: Span,
|
||||
pub ty_span: Option<Span>,
|
||||
#[suggestion_part(code = "")]
|
||||
pub ty_ref_span: Span,
|
||||
#[suggestion_part(code = "*")]
|
||||
|
|
|
|||
|
|
@ -1620,24 +1620,28 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
&& let item = self.ir.tcx.hir_owner_node(item_id)
|
||||
&& let Some(fn_decl) = item.fn_decl()
|
||||
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
||||
&& let Some((ty_span, pre)) = fn_decl
|
||||
&& let Some((lt, mut_ty)) = fn_decl
|
||||
.inputs
|
||||
.iter()
|
||||
.filter_map(|ty| {
|
||||
if ty.span == *ty_span
|
||||
&& let hir::TyKind::Ref(lt, mut_ty) = ty.kind
|
||||
{
|
||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||
Some((
|
||||
mut_ty.ty.span.shrink_to_lo(),
|
||||
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " },
|
||||
))
|
||||
Some((lt, mut_ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.next()
|
||||
{
|
||||
let ty_span = if mut_ty.mutbl.is_mut() {
|
||||
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
|
||||
None
|
||||
} else {
|
||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||
Some(mut_ty.ty.span.shrink_to_lo())
|
||||
};
|
||||
let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " };
|
||||
Some(errors::UnusedAssignSuggestion {
|
||||
ty_span,
|
||||
pre,
|
||||
|
|
|
|||
|
|
@ -794,9 +794,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||
// fictitious values after `{u,i}size::MAX` (see [`IntRange::split`] for why we do
|
||||
// this). We show this to the user as `usize::MAX..` which is slightly incorrect but
|
||||
// probably clear enough.
|
||||
let c = ty.numeric_max_val(cx.tcx).unwrap();
|
||||
let value = mir::Const::from_ty_const(c, ty.0, cx.tcx);
|
||||
lo = PatRangeBoundary::Finite(value);
|
||||
lo = PatRangeBoundary::Finite(ty.numeric_max_val(cx.tcx).unwrap());
|
||||
}
|
||||
let hi = if let Some(hi) = range.hi.minus_one() {
|
||||
hi
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
}
|
||||
if could_be_path {
|
||||
let import_suggestions = self.lookup_import_candidates(
|
||||
Ident::with_dummy_span(name),
|
||||
name,
|
||||
Namespace::ValueNS,
|
||||
&parent_scope,
|
||||
&|res: Res| {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ pub(crate) struct NameAlreadyUsedInParameterList {
|
|||
pub(crate) span: Span,
|
||||
#[label(resolve_first_use_of_name)]
|
||||
pub(crate) first_use_span: Span,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -142,7 +142,7 @@ pub(crate) struct VariableBoundWithDifferentMode {
|
|||
pub(crate) span: Span,
|
||||
#[label(resolve_first_binding_span)]
|
||||
pub(crate) first_binding_span: Span,
|
||||
pub(crate) variable_name: Symbol,
|
||||
pub(crate) variable_name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -151,7 +151,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) identifier: Symbol,
|
||||
pub(crate) identifier: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -160,7 +160,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) identifier: Symbol,
|
||||
pub(crate) identifier: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -478,7 +478,7 @@ pub(crate) struct TraitImplDuplicate {
|
|||
pub(crate) old_span: Span,
|
||||
#[label(resolve_trait_item_span)]
|
||||
pub(crate) trait_item_span: Span,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
@ -976,7 +976,7 @@ pub(crate) struct AttemptToDefineBuiltinMacroTwice {
|
|||
pub(crate) struct VariableIsNotBoundInAllPatterns {
|
||||
#[primary_span]
|
||||
pub(crate) multispan: MultiSpan,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic, Debug, Clone)]
|
||||
|
|
@ -984,7 +984,7 @@ pub(crate) struct VariableIsNotBoundInAllPatterns {
|
|||
pub(crate) struct PatternDoesntBindName {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic, Debug, Clone)]
|
||||
|
|
@ -1260,7 +1260,7 @@ pub(crate) struct TraitImplMismatch {
|
|||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) name: Ident,
|
||||
pub(crate) kind: &'static str,
|
||||
pub(crate) trait_path: String,
|
||||
#[label(resolve_trait_impl_mismatch_label_item)]
|
||||
|
|
|
|||
|
|
@ -2835,7 +2835,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
match seen_bindings.entry(ident) {
|
||||
Entry::Occupied(entry) => {
|
||||
let span = *entry.get();
|
||||
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
|
||||
let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span);
|
||||
self.report_error(param.ident.span, err);
|
||||
let rib = match param.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
|
|
@ -3422,7 +3422,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
match seen_trait_items.entry(id_in_trait) {
|
||||
Entry::Occupied(entry) => {
|
||||
self.report_error(span, ResolutionError::TraitImplDuplicate {
|
||||
name: ident.name,
|
||||
name: ident,
|
||||
old_span: *entry.get(),
|
||||
trait_item_span: binding.span,
|
||||
});
|
||||
|
|
@ -3457,7 +3457,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
};
|
||||
let trait_path = path_names_to_string(path);
|
||||
self.report_error(span, ResolutionError::TraitImplMismatch {
|
||||
name: ident.name,
|
||||
name: ident,
|
||||
kind,
|
||||
code,
|
||||
trait_path,
|
||||
|
|
@ -3640,9 +3640,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
.filter(|(_, pat)| pat.id != pat_outer.id)
|
||||
.flat_map(|(map, _)| map);
|
||||
|
||||
for (key, binding_inner) in inners {
|
||||
let name = key.name;
|
||||
match map_outer.get(key) {
|
||||
for (&name, binding_inner) in inners {
|
||||
match map_outer.get(&name) {
|
||||
None => {
|
||||
// The inner binding is missing in the outer.
|
||||
let binding_error =
|
||||
|
|
@ -3880,7 +3879,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
// `Variant(a, a)`:
|
||||
_ => IdentifierBoundMoreThanOnceInSamePattern,
|
||||
};
|
||||
self.report_error(ident.span, error(ident.name));
|
||||
self.report_error(ident.span, error(ident));
|
||||
}
|
||||
|
||||
// Record as bound if it's valid:
|
||||
|
|
|
|||
|
|
@ -1636,13 +1636,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
.enumerate()
|
||||
.map(|(idx, new)| (new, old_fields.get(idx)))
|
||||
.map(|(new, old)| {
|
||||
let new = new.name.to_ident_string();
|
||||
if let Some(Some(old)) = old
|
||||
&& new != *old
|
||||
&& new.as_str() != old
|
||||
{
|
||||
format!("{new}: {old}")
|
||||
} else {
|
||||
new
|
||||
new.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ enum Used {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct BindingError {
|
||||
name: Symbol,
|
||||
name: Ident,
|
||||
origin: BTreeSet<Span>,
|
||||
target: BTreeSet<Span>,
|
||||
could_be_path: bool,
|
||||
|
|
@ -226,7 +226,7 @@ enum ResolutionError<'ra> {
|
|||
GenericParamsFromOuterItem(Res, HasGenericParams, DefKind),
|
||||
/// Error E0403: the name is already used for a type or const parameter in this generic
|
||||
/// parameter list.
|
||||
NameAlreadyUsedInParameterList(Symbol, Span),
|
||||
NameAlreadyUsedInParameterList(Ident, Span),
|
||||
/// Error E0407: method is not a member of trait.
|
||||
MethodNotMemberOfTrait(Ident, String, Option<Symbol>),
|
||||
/// Error E0437: type is not a member of trait.
|
||||
|
|
@ -236,11 +236,11 @@ enum ResolutionError<'ra> {
|
|||
/// Error E0408: variable `{}` is not bound in all patterns.
|
||||
VariableNotBoundInPattern(BindingError, ParentScope<'ra>),
|
||||
/// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm.
|
||||
VariableBoundWithDifferentMode(Symbol, Span),
|
||||
VariableBoundWithDifferentMode(Ident, Span),
|
||||
/// Error E0415: identifier is bound more than once in this parameter list.
|
||||
IdentifierBoundMoreThanOnceInParameterList(Symbol),
|
||||
IdentifierBoundMoreThanOnceInParameterList(Ident),
|
||||
/// Error E0416: identifier is bound more than once in the same pattern.
|
||||
IdentifierBoundMoreThanOnceInSamePattern(Symbol),
|
||||
IdentifierBoundMoreThanOnceInSamePattern(Ident),
|
||||
/// Error E0426: use of undeclared label.
|
||||
UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
|
||||
/// Error E0429: `self` imports are only allowed within a `{ }` list.
|
||||
|
|
@ -292,14 +292,14 @@ enum ResolutionError<'ra> {
|
|||
UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
|
||||
/// Error E0323, E0324, E0325: mismatch between trait item and impl item.
|
||||
TraitImplMismatch {
|
||||
name: Symbol,
|
||||
name: Ident,
|
||||
kind: &'static str,
|
||||
trait_path: String,
|
||||
trait_item_span: Span,
|
||||
code: ErrCode,
|
||||
},
|
||||
/// Error E0201: multiple impl items for the same trait item.
|
||||
TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
|
||||
TraitImplDuplicate { name: Ident, trait_item_span: Span, old_span: Span },
|
||||
/// Inline asm `sym` operand must refer to a `fn` or `static`.
|
||||
InvalidAsmSym,
|
||||
/// `self` used instead of `Self` in a generic parameter
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue