diff --git a/.mailmap b/.mailmap index f55200c3fe976..2a53cbf9effc4 100644 --- a/.mailmap +++ b/.mailmap @@ -162,8 +162,10 @@ David Carlier David Klein David Manescu David Ross -David Wood +David Wood +David Wood David Wood +David Wood Deadbeef Deadbeef dependabot[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> diff --git a/Cargo.lock b/Cargo.lock index a170ece0a0ddc..7e798d6d26144 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 54781e8235e2f..9b4535dcfbceb 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -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, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 095c0df98acc1..f9e52239d6f67 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -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 diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5e3f3ffa2ea85..7b4e38969eedf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -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 { + *self.local_names().get(index)? + } + + fn local_names(&self) -> &IndexSlice> { + 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('_')) + } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 0394a42ea9c77..b21d348183fc6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -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, }); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a5c9bad3ac2db..fd8a2a6bc3544 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -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, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 3bec07afa0fe0..d27e08573e037 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -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, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 487f78058a8ca..1ad629ad167d4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -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(); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4d85f1090201c..82b300dcb17d9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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_names: OnceCell>>, /// 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; } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8882ba359b774..4a2425967e4fa 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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; } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8fc83908efbcc..30304d7929b94 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1059,7 +1059,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 { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index daeca43169d4a..4855fc58d034a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -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) } diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 5dc582b9c3a56..0951859fa531f 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -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 diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 194fc2450ba47..4e4345cfe0fd5 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -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> for TranslationBundleError { /// (overriding any conflicting messages). #[instrument(level = "trace")] pub fn fluent_bundle( - sysroot_candidates: SmallVec<[PathBuf; 2]>, + sysroot_candidates: &[&Path], requested_locale: Option, 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()); diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 8b7c47dad991f..b7555bba28ec6 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -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 = diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 9a359e9b03106..170ac39d1ec34 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -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; diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 714ba3bf0f4f2..fe4d2af97a0db 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -162,7 +162,6 @@ pub(crate) struct FeatureRemoved<'a> { #[subdiagnostic] pub reason: Option>, 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)] diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs index 4ff8c02bcdb82..3082c881a7a66 100644 --- a/compiler/rustc_expand/src/mbe.rs +++ b/compiler/rustc_expand/src/mbe.rs @@ -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), + 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(), diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 698492f42e28f..99aa376626d45 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -24,6 +24,7 @@ pub(super) fn failed_to_match_macro( arg: TokenStream, lhses: &[Vec], ) -> (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); diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 3cd803c3e8482..dc2d46c4a1419 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -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) => { diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index c78beb40688fe..802e43209a51e 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -122,7 +122,7 @@ pub(crate) enum MatcherLoc { MetaVarDecl { span: Span, bind: Ident, - kind: Option, + 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 { 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) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 783f061ec6c58..432ab32474059 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -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} \ diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 0c2362f23bcfc..2daa4e7155843 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -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, - }; - result.push(TokenTree::MetaVarDecl(span, ident, None)); - } + if !parsing_patterns { + // No matchers allowed, nothing to process here + result.push(tree); + continue; + } + + 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 diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 0520be5fbaee5..a8c4a9e4b1b4d 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -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 { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index d62bf7f85e0e6..c46e879b976ac 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -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(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(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(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::>(), 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(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, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index a0012b04c4f29..360b5629e9d6e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -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, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 8a7d61172655f..0ca4fcc66ca55 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -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 { @@ -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> = 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 { - 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::>() .join("\n* "); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 297b8ef7e76ae..95663204ec368 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -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, 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 diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index abdf8e3853bfb..4d405d915fbd6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1353,6 +1353,8 @@ pub(crate) struct NonUpperCaseGlobal<'a> { pub name: &'a str, #[subdiagnostic] pub sub: NonUpperCaseGlobalSub, + #[subdiagnostic] + pub usages: Vec, } #[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)] diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index f39e1506390d5..97e627f2eb29c 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -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, 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, + } + + 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", ¶m.name.ident()); + NonUpperCaseGlobals::check_upper_case( + cx, + "const parameter", + Some(param.def_id), + ¶m.name.ident(), + ); } } } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 259bcb1b96dbb..941f16bd960b5 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -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, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index e989209e177a3..1b7a2c3bda08c 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -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); diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index f0ee19e3c6774..5b88a7017c51b 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -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 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 87e4b0a17aad1..c62e4ac30ea74 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1296,6 +1296,28 @@ bitflags::bitflags! { } } +#[derive(Clone, Debug)] +pub struct Sysroot { + pub explicit: Option, + pub default: PathBuf, +} + +impl Sysroot { + pub fn new(explicit: Option) -> 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 { + 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, diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 4f8c3926207f3..f64fa86948c8d 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -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 { 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 { - 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 { let dll = current_dll_path()?; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7fef942525b96..232531dc673a1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -337,7 +337,7 @@ top_level_options!( output_types: OutputTypes [TRACKED], search_paths: Vec [UNTRACKED], libs: Vec [TRACKED], - sysroot: PathBuf [UNTRACKED], + sysroot: Sysroot [UNTRACKED], target_triple: TargetTuple [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ad58c3c8f7d8b..bad2581ae31b9 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -149,7 +149,6 @@ pub struct Session { pub opts: config::Options, pub target_tlib_path: Arc, 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 { - 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, target: Target, - sysroot: PathBuf, cfg_version: &'static str, ice_file: Option, 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, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index f93aa8ffd0de9..986390dbaa084 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -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, + 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, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 130fdff1afe29..1b5c9fd466411 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -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); diff --git a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs index 426d65b7af391..cca528c425264 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/rmake.rs @@ -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}; diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index fa651baa7bc8f..87504b8301f03 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -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; diff --git a/tests/ui/deprecation/deprecated_no_stack_check.rs b/tests/ui/deprecation/deprecated_no_stack_check.rs index 64635c5f5e88d..8e1f5bbf045a5 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check.rs +++ b/tests/ui/deprecation/deprecated_no_stack_check.rs @@ -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] diff --git a/tests/ui/deprecation/deprecated_no_stack_check.stderr b/tests/ui/deprecation/deprecated_no_stack_check.stderr index 2d08b1b8db54c..33788661d7300 100644 --- a/tests/ui/deprecation/deprecated_no_stack_check.stderr +++ b/tests/ui/deprecation/deprecated_no_stack_check.stderr @@ -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 for more information + = note: removed in 1.0.0; see for more information error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.rs b/tests/ui/feature-gates/feature-gate-coverage-attribute.rs index 67ac866803c06..0a463755f1373 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.rs +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.rs @@ -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] diff --git a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr index 8c23544698d08..68d0d9bc3c31e 100644 --- a/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-coverage-attribute.stderr @@ -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 for more information + = note: removed in 1.74.0; see 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)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/gated-bad-feature.rs b/tests/ui/feature-gates/gated-bad-feature.rs index aa094acba374c..51f2db5556e2b 100644 --- a/tests/ui/feature-gates/gated-bad-feature.rs +++ b/tests/ui/feature-gates/gated-bad-feature.rs @@ -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` diff --git a/tests/ui/feature-gates/gated-bad-feature.stderr b/tests/ui/feature-gates/gated-bad-feature.stderr index 0e75dff14f8a2..e0e84d842352d 100644 --- a/tests/ui/feature-gates/gated-bad-feature.stderr +++ b/tests/ui/feature-gates/gated-bad-feature.stderr @@ -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)] | ^^^ diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs index a217a7fda51b4..d8c5f48f9fd9b 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs @@ -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` diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr index 43205c7360b23..bd8c56c61c3c9 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr @@ -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 for more information + = note: removed in 1.54.0; see 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"))] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/in-bindings/lifetime-equality.rs b/tests/ui/impl-trait/in-bindings/lifetime-equality.rs new file mode 100644 index 0000000000000..6cf48dccc7d97 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/lifetime-equality.rs @@ -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 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() { } diff --git a/tests/ui/impl-trait/in-bindings/region-lifetimes.rs b/tests/ui/impl-trait/in-bindings/region-lifetimes.rs new file mode 100644 index 0000000000000..189ab85a27698 --- /dev/null +++ b/tests/ui/impl-trait/in-bindings/region-lifetimes.rs @@ -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; +} diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr similarity index 75% rename from tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr rename to tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr index 1da5aa8707043..985cd654c394d 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-underscore.stderr +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2015.stderr @@ -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 diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr new file mode 100644 index 0000000000000..985cd654c394d --- /dev/null +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.ed2021.stderr @@ -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 + diff --git a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs index ddf735d894753..ab877e0624630 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs +++ b/tests/ui/imports/multiple-extern-by-macro-for-underscore.rs @@ -1,4 +1,6 @@ -//@ edition: 2021 +//@ revisions: ed2015 ed2021 +//@[ed2015] edition: 2015 +//@[ed2021] edition: 2021 // issue#128813 diff --git a/tests/ui/lint/lint-non-uppercase-usages.fixed b/tests/ui/lint/lint-non-uppercase-usages.fixed new file mode 100644 index 0000000000000..231991dcae08c --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.fixed @@ -0,0 +1,44 @@ +// Checks that the `non_upper_case_globals` emits suggestions for usages as well +// + +//@ 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 = unreachable!(); + //~^ WARN constant `fooFOO` should have an upper case name + //~| SUGGESTION FOO_FOO +} + +fn foo() { + //~^ 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 +} diff --git a/tests/ui/lint/lint-non-uppercase-usages.rs b/tests/ui/lint/lint-non-uppercase-usages.rs new file mode 100644 index 0000000000000..9cdf5e47003d5 --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.rs @@ -0,0 +1,44 @@ +// Checks that the `non_upper_case_globals` emits suggestions for usages as well +// + +//@ 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 = unreachable!(); + //~^ WARN constant `fooFOO` should have an upper case name + //~| SUGGESTION FOO_FOO +} + +fn foo() { + //~^ 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 +} diff --git a/tests/ui/lint/lint-non-uppercase-usages.stderr b/tests/ui/lint/lint-non-uppercase-usages.stderr new file mode 100644 index 0000000000000..7c7e573a88edc --- /dev/null +++ b/tests/ui/lint/lint-non-uppercase-usages.stderr @@ -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 = unreachable!(); + | ^^^^^^ + | +help: convert the identifier to upper case + | +LL - static fooFOO: Cell = unreachable!(); +LL + static FOO_FOO: Cell = unreachable!(); + | + +warning: const parameter `foo` should have an upper case name + --> $DIR/lint-non-uppercase-usages.rs:29:14 + | +LL | fn foo() { + | ^^^ + | +help: convert the identifier to upper case (notice the capitalization difference) + | +LL - fn foo() { +LL + fn foo() { + | + +warning: 3 warnings emitted + diff --git a/tests/ui/macros/macro-match-nonterminal.rs b/tests/ui/macros/macro-match-nonterminal.rs index fa2af945a1f1b..1643cddb192be 100644 --- a/tests/ui/macros/macro-match-nonterminal.rs +++ b/tests/ui/macros/macro-match-nonterminal.rs @@ -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 } diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr index 8196d795c4c8f..a92d099ca0083 100644 --- a/tests/ui/macros/macro-match-nonterminal.stderr +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -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) => { diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.rs b/tests/ui/macros/macro-missing-fragment-deduplication.rs index 481f08fa11199..fc81c713b4d5c 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.rs +++ b/tests/ui/macros/macro-missing-fragment-deduplication.rs @@ -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 } diff --git a/tests/ui/macros/macro-missing-fragment-deduplication.stderr b/tests/ui/macros/macro-missing-fragment-deduplication.stderr index 820f7eb3cf7fd..29d2ae0e16edb 100644 --- a/tests/ui/macros/macro-missing-fragment-deduplication.stderr +++ b/tests/ui/macros/macro-missing-fragment-deduplication.stderr @@ -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: 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 2 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/macros/macro-missing-fragment.rs b/tests/ui/macros/macro-missing-fragment.rs index 533aa147bcbf5..7ed9074020e4b 100644 --- a/tests/ui/macros/macro-missing-fragment.rs +++ b/tests/ui/macros/macro-missing-fragment.rs @@ -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 { diff --git a/tests/ui/macros/macro-missing-fragment.stderr b/tests/ui/macros/macro-missing-fragment.stderr index 4a99d7d949cfe..886292378d1a0 100644 --- a/tests/ui/macros/macro-missing-fragment.stderr +++ b/tests/ui/macros/macro-missing-fragment.stderr @@ -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 diff --git a/tests/ui/macros/macro-reexport-removed.rs b/tests/ui/macros/macro-reexport-removed.rs index 33e7cab4068e2..4a054686d7767 100644 --- a/tests/ui/macros/macro-reexport-removed.rs +++ b/tests/ui/macros/macro-reexport-removed.rs @@ -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 diff --git a/tests/ui/macros/macro-reexport-removed.stderr b/tests/ui/macros/macro-reexport-removed.stderr index d4940eeb77553..8130fe0c4bdaa 100644 --- a/tests/ui/macros/macro-reexport-removed.stderr +++ b/tests/ui/macros/macro-reexport-removed.stderr @@ -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 for more information + = note: removed in 1.0.0; see 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` diff --git a/tests/ui/parser/macro/issue-33569.rs b/tests/ui/parser/macro/issue-33569.rs index e0a5352ab06db..7288fa858dbee 100644 --- a/tests/ui/parser/macro/issue-33569.rs +++ b/tests/ui/parser/macro/issue-33569.rs @@ -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() {} diff --git a/tests/ui/parser/macro/issue-33569.stderr b/tests/ui/parser/macro/issue-33569.stderr index 0d53c04c1c9f0..dd8e38f0d6e94 100644 --- a/tests/ui/parser/macro/issue-33569.stderr +++ b/tests/ui/parser/macro/issue-33569.stderr @@ -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 `$:tt` --> $DIR/issue-33569.rs:2:8 | LL | { $+ } => { diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs index c0f3c190b65bc..739c624d0c6f7 100644 --- a/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.rs @@ -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"] diff --git a/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr index 9c664da8ee6cd..0608a8b58a219 100644 --- a/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr +++ b/tests/ui/rustdoc/renamed-features-rustdoc_internals.stderr @@ -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 for more information + = note: removed in 1.58.0; see 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 for more information + = note: removed in 1.58.0; see for more information = note: merged into `#![feature(rustdoc_internals)]` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs index 9a41b9c8173af..f90ff91aff4bb 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs @@ -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 diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr index a04f98e68a633..566961b27f3ac 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr @@ -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 for more information + = note: removed in 1.84.0; see 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() -> u32; | - expected 1 type parameter diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.ed2015.stderr similarity index 56% rename from tests/ui/underscore-imports/issue-110164.stderr rename to tests/ui/underscore-imports/issue-110164.ed2015.stderr index d8a4b6bbb7549..f34b5ab5dde74 100644 --- a/tests/ui/underscore-imports/issue-110164.stderr +++ b/tests/ui/underscore-imports/issue-110164.ed2015.stderr @@ -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`. diff --git a/tests/ui/underscore-imports/issue-110164.ed2021.stderr b/tests/ui/underscore-imports/issue-110164.ed2021.stderr new file mode 100644 index 0000000000000..f34b5ab5dde74 --- /dev/null +++ b/tests/ui/underscore-imports/issue-110164.ed2021.stderr @@ -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`. diff --git a/tests/ui/underscore-imports/issue-110164.rs b/tests/ui/underscore-imports/issue-110164.rs index 6fd13414500da..bb080c5e471d4 100644 --- a/tests/ui/underscore-imports/issue-110164.rs +++ b/tests/ui/underscore-imports/issue-110164.rs @@ -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 `_` } diff --git a/tests/ui/underscore-imports/multiple-uses.ed2015.stderr b/tests/ui/underscore-imports/multiple-uses.ed2015.stderr new file mode 100644 index 0000000000000..a295586fa16fd --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.ed2015.stderr @@ -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`. diff --git a/tests/ui/underscore-imports/multiple-uses.ed2021.stderr b/tests/ui/underscore-imports/multiple-uses.ed2021.stderr new file mode 100644 index 0000000000000..a295586fa16fd --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.ed2021.stderr @@ -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`. diff --git a/tests/ui/underscore-imports/multiple-uses.rs b/tests/ui/underscore-imports/multiple-uses.rs new file mode 100644 index 0000000000000..31dd1862429ea --- /dev/null +++ b/tests/ui/underscore-imports/multiple-uses.rs @@ -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() {} diff --git a/tests/ui/unsized-locals/yote.rs b/tests/ui/unsized-locals/yote.rs index f09db9dd006c9..1de75a6ce6171 100644 --- a/tests/ui/unsized-locals/yote.rs +++ b/tests/ui/unsized-locals/yote.rs @@ -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"] diff --git a/tests/ui/unsized-locals/yote.stderr b/tests/ui/unsized-locals/yote.stderr index 655aad5360cc8..8e7da64038a40 100644 --- a/tests/ui/unsized-locals/yote.stderr +++ b/tests/ui/unsized-locals/yote.stderr @@ -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