Auto merge of #139912 - matthiaskrgr:rollup-va0rqvk, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #139647 (Add unstable parsing of `--extern foo::bar=libbar.rlib` command line options)
 - #139823 (Fix some bootstrap papercuts)
 - #139867 (Fix some tidy paper cuts)
 - #139871 (Fix wrong "move keyword" suggestion for async gen block)
 - #139876 (Make CodeStats' type_sizes public)
 - #139880 (Don't compute name of associated item if it's an RPITIT)
 - #139884 (Update books)
 - #139886 (`borrowck_graphviz_*` attribute tweaks)
 - #139893 (Add test for issue 125668)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-16 18:58:17 +00:00
commit 78f2104e33
27 changed files with 395 additions and 74 deletions

View file

@ -3376,10 +3376,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
Ok(string) => {
let coro_prefix = if string.starts_with("async") {
// `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize`
// to `u32`.
Some(5)
let coro_prefix = if let Some(sub) = string.strip_prefix("async") {
let trimmed_sub = sub.trim_end();
if trimmed_sub.ends_with("gen") {
// `async` is 5 chars long.
Some((trimmed_sub.len() + 5) as _)
} else {
// `async` is 5 chars long.
Some(5)
}
} else if string.starts_with("gen") {
// `gen` is 3 chars long
Some(3)

View file

@ -204,8 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.iter()
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
.filter_map(|item| {
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag)
.then_some(item.name())
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
})
.collect();

View file

@ -122,7 +122,7 @@ impl RustcMirAttrs {
})
} else if attr.has_name(sym::borrowck_graphviz_format) {
Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
sym::gen_kill | sym::two_phase => Ok(s),
sym::two_phase => Ok(s),
_ => {
tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
Err(())

View file

@ -72,7 +72,7 @@ pub struct TypeSizeInfo {
#[derive(Default)]
pub struct CodeStats {
type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
pub type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
}
impl CodeStats {

View file

@ -14,6 +14,7 @@ use std::str::{self, FromStr};
use std::sync::LazyLock;
use std::{cmp, fmt, fs, iter};
use externs::{ExternOpt, split_extern_opt};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
use rustc_errors::emitter::HumanReadableErrorType;
@ -39,6 +40,7 @@ use crate::utils::CanonicalizedPath;
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
mod cfg;
mod externs;
mod native_libs;
pub mod sigpipe;
@ -2205,44 +2207,13 @@ pub fn parse_externs(
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Externs {
fn is_ascii_ident(string: &str) -> bool {
let mut chars = string.chars();
if let Some(start) = chars.next()
&& (start.is_ascii_alphabetic() || start == '_')
{
chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
} else {
false
}
}
let is_unstable_enabled = unstable_opts.unstable_options;
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
for arg in matches.opt_strs("extern") {
let (name, path) = match arg.split_once('=') {
None => (arg, None),
Some((name, path)) => (name.to_string(), Some(Path::new(path))),
};
let (options, name) = match name.split_once(':') {
None => (None, name),
Some((opts, name)) => (Some(opts), name.to_string()),
};
let ExternOpt { crate_name: name, path, options } =
split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit());
if !is_ascii_ident(&name) {
let mut error = early_dcx.early_struct_fatal(format!(
"crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
));
let adjusted_name = name.replace('-', "_");
if is_ascii_ident(&adjusted_name) {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
error.help(format!(
"consider replacing the dashes with underscores: `{adjusted_name}`"
));
}
error.emit();
}
let path = path.map(|p| CanonicalizedPath::new(p));
let path = path.map(|p| CanonicalizedPath::new(p.as_path()));
let entry = externs.entry(name.to_owned());

View file

@ -0,0 +1,79 @@
//! This module contains code to help parse and manipulate `--extern` arguments.
use std::path::PathBuf;
use rustc_errors::{Diag, FatalAbort};
use super::UnstableOptions;
use crate::EarlyDiagCtxt;
#[cfg(test)]
mod tests;
/// Represents the pieces of an `--extern` argument.
pub(crate) struct ExternOpt {
pub(crate) crate_name: String,
pub(crate) path: Option<PathBuf>,
pub(crate) options: Option<String>,
}
/// Breaks out the major components of an `--extern` argument.
///
/// The options field will be a string containing comma-separated options that will need further
/// parsing and processing.
pub(crate) fn split_extern_opt<'a>(
early_dcx: &'a EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
extern_opt: &str,
) -> Result<ExternOpt, Diag<'a, FatalAbort>> {
let (name, path) = match extern_opt.split_once('=') {
None => (extern_opt.to_string(), None),
Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))),
};
let (options, crate_name) = match name.split_once(':') {
None => (None, name),
Some((opts, crate_name)) => {
if unstable_opts.namespaced_crates && crate_name.starts_with(':') {
// If the name starts with `:`, we know this was actually something like `foo::bar` and
// not a set of options. We can just use the original name as the crate name.
(None, name)
} else {
(Some(opts.to_string()), crate_name.to_string())
}
}
};
if !valid_crate_name(&crate_name, unstable_opts) {
let mut error = early_dcx.early_struct_fatal(format!(
"crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier"
));
let adjusted_name = crate_name.replace('-', "_");
if is_ascii_ident(&adjusted_name) {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
error
.help(format!("consider replacing the dashes with underscores: `{adjusted_name}`"));
}
return Err(error);
}
Ok(ExternOpt { crate_name, path, options })
}
fn valid_crate_name(name: &str, unstable_opts: &UnstableOptions) -> bool {
match name.split_once("::") {
Some((a, b)) if unstable_opts.namespaced_crates => is_ascii_ident(a) && is_ascii_ident(b),
Some(_) => false,
None => is_ascii_ident(name),
}
}
fn is_ascii_ident(string: &str) -> bool {
let mut chars = string.chars();
if let Some(start) = chars.next()
&& (start.is_ascii_alphabetic() || start == '_')
{
chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
} else {
false
}
}

View file

@ -0,0 +1,92 @@
use std::path::PathBuf;
use super::split_extern_opt;
use crate::EarlyDiagCtxt;
use crate::config::UnstableOptions;
/// Verifies split_extern_opt handles the supported cases.
#[test]
fn test_split_extern_opt() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions::default();
let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, None);
let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, None);
}
/// Tests some invalid cases for split_extern_opt.
#[test]
fn test_split_extern_opt_invalid() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions::default();
// too many `:`s
let result = split_extern_opt(&early_dcx, unstable_opts, "priv:noprelude:foo=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());
// can't nest externs without the unstable flag
let result = split_extern_opt(&early_dcx, unstable_opts, "noprelude:foo::bar=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());
}
/// Tests some cases for split_extern_opt with nested crates like `foo::bar`.
#[test]
fn test_split_extern_opt_nested() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };
let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));
let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, None);
let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, None);
}
/// Tests some invalid cases for split_extern_opt with nested crates like `foo::bar`.
#[test]
fn test_split_extern_opt_nested_invalid() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };
// crates can only be nested one deep.
let result =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar::baz=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());
}

View file

@ -2334,6 +2334,8 @@ options! {
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: bool = (true, parse_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes)"),
namespaced_crates: bool = (false, parse_bool, [TRACKED],
"allow crates to be namespaced by other crates (default: no)"),
next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
"enable and configure the next generation trait solver used by rustc"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],

View file

@ -1068,7 +1068,6 @@ symbols! {
ge,
gen_blocks,
gen_future,
gen_kill,
generator_clone,
generators,
generic_arg_infer,

View file

@ -81,14 +81,19 @@ fn update_rustfmt_version(build: &Builder<'_>) {
let Some((version, stamp_file)) = get_rustfmt_version(build) else {
return;
};
t!(std::fs::write(stamp_file.path(), version))
t!(stamp_file.add_stamp(version).write());
}
/// Returns the Rust files modified between the `merge-base` of HEAD and
/// rust-lang/master and what is now on the disk. Does not include removed files.
/// Returns the Rust files modified between the last merge commit and what is now on the disk.
/// Does not include removed files.
///
/// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
// In CI `get_git_modified_files` returns something different to normal environment.
// This shouldn't be called in CI anyway.
assert!(!build.config.is_running_on_ci);
if !verify_rustfmt_version(build) {
return Ok(None);
}
@ -103,7 +108,7 @@ struct RustfmtConfig {
// Prints output describing a collection of paths, with lines such as "formatted modified file
// foo/bar/baz" or "skipped 20 untracked files".
fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: &[String]) {
fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
let len = paths.len();
let adjective =
if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
@ -114,9 +119,6 @@ fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths:
} else {
println!("fmt: {verb} {len} {adjective}files");
}
if len > 1000 && !build.config.is_running_on_ci {
println!("hint: if this number seems too high, try running `git fetch origin master`");
}
}
pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
@ -189,7 +191,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
)
.map(|x| x.to_string())
.collect();
print_paths(build, "skipped", Some("untracked"), &untracked_paths);
print_paths("skipped", Some("untracked"), &untracked_paths);
for untracked_path in untracked_paths {
// The leading `/` makes it an exact match against the
@ -212,7 +214,13 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
override_builder.add(&format!("/{file}")).expect(&file);
}
}
Ok(None) => {}
Ok(None) => {
// NOTE: `Ok(None)` signifies that we need to format all files.
// The tricky part here is that if `override_builder` isn't given any white
// list files (i.e. files to be formatted, added without leading `!`), it
// will instead look for *all* files. So, by doing nothing here, we are
// actually making it so we format all files.
}
Err(err) => {
eprintln!("fmt warning: Something went wrong running git commands:");
eprintln!("fmt warning: {err}");
@ -318,7 +326,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
});
let mut paths = formatted_paths.into_inner().unwrap();
paths.sort();
print_paths(build, if check { "checked" } else { "formatted" }, adjective, &paths);
print_paths(if check { "checked" } else { "formatted" }, adjective, &paths);
drop(tx);
@ -328,7 +336,10 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
crate::exit!(1);
}
if !check {
update_rustfmt_version(build);
}
// Update `build/.rustfmt-stamp`, allowing this code to ignore files which have not been changed
// since last merge.
//
// NOTE: Because of the exit above, this is only reachable if formatting / format checking
// succeeded. So we are not commiting the version if formatting was not good.
update_rustfmt_version(build);
}

View file

@ -2888,6 +2888,13 @@ impl Config {
let absolute_path = self.src.join(relative_path);
// NOTE: This check is required because `jj git clone` doesn't create directories for
// submodules, they are completely ignored. The code below assumes this directory exists,
// so create it here.
if !absolute_path.exists() {
t!(fs::create_dir_all(&absolute_path));
}
// NOTE: The check for the empty directory is here because when running x.py the first time,
// the submodule won't be checked out. Check it out now so we can build it.
if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository()

View file

@ -114,7 +114,9 @@ fn git_upstream_merge_base(
Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned())
}
/// Searches for the nearest merge commit in the repository that also exists upstream.
/// Searches for the nearest merge commit in the repository.
///
/// **In CI** finds the nearest merge commit that *also exists upstream*.
///
/// It looks for the most recent commit made by the merge bot by matching the author's email
/// address with the merge bot's email.
@ -165,7 +167,7 @@ pub fn get_closest_merge_commit(
Ok(output_result(&mut git)?.trim().to_owned())
}
/// Returns the files that have been modified in the current branch compared to the master branch.
/// Returns the files that have been modified in the current branch compared to the last merge.
/// The `extensions` parameter can be used to filter the files by their extension.
/// Does not include removed files.
/// If `extensions` is empty, all files will be returned.

@ -1 +1 @@
Subproject commit 45f05367360f033f89235eacbbb54e8d73ce6b70
Subproject commit d33916341d480caede1d0ae57cbeae23aab23e88

@ -1 +1 @@
Subproject commit 1e27e5e6d5133ae4612f5cc195c15fc8d51b1c9c
Subproject commit 467f45637b73ec6aa70fb36bc3054bb50b8967ea

@ -1 +1 @@
Subproject commit b4448fa406a6dccde62d1e2f34f70fc51814cdcc
Subproject commit 0c10c30cc54736c5c194ce98c50e2de84eeb6e79

@ -1 +1 @@
Subproject commit 46435cd4eba11b66acaa42c01da5c80ad88aee4b
Subproject commit 3340922df189bddcbaad17dc3927d51a76bcd5ed

View file

@ -301,7 +301,8 @@ Right below you can find elaborate explainers on a selected few.
Some compiler options for debugging specific features yield graphviz graphs -
e.g. the `#[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute
dumps various borrow-checker dataflow graphs.
on a function dumps various borrow-checker dataflow graphs in conjunction with
`-Zdump-mir-dataflow`.
These all produce `.dot` files. To view these files, install graphviz (e.g.
`apt-get install graphviz`) and then run the following commands:

View file

@ -2378,12 +2378,19 @@ impl<'test> TestCx<'test> {
// eg.
// /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui/<test_dir>/$name.$revision.$mode/
normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR");
// Same as above, but with a canonicalized path.
// This is required because some tests print canonical paths inside test build directory,
// so if the build directory is a symlink, normalization doesn't help.
//
// NOTE: There are also tests which print the non-canonical name, so we need both this and
// the above normalizations.
normalize_path(&self.output_base_dir().canonicalize_utf8().unwrap(), "$TEST_BUILD_DIR");
// eg. /home/user/rust/build
normalize_path(&self.config.build_root, "$BUILD_DIR");
if json {
// escaped newlines in json strings should be readable
// in the stderr files. There's no point int being correct,
// in the stderr files. There's no point in being correct,
// since only humans process the stderr files.
// Thus we just turn escaped newlines back into newlines.
normalized = normalized.replace("\\n", "\n");

View file

@ -951,6 +951,7 @@ dependencies = [
"once_cell",
"pathdiff",
"pulldown-cmark 0.10.3",
"railroad",
"regex",
"semver",
"serde_json",
@ -1300,6 +1301,15 @@ version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "railroad"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ecedffc46c1b2cb04f4b80e094eae6b3f3f470a9635f1f396dd5206428f6b58"
dependencies = [
"unicode-width",
]
[[package]]
name = "rand"
version = "0.8.5"

View file

@ -682,8 +682,10 @@ pub static CRATES: &[&str] = &[
pub fn has_missing_submodule(root: &Path, submodules: &[&str]) -> bool {
!CiEnv::is_ci()
&& submodules.iter().any(|submodule| {
let path = root.join(submodule);
!path.exists()
// If the directory is empty, we can consider it as an uninitialized submodule.
read_dir(root.join(submodule)).unwrap().next().is_none()
|| read_dir(path).unwrap().next().is_none()
})
}

View file

@ -0,0 +1,35 @@
// This is a regression test for <https://github.com/rust-lang/rust/issues/139839>.
// It ensures that the "add `move` keyword" suggestion is valid.
//@ run-rustfix
//@ edition:2024
#![feature(coroutines)]
#![feature(gen_blocks)]
#![feature(async_iterator)]
use std::async_iter::AsyncIterator;
#[allow(dead_code)]
fn moved() -> impl AsyncIterator<Item = u32> {
let mut x = "foo".to_string();
async gen move { //~ ERROR
x.clear();
for x in 3..6 { yield x }
}
}
#[allow(dead_code)]
fn check_with_whitespace_chars() -> impl AsyncIterator<Item = u32> {
let mut x = "foo".to_string();
async // Just to check that whitespace characters are correctly handled
gen move { //~^ ERROR
x.clear();
for x in 3..6 { yield x }
}
}
fn main() {
}

View file

@ -0,0 +1,35 @@
// This is a regression test for <https://github.com/rust-lang/rust/issues/139839>.
// It ensures that the "add `move` keyword" suggestion is valid.
//@ run-rustfix
//@ edition:2024
#![feature(coroutines)]
#![feature(gen_blocks)]
#![feature(async_iterator)]
use std::async_iter::AsyncIterator;
#[allow(dead_code)]
fn moved() -> impl AsyncIterator<Item = u32> {
let mut x = "foo".to_string();
async gen { //~ ERROR
x.clear();
for x in 3..6 { yield x }
}
}
#[allow(dead_code)]
fn check_with_whitespace_chars() -> impl AsyncIterator<Item = u32> {
let mut x = "foo".to_string();
async // Just to check that whitespace characters are correctly handled
gen { //~^ ERROR
x.clear();
for x in 3..6 { yield x }
}
}
fn main() {
}

View file

@ -0,0 +1,47 @@
error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function
--> $DIR/async-gen-move-suggestion.rs:17:5
|
LL | async gen {
| ^^^^^^^^^ may outlive borrowed value `x`
LL | x.clear();
| - `x` is borrowed here
|
note: async gen block is returned here
--> $DIR/async-gen-move-suggestion.rs:17:5
|
LL | / async gen {
LL | | x.clear();
LL | | for x in 3..6 { yield x }
LL | | }
| |_____^
help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
LL | async gen move {
| ++++
error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function
--> $DIR/async-gen-move-suggestion.rs:27:5
|
LL | / async // Just to check that whitespace characters are correctly handled
LL | | gen {
| |_______^ may outlive borrowed value `x`
LL | x.clear();
| - `x` is borrowed here
|
note: async gen block is returned here
--> $DIR/async-gen-move-suggestion.rs:27:5
|
LL | / async // Just to check that whitespace characters are correctly handled
LL | | gen {
LL | | x.clear();
LL | | for x in 3..6 { yield x }
LL | | }
| |_____^
help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
LL | gen move {
| ++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0373`.

View file

@ -0,0 +1,5 @@
//@ check-pass
type A = [u32; const { 2 }];
fn main() {}

View file

@ -0,0 +1,12 @@
// Regression test for <https://github.com/rust-lang/rust/issues/139873>.
// Test that we don't try to get the (nonexistent) name of the RPITIT in `Trait::foo`
// when emitting an error for a missing associated item `Trait::Output`.
trait Trait {
fn foo() -> impl Sized;
fn bar() -> Self::Output;
//~^ ERROR associated type `Output` not found for `Self`
}
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0220]: associated type `Output` not found for `Self`
--> $DIR/dont-probe-missing-item-name.rs:8:23
|
LL | fn bar() -> Self::Output;
| ^^^^^^ associated type `Output` not found
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0220`.

View file

@ -42,12 +42,3 @@ each generated output path.
on *entry* to each block, as well as the gen- and kill-sets that
were so-called "transfer functions" summarizing the effect of each
basic block.
* (In addition to the `borrowck_graphviz_postflow` attribute-key
noted above, there is also `borrowck_graphviz_preflow`; it has the
same interface and generates the same set of files, but it renders
the dataflow state after building the gen- and kill-sets but
*before* running the dataflow analysis itself, so each entry-set is
just the initial default state for that dataflow analysis. This is
less useful for understanding the error message output in these
tests.)