Auto merge of #142979 - matthiaskrgr:rollup-szqah4e, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#142645 (Also emit suggestions for usages in the `non_upper_case_globals` lint)
 - rust-lang/rust#142657 (mbe: Clean up code with non-optional `NonterminalKind`)
 - rust-lang/rust#142799 (rustc_session: Add a structure for keeping both explicit and default sysroots)
 - rust-lang/rust#142805 (Emit a single error when importing a path with `_`)
 - rust-lang/rust#142882 (Lazy init diagnostics-only local_names in borrowck)
 - rust-lang/rust#142883 (Add impl_trait_in_bindings tests from rust-lang/rust#61773)
 - rust-lang/rust#142943 (Don't include current rustc version string in feature removed help)
 - rust-lang/rust#142965 ([RTE-497] Ignore `c-link-to-rust-va-list-fn` test on SGX platform)
 - rust-lang/rust#142972 (Add a missing mailmap entry)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-06-24 21:58:31 +00:00
commit 3de5b08ef6
80 changed files with 880 additions and 405 deletions

View file

@ -162,8 +162,10 @@ David Carlier <devnexen@gmail.com>
David Klein <david.klein@baesystemsdetica.com>
David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
David Ross <daboross@daboross.net>
David Wood <david@davidtw.co> <david.wood@huawei.com>
David Wood <david@davidtw.co> <Q0KPU0H1YOEPHRY1R2SN5B5RL@david.davidtw.co>
David Wood <david@davidtw.co> <agile.lion3441@fuligin.ink>
David Wood <david@davidtw.co> <david.wood2@arm.com>
David Wood <david@davidtw.co> <david.wood@huawei.com>
Deadbeef <ent3rm4n@gmail.com>
Deadbeef <ent3rm4n@gmail.com> <fee1-dead-beef@protonmail.com>
dependabot[bot] <dependabot[bot]@users.noreply.github.com> <27856297+dependabot-preview[bot]@users.noreply.github.com>

View file

@ -3655,7 +3655,6 @@ dependencies = [
"rustc_macros",
"rustc_serialize",
"rustc_span",
"smallvec",
"tracing",
"unic-langid",
]
@ -4446,7 +4445,6 @@ dependencies = [
"rustc_serialize",
"rustc_span",
"rustc_target",
"smallvec",
"termize",
"tracing",
"windows",

View file

@ -1085,6 +1085,7 @@ pub enum NtExprKind {
Expr2021 { inferred: bool },
}
/// A macro nonterminal, known in documentation as a fragment specifier.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
pub enum NonterminalKind {
Item,

View file

@ -71,7 +71,6 @@ impl<'tcx> BorrowExplanation<'tcx> {
) {
let tcx = cx.infcx.tcx;
let body = cx.body;
let local_names = &cx.local_names;
if let Some(span) = borrow_span {
let def_id = body.source.def_id();
@ -220,7 +219,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
_ => ("destructor", format!("type `{}`", local_decl.ty)),
};
match local_names[dropped_local] {
match cx.local_name(dropped_local) {
Some(local_name) if !local_decl.from_compiler_desugaring() => {
let message = format!(
"{borrow_desc}borrow might be used here, when `{local_name}` is dropped \
@ -670,10 +669,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
Some(Cause::DropVar(local, location)) => {
let mut should_note_order = false;
if self.local_names[local].is_some()
if self.local_name(local).is_some()
&& let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
&& let Some(borrowed_local) = place.as_local()
&& self.local_names[borrowed_local].is_some()
&& self.local_name(borrowed_local).is_some()
&& local != borrowed_local
{
should_note_order = true;
@ -748,7 +747,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
Operand::Copy(place) | Operand::Move(place) => {
if let Some(l) = place.as_local() {
let local_decl = &self.body.local_decls[l];
if self.local_names[l].is_none() {
if self.local_name(l).is_none() {
local_decl.source_info.span
} else {
span
@ -793,7 +792,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
Operand::Copy(place) | Operand::Move(place) => {
if let Some(l) = place.as_local() {
let local_decl = &self.body.local_decls[l];
if self.local_names[l].is_none() {
if self.local_name(l).is_none() {
local_decl.source_info.span
} else {
span

View file

@ -7,17 +7,17 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::{self as hir, CoroutineKind, LangItem};
use rustc_index::IndexSlice;
use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin};
use rustc_infer::traits::SelectionError;
use rustc_middle::bug;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
LocalKind, Location, Operand, Place, PlaceRef, PlaceTy, ProjectionElem, Rvalue, Statement,
StatementKind, Terminator, TerminatorKind, find_self_call,
StatementKind, Terminator, TerminatorKind, VarDebugInfoContents, find_self_call,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveOutIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Spanned;
@ -190,6 +190,36 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) -> Option<&(PlaceRef<'tcx>, Diag<'infcx>)> {
self.diags_buffer.buffered_move_errors.get(move_out_indices)
}
/// Uses `body.var_debug_info` to find the symbol
fn local_name(&self, index: Local) -> Option<Symbol> {
*self.local_names().get(index)?
}
fn local_names(&self) -> &IndexSlice<Local, Option<Symbol>> {
self.local_names.get_or_init(|| {
let mut local_names = IndexVec::from_elem(None, &self.body.local_decls);
for var_debug_info in &self.body.var_debug_info {
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
if let Some(local) = place.as_local() {
if let Some(prev_name) = local_names[local]
&& var_debug_info.name != prev_name
{
span_bug!(
var_debug_info.source_info.span,
"local {:?} has many names (`{}` vs `{}`)",
local,
prev_name,
var_debug_info.name
);
}
local_names[local] = Some(var_debug_info.name);
}
}
}
local_names
})
}
}
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
@ -430,7 +460,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// a name, or its name was generated by the compiler, then `Err` is returned
fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> {
let decl = &self.body.local_decls[local];
match self.local_names[local] {
match self.local_name(local) {
Some(name) if !decl.from_compiler_desugaring() => {
buf.push_str(name.as_str());
Ok(())
@ -1500,4 +1530,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
}
/// Skip over locals that begin with an underscore or have no name
pub(crate) fn local_excluded_from_unused_mut_lint(&self, index: Local) -> bool {
self.local_name(index).is_none_or(|name| name.as_str().starts_with('_'))
}
}

View file

@ -465,11 +465,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if let PlaceRef { local, projection: [] } = deref_base {
let decl = &self.body.local_decls[local];
let local_name = self.local_name(local).map(|sym| format!("`{sym}`"));
if decl.is_ref_for_guard() {
return self
.cannot_move_out_of(
span,
&format!("`{}` in pattern guard", self.local_names[local].unwrap()),
&format!(
"{} in pattern guard",
local_name.as_deref().unwrap_or("the place")
),
)
.with_note(
"variables bound in patterns cannot be moved from \
@ -825,7 +829,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
if binds_to.len() == 1 {
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
let place_desc = self.local_name(*local).map(|sym| format!("`{sym}`"));
if let Some(expr) = self.find_expr(binding_span) {
self.suggest_cloning(err, bind_to.ty, expr, None);
@ -834,7 +838,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: bind_to.ty,
place: place_desc,
place: place_desc.as_deref().unwrap_or("the place"),
span: binding_span,
});
}

View file

@ -60,7 +60,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if access_place.as_local().is_some() {
reason = ", as it is not declared as mutable".to_string();
} else {
let name = self.local_names[local].expect("immutable unnamed local");
let name = self.local_name(local).expect("immutable unnamed local");
reason = format!(", as `{name}` is not declared as mutable");
}
}
@ -285,7 +285,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.body
.local_decls
.get(local)
.is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) =>
.is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_name(local))) =>
{
let decl = &self.body.local_decls[local];
err.span_label(span, format!("cannot {act}"));
@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let (pointer_sigil, pointer_desc) =
if local_decl.ty.is_ref() { ("&", "reference") } else { ("*const", "pointer") };
match self.local_names[local] {
match self.local_name(local) {
Some(name) if !local_decl.from_compiler_desugaring() => {
err.span_label(
span,

View file

@ -664,14 +664,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
self.infcx.tcx,
self.body,
&self.local_names,
&self.local_names(),
&self.upvars,
errci.fr,
);
let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
self.infcx.tcx,
self.body,
&self.local_names,
&self.local_names(),
&self.upvars,
errci.outlived_fr,
);

View file

@ -399,7 +399,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
[implicit_inputs + argument_index];
let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
self.body,
&self.local_names,
self.local_names(),
argument_index,
);
@ -973,7 +973,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
{
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
self.body,
&self.local_names,
self.local_names(),
arg_index,
);
let region_name = self.synthesize_region_name();

View file

@ -16,7 +16,7 @@
// tidy-alphabetical-end
use std::borrow::Cow;
use std::cell::RefCell;
use std::cell::{OnceCell, RefCell};
use std::marker::PhantomData;
use std::ops::{ControlFlow, Deref};
@ -391,7 +391,7 @@ fn do_mir_borrowck<'tcx>(
used_mut_upvars: SmallVec::new(),
borrow_set: &borrow_set,
upvars: &[],
local_names: IndexVec::from_elem(None, &promoted_body.local_decls),
local_names: OnceCell::from(IndexVec::from_elem(None, &promoted_body.local_decls)),
region_names: RefCell::default(),
next_region_name: RefCell::new(1),
polonius_output: None,
@ -414,26 +414,6 @@ fn do_mir_borrowck<'tcx>(
promoted_mbcx.report_move_errors();
}
let mut local_names = IndexVec::from_elem(None, &body.local_decls);
for var_debug_info in &body.var_debug_info {
if let VarDebugInfoContents::Place(place) = var_debug_info.value {
if let Some(local) = place.as_local() {
if let Some(prev_name) = local_names[local]
&& var_debug_info.name != prev_name
{
span_bug!(
var_debug_info.source_info.span,
"local {:?} has many names (`{}` vs `{}`)",
local,
prev_name,
var_debug_info.name
);
}
local_names[local] = Some(var_debug_info.name);
}
}
}
let mut mbcx = MirBorrowckCtxt {
root_cx,
infcx: &infcx,
@ -450,7 +430,7 @@ fn do_mir_borrowck<'tcx>(
used_mut_upvars: SmallVec::new(),
borrow_set: &borrow_set,
upvars: tcx.closure_captures(def),
local_names,
local_names: OnceCell::new(),
region_names: RefCell::default(),
next_region_name: RefCell::new(1),
move_errors: Vec::new(),
@ -682,7 +662,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
upvars: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
/// Names of local (user) variables (extracted from `var_debug_info`).
local_names: IndexVec<Local, Option<Symbol>>,
local_names: OnceCell<IndexVec<Local, Option<Symbol>>>,
/// Record the region names generated for each region in the given
/// MIR def so that we can reuse them later in help/error messages.
@ -2610,7 +2590,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
};
// Skip over locals that begin with an underscore or have no name
if self.local_names[local].is_none_or(|name| name.as_str().starts_with('_')) {
if self.local_excluded_from_unused_mut_lint(local) {
continue;
}

View file

@ -865,7 +865,7 @@ fn link_natively(
command: cmd,
escaped_output,
verbose: sess.opts.verbose,
sysroot_dir: sess.sysroot.clone(),
sysroot_dir: sess.opts.sysroot.path().to_owned(),
};
sess.dcx().emit_err(err);
// If MSVC's `link.exe` was expected but the return code
@ -1249,10 +1249,10 @@ fn link_sanitizer_runtime(
if path.exists() {
sess.target_tlib_path.dir.clone()
} else {
let default_sysroot = filesearch::get_or_default_sysroot();
let default_tlib =
filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.tuple());
default_tlib
filesearch::make_target_lib_path(
&sess.opts.sysroot.default,
sess.opts.target_triple.tuple(),
)
}
}
@ -1758,7 +1758,7 @@ fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool {
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
let full_path = dir.join(&linker_with_extension);
// If linker comes from sysroot assume self-contained mode
if full_path.is_file() && !full_path.starts_with(&sess.sysroot) {
if full_path.is_file() && !full_path.starts_with(sess.opts.sysroot.path()) {
return false;
}
}

View file

@ -1070,7 +1070,7 @@ impl<'a> Linker for MsvcLinker<'a> {
self.link_arg("/PDBALTPATH:%_PDB%");
// This will cause the Microsoft linker to embed .natvis info into the PDB file
let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
let natvis_dir_path = self.sess.opts.sysroot.path().join("lib\\rustlib\\etc");
if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
for entry in natvis_dir {
match entry {

View file

@ -53,13 +53,13 @@ use rustc_metadata::locator;
use rustc_middle::ty::TyCtxt;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::config::{
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType,
CG_OPTIONS, CrateType, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, Sysroot,
UnstableOptions, Z_OPTIONS, nightly_options, parse_target_triple,
};
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
use rustc_session::output::{CRATE_TYPES, collect_crate_types, invalid_output_for_target};
use rustc_session::{EarlyDiagCtxt, Session, config, filesearch};
use rustc_session::{EarlyDiagCtxt, Session, config};
use rustc_span::FileName;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_target::json::ToJson;
@ -662,7 +662,7 @@ fn print_crate_info(
println_info!("{}", targets.join("\n"));
}
HostTuple => println_info!("{}", rustc_session::config::host_tuple()),
Sysroot => println_info!("{}", sess.sysroot.display()),
Sysroot => println_info!("{}", sess.opts.sysroot.path().display()),
TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()),
TargetSpecJson => {
println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
@ -1114,8 +1114,8 @@ fn get_backend_from_raw_matches(
let debug_flags = matches.opt_strs("Z");
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
let target = parse_target_triple(early_dcx, matches);
let sysroot = filesearch::materialize_sysroot(matches.opt_str("sysroot").map(PathBuf::from));
let target = config::build_target_config(early_dcx, &target, &sysroot);
let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
let target = config::build_target_config(early_dcx, &target, sysroot.path());
get_codegen_backend(early_dcx, &sysroot, backend_name, &target)
}

View file

@ -16,7 +16,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end

View file

@ -8,7 +8,7 @@
use std::borrow::Cow;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::sync::{Arc, LazyLock};
use std::{fmt, fs, io};
@ -21,7 +21,6 @@ use intl_memoizer::concurrent::IntlLangMemoizer;
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
use rustc_macros::{Decodable, Encodable};
use rustc_span::Span;
use smallvec::SmallVec;
use tracing::{instrument, trace};
pub use unic_langid::{LanguageIdentifier, langid};
@ -107,7 +106,7 @@ impl From<Vec<FluentError>> for TranslationBundleError {
/// (overriding any conflicting messages).
#[instrument(level = "trace")]
pub fn fluent_bundle(
sysroot_candidates: SmallVec<[PathBuf; 2]>,
sysroot_candidates: &[&Path],
requested_locale: Option<LanguageIdentifier>,
additional_ftl_path: Option<&Path>,
with_directionality_markers: bool,
@ -141,7 +140,8 @@ pub fn fluent_bundle(
// If the user requests the default locale then don't try to load anything.
if let Some(requested_locale) = requested_locale {
let mut found_resources = false;
for mut sysroot in sysroot_candidates {
for sysroot in sysroot_candidates {
let mut sysroot = sysroot.to_path_buf();
sysroot.push("share");
sysroot.push("locale");
sysroot.push(requested_locale.to_string());

View file

@ -62,7 +62,7 @@ expand_feature_not_allowed =
expand_feature_removed =
feature has been removed
.label = feature has been removed
.note = removed in {$removed_rustc_version} (you are using {$current_rustc_version}){$pull_note}
.note = removed in {$removed_rustc_version}{$pull_note}
.reason = {$reason}
expand_glob_delegation_outside_impls =

View file

@ -92,7 +92,6 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
span: mi.span(),
reason: f.reason.map(|reason| FeatureRemovedReason { reason }),
removed_rustc_version: f.feature.since,
current_rustc_version: sess.cfg_version,
pull_note,
});
continue;

View file

@ -162,7 +162,6 @@ pub(crate) struct FeatureRemoved<'a> {
#[subdiagnostic]
pub reason: Option<FeatureRemovedReason<'a>>,
pub removed_rustc_version: &'a str,
pub current_rustc_version: &'a str,
pub pull_note: String,
}
@ -444,7 +443,7 @@ pub(crate) struct InvalidFragmentSpecifier {
#[primary_span]
pub span: Span,
pub fragment: Ident,
pub help: String,
pub help: &'static str,
}
#[derive(Diagnostic)]

View file

@ -78,7 +78,13 @@ enum TokenTree {
/// only covers the ident, e.g. `var`.)
MetaVar(Span, Ident),
/// e.g., `$var:expr`. Only appears on the LHS.
MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),
MetaVarDecl {
span: Span,
/// Name to bind.
name: Ident,
/// The fragment specifier.
kind: NonterminalKind,
},
/// A meta-variable expression inside `${...}`.
MetaVarExpr(DelimSpan, MetaVarExpr),
}
@ -102,7 +108,7 @@ impl TokenTree {
match *self {
TokenTree::Token(Token { span, .. })
| TokenTree::MetaVar(span, _)
| TokenTree::MetaVarDecl(span, _, _) => span,
| TokenTree::MetaVarDecl { span, .. } => span,
TokenTree::Delimited(span, ..)
| TokenTree::MetaVarExpr(span, _)
| TokenTree::Sequence(span, _) => span.entire(),

View file

@ -24,6 +24,7 @@ pub(super) fn failed_to_match_macro(
arg: TokenStream,
lhses: &[Vec<MatcherLoc>],
) -> (Span, ErrorGuaranteed) {
debug!("failed to match macro");
// An error occurred, try the expansion again, tracking the expansion closely for better
// diagnostics.
let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);

View file

@ -117,7 +117,6 @@ use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw};
use smallvec::SmallVec;
use super::quoted::VALID_FRAGMENT_NAMES_MSG;
use crate::errors;
use crate::mbe::{KleeneToken, TokenTree};
@ -263,14 +262,7 @@ fn check_binders(
}
}
// Similarly, this can only happen when checking a toplevel macro.
TokenTree::MetaVarDecl(span, name, kind) => {
if kind.is_none() && node_id != DUMMY_NODE_ID {
psess.dcx().emit_err(errors::MissingFragmentSpecifier {
span,
add_span: span.shrink_to_hi(),
valid: VALID_FRAGMENT_NAMES_MSG,
});
}
TokenTree::MetaVarDecl { span, name, .. } => {
if !macros.is_empty() {
psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs");
}
@ -339,7 +331,7 @@ fn check_occurrences(
) {
match *rhs {
TokenTree::Token(..) => {}
TokenTree::MetaVarDecl(span, _name, _kind) => {
TokenTree::MetaVarDecl { span, .. } => {
psess.dcx().span_bug(span, "unexpected MetaVarDecl in rhs")
}
TokenTree::MetaVar(span, name) => {

View file

@ -122,7 +122,7 @@ pub(crate) enum MatcherLoc {
MetaVarDecl {
span: Span,
bind: Ident,
kind: Option<NonterminalKind>,
kind: NonterminalKind,
next_metavar: usize,
seq_depth: usize,
},
@ -151,12 +151,7 @@ impl Display for MatcherLoc {
write!(f, "{}", token_descr(token))
}
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
write!(f, "meta-variable `${bind}")?;
if let Some(kind) = kind {
write!(f, ":{kind}")?;
}
write!(f, "`")?;
Ok(())
write!(f, "meta-variable `${bind}:{kind}`")
}
MatcherLoc::Eof => f.write_str("end of macro"),
@ -220,7 +215,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
seq_depth,
};
}
&TokenTree::MetaVarDecl(span, bind, kind) => {
&TokenTree::MetaVarDecl { span, name: bind, kind } => {
locs.push(MatcherLoc::MetaVarDecl {
span,
bind,
@ -330,7 +325,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
matcher
.iter()
.map(|tt| match tt {
TokenTree::MetaVarDecl(..) => 1,
TokenTree::MetaVarDecl { .. } => 1,
TokenTree::Sequence(_, seq) => seq.num_captures,
TokenTree::Delimited(.., delim) => count_metavar_decls(&delim.tts),
TokenTree::Token(..) => 0,
@ -551,18 +546,12 @@ impl TtParser {
mp.idx = idx_first;
self.cur_mps.push(mp);
}
&MatcherLoc::MetaVarDecl { span, kind, .. } => {
&MatcherLoc::MetaVarDecl { kind, .. } => {
// Built-in nonterminals never start with these tokens, so we can eliminate
// them from consideration. We use the span of the metavariable declaration
// to determine any edition-specific matching behavior for non-terminals.
if let Some(kind) = kind {
if Parser::nonterminal_may_begin_with(kind, token) {
self.bb_mps.push(mp);
}
} else {
// E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used.
// Both this check and the one in `nameize` are necessary, surprisingly.
return Some(Error(span, "missing fragment specifier".to_string()));
if Parser::nonterminal_may_begin_with(kind, token) {
self.bb_mps.push(mp);
}
}
MatcherLoc::Eof => {
@ -666,11 +655,7 @@ impl TtParser {
let mut mp = self.bb_mps.pop().unwrap();
let loc = &matcher[mp.idx];
if let &MatcherLoc::MetaVarDecl {
span,
kind: Some(kind),
next_metavar,
seq_depth,
..
span, kind, next_metavar, seq_depth, ..
} = loc
{
// We use the span of the metavariable declaration to determine any
@ -715,7 +700,7 @@ impl TtParser {
.bb_mps
.iter()
.map(|mp| match &matcher[mp.idx] {
MatcherLoc::MetaVarDecl { bind, kind: Some(kind), .. } => {
MatcherLoc::MetaVarDecl { bind, kind, .. } => {
format!("{kind} ('{bind}')")
}
_ => unreachable!(),
@ -745,19 +730,13 @@ impl TtParser {
// `NamedParseResult`. Otherwise, it's an error.
let mut ret_val = FxHashMap::default();
for loc in matcher {
if let &MatcherLoc::MetaVarDecl { span, bind, kind, .. } = loc {
if kind.is_some() {
match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) {
Vacant(spot) => spot.insert(res.next().unwrap()),
Occupied(..) => {
return Error(span, format!("duplicated bind name: {bind}"));
}
};
} else {
// E.g. `$e` instead of `$e:expr`, reported as a hard error if actually used.
// Both this check and the one in `parse_tt_inner` are necessary, surprisingly.
return Error(span, "missing fragment specifier".to_string());
}
if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc {
match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) {
Vacant(spot) => spot.insert(res.next().unwrap()),
Occupied(..) => {
return Error(span, format!("duplicated bind name: {bind}"));
}
};
}
}
Success(ret_val)

View file

@ -392,7 +392,7 @@ pub fn compile_declarative_macro(
let lhs_nm = Ident::new(sym::lhs, span);
let rhs_nm = Ident::new(sym::rhs, span);
let tt_spec = Some(NonterminalKind::TT);
let tt_spec = NonterminalKind::TT;
let macro_rules = macro_def.macro_rules;
// Parse the macro_rules! invocation
@ -407,9 +407,9 @@ pub fn compile_declarative_macro(
DelimSpan::dummy(),
mbe::SequenceRepetition {
tts: vec![
mbe::TokenTree::MetaVarDecl(span, lhs_nm, tt_spec),
mbe::TokenTree::MetaVarDecl { span, name: lhs_nm, kind: tt_spec },
mbe::TokenTree::token(token::FatArrow, span),
mbe::TokenTree::MetaVarDecl(span, rhs_nm, tt_spec),
mbe::TokenTree::MetaVarDecl { span, name: rhs_nm, kind: tt_spec },
],
separator: Some(Token::new(
if macro_rules { token::Semi } else { token::Comma },
@ -448,6 +448,7 @@ pub fn compile_declarative_macro(
match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) {
Success(m) => m,
Failure(()) => {
debug!("failed to parse macro tt");
// The fast `NoopTracker` doesn't have any info on failure, so we need to retry it
// with another one that gives us the information we need.
// For this we need to reclone the macro body as the previous parser consumed it.
@ -616,7 +617,7 @@ fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
let mut iter = seq.tts.iter().peekable();
while let Some(tt) = iter.next() {
match tt {
mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)) => {}
mbe::TokenTree::MetaVarDecl { kind: NonterminalKind::Vis, .. } => {}
mbe::TokenTree::Token(t @ Token { kind: DocComment(..), .. }) => {
let mut now = t;
while let Some(&mbe::TokenTree::Token(
@ -651,7 +652,7 @@ fn check_redundant_vis_repetition(
) {
let is_zero_or_one: bool = seq.kleene.op == KleeneOp::ZeroOrOne;
let is_vis = seq.tts.first().map_or(false, |tt| {
matches!(tt, mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis)))
matches!(tt, mbe::TokenTree::MetaVarDecl { kind: NonterminalKind::Vis, .. })
});
if is_vis && is_zero_or_one {
@ -678,7 +679,7 @@ fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(),
match tt {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarDecl { .. }
| TokenTree::MetaVarExpr(..) => (),
TokenTree::Delimited(.., del) => check_lhs_no_empty_seq(sess, &del.tts)?,
TokenTree::Sequence(span, seq) => {
@ -777,7 +778,7 @@ impl<'tt> FirstSets<'tt> {
match tt {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarDecl { .. }
| TokenTree::MetaVarExpr(..) => {
first.replace_with(TtHandle::TtRef(tt));
}
@ -845,7 +846,7 @@ impl<'tt> FirstSets<'tt> {
match tt {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarDecl { .. }
| TokenTree::MetaVarExpr(..) => {
first.add_one(TtHandle::TtRef(tt));
return first;
@ -1084,7 +1085,7 @@ fn check_matcher_core<'tt>(
match token {
TokenTree::Token(..)
| TokenTree::MetaVar(..)
| TokenTree::MetaVarDecl(..)
| TokenTree::MetaVarDecl { .. }
| TokenTree::MetaVarExpr(..) => {
if token_can_be_followed_by_any(token) {
// don't need to track tokens that work with any,
@ -1152,7 +1153,7 @@ fn check_matcher_core<'tt>(
// Now `last` holds the complete set of NT tokens that could
// end the sequence before SUFFIX. Check that every one works with `suffix`.
for tt in &last.tokens {
if let &TokenTree::MetaVarDecl(span, name, Some(kind)) = tt.get() {
if let &TokenTree::MetaVarDecl { span, name, kind } = tt.get() {
for next_token in &suffix_first.tokens {
let next_token = next_token.get();
@ -1172,11 +1173,11 @@ fn check_matcher_core<'tt>(
)
{
// It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl {
span,
name,
Some(NonterminalKind::Pat(PatParam { inferred: false })),
));
kind: NonterminalKind::Pat(PatParam { inferred: false }),
});
sess.psess.buffer_lint(
RUST_2021_INCOMPATIBLE_OR_PATTERNS,
span,
@ -1212,11 +1213,11 @@ fn check_matcher_core<'tt>(
&& sess.psess.edition.at_least_rust_2021()
&& next_token.is_token(&token::Or)
{
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl {
span,
name,
Some(NonterminalKind::Pat(PatParam { inferred: false })),
));
kind: NonterminalKind::Pat(PatParam { inferred: false }),
});
err.span_suggestion(
span,
"try a `pat_param` fragment specifier instead",
@ -1254,7 +1255,7 @@ fn check_matcher_core<'tt>(
}
fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool {
if let mbe::TokenTree::MetaVarDecl(_, _, Some(kind)) = *tok {
if let mbe::TokenTree::MetaVarDecl { kind, .. } = *tok {
frag_can_be_followed_by_any(kind)
} else {
// (Non NT's can always be followed by anything in matchers.)
@ -1367,7 +1368,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
}
_ => IsInFollow::No(TOKENS),
},
TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Block)) => IsInFollow::Yes,
TokenTree::MetaVarDecl { kind: NonterminalKind::Block, .. } => IsInFollow::Yes,
_ => IsInFollow::No(TOKENS),
}
}
@ -1400,11 +1401,10 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
}
}
},
TokenTree::MetaVarDecl(
_,
_,
Some(NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path),
) => IsInFollow::Yes,
TokenTree::MetaVarDecl {
kind: NonterminalKind::Ident | NonterminalKind::Ty | NonterminalKind::Path,
..
} => IsInFollow::Yes,
_ => IsInFollow::No(TOKENS),
}
}
@ -1416,8 +1416,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
match tt {
mbe::TokenTree::Token(token) => pprust::token_to_string(token).into(),
mbe::TokenTree::MetaVar(_, name) => format!("${name}"),
mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${name}:{kind}"),
mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${name}:"),
mbe::TokenTree::MetaVarDecl { name, kind, .. } => format!("${name}:{kind}"),
_ => panic!(
"{}",
"unexpected mbe::TokenTree::{Sequence or Delimited} \

View file

@ -54,66 +54,78 @@ pub(super) fn parse(
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
// parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
let tree = parse_tree(tree, &mut iter, parsing_patterns, sess, node_id, features, edition);
match tree {
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
// Not consuming the next token immediately, as it may not be a colon
let span = match iter.peek() {
Some(&tokenstream::TokenTree::Token(
Token { kind: token::Colon, span: colon_span },
_,
)) => {
// Consume the colon first
iter.next();
// It's ok to consume the next tree no matter how,
// since if it's not a token then it will be an invalid declaration.
match iter.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
Some((fragment, _)) => {
let span = token.span.with_lo(start_sp.lo());
let edition = || {
// FIXME(#85708) - once we properly decode a foreign
// crate's `SyntaxContext::root`, then we can replace
// this with just `span.edition()`. A
// `SyntaxContext::root()` from the current crate will
// have the edition of the current crate, and a
// `SyntaxContext::root()` from a foreign crate will
// have the edition of that crate (which we manually
// retrieve via the `edition` parameter).
if !span.from_expansion() {
edition
} else {
span.edition()
}
};
let kind = NonterminalKind::from_symbol(fragment.name, edition)
.unwrap_or_else(|| {
sess.dcx().emit_err(errors::InvalidFragmentSpecifier {
span,
fragment,
help: VALID_FRAGMENT_NAMES_MSG.into(),
});
NonterminalKind::Ident
});
result.push(TokenTree::MetaVarDecl(span, ident, Some(kind)));
continue;
}
_ => token.span,
},
// Invalid, return a nice source location
_ => colon_span.with_lo(start_sp.lo()),
}
}
// Whether it's none or some other tree, it doesn't belong to
// the current meta variable, returning the original span.
_ => start_sp,
};
if !parsing_patterns {
// No matchers allowed, nothing to process here
result.push(tree);
continue;
}
result.push(TokenTree::MetaVarDecl(span, ident, None));
}
let TokenTree::MetaVar(start_sp, ident) = tree else {
// Not a metavariable, just return the tree
result.push(tree);
continue;
};
// Not a metavar or no matchers allowed, so just return the tree
_ => result.push(tree),
// Push a metavariable with no fragment specifier at the given span
let mut missing_fragment_specifier = |span| {
sess.dcx().emit_err(errors::MissingFragmentSpecifier {
span,
add_span: span.shrink_to_hi(),
valid: VALID_FRAGMENT_NAMES_MSG,
});
// Fall back to a `TokenTree` since that will match anything if we continue expanding.
result.push(TokenTree::MetaVarDecl { span, name: ident, kind: NonterminalKind::TT });
};
// Not consuming the next token immediately, as it may not be a colon
if let Some(peek) = iter.peek()
&& let tokenstream::TokenTree::Token(token, _spacing) = peek
&& let Token { kind: token::Colon, span: colon_span } = token
{
// Next token is a colon; consume it
iter.next();
// It's ok to consume the next tree no matter how,
// since if it's not a token then it will be an invalid declaration.
let Some(tokenstream::TokenTree::Token(token, _)) = iter.next() else {
// Invalid, return a nice source location as `var:`
missing_fragment_specifier(colon_span.with_lo(start_sp.lo()));
continue;
};
let Some((fragment, _)) = token.ident() else {
// No identifier for the fragment specifier;
missing_fragment_specifier(token.span);
continue;
};
let span = token.span.with_lo(start_sp.lo());
let edition = || {
// FIXME(#85708) - once we properly decode a foreign
// crate's `SyntaxContext::root`, then we can replace
// this with just `span.edition()`. A
// `SyntaxContext::root()` from the current crate will
// have the edition of the current crate, and a
// `SyntaxContext::root()` from a foreign crate will
// have the edition of that crate (which we manually
// retrieve via the `edition` parameter).
if !span.from_expansion() { edition } else { span.edition() }
};
let kind = NonterminalKind::from_symbol(fragment.name, edition).unwrap_or_else(|| {
sess.dcx().emit_err(errors::InvalidFragmentSpecifier {
span,
fragment,
help: VALID_FRAGMENT_NAMES_MSG,
});
NonterminalKind::TT
});
result.push(TokenTree::MetaVarDecl { span, name: ident, kind });
} else {
// Whether it's none or some other tree, it doesn't belong to
// the current meta variable, returning the original span.
missing_fragment_specifier(start_sp);
}
}
result

View file

@ -283,7 +283,7 @@ pub(super) fn transcribe<'a>(
}
// There should be no meta-var declarations in the invocation of a macro.
mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
mbe::TokenTree::MetaVarDecl { .. } => panic!("unexpected `TokenTree::MetaVarDecl`"),
}
}
}
@ -776,7 +776,7 @@ fn lockstep_iter_size(
size.with(lockstep_iter_size(tt, interpolations, repeats))
})
}
TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => {
TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl { name, .. } => {
let name = MacroRulesNormalizedIdent::new(*name);
match lookup_cur_matched(name, interpolations, repeats) {
Some(matched) => match matched {

View file

@ -18,7 +18,6 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
use rustc_session::filesearch::sysroot_with_fallback;
use rustc_session::parse::ParseSess;
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
@ -405,8 +404,11 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
crate::callbacks::setup_callbacks();
let sysroot = config.opts.sysroot.clone();
let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot);
let target = config::build_target_config(
&early_dcx,
&config.opts.target_triple,
config.opts.sysroot.path(),
);
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
let path_mapping = config.opts.file_path_mapping();
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
@ -426,7 +428,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
let codegen_backend = match config.make_codegen_backend {
None => util::get_codegen_backend(
&early_dcx,
&sysroot,
&config.opts.sysroot,
config.opts.unstable_opts.codegen_backend.as_deref(),
&target,
),
@ -440,7 +442,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
let bundle = match rustc_errors::fluent_bundle(
sysroot_with_fallback(&config.opts.sysroot),
&config.opts.sysroot.all_paths().collect::<Vec<_>>(),
config.opts.unstable_opts.translate_lang.clone(),
config.opts.unstable_opts.translate_additional_ftl.as_deref(),
config.opts.unstable_opts.translate_directionality_markers,
@ -469,7 +471,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
locale_resources,
config.lint_caps,
target,
sysroot,
util::rustc_version_str().unwrap_or("unknown"),
config.ice_file,
config.using_internal_features,

View file

@ -41,9 +41,11 @@ where
let matches = optgroups().parse(args).unwrap();
let sessopts = build_session_options(&mut early_dcx, &matches);
let sysroot = sessopts.sysroot.clone();
let target =
rustc_session::config::build_target_config(&early_dcx, &sessopts.target_triple, &sysroot);
let target = rustc_session::config::build_target_config(
&early_dcx,
&sessopts.target_triple,
sessopts.sysroot.path(),
);
let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target);
let checksum_hash_kind = sessopts.unstable_opts.checksum_hash_algorithm();
let sm_inputs = Some(SourceMapInputs {
@ -72,7 +74,6 @@ where
vec![],
Default::default(),
target,
sysroot,
"",
None,
&USING_INTERNAL_FEATURES,

View file

@ -11,7 +11,7 @@ use rustc_data_structures::sync;
use rustc_metadata::{DylibError, load_symbol_from_dylib};
use rustc_middle::ty::CurrentGcx;
use rustc_parse::validate_attr;
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_tuple};
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple};
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
use rustc_session::{EarlyDiagCtxt, Session, filesearch};
@ -305,7 +305,7 @@ fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBacken
/// A name of `None` indicates that the default backend should be used.
pub fn get_codegen_backend(
early_dcx: &EarlyDiagCtxt,
sysroot: &Path,
sysroot: &Sysroot,
backend_name: Option<&str>,
target: &Target,
) -> Box<dyn CodegenBackend> {
@ -336,25 +336,24 @@ pub fn get_codegen_backend(
// This is used for rustdoc, but it uses similar machinery to codegen backend
// loading, so we leave the code here. It is potentially useful for other tools
// that want to invoke the rustc binary while linking to rustc as well.
pub fn rustc_path<'a>() -> Option<&'a Path> {
pub fn rustc_path<'a>(sysroot: &Sysroot) -> Option<&'a Path> {
static RUSTC_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR");
RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_deref()
}
fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
let candidate = filesearch::get_or_default_sysroot()
.join(bin_path)
.join(if cfg!(target_os = "windows") { "rustc.exe" } else { "rustc" });
candidate.exists().then_some(candidate)
RUSTC_PATH
.get_or_init(|| {
let candidate = sysroot
.default
.join(env!("RUSTC_INSTALL_BINDIR"))
.join(if cfg!(target_os = "windows") { "rustc.exe" } else { "rustc" });
candidate.exists().then_some(candidate)
})
.as_deref()
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn get_codegen_sysroot(
early_dcx: &EarlyDiagCtxt,
sysroot: &Path,
sysroot: &Sysroot,
backend_name: &str,
) -> MakeBackendFn {
// For now we only allow this function to be called once as it'll dlopen a
@ -369,10 +368,9 @@ fn get_codegen_sysroot(
);
let target = host_tuple();
let sysroot_candidates = filesearch::sysroot_with_fallback(&sysroot);
let sysroot = sysroot_candidates
.iter()
let sysroot = sysroot
.all_paths()
.map(|sysroot| {
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
})
@ -381,8 +379,8 @@ fn get_codegen_sysroot(
f.exists()
})
.unwrap_or_else(|| {
let candidates = sysroot_candidates
.iter()
let candidates = sysroot
.all_paths()
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join("\n* ");

View file

@ -524,6 +524,20 @@ pub trait LintContext {
});
}
/// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements
/// `LintDiagnostic`, typically generated by `#[derive(LintDiagnostic)]`).
fn emit_span_lint_lazy<S: Into<MultiSpan>, L: for<'a> LintDiagnostic<'a, ()>>(
&self,
lint: &'static Lint,
span: S,
decorator: impl FnOnce() -> L,
) {
self.opt_span_lint(lint, Some(span), |lint| {
let decorator = decorator();
decorator.decorate_lint(lint);
});
}
/// Emit a lint at the appropriate level, with an associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature

View file

@ -1353,6 +1353,8 @@ pub(crate) struct NonUpperCaseGlobal<'a> {
pub name: &'a str,
#[subdiagnostic]
pub sub: NonUpperCaseGlobalSub,
#[subdiagnostic]
pub usages: Vec<NonUpperCaseGlobalSubTool>,
}
#[derive(Subdiagnostic)]
@ -1362,14 +1364,29 @@ pub(crate) enum NonUpperCaseGlobalSub {
#[primary_span]
span: Span,
},
#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
#[suggestion(lint_suggestion, code = "{replace}")]
Suggestion {
#[primary_span]
span: Span,
#[applicability]
applicability: Applicability,
replace: String,
},
}
#[derive(Subdiagnostic)]
#[suggestion(
lint_suggestion,
code = "{replace}",
applicability = "machine-applicable",
style = "tool-only"
)]
pub(crate) struct NonUpperCaseGlobalSubTool {
#[primary_span]
pub(crate) span: Span,
pub(crate) replace: String,
}
// noop_method_call.rs
#[derive(LintDiagnostic)]
#[diag(lint_noop_method_call)]

View file

@ -1,9 +1,12 @@
use rustc_abi::ExternAbi;
use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
use rustc_attr_parsing::AttributeParser;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{FnKind, Visitor};
use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind};
use rustc_middle::hir::nested_filter::All;
use rustc_middle::ty;
use rustc_session::config::CrateType;
use rustc_session::{declare_lint, declare_lint_pass};
@ -13,7 +16,7 @@ use {rustc_ast as ast, rustc_hir as hir};
use crate::lints::{
NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub,
NonUpperCaseGlobal, NonUpperCaseGlobalSub,
NonUpperCaseGlobal, NonUpperCaseGlobalSub, NonUpperCaseGlobalSubTool,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@ -493,22 +496,82 @@ declare_lint! {
declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
impl NonUpperCaseGlobals {
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option<LocalDefId>, ident: &Ident) {
let name = ident.name.as_str();
if name.chars().any(|c| c.is_lowercase()) {
let uc = NonSnakeCase::to_snake_case(name).to_uppercase();
// If the item is exported, suggesting changing it's name would be breaking-change
// and could break users without a "nice" applicable fix, so let's avoid it.
let can_change_usages = if let Some(did) = did {
!cx.tcx.effective_visibilities(()).is_exported(did)
} else {
false
};
// We cannot provide meaningful suggestions
// if the characters are in the category of "Lowercase Letter".
let sub = if *name != uc {
NonUpperCaseGlobalSub::Suggestion { span: ident.span, replace: uc }
NonUpperCaseGlobalSub::Suggestion {
span: ident.span,
replace: uc.clone(),
applicability: if can_change_usages {
Applicability::MachineApplicable
} else {
Applicability::MaybeIncorrect
},
}
} else {
NonUpperCaseGlobalSub::Label { span: ident.span }
};
cx.emit_span_lint(
NON_UPPER_CASE_GLOBALS,
ident.span,
NonUpperCaseGlobal { sort, name, sub },
);
struct UsageCollector<'a, 'tcx> {
cx: &'tcx LateContext<'a>,
did: DefId,
collected: Vec<Span>,
}
impl<'v, 'tcx> Visitor<'v> for UsageCollector<'v, 'tcx> {
type NestedFilter = All;
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
self.cx.tcx
}
fn visit_path(
&mut self,
path: &rustc_hir::Path<'v>,
_id: rustc_hir::HirId,
) -> Self::Result {
if let Some(final_seg) = path.segments.last()
&& final_seg.res.opt_def_id() == Some(self.did)
{
self.collected.push(final_seg.ident.span);
}
}
}
cx.emit_span_lint_lazy(NON_UPPER_CASE_GLOBALS, ident.span, || {
// Compute usages lazily as it can expansive and useless when the lint is allowed.
// cf. https://github.com/rust-lang/rust/pull/142645#issuecomment-2993024625
let usages = if can_change_usages
&& *name != uc
&& let Some(did) = did
{
let mut usage_collector =
UsageCollector { cx, did: did.to_def_id(), collected: Vec::new() };
cx.tcx.hir_walk_toplevel_module(&mut usage_collector);
usage_collector
.collected
.into_iter()
.map(|span| NonUpperCaseGlobalSubTool { span, replace: uc.clone() })
.collect()
} else {
vec![]
};
NonUpperCaseGlobal { sort, name, sub, usages }
});
}
}
}
@ -520,10 +583,20 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
hir::ItemKind::Static(_, ident, ..)
if !find_attr!(attrs, AttributeKind::NoMangle(..)) =>
{
NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident);
NonUpperCaseGlobals::check_upper_case(
cx,
"static variable",
Some(it.owner_id.def_id),
&ident,
);
}
hir::ItemKind::Const(ident, ..) => {
NonUpperCaseGlobals::check_upper_case(cx, "constant", &ident);
NonUpperCaseGlobals::check_upper_case(
cx,
"constant",
Some(it.owner_id.def_id),
&ident,
);
}
_ => {}
}
@ -531,7 +604,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
fn check_trait_item(&mut self, cx: &LateContext<'_>, ti: &hir::TraitItem<'_>) {
if let hir::TraitItemKind::Const(..) = ti.kind {
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident);
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ti.ident);
}
}
@ -539,7 +612,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
if let hir::ImplItemKind::Const(..) = ii.kind
&& !assoc_item_in_trait_impl(cx, ii)
{
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", None, &ii.ident);
}
}
@ -555,6 +628,7 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
NonUpperCaseGlobals::check_upper_case(
cx,
"constant in pattern",
None,
&segment.ident,
);
}
@ -564,7 +638,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
fn check_generic_param(&mut self, cx: &LateContext<'_>, param: &hir::GenericParam<'_>) {
if let GenericParamKind::Const { .. } = param.kind {
NonUpperCaseGlobals::check_upper_case(cx, "const parameter", &param.name.ident());
NonUpperCaseGlobals::check_upper_case(
cx,
"const parameter",
Some(param.def_id),
&param.name.ident(),
);
}
}
}

View file

@ -321,7 +321,7 @@ impl<'a> CrateLocator<'a> {
CrateLocator {
only_needs_metadata,
sysroot: &sess.sysroot,
sysroot: sess.opts.sysroot.path(),
metadata_loader,
cfg_version: sess.cfg_version,
crate_name,

View file

@ -608,7 +608,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
self.throw_unresolved_import_error(errors, glob_error);
if !errors.is_empty() {
self.throw_unresolved_import_error(errors, glob_error);
}
}
pub(crate) fn check_hidden_glob_reexports(
@ -688,14 +690,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
_ => true,
});
errors.retain(|(_import, err)| {
// If we've encountered something like `use _;`, we've already emitted an error stating
// that `_` is not a valid identifier, so we ignore that resolve error.
err.segment != Some(kw::Underscore)
});
if errors.is_empty() {
self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");
return;
}
/// Upper limit on the number of `span_label` messages.
const MAX_LABEL_COUNT: usize = 10;
let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
let paths = errors
.iter()
.map(|(import, err)| {
@ -715,6 +722,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
diag.note(note.clone());
}
/// Upper limit on the number of `span_label` messages.
const MAX_LABEL_COUNT: usize = 10;
for (import, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
if let Some(label) = err.label {
diag.span_label(err.span, label);

View file

@ -22,7 +22,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = "1.8.1"
termize = "0.1.1"
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -1296,6 +1296,28 @@ bitflags::bitflags! {
}
}
#[derive(Clone, Debug)]
pub struct Sysroot {
pub explicit: Option<PathBuf>,
pub default: PathBuf,
}
impl Sysroot {
pub fn new(explicit: Option<PathBuf>) -> Sysroot {
Sysroot { explicit, default: filesearch::default_sysroot() }
}
/// Return explicit sysroot if it was passed with `--sysroot`, or default sysroot otherwise.
pub fn path(&self) -> &Path {
self.explicit.as_deref().unwrap_or(&self.default)
}
/// Returns both explicit sysroot if it was passed with `--sysroot` and the default sysroot.
pub fn all_paths(&self) -> impl Iterator<Item = &Path> {
self.explicit.as_deref().into_iter().chain(iter::once(&*self.default))
}
}
pub fn host_tuple() -> &'static str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
@ -1342,7 +1364,7 @@ impl Default for Options {
describe_lints: false,
output_types: OutputTypes(BTreeMap::new()),
search_paths: vec![],
sysroot: filesearch::materialize_sysroot(None),
sysroot: Sysroot::new(None),
target_triple: TargetTuple::from_tuple(host_tuple()),
test: false,
incremental: None,
@ -2673,7 +2695,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let cg = cg;
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target_triple = parse_target_triple(early_dcx, matches);
let opt_level = parse_opt_level(early_dcx, matches, &cg);
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
@ -2712,10 +2733,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let logical_env = parse_logical_env(early_dcx, matches);
let sysroot = filesearch::materialize_sysroot(sysroot_opt);
let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
let real_source_base_dir = |suffix: &str, confirm: &str| {
let mut candidate = sysroot.join(suffix);
let mut candidate = sysroot.path().join(suffix);
if let Ok(metadata) = candidate.symlink_metadata() {
// Replace the symlink bootstrap creates, with its destination.
// We could try to use `fs::canonicalize` instead, but that might
@ -2742,7 +2763,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let mut search_paths = vec![];
for s in &matches.opt_strs("L") {
search_paths.push(SearchPath::from_cli_opt(
&sysroot,
sysroot.path(),
&target_triple,
early_dcx,
s,

View file

@ -5,7 +5,6 @@ use std::{env, fs};
use rustc_fs_util::try_canonicalize;
use rustc_target::spec::Target;
use smallvec::{SmallVec, smallvec};
use crate::search_paths::{PathKind, SearchPath};
@ -182,24 +181,9 @@ fn current_dll_path() -> Result<PathBuf, String> {
Err("current_dll_path is not supported on WASI".to_string())
}
pub fn sysroot_with_fallback(sysroot: &Path) -> SmallVec<[PathBuf; 2]> {
let mut candidates = smallvec![sysroot.to_owned()];
let default_sysroot = get_or_default_sysroot();
if default_sysroot != sysroot {
candidates.push(default_sysroot);
}
candidates
}
/// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
/// Panics if [`get_or_default_sysroot`] returns an error.
pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot())
}
/// This function checks if sysroot is found using env::args().next(), and if it
/// is not found, finds sysroot from current rustc_driver dll.
pub fn get_or_default_sysroot() -> PathBuf {
pub(crate) fn default_sysroot() -> PathBuf {
fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
let dll = current_dll_path()?;

View file

@ -337,7 +337,7 @@ top_level_options!(
output_types: OutputTypes [TRACKED],
search_paths: Vec<SearchPath> [UNTRACKED],
libs: Vec<NativeLib> [TRACKED],
sysroot: PathBuf [UNTRACKED],
sysroot: Sysroot [UNTRACKED],
target_triple: TargetTuple [TRACKED],

View file

@ -149,7 +149,6 @@ pub struct Session {
pub opts: config::Options,
pub target_tlib_path: Arc<SearchPath>,
pub psess: ParseSess,
pub sysroot: PathBuf,
/// Input, input file path and output file path to this compilation process.
pub io: CompilerIO,
@ -456,8 +455,10 @@ impl Session {
/// directories are also returned, for example if `--sysroot` is used but tools are missing
/// (#125246): we also add the bin directories to the sysroot where rustc is located.
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
let search_paths = filesearch::sysroot_with_fallback(&self.sysroot)
.into_iter()
let search_paths = self
.opts
.sysroot
.all_paths()
.map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_tuple()));
if self_contained {
@ -1028,7 +1029,6 @@ pub fn build_session(
fluent_resources: Vec<&'static str>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
target: Target,
sysroot: PathBuf,
cfg_version: &'static str,
ice_file: Option<PathBuf>,
using_internal_features: &'static AtomicBool,
@ -1063,7 +1063,7 @@ pub fn build_session(
}
let host_triple = TargetTuple::from_tuple(config::host_tuple());
let (host, target_warnings) = Target::search(&host_triple, &sysroot)
let (host, target_warnings) = Target::search(&host_triple, sopts.sysroot.path())
.unwrap_or_else(|e| dcx.handle().fatal(format!("Error loading host specification: {e}")));
for warning in target_warnings.warning_messages() {
dcx.handle().warn(warning)
@ -1096,13 +1096,14 @@ pub fn build_session(
let host_triple = config::host_tuple();
let target_triple = sopts.target_triple.tuple();
// FIXME use host sysroot?
let host_tlib_path = Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
let host_tlib_path =
Arc::new(SearchPath::from_sysroot_and_triple(sopts.sysroot.path(), host_triple));
let target_tlib_path = if host_triple == target_triple {
// Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
// rescanning of the target lib path and an unnecessary allocation.
Arc::clone(&host_tlib_path)
} else {
Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
Arc::new(SearchPath::from_sysroot_and_triple(sopts.sysroot.path(), target_triple))
};
let prof = SelfProfilerRef::new(
@ -1134,7 +1135,6 @@ pub fn build_session(
opts: sopts,
target_tlib_path,
psess,
sysroot,
io,
incr_comp_session: RwLock::new(IncrCompSession::NotInitialized),
prof,

View file

@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::DiagCtxtHandle;
use rustc_session::config::{
self, CodegenOptions, CrateType, ErrorOutputType, Externs, Input, JsonUnusedExterns,
OptionsTargetModifiers, UnstableOptions, get_cmd_lint_options, nightly_options,
OptionsTargetModifiers, Sysroot, UnstableOptions, get_cmd_lint_options, nightly_options,
parse_crate_types_from_list, parse_externs, parse_target_triple,
};
use rustc_session::lint::Level;
@ -103,9 +103,7 @@ pub(crate) struct Options {
/// compiling doctests from the crate.
pub(crate) edition: Edition,
/// The path to the sysroot. Used during the compilation process.
pub(crate) sysroot: PathBuf,
/// Has the same value as `sysroot` except is `None` when the user didn't pass `---sysroot`.
pub(crate) maybe_sysroot: Option<PathBuf>,
pub(crate) sysroot: Sysroot,
/// Lint information passed over the command-line.
pub(crate) lint_opts: Vec<(String, Level)>,
/// Whether to ask rustc to describe the lints it knows.
@ -201,7 +199,6 @@ impl fmt::Debug for Options {
.field("target", &self.target)
.field("edition", &self.edition)
.field("sysroot", &self.sysroot)
.field("maybe_sysroot", &self.maybe_sysroot)
.field("lint_opts", &self.lint_opts)
.field("describe_lints", &self.describe_lints)
.field("lint_cap", &self.lint_cap)
@ -725,16 +722,14 @@ impl Options {
}
let target = parse_target_triple(early_dcx, matches);
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
let sysroot = rustc_session::filesearch::materialize_sysroot(maybe_sysroot.clone());
let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
let libs = matches
.opt_strs("L")
.iter()
.map(|s| {
SearchPath::from_cli_opt(
&sysroot,
sysroot.path(),
&target,
early_dcx,
s,
@ -827,7 +822,6 @@ impl Options {
target,
edition,
sysroot,
maybe_sysroot,
lint_opts,
describe_lints,
lint_cap,

View file

@ -514,8 +514,9 @@ fn run_test(
compiler_args.push(format!("@{}", doctest.global_opts.args_file.display()));
if let Some(sysroot) = &rustdoc_options.maybe_sysroot {
compiler_args.push(format!("--sysroot={}", sysroot.display()));
let sysroot = &rustdoc_options.sysroot;
if let Some(explicit_sysroot) = &sysroot.explicit {
compiler_args.push(format!("--sysroot={}", explicit_sysroot.display()));
}
compiler_args.extend_from_slice(&["--edition".to_owned(), doctest.edition.to_string()]);
@ -574,7 +575,7 @@ fn run_test(
let rustc_binary = rustdoc_options
.test_builder
.as_deref()
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
.unwrap_or_else(|| rustc_interface::util::rustc_path(sysroot).expect("found rustc"));
let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
compiler.args(&compiler_args);

View file

@ -5,6 +5,7 @@
//@ needs-target-std
//@ ignore-android: FIXME(#142855)
//@ ignore-sgx: (x86 machine code cannot be directly executed)
use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};

View file

@ -18,7 +18,7 @@ extern crate rustc_span;
use std::path::{Path, PathBuf};
use rustc_interface::{Linker, interface};
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes};
use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes, Sysroot};
use rustc_span::FileName;
fn main() {
@ -32,7 +32,7 @@ fn main() {
panic!("expected sysroot (and optional linker)");
}
let sysroot = PathBuf::from(&args[1]);
let sysroot = Sysroot::new(Some(PathBuf::from(&args[1])));
let linker = args.get(2).map(PathBuf::from);
// compiletest sets the current dir to `output_base_dir` when running.
@ -43,7 +43,7 @@ fn main() {
compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref());
}
fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) {
fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path>) {
let mut opts = Options::default();
opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
opts.sysroot = sysroot;

View file

@ -1,5 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![deny(warnings)]
#![feature(no_stack_check)]
//~^ ERROR: feature has been removed [E0557]

View file

@ -1,10 +1,10 @@
error[E0557]: feature has been removed
--> $DIR/deprecated_no_stack_check.rs:4:12
--> $DIR/deprecated_no_stack_check.rs:2:12
|
LL | #![feature(no_stack_check)]
| ^^^^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.0.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/40110> for more information
= note: removed in 1.0.0; see <https://github.com/rust-lang/rust/pull/40110> for more information
error: aborting due to 1 previous error

View file

@ -1,5 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![crate_type = "lib"]
#![feature(no_coverage)] //~ ERROR feature has been removed [E0557]

View file

@ -1,14 +1,14 @@
error[E0557]: feature has been removed
--> $DIR/feature-gate-coverage-attribute.rs:4:12
--> $DIR/feature-gate-coverage-attribute.rs:2:12
|
LL | #![feature(no_coverage)]
| ^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.74.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/114656> for more information
= note: removed in 1.74.0; see <https://github.com/rust-lang/rust/pull/114656> for more information
= note: renamed to `coverage_attribute`
error[E0658]: the `#[coverage]` attribute is an experimental feature
--> $DIR/feature-gate-coverage-attribute.rs:12:1
--> $DIR/feature-gate-coverage-attribute.rs:10:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^

View file

@ -1,4 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
//~^ ERROR malformed `feature`
//~| ERROR malformed `feature`

View file

@ -1,43 +1,43 @@
error[E0556]: malformed `feature` attribute input
--> $DIR/gated-bad-feature.rs:2:25
--> $DIR/gated-bad-feature.rs:1:25
|
LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
| ^^^^^^^^ help: expected just one word: `foo`
error[E0556]: malformed `feature` attribute input
--> $DIR/gated-bad-feature.rs:2:35
--> $DIR/gated-bad-feature.rs:1:35
|
LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
| ^^^^^^^^^^^ help: expected just one word: `foo`
error[E0557]: feature has been removed
--> $DIR/gated-bad-feature.rs:9:12
--> $DIR/gated-bad-feature.rs:8:12
|
LL | #![feature(test_removed_feature)]
| ^^^^^^^^^^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.0.0 (you are using $RUSTC_VERSION)
= note: removed in 1.0.0
error: malformed `feature` attribute input
--> $DIR/gated-bad-feature.rs:7:1
--> $DIR/gated-bad-feature.rs:6:1
|
LL | #![feature]
| ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]`
error: malformed `feature` attribute input
--> $DIR/gated-bad-feature.rs:8:1
--> $DIR/gated-bad-feature.rs:7:1
|
LL | #![feature = "foo"]
| ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name2, ...)]`
error[E0635]: unknown feature `foo_bar_baz`
--> $DIR/gated-bad-feature.rs:2:12
--> $DIR/gated-bad-feature.rs:1:12
|
LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
| ^^^^^^^^^^^
error[E0635]: unknown feature `foo`
--> $DIR/gated-bad-feature.rs:2:48
--> $DIR/gated-bad-feature.rs:1:48
|
LL | #![feature(foo_bar_baz, foo(bar), foo = "baz", foo)]
| ^^^

View file

@ -1,5 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(external_doc)] //~ ERROR feature has been removed
#![doc(include("README.md"))] //~ ERROR unknown `doc` attribute `include`

View file

@ -1,14 +1,14 @@
error[E0557]: feature has been removed
--> $DIR/removed-features-note-version-and-pr-issue-141619.rs:3:12
--> $DIR/removed-features-note-version-and-pr-issue-141619.rs:1:12
|
LL | #![feature(external_doc)]
| ^^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.54.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/85457> for more information
= note: removed in 1.54.0; see <https://github.com/rust-lang/rust/pull/85457> for more information
= note: use #[doc = include_str!("filename")] instead, which handles macro invocations
error: unknown `doc` attribute `include`
--> $DIR/removed-features-note-version-and-pr-issue-141619.rs:4:8
--> $DIR/removed-features-note-version-and-pr-issue-141619.rs:2:8
|
LL | #![doc(include("README.md"))]
| ^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,19 @@
//@ check-pass
#![feature(impl_trait_in_bindings)]
// A test for #61773 which would have been difficult to support if we
// were to represent `impl_trait_in_bindings` using opaque types.
trait Trait<'a, 'b> { }
impl<T> Trait<'_, '_> for T { }
fn bar<'a, 'b>(data0: &'a u32, data1: &'b u32) {
let x: impl Trait<'_, '_> = (data0, data1);
force_equal(x);
}
fn force_equal<'a>(t: impl Trait<'a, 'a>) { }
fn main() { }

View file

@ -0,0 +1,17 @@
//@ check-pass
#![feature(impl_trait_in_bindings)]
// A test for #61773 which would have been difficult to support if we
// were to represent `impl_trait_in_bindings` using opaque types.
trait Foo<'a> { }
impl Foo<'_> for &u32 { }
fn bar<'a>(data: &'a u32) {
let x: impl Foo<'_> = data;
}
fn main() {
let _: impl Foo<'_> = &44;
}

View file

@ -1,5 +1,5 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-extern-by-macro-for-underscore.rs:16:11
--> $DIR/multiple-extern-by-macro-for-underscore.rs:18:11
|
LL | use ::_;
| ^ expected identifier, found reserved identifier

View file

@ -0,0 +1,8 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-extern-by-macro-for-underscore.rs:18:11
|
LL | use ::_;
| ^ expected identifier, found reserved identifier
error: aborting due to 1 previous error

View file

@ -1,4 +1,6 @@
//@ edition: 2021
//@ revisions: ed2015 ed2021
//@[ed2015] edition: 2015
//@[ed2021] edition: 2021
// issue#128813

View file

@ -0,0 +1,44 @@
// Checks that the `non_upper_case_globals` emits suggestions for usages as well
// <https://github.com/rust-lang/rust/issues/124061>
//@ check-pass
//@ run-rustfix
#![allow(dead_code)]
use std::cell::Cell;
const MY_STATIC: u32 = 0;
//~^ WARN constant `my_static` should have an upper case name
//~| SUGGESTION MY_STATIC
const LOL: u32 = MY_STATIC + 0;
//~^ SUGGESTION MY_STATIC
mod my_mod {
const INSIDE_MOD: u32 = super::MY_STATIC + 0;
//~^ SUGGESTION MY_STATIC
}
thread_local! {
static FOO_FOO: Cell<usize> = unreachable!();
//~^ WARN constant `fooFOO` should have an upper case name
//~| SUGGESTION FOO_FOO
}
fn foo<const FOO: u32>() {
//~^ WARN const parameter `foo` should have an upper case name
//~| SUGGESTION FOO
let _a = FOO + 1;
//~^ SUGGESTION FOO
}
fn main() {
let _a = crate::MY_STATIC;
//~^ SUGGESTION MY_STATIC
FOO_FOO.set(9);
//~^ SUGGESTION FOO_FOO
println!("{}", FOO_FOO.get());
//~^ SUGGESTION FOO_FOO
}

View file

@ -0,0 +1,44 @@
// Checks that the `non_upper_case_globals` emits suggestions for usages as well
// <https://github.com/rust-lang/rust/issues/124061>
//@ check-pass
//@ run-rustfix
#![allow(dead_code)]
use std::cell::Cell;
const my_static: u32 = 0;
//~^ WARN constant `my_static` should have an upper case name
//~| SUGGESTION MY_STATIC
const LOL: u32 = my_static + 0;
//~^ SUGGESTION MY_STATIC
mod my_mod {
const INSIDE_MOD: u32 = super::my_static + 0;
//~^ SUGGESTION MY_STATIC
}
thread_local! {
static fooFOO: Cell<usize> = unreachable!();
//~^ WARN constant `fooFOO` should have an upper case name
//~| SUGGESTION FOO_FOO
}
fn foo<const foo: u32>() {
//~^ WARN const parameter `foo` should have an upper case name
//~| SUGGESTION FOO
let _a = foo + 1;
//~^ SUGGESTION FOO
}
fn main() {
let _a = crate::my_static;
//~^ SUGGESTION MY_STATIC
fooFOO.set(9);
//~^ SUGGESTION FOO_FOO
println!("{}", fooFOO.get());
//~^ SUGGESTION FOO_FOO
}

View file

@ -0,0 +1,39 @@
warning: constant `my_static` should have an upper case name
--> $DIR/lint-non-uppercase-usages.rs:11:7
|
LL | const my_static: u32 = 0;
| ^^^^^^^^^
|
= note: `#[warn(non_upper_case_globals)]` on by default
help: convert the identifier to upper case
|
LL - const my_static: u32 = 0;
LL + const MY_STATIC: u32 = 0;
|
warning: constant `fooFOO` should have an upper case name
--> $DIR/lint-non-uppercase-usages.rs:24:12
|
LL | static fooFOO: Cell<usize> = unreachable!();
| ^^^^^^
|
help: convert the identifier to upper case
|
LL - static fooFOO: Cell<usize> = unreachable!();
LL + static FOO_FOO: Cell<usize> = unreachable!();
|
warning: const parameter `foo` should have an upper case name
--> $DIR/lint-non-uppercase-usages.rs:29:14
|
LL | fn foo<const foo: u32>() {
| ^^^
|
help: convert the identifier to upper case (notice the capitalization difference)
|
LL - fn foo<const foo: u32>() {
LL + fn foo<const FOO: u32>() {
|
warning: 3 warnings emitted

View file

@ -2,11 +2,10 @@ macro_rules! test {
($a, $b) => {
//~^ ERROR missing fragment
//~| ERROR missing fragment
//~| ERROR missing fragment
()
};
}
fn main() {
test!()
test!() //~ ERROR unexpected end of macro invocation
}

View file

@ -24,7 +24,16 @@ help: try adding a specifier here
LL | ($a, $b:spec) => {
| +++++
error: missing fragment specifier
error: unexpected end of macro invocation
--> $DIR/macro-match-nonterminal.rs:10:5
|
LL | macro_rules! test {
| ----------------- when calling this macro
...
LL | test!()
| ^^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$a:tt`
--> $DIR/macro-match-nonterminal.rs:2:6
|
LL | ($a, $b) => {

View file

@ -2,12 +2,11 @@
macro_rules! m {
($name) => {}; //~ ERROR missing fragment
//~| ERROR missing fragment
}
fn main() {
m!();
m!();
m!();
m!();
m!(); //~ ERROR unexpected end
m!(); //~ ERROR unexpected end
m!(); //~ ERROR unexpected end
m!(); //~ ERROR unexpected end
}

View file

@ -11,11 +11,65 @@ help: try adding a specifier here
LL | ($name:spec) => {};
| +++++
error: missing fragment specifier
error: unexpected end of macro invocation
--> $DIR/macro-missing-fragment-deduplication.rs:8:5
|
LL | macro_rules! m {
| -------------- when calling this macro
...
LL | m!();
| ^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$name:tt`
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
LL | ($name) => {};
| ^^^^^
error: aborting due to 2 previous errors
error: unexpected end of macro invocation
--> $DIR/macro-missing-fragment-deduplication.rs:9:5
|
LL | macro_rules! m {
| -------------- when calling this macro
...
LL | m!();
| ^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$name:tt`
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
LL | ($name) => {};
| ^^^^^
error: unexpected end of macro invocation
--> $DIR/macro-missing-fragment-deduplication.rs:10:5
|
LL | macro_rules! m {
| -------------- when calling this macro
...
LL | m!();
| ^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$name:tt`
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
LL | ($name) => {};
| ^^^^^
error: unexpected end of macro invocation
--> $DIR/macro-missing-fragment-deduplication.rs:11:5
|
LL | macro_rules! m {
| -------------- when calling this macro
...
LL | m!();
| ^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$name:tt`
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
LL | ($name) => {};
| ^^^^^
error: aborting due to 5 previous errors

View file

@ -2,7 +2,6 @@
macro_rules! used_arm {
( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment
//~| ERROR missing fragment
}
macro_rules! used_macro_unused_arm {

View file

@ -12,7 +12,7 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {};
| +++++
error: missing fragment specifier
--> $DIR/macro-missing-fragment.rs:10:7
--> $DIR/macro-missing-fragment.rs:9:7
|
LL | ( $name ) => {};
| ^^^^^
@ -25,7 +25,7 @@ LL | ( $name:spec ) => {};
| +++++
error: missing fragment specifier
--> $DIR/macro-missing-fragment.rs:14:7
--> $DIR/macro-missing-fragment.rs:13:7
|
LL | ( $name ) => {};
| ^^^^^
@ -37,11 +37,5 @@ help: try adding a specifier here
LL | ( $name:spec ) => {};
| +++++
error: missing fragment specifier
--> $DIR/macro-missing-fragment.rs:4:20
|
LL | ( $( any_token $field_rust_type )* ) => {};
| ^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

View file

@ -1,5 +1,4 @@
//@ aux-build:two_macros.rs
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(macro_reexport)] //~ ERROR feature has been removed

View file

@ -1,14 +1,14 @@
error[E0557]: feature has been removed
--> $DIR/macro-reexport-removed.rs:4:12
--> $DIR/macro-reexport-removed.rs:3:12
|
LL | #![feature(macro_reexport)]
| ^^^^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.0.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/49982> for more information
= note: removed in 1.0.0; see <https://github.com/rust-lang/rust/pull/49982> for more information
= note: subsumed by `pub use`
error: cannot find attribute `macro_reexport` in this scope
--> $DIR/macro-reexport-removed.rs:6:3
--> $DIR/macro-reexport-removed.rs:5:3
|
LL | #[macro_reexport(macro_one)]
| ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export`

View file

@ -1,11 +1,10 @@
macro_rules! foo {
{ $+ } => { //~ ERROR expected identifier, found `+`
//~^ ERROR missing fragment specifier
//~| ERROR missing fragment specifier
$(x)(y) //~ ERROR expected one of: `*`, `+`, or `?`
}
}
foo!();
foo!(); //~ ERROR unexpected end
fn main() {}

View file

@ -4,12 +4,6 @@ error: expected identifier, found `+`
LL | { $+ } => {
| ^
error: expected one of: `*`, `+`, or `?`
--> $DIR/issue-33569.rs:5:13
|
LL | $(x)(y)
| ^^^
error: missing fragment specifier
--> $DIR/issue-33569.rs:2:8
|
@ -23,7 +17,22 @@ help: try adding a specifier here
LL | { $+:spec } => {
| +++++
error: missing fragment specifier
error: expected one of: `*`, `+`, or `?`
--> $DIR/issue-33569.rs:4:13
|
LL | $(x)(y)
| ^^^
error: unexpected end of macro invocation
--> $DIR/issue-33569.rs:8:1
|
LL | macro_rules! foo {
| ---------------- when calling this macro
...
LL | foo!();
| ^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$<!dummy!>:tt`
--> $DIR/issue-33569.rs:2:8
|
LL | { $+ } => {

View file

@ -1,5 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(doc_keyword)] //~ ERROR
#![feature(doc_primitive)] //~ ERROR
#![crate_type = "lib"]

View file

@ -1,19 +1,19 @@
error[E0557]: feature has been removed
--> $DIR/renamed-features-rustdoc_internals.rs:3:12
--> $DIR/renamed-features-rustdoc_internals.rs:1:12
|
LL | #![feature(doc_keyword)]
| ^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.58.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/90420> for more information
= note: removed in 1.58.0; see <https://github.com/rust-lang/rust/pull/90420> for more information
= note: merged into `#![feature(rustdoc_internals)]`
error[E0557]: feature has been removed
--> $DIR/renamed-features-rustdoc_internals.rs:4:12
--> $DIR/renamed-features-rustdoc_internals.rs:2:12
|
LL | #![feature(doc_primitive)]
| ^^^^^^^^^^^^^ feature has been removed
|
= note: removed in 1.58.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/90420> for more information
= note: removed in 1.58.0; see <https://github.com/rust-lang/rust/pull/90420> for more information
= note: merged into `#![feature(rustdoc_internals)]`
error: aborting due to 2 previous errors

View file

@ -6,7 +6,6 @@
// Regression test for issue #125877.
//@ compile-flags: -Znext-solver
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(const_trait_impl, effects)]
//~^ ERROR feature has been removed

View file

@ -1,14 +1,14 @@
error[E0557]: feature has been removed
--> $DIR/const-trait-impl-parameter-mismatch.rs:11:30
--> $DIR/const-trait-impl-parameter-mismatch.rs:10:30
|
LL | #![feature(const_trait_impl, effects)]
| ^^^^^^^ feature has been removed
|
= note: removed in 1.84.0 (you are using $RUSTC_VERSION); see <https://github.com/rust-lang/rust/pull/132479> for more information
= note: removed in 1.84.0; see <https://github.com/rust-lang/rust/pull/132479> for more information
= note: removed, redundant with `#![feature(const_trait_impl)]`
error[E0049]: associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/const-trait-impl-parameter-mismatch.rs:20:16
--> $DIR/const-trait-impl-parameter-mismatch.rs:19:16
|
LL | fn compute<T: ~const Aux>() -> u32;
| - expected 1 type parameter

View file

@ -1,17 +1,17 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:5:5
--> $DIR/issue-110164.rs:8:5
|
LL | use _::a;
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:8:5
--> $DIR/issue-110164.rs:10:5
|
LL | use _::*;
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:13:9
--> $DIR/issue-110164.rs:14:9
|
LL | use _::a;
| ^ expected identifier, found reserved identifier
@ -23,41 +23,17 @@ LL | use _::*;
| ^ expected identifier, found reserved identifier
error[E0432]: unresolved import `self::*`
--> $DIR/issue-110164.rs:1:5
--> $DIR/issue-110164.rs:4:5
|
LL | use self::*;
| ^^^^^^^ cannot glob-import a module into itself
error[E0432]: unresolved import `crate::*`
--> $DIR/issue-110164.rs:3:5
--> $DIR/issue-110164.rs:6:5
|
LL | use crate::*;
| ^^^^^^^^ cannot glob-import a module into itself
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:8:5
|
LL | use _::*;
| ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:5:5
|
LL | use _::a;
| ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:13:9
|
LL | use _::a;
| ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:16:9
|
LL | use _::*;
| ^ `_` is not a valid crate or module name
error: aborting due to 10 previous errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0432`.

View file

@ -0,0 +1,39 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:8:5
|
LL | use _::a;
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:10:5
|
LL | use _::*;
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:14:9
|
LL | use _::a;
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/issue-110164.rs:16:9
|
LL | use _::*;
| ^ expected identifier, found reserved identifier
error[E0432]: unresolved import `self::*`
--> $DIR/issue-110164.rs:4:5
|
LL | use self::*;
| ^^^^^^^ cannot glob-import a module into itself
error[E0432]: unresolved import `crate::*`
--> $DIR/issue-110164.rs:6:5
|
LL | use crate::*;
| ^^^^^^^^ cannot glob-import a module into itself
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0432`.

View file

@ -1,19 +1,18 @@
//@ revisions: ed2015 ed2021
//@[ed2015] edition: 2015
//@[ed2021] edition: 2021
use self::*;
//~^ ERROR unresolved import `self::*`
use crate::*;
//~^ ERROR unresolved import `crate::*`
use _::a;
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `_`
use _::*;
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `_`
fn main() {
use _::a;
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `_`
use _::*;
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `_`
}

View file

@ -0,0 +1,49 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:4:9
|
LL | pub use _::{a, b};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:6:18
|
LL | pub use std::{a, _};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:9:18
|
LL | pub use std::{b, _, c};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:12:15
|
LL | pub use std::{_, d};
| ^ expected identifier, found reserved identifier
error[E0432]: unresolved import `std::a`
--> $DIR/multiple-uses.rs:6:15
|
LL | pub use std::{a, _};
| ^ no `a` in the root
error[E0432]: unresolved imports `std::b`, `std::c`
--> $DIR/multiple-uses.rs:9:15
|
LL | pub use std::{b, _, c};
| ^ ^
| | |
| | no `c` in the root
| | help: a similar name exists in the module: `rc`
| no `b` in the root
error[E0432]: unresolved import `std::d`
--> $DIR/multiple-uses.rs:12:18
|
LL | pub use std::{_, d};
| ^ no `d` in the root
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0432`.

View file

@ -0,0 +1,49 @@
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:4:9
|
LL | pub use _::{a, b};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:6:18
|
LL | pub use std::{a, _};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:9:18
|
LL | pub use std::{b, _, c};
| ^ expected identifier, found reserved identifier
error: expected identifier, found reserved identifier `_`
--> $DIR/multiple-uses.rs:12:15
|
LL | pub use std::{_, d};
| ^ expected identifier, found reserved identifier
error[E0432]: unresolved import `std::a`
--> $DIR/multiple-uses.rs:6:15
|
LL | pub use std::{a, _};
| ^ no `a` in the root
error[E0432]: unresolved imports `std::b`, `std::c`
--> $DIR/multiple-uses.rs:9:15
|
LL | pub use std::{b, _, c};
| ^ ^
| | |
| | no `c` in the root
| | help: a similar name exists in the module: `rc`
| no `b` in the root
error[E0432]: unresolved import `std::d`
--> $DIR/multiple-uses.rs:12:18
|
LL | pub use std::{_, d};
| ^ no `d` in the root
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0432`.

View file

@ -0,0 +1,16 @@
//@ revisions: ed2015 ed2021
//@[ed2015] edition: 2015
//@[ed2021] edition: 2021
pub use _::{a, b};
//~^ ERROR expected identifier, found reserved identifier `_`
pub use std::{a, _};
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `std::a`
pub use std::{b, _, c};
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved imports `std::b`, `std::c`
pub use std::{_, d};
//~^ ERROR expected identifier, found reserved identifier `_`
//~| ERROR unresolved import `std::d`
fn main() {}

View file

@ -1,4 +1,2 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(unsized_locals)] //~ERROR feature has been removed
#![crate_type = "lib"]

View file

@ -1,10 +1,10 @@
error[E0557]: feature has been removed
--> $DIR/yote.rs:3:12
--> $DIR/yote.rs:1:12
|
LL | #![feature(unsized_locals)]
| ^^^^^^^^^^^^^^ feature has been removed
|
= note: removed in CURRENT_RUSTC_VERSION (you are using $RUSTC_VERSION)
= note: removed in CURRENT_RUSTC_VERSION
= note: removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942
error: aborting due to 1 previous error