Merge pull request #4157 from RalfJung/rustup

Rustup
This commit is contained in:
Ralf Jung 2025-01-28 03:03:29 +00:00 committed by GitHub
commit 6963ecd371
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
519 changed files with 3396 additions and 5419 deletions

View file

@ -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, .. }])
}
}

View file

@ -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 {

View file

@ -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"
),

View file

@ -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();

View file

@ -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 {
'>' => "&gt;",
'<' => "&lt;",
'&' => "&amp;",
'\'' => "&#39;",
'"' => "&quot;",
_ => {
// 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(())
}

View file

@ -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,
}

View file

@ -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),
);

View file

@ -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)

View file

@ -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")]

View file

@ -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() {
}
}

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -17,7 +17,7 @@ env:
jobs:
build:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false

View file

@ -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

View file

@ -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

View file

@ -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());

View file

@ -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

View file

@ -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(())
}

View file

@ -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.

View file

@ -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)?;

View file

@ -1 +1 @@
45648c2edd4ecd862d9f08196d3d6c6ccba79f07
e607be166673a8de9fc07f6f02c60426e556c5f2

View file

@ -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}

View file

@ -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 {

View file

@ -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(_) => {

View file

@ -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,

View file

@ -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)]

View file

@ -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);

View file

@ -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))) => {

View file

@ -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 {

View file

@ -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, .. } => {

View file

@ -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;

View file

@ -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)]

View file

@ -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),
}));
}

View file

@ -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) => {

View file

@ -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,
}));

View file

@ -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(

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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",

View file

@ -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,

View file

@ -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()

View file

@ -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
}
}

View file

@ -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,

View file

@ -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)]

View file

@ -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(

View file

@ -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();

View file

@ -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 {

View file

@ -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);

View file

@ -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(".")
})

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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(),

View file

@ -181,6 +181,7 @@ early_lint_methods!(
UnusedDocComment: UnusedDocComment,
Expr2024: Expr2024,
Precedence: Precedence,
DoubleNegations: DoubleNegations,
]
]
);

View file

@ -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 {

View file

@ -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()
}

View file

@ -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,

View file

@ -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)));
}

View file

@ -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

View file

@ -795,7 +795,6 @@ pub enum BuiltinLintDiag {
extern_crate: Symbol,
local_crate: Symbol,
},
WasmCAbi,
IllFormedAttributeInput {
suggestions: Vec<String>,
},

View file

@ -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"`

View file

@ -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 });
}
}

View file

@ -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,
}

View file

@ -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}'

View file

@ -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> },

View file

@ -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)]

View file

@ -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 {

View file

@ -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

View file

@ -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 {

View file

@ -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()
}

View file

@ -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 {

View file

@ -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,

View file

@ -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" }
}

View file

@ -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(())
})
}
}

View file

@ -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),
}
}

View file

@ -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))

View file

@ -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

View file

@ -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>,

View file

@ -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),
},
)
}

View file

@ -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;

View file

@ -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.

View file

@ -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 {}

View file

@ -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)]

View file

@ -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)]

View file

@ -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(", "),

View file

@ -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`.

View file

@ -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)));
}

View file

@ -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:?}"))
};

View file

@ -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)]

View file

@ -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);
};

View file

@ -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) {

View file

@ -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 = "*")]

View file

@ -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,

View file

@ -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

View file

@ -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| {

View file

@ -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)]

View file

@ -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:

View file

@ -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>>()

View file

@ -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