diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 2da9bda19e034..134a6baea6e8b 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -3,18 +3,20 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; +use rustc_data_structures::sync::Lrc; use rustc_expand::base::{ - check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt, - MacEager, MacResult, + check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, + resolve_path, DummyResult, ExtCtxt, MacEager, MacResult, }; use rustc_expand::module::DirOwnership; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; +use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; use rustc_span::{Pos, Span}; - use smallvec::SmallVec; +use std::path::{Path, PathBuf}; use std::rc::Rc; // These macros all relate to the file system; they either return @@ -180,32 +182,22 @@ pub fn expand_include_str( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { - Ok(file) => file, + let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_str!") { + Ok(res) => res, Err(guar) => return DummyResult::any(sp, guar), }; - let file = match resolve_path(&cx.sess, file.as_str(), sp) { - Ok(f) => f, - Err(err) => { - let guar = err.emit(); - return DummyResult::any(sp, guar); - } - }; - match cx.source_map().load_binary_file(&file) { + match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) { Ok(bytes) => match std::str::from_utf8(&bytes) { Ok(src) => { let interned_src = Symbol::intern(src); MacEager::expr(cx.expr_str(sp, interned_src)) } Err(_) => { - let guar = cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display())); + let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file")); DummyResult::any(sp, guar) } }, - Err(e) => { - let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - DummyResult::any(sp, guar) - } + Err(dummy) => dummy, } } @@ -215,25 +207,123 @@ pub fn expand_include_bytes( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { - Ok(file) => file, + let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_bytes!") { + Ok(res) => res, Err(guar) => return DummyResult::any(sp, guar), }; - let file = match resolve_path(&cx.sess, file.as_str(), sp) { - Ok(f) => f, + match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) { + Ok(bytes) => { + let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); + MacEager::expr(expr) + } + Err(dummy) => dummy, + } +} + +fn load_binary_file( + cx: &mut ExtCtxt<'_>, + original_path: &Path, + macro_span: Span, + path_span: Span, +) -> Result, Box> { + let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) { + Ok(path) => path, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return Err(DummyResult::any(macro_span, guar)); } }; - match cx.source_map().load_binary_file(&file) { - Ok(bytes) => { - let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); - MacEager::expr(expr) + match cx.source_map().load_binary_file(&resolved_path) { + Ok(data) => Ok(data), + Err(io_err) => { + let mut err = cx.dcx().struct_span_err( + macro_span, + format!("couldn't read `{}`: {io_err}", resolved_path.display()), + ); + + if original_path.is_relative() { + let source_map = cx.sess.source_map(); + let new_path = source_map + .span_to_filename(macro_span.source_callsite()) + .into_local_path() + .and_then(|src| find_path_suggestion(source_map, src.parent()?, original_path)) + .and_then(|path| path.into_os_string().into_string().ok()); + + if let Some(new_path) = new_path { + err.span_suggestion( + path_span, + "there is a file with the same name in a different directory", + format!("\"{}\"", new_path.escape_debug()), + rustc_lint_defs::Applicability::MachineApplicable, + ); + } + } + let guar = err.emit(); + Err(DummyResult::any(macro_span, guar)) } - Err(e) => { - let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); - DummyResult::any(sp, guar) + } +} + +fn find_path_suggestion( + source_map: &SourceMap, + base_dir: &Path, + wanted_path: &Path, +) -> Option { + // Fix paths that assume they're relative to cargo manifest dir + let mut base_c = base_dir.components(); + let mut wanted_c = wanted_path.components(); + let mut without_base = None; + while let Some(wanted_next) = wanted_c.next() { + if wanted_c.as_path().file_name().is_none() { + break; + } + // base_dir may be absolute + while let Some(base_next) = base_c.next() { + if base_next == wanted_next { + without_base = Some(wanted_c.as_path()); + break; + } + } + } + let root_absolute = without_base.into_iter().map(PathBuf::from); + + let base_dir_components = base_dir.components().count(); + // Avoid going all the way to the root dir + let max_parent_components = if base_dir.is_relative() { + base_dir_components + 1 + } else { + base_dir_components.saturating_sub(1) + }; + + // Try with additional leading ../ + let mut prefix = PathBuf::new(); + let add = std::iter::from_fn(|| { + prefix.push(".."); + Some(prefix.join(wanted_path)) + }) + .take(max_parent_components.min(3)); + + // Try without leading directories + let mut trimmed_path = wanted_path; + let remove = std::iter::from_fn(|| { + let mut components = trimmed_path.components(); + let removed = components.next()?; + trimmed_path = components.as_path(); + let _ = trimmed_path.file_name()?; // ensure there is a file name left + Some([ + Some(trimmed_path.to_path_buf()), + (removed != std::path::Component::ParentDir) + .then(|| Path::new("..").join(trimmed_path)), + ]) + }) + .flatten() + .flatten() + .take(4); + + for new_path in root_absolute.chain(add).chain(remove) { + if source_map.file_exists(&base_dir.join(&new_path)) { + return Some(new_path); } } + None } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 81c9e02e2ee80..f3af633b4e561 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -146,9 +146,6 @@ const_eval_intern_kind = {$kind -> *[other] {""} } -const_eval_invalid_align = - align has to be a power of 2 - const_eval_invalid_align_details = invalid align passed to `{$name}`: {$align} is {$err_kind -> [not_power_of_two] not a power of 2 diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 57b8df52f4b79..a01677e4b3158 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1638,6 +1638,27 @@ impl HumanEmitter { *style, ); } + if let Some(line) = annotated_file.lines.get(line_idx) { + for ann in &line.annotations { + if let AnnotationType::MultilineStart(pos) = ann.annotation_type + { + // In the case where we have elided the entire start of the + // multispan because those lines were empty, we still need + // to draw the `|`s across the `...`. + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + pos, + if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }, + ); + } + } + } } else if line_idx_delta == 2 { let unannotated_line = annotated_file .file @@ -1665,6 +1686,24 @@ impl HumanEmitter { *style, ); } + if let Some(line) = annotated_file.lines.get(line_idx) { + for ann in &line.annotations { + if let AnnotationType::MultilineStart(pos) = ann.annotation_type + { + draw_multiline_line( + &mut buffer, + last_buffer_line_num, + width_offset, + pos, + if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }, + ); + } + } + } } } @@ -2417,7 +2456,15 @@ impl FileWithAnnotatedLines { // the beginning doesn't have an underline, but the current logic seems to be // working correctly. let middle = min(ann.line_start + 4, ann.line_end); - for line in ann.line_start + 1..middle { + // We'll show up to 4 lines past the beginning of the multispan start. + // We will *not* include the tail of lines that are only whitespace. + let until = (ann.line_start..middle) + .rev() + .filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s))) + .find(|(_, s)| !s.trim().is_empty()) + .map(|(line, _)| line) + .unwrap_or(ann.line_start); + for line in ann.line_start + 1..until { // Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`). add_annotation_to_file(&mut output, file.clone(), line, ann.as_line()); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 69dfb48919cdb..58589ebdca675 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1233,21 +1233,18 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe // after macro expansion (that is, they are unhygienic). if !path.is_absolute() { let callsite = span.source_callsite(); - let mut result = match sess.source_map().span_to_filename(callsite) { - FileName::Real(name) => name - .into_local_path() - .expect("attempting to resolve a file path in an external file"), - FileName::DocTest(path, _) => path, - other => { - return Err(sess.dcx().create_err(errors::ResolveRelativePath { - span, - path: sess.source_map().filename_for_diagnostics(&other).to_string(), - })); - } + let source_map = sess.source_map(); + let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else { + return Err(sess.dcx().create_err(errors::ResolveRelativePath { + span, + path: source_map + .filename_for_diagnostics(&source_map.span_to_filename(callsite)) + .to_string(), + })); }; - result.pop(); - result.push(path); - Ok(result) + base_path.pop(); + base_path.push(path); + Ok(base_path) } else { Ok(path) } @@ -1344,6 +1341,15 @@ pub fn get_single_str_from_tts( tts: TokenStream, name: &str, ) -> Result { + get_single_str_spanned_from_tts(cx, span, tts, name).map(|(s, _)| s) +} + +pub fn get_single_str_spanned_from_tts( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, + name: &str, +) -> Result<(Symbol, Span), ErrorGuaranteed> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); @@ -1355,7 +1361,12 @@ pub fn get_single_str_from_tts( if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) + expr_to_spanned_string(cx, ret, "argument must be a string literal") + .map_err(|err| match err { + Ok((err, _)) => err.emit(), + Err(guar) => guar, + }) + .map(|(symbol, _style, span)| (symbol, span)) } /// Extracts comma-separated expressions from `tts`. diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index a3510dc9bff4d..2b0b58eb1d924 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -276,8 +276,7 @@ error: foo | 2 | fn foo() { | __________^ -3 | | -4 | | +... | 5 | | } | |___^ test diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index 2de87cbe631ac..e44a6ae3b3f2e 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -181,14 +181,6 @@ infer_more_targeted = {$has_param_name -> infer_msl_introduces_static = introduces a `'static` lifetime requirement infer_msl_unmet_req = because this has an unmet lifetime requirement -infer_need_type_info_in_coroutine = - type inside {$coroutine_kind -> - [async_block] `async` block - [async_closure] `async` closure - [async_fn] `async fn` body - *[coroutine] coroutine - } must be known in this context - infer_nothing = {""} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 63e2fe47659db..8bf9d0b9d4aac 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -562,8 +562,6 @@ lint_suspicious_double_ref_clone = lint_suspicious_double_ref_deref = using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type -lint_trivial_untranslatable_diag = diagnostic with static strings only - lint_ty_qualified = usage of qualified `ty::{$ty}` .suggestion = try importing it and using it unqualified diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 31591983101f3..48c3ee1ba0ff3 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -506,13 +506,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { traverse_candidate( candidate, &mut Vec::new(), - &mut |leaf_candidate, parent_bindings| { + &mut |leaf_candidate, parent_data| { if let Some(arm) = arm { self.clear_top_scope(arm.scope); } let binding_end = self.bind_and_guard_matched_candidate( leaf_candidate, - parent_bindings, + parent_data, fake_borrow_temps, scrutinee_span, arm_match_scope, @@ -524,12 +524,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } self.cfg.goto(binding_end, outer_source_info, target_block); }, - |inner_candidate, parent_bindings| { - parent_bindings.push((inner_candidate.bindings, inner_candidate.ascriptions)); + |inner_candidate, parent_data| { + parent_data.push(inner_candidate.extra_data); inner_candidate.subcandidates.into_iter() }, - |parent_bindings| { - parent_bindings.pop(); + |parent_data| { + parent_data.pop(); }, ); @@ -651,7 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if set_match_place { let mut next = Some(&candidate); while let Some(candidate_ref) = next.take() { - for binding in &candidate_ref.bindings { + for binding in &candidate_ref.extra_data.bindings { let local = self.var_local_id(binding.var_id, OutsideGuard); // `try_to_place` may fail if it is unable to resolve the given // `PlaceBuilder` inside a closure. In this case, we don't want to include @@ -924,22 +924,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } -/// A pattern in a form suitable for generating code. +/// Data extracted from a pattern that doesn't affect which branch is taken. Collected during +/// pattern simplification and not mutated later. #[derive(Debug, Clone)] -struct FlatPat<'pat, 'tcx> { +struct PatternExtraData<'tcx> { /// [`Span`] of the original pattern. span: Span, + /// Bindings that must be established. + bindings: Vec>, + + /// Types that must be asserted. + ascriptions: Vec>, +} + +impl<'tcx> PatternExtraData<'tcx> { + fn is_empty(&self) -> bool { + self.bindings.is_empty() && self.ascriptions.is_empty() + } +} + +/// A pattern in a form suitable for generating code. +#[derive(Debug, Clone)] +struct FlatPat<'pat, 'tcx> { /// To match the pattern, all of these must be satisfied... // Invariant: all the `MatchPair`s are recursively simplified. // Invariant: or-patterns must be sorted to the end. match_pairs: Vec>, - /// ...these bindings established... - bindings: Vec>, - - /// ...and these types asserted. - ascriptions: Vec>, + extra_data: PatternExtraData<'tcx>, } impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { @@ -948,43 +961,38 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> { pattern: &'pat Pat<'tcx>, cx: &mut Builder<'_, 'tcx>, ) -> Self { - let mut match_pairs = vec![MatchPair::new(place, pattern, cx)]; - let mut bindings = Vec::new(); - let mut ascriptions = Vec::new(); - - cx.simplify_match_pairs(&mut match_pairs, &mut bindings, &mut ascriptions); - - FlatPat { span: pattern.span, match_pairs, bindings, ascriptions } + let mut flat_pat = FlatPat { + match_pairs: vec![MatchPair::new(place, pattern, cx)], + extra_data: PatternExtraData { + span: pattern.span, + bindings: Vec::new(), + ascriptions: Vec::new(), + }, + }; + cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data); + flat_pat } } #[derive(Debug)] struct Candidate<'pat, 'tcx> { - /// [`Span`] of the original pattern that gave rise to this candidate. - span: Span, - - /// Whether this `Candidate` has a guard. - has_guard: bool, - - /// All of these must be satisfied... + /// For the candidate to match, all of these must be satisfied... // Invariant: all the `MatchPair`s are recursively simplified. // Invariant: or-patterns must be sorted at the end. match_pairs: Vec>, - /// ...these bindings established... - // Invariant: not mutated after candidate creation. - bindings: Vec>, - - /// ...and these types asserted... - // Invariant: not mutated after candidate creation. - ascriptions: Vec>, - /// ...and if this is non-empty, one of these subcandidates also has to match... subcandidates: Vec>, - /// ...and the guard must be evaluated; if it's `false` then branch to `otherwise_block`. + /// ...and the guard must be evaluated if there is one. + has_guard: bool, + + /// If the guard is `false` then branch to `otherwise_block`. otherwise_block: Option, + /// If the candidate matches, bindings and ascriptions must be established. + extra_data: PatternExtraData<'tcx>, + /// The block before the `bindings` have been established. pre_binding_block: Option, /// The pre-binding block of the next candidate. @@ -1003,10 +1011,8 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> { fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self { Candidate { - span: flat_pat.span, match_pairs: flat_pat.match_pairs, - bindings: flat_pat.bindings, - ascriptions: flat_pat.ascriptions, + extra_data: flat_pat.extra_data, has_guard, subcandidates: Vec::new(), otherwise_block: None, @@ -1518,9 +1524,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.merge_trivial_subcandidates(subcandidate, source_info); // FIXME(or_patterns; matthewjasper) Try to be more aggressive here. - can_merge &= subcandidate.subcandidates.is_empty() - && subcandidate.bindings.is_empty() - && subcandidate.ascriptions.is_empty(); + can_merge &= + subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty(); } if can_merge { @@ -1943,7 +1948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn bind_and_guard_matched_candidate<'pat>( &mut self, candidate: Candidate<'pat, 'tcx>, - parent_bindings: &[(Vec>, Vec>)], + parent_data: &[PatternExtraData<'tcx>], fake_borrows: &[(Place<'tcx>, Local)], scrutinee_span: Span, arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>, @@ -1954,7 +1959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug_assert!(candidate.match_pairs.is_empty()); - let candidate_source_info = self.source_info(candidate.span); + let candidate_source_info = self.source_info(candidate.extra_data.span); let mut block = candidate.pre_binding_block.unwrap(); @@ -1971,11 +1976,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.ascribe_types( block, - parent_bindings + parent_data .iter() - .flat_map(|(_, ascriptions)| ascriptions) + .flat_map(|d| &d.ascriptions) .cloned() - .chain(candidate.ascriptions), + .chain(candidate.extra_data.ascriptions), ); // rust-lang/rust#27282: The `autoref` business deserves some @@ -2063,10 +2068,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { && let Some(guard) = arm.guard { let tcx = self.tcx; - let bindings = parent_bindings - .iter() - .flat_map(|(bindings, _)| bindings) - .chain(&candidate.bindings); + let bindings = + parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings); self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone()); let guard_frame = GuardFrame { @@ -2144,10 +2147,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // ``` // // and that is clearly not correct. - let by_value_bindings = parent_bindings + let by_value_bindings = parent_data .iter() - .flat_map(|(bindings, _)| bindings) - .chain(&candidate.bindings) + .flat_map(|d| &d.bindings) + .chain(&candidate.extra_data.bindings) .filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue)); // Read all of the by reference bindings to ensure that the // place they refer to can't be modified by the guard. @@ -2172,10 +2175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.bind_matched_candidate_for_arm_body( block, schedule_drops, - parent_bindings - .iter() - .flat_map(|(bindings, _)| bindings) - .chain(&candidate.bindings), + parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings), storages_alive, ); block diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index a3fccb7c31955..97b94a0b362af 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -12,20 +12,19 @@ //! sort of test: for example, testing which variant an enum is, or //! testing a value against a constant. -use crate::build::matches::{Ascription, Binding, Candidate, FlatPat, MatchPair, TestCase}; +use crate::build::matches::{Candidate, FlatPat, MatchPair, PatternExtraData, TestCase}; use crate::build::Builder; use std::mem; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and - /// ascriptions in the provided `Vec`s. + /// ascriptions in `extra_data`. #[instrument(skip(self), level = "debug")] pub(super) fn simplify_match_pairs<'pat>( &mut self, match_pairs: &mut Vec>, - candidate_bindings: &mut Vec>, - candidate_ascriptions: &mut Vec>, + extra_data: &mut PatternExtraData<'tcx>, ) { // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the // bindings in `pat` before `x`. E.g. (#69971): @@ -45,17 +44,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // after any bindings in `pat`. This doesn't work for or-patterns: the current structure of // match lowering forces us to lower bindings inside or-patterns last. for mut match_pair in mem::take(match_pairs) { - self.simplify_match_pairs( - &mut match_pair.subpairs, - candidate_bindings, - candidate_ascriptions, - ); + self.simplify_match_pairs(&mut match_pair.subpairs, extra_data); if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case { if let Some(binding) = binding { - candidate_bindings.push(binding); + extra_data.bindings.push(binding); } if let Some(ascription) = ascription { - candidate_ascriptions.push(ascription); + extra_data.ascriptions.push(ascription); } // Simplifiable pattern; we replace it with its already simplified subpairs. match_pairs.append(&mut match_pair.subpairs); diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 2351f69a9141f..d0d49c13f133d 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -280,7 +280,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) { - for binding in &candidate.bindings { + for binding in &candidate.extra_data.bindings { self.visit_binding(binding); } for match_pair in &candidate.match_pairs { @@ -289,7 +289,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) { - for binding in &flat_pat.bindings { + for binding in &flat_pat.extra_data.bindings { self.visit_binding(binding); } for match_pair in &flat_pat.match_pairs { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 60cc138fd7bc2..a100e2d47bbbb 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -392,9 +392,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n parse_invalid_interpolated_expression = invalid interpolated expression -parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid - .label = invalid suffix `{$suffix}` - parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid .label = invalid suffix `{$suffix}` .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases @@ -609,7 +606,6 @@ parse_nonterminal_expected_item_keyword = expected an item keyword parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}` parse_nonterminal_expected_statement = expected a statement -parse_not_supported = not supported parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c223b8475288b..7fc523ffe0dea 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -302,9 +302,6 @@ passes_export_name = attribute should be applied to a free function, impl method or static .label = not a free function, impl method or static -passes_expr_not_allowed_in_context = - {$expr} is not allowed in a `{$context}` - passes_extern_main = the `main` function cannot be declared in an `extern` block @@ -405,8 +402,6 @@ passes_lang_item_on_incorrect_target = `{$name}` language item must be applied to a {$expected_target} .label = attribute should be applied to a {$expected_target}, not a {$actual_target} -passes_layout = - layout error: {$layout_error} passes_layout_abi = abi: {$abi} passes_layout_align = diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 616a7ccc7c64f..0c974ef4ca3eb 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -427,6 +427,17 @@ impl FileName { src.hash(&mut hasher); FileName::InlineAsm(hasher.finish()) } + + /// Returns the path suitable for reading from the file system on the local host, + /// if this information exists. + /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that. + pub fn into_local_path(self) -> Option { + match self { + FileName::Real(path) => path.into_local_path(), + FileName::DocTest(path, _) => Some(path), + _ => None, + } + } } /// Represents a span. diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 8fc942dedc9be..1b43c46bda515 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -622,7 +622,7 @@ impl LocalWaker { /// /// [`poll()`]: crate::future::Future::poll #[inline] - #[stable(feature = "futures_api", since = "1.36.0")] + #[unstable(feature = "local_waker", issue = "118959")] pub fn wake(self) { // The actual wakeup call is delegated through a virtual function call // to the implementation which is defined by the executor. @@ -644,7 +644,7 @@ impl LocalWaker { /// the case where an owned `Waker` is available. This method should be preferred to /// calling `waker.clone().wake()`. #[inline] - #[stable(feature = "futures_api", since = "1.36.0")] + #[unstable(feature = "local_waker", issue = "118959")] pub fn wake_by_ref(&self) { // The actual wakeup call is delegated through a virtual function call // to the implementation which is defined by the executor. @@ -664,7 +664,7 @@ impl LocalWaker { /// avoid cloning the waker when they would wake the same task anyway. #[inline] #[must_use] - #[stable(feature = "futures_api", since = "1.36.0")] + #[unstable(feature = "local_waker", issue = "118959")] pub fn will_wake(&self, other: &LocalWaker) -> bool { self.waker == other.waker } @@ -676,7 +676,7 @@ impl LocalWaker { /// Therefore this method is unsafe. #[inline] #[must_use] - #[stable(feature = "futures_api", since = "1.36.0")] + #[unstable(feature = "local_waker", issue = "118959")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { Self { waker } @@ -748,7 +748,18 @@ impl AsRef for Waker { } } -#[stable(feature = "futures_api", since = "1.36.0")] +#[unstable(feature = "local_waker", issue = "118959")] +impl Drop for LocalWaker { + #[inline] + fn drop(&mut self) { + // SAFETY: This is safe because `LocalWaker::from_raw` is the only way + // to initialize `drop` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (self.waker.vtable.drop)(self.waker.data) } + } +} + +#[unstable(feature = "local_waker", issue = "118959")] impl fmt::Debug for LocalWaker { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let vtable_ptr = self.waker.vtable as *const RawWakerVTable; diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index f6f4253a36435..a90139a070ac2 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -8,12 +8,10 @@ use crate::core::builder::{ self, crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step, }; use crate::core::config::TargetSelection; -use crate::utils::cache::Interned; -use crate::INTERNER; use crate::{Compiler, Mode, Subcommand}; use std::path::{Path, PathBuf}; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Std { pub target: TargetSelection, /// Whether to build only a subset of crates. @@ -21,7 +19,7 @@ pub struct Std { /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc - crates: Interned>, + crates: Vec, } /// Returns args for the subcommand itself (not for cargo) @@ -89,7 +87,7 @@ fn cargo_subcommand(kind: Kind) -> &'static str { impl Std { pub fn new(target: TargetSelection) -> Self { - Self { target, crates: INTERNER.intern_list(vec![]) } + Self { target, crates: vec![] } } } @@ -204,7 +202,7 @@ impl Step for Std { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: TargetSelection, /// Whether to build only a subset of crates. @@ -212,7 +210,7 @@ pub struct Rustc { /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`]. /// /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc - crates: Interned>, + crates: Vec, } impl Rustc { @@ -222,7 +220,7 @@ impl Rustc { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Self { target, crates: INTERNER.intern_list(crates) } + Self { target, crates } } } @@ -305,10 +303,10 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { pub target: TargetSelection, - pub backend: Interned, + pub backend: &'static str, } impl Step for CodegenBackend { @@ -321,14 +319,14 @@ impl Step for CodegenBackend { } fn make_run(run: RunConfig<'_>) { - for &backend in &[INTERNER.intern_str("cranelift"), INTERNER.intern_str("gcc")] { + for &backend in &["cranelift", "gcc"] { run.builder.ensure(CodegenBackend { target: run.target, backend }); } } fn run(self, builder: &Builder<'_>) { // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved - if builder.build.config.vendor && &self.backend == "gcc" { + if builder.build.config.vendor && self.backend == "gcc" { println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled."); return; } @@ -552,7 +550,7 @@ fn codegen_backend_stamp( builder: &Builder<'_>, compiler: Compiler, target: TargetSelection, - backend: Interned, + backend: &str, ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 17ca92f25a928..9e103a350e654 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -10,7 +10,6 @@ use std::io::{self, ErrorKind}; use std::path::Path; use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; -use crate::utils::cache::Interned; use crate::utils::helpers::t; use crate::{Build, Compiler, Mode, Subcommand}; @@ -44,10 +43,10 @@ impl Step for CleanAll { macro_rules! clean_crate_tree { ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $( - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { compiler: Compiler, - crates: Interned>, + crates: Vec, } impl Step for $name { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4bf50e19c3fd0..6a2bff5970f36 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -27,7 +27,6 @@ use crate::core::builder::crate_description; use crate::core::builder::Cargo; use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath}; use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::helpers::{ exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date, }; @@ -35,14 +34,14 @@ use crate::LLVM_TOOLS; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; use filetime::FileTime; -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { pub target: TargetSelection, pub compiler: Compiler, /// Whether to build only a subset of crates in the standard library. /// /// This shouldn't be used from other steps; see the comment on [`Rustc`]. - crates: Interned>, + crates: Vec, /// When using download-rustc, we need to use a new build of `std` for running unit tests of Std itself, /// but we need to use the downloaded copy of std for linking to rustdoc. Allow this to be overriden by `builder.ensure` from other steps. force_recompile: bool, @@ -559,13 +558,13 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] struct StdLink { pub compiler: Compiler, pub target_compiler: Compiler, pub target: TargetSelection, /// Not actually used; only present to make sure the cache invalidation is correct. - crates: Interned>, + crates: Vec, /// See [`Std::force_recompile`]. force_recompile: bool, } @@ -612,7 +611,7 @@ impl Step for StdLink { }); let libdir = sysroot.join(lib).join("rustlib").join(target.triple).join("lib"); let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host.triple).join("lib"); - (INTERNER.intern_path(libdir), INTERNER.intern_path(hostdir)) + (libdir, hostdir) } else { let libdir = builder.sysroot_libdir(target_compiler, target); let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); @@ -818,7 +817,7 @@ fn cp_rustc_component_to_ci_sysroot( } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)] pub struct Rustc { pub target: TargetSelection, pub compiler: Compiler, @@ -827,7 +826,7 @@ pub struct Rustc { /// This should only be requested by the user, not used within rustbuild itself. /// Using it within rustbuild can lead to confusing situation where lints are replayed /// in two different steps. - crates: Interned>, + crates: Vec, } impl Rustc { @@ -1220,13 +1219,13 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] struct RustcLink { pub compiler: Compiler, pub target_compiler: Compiler, pub target: TargetSelection, /// Not actually used; only present to make sure the cache invalidation is correct. - crates: Interned>, + crates: Vec, } impl RustcLink { @@ -1261,11 +1260,11 @@ impl Step for RustcLink { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenBackend { pub target: TargetSelection, pub compiler: Compiler, - pub backend: Interned, + pub backend: String, } fn needs_codegen_config(run: &RunConfig<'_>) -> bool { @@ -1284,7 +1283,7 @@ pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_"; fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) { let mut needs_codegen_backend_config = true; - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if path .path .to_str() @@ -1321,7 +1320,7 @@ impl Step for CodegenBackend { return; } - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if backend == "llvm" { continue; // Already built as part of rustc } @@ -1329,7 +1328,7 @@ impl Step for CodegenBackend { run.builder.ensure(CodegenBackend { target: run.target, compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), - backend, + backend: backend.clone(), }); } } @@ -1394,7 +1393,7 @@ impl Step for CodegenBackend { f.display() ); } - let stamp = codegen_backend_stamp(builder, compiler, target, backend); + let stamp = codegen_backend_stamp(builder, compiler, target, &backend); let codegen_backend = codegen_backend.to_str().unwrap(); t!(fs::write(stamp, codegen_backend)); } @@ -1433,7 +1432,7 @@ fn copy_codegen_backends_to_sysroot( continue; // Already built as part of rustc } - let stamp = codegen_backend_stamp(builder, compiler, target, *backend); + let stamp = codegen_backend_stamp(builder, compiler, target, backend); let dylib = t!(fs::read_to_string(&stamp)); let file = Path::new(&dylib); let filename = file.file_name().unwrap().to_str().unwrap(); @@ -1470,7 +1469,7 @@ fn codegen_backend_stamp( builder: &Builder<'_>, compiler: Compiler, target: TargetSelection, - backend: Interned, + backend: &str, ) -> PathBuf { builder .cargo_out(compiler, Mode::Codegen, target) @@ -1508,7 +1507,7 @@ impl Sysroot { } impl Step for Sysroot { - type Output = Interned; + type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() @@ -1520,7 +1519,7 @@ impl Step for Sysroot { /// That is, the sysroot for the stage0 compiler is not what the compiler /// thinks it is by default, but it's the same as the default for stages /// 1-3. - fn run(self, builder: &Builder<'_>) -> Interned { + fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let host_dir = builder.out.join(compiler.host.triple); @@ -1652,7 +1651,7 @@ impl Step for Sysroot { ); } - INTERNER.intern_path(sysroot) + sysroot } } @@ -1735,7 +1734,7 @@ impl Step for Assemble { // to not fail while linking the artifacts. build_compiler.stage = actual_stage; - for &backend in builder.config.codegen_backends(target_compiler.host) { + for backend in builder.config.codegen_backends(target_compiler.host) { if backend == "llvm" { continue; // Already built as part of rustc } @@ -1743,7 +1742,7 @@ impl Step for Assemble { builder.ensure(CodegenBackend { compiler: build_compiler, target: target_compiler.host, - backend, + backend: backend.clone(), }); } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 1090edc9c927e..613c58252d3bd 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -25,7 +25,6 @@ use crate::core::build_steps::llvm; use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel; use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit}; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; @@ -489,8 +488,7 @@ impl Step for Rustc { } // Debugger scripts - builder - .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host }); + builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host }); // Misc license info let cp = |file: &str| { @@ -504,9 +502,9 @@ impl Step for Rustc { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DebuggerScripts { - pub sysroot: Interned, + pub sysroot: PathBuf, pub host: TargetSelection, } @@ -1264,10 +1262,10 @@ impl Step for Miri { } } -#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct CodegenBackend { pub compiler: Compiler, - pub backend: Interned, + pub backend: String, } impl Step for CodegenBackend { @@ -1280,14 +1278,14 @@ impl Step for CodegenBackend { } fn make_run(run: RunConfig<'_>) { - for &backend in run.builder.config.codegen_backends(run.target) { + for backend in run.builder.config.codegen_backends(run.target) { if backend == "llvm" { continue; // Already built as part of rustc } run.builder.ensure(CodegenBackend { compiler: run.builder.compiler(run.builder.top_stage, run.target), - backend, + backend: backend.clone(), }); } } @@ -1304,7 +1302,8 @@ impl Step for CodegenBackend { return None; } - if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) { + if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string()) + { return None; } @@ -1529,7 +1528,7 @@ impl Step for Extended { add_component!("analysis" => Analysis { compiler, target }); add_component!("rustc-codegen-cranelift" => CodegenBackend { compiler: builder.compiler(stage, target), - backend: INTERNER.intern_str("cranelift"), + backend: "cranelift".to_string(), }); let etc = builder.src.join("src/etc/installer"); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index c4235755ba865..c23cd9374a6ba 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -16,7 +16,6 @@ use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool} use crate::core::builder::{self, crate_description}; use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; @@ -59,8 +58,8 @@ macro_rules! book { )? builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str($book_name), - src: INTERNER.intern_path(builder.src.join($path)), + name: $book_name.to_owned(), + src: builder.src.join($path), parent: Some(self), }) } @@ -108,18 +107,18 @@ impl Step for UnstableBook { builder.ensure(UnstableBookGen { target: self.target }); builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str("unstable-book"), - src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")), + name: "unstable-book".to_owned(), + src: builder.md_doc_out(self.target).join("unstable-book"), parent: Some(self), }) } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] struct RustbookSrc { target: TargetSelection, - name: Interned, - src: Interned, + name: String, + src: PathBuf, parent: Option

, } @@ -141,7 +140,7 @@ impl Step for RustbookSrc

{ let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let out = out.join(name); + let out = out.join(&name); let index = out.join("index.html"); let rustbook = builder.tool_exe(Tool::Rustbook); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); @@ -211,8 +210,8 @@ impl Step for TheBook { // build book builder.ensure(RustbookSrc { target, - name: INTERNER.intern_str("book"), - src: INTERNER.intern_path(absolute_path.clone()), + name: "book".to_owned(), + src: absolute_path.clone(), parent: Some(self), }); @@ -220,8 +219,8 @@ impl Step for TheBook { for edition in &["first-edition", "second-edition", "2018-edition"] { builder.ensure(RustbookSrc { target, - name: INTERNER.intern_string(format!("book/{edition}")), - src: INTERNER.intern_path(absolute_path.join(edition)), + name: format!("book/{edition}"), + src: absolute_path.join(edition), // There should only be one book that is marked as the parent for each target, so // treat the other editions as not having a parent. parent: Option::::None, @@ -526,12 +525,12 @@ impl Step for SharedAssets { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Std { pub stage: u32, pub target: TargetSelection, pub format: DocumentationFormat, - crates: Interned>, + crates: Vec, } impl Std { @@ -546,7 +545,7 @@ impl Std { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Std { stage, target, format, crates: INTERNER.intern_list(crates) } + Std { stage, target, format, crates } } } @@ -721,11 +720,11 @@ fn doc_std( builder.cp_r(&out_dir, out); } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustc { pub stage: u32, pub target: TargetSelection, - crates: Interned>, + crates: Vec, } impl Rustc { @@ -735,7 +734,7 @@ impl Rustc { .into_iter() .map(|krate| krate.name.to_string()) .collect(); - Self { stage, target, crates: INTERNER.intern_list(crates) } + Self { stage, target, crates } } } @@ -1194,8 +1193,8 @@ impl Step for RustcBook { // Run rustbook/mdbook to generate the HTML pages. builder.ensure(RustbookSrc { target: self.target, - name: INTERNER.intern_str("rustc"), - src: INTERNER.intern_path(out_base), + name: "rustc".to_owned(), + src: out_base, parent: Some(self), }); } diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 6726671ddd9b3..41920fabaa974 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -13,7 +13,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; use crate::utils::helpers::t; use crate::utils::tarball::GeneratedTarball; -use crate::INTERNER; use crate::{Compiler, Kind}; #[cfg(target_os = "illumos")] @@ -291,7 +290,7 @@ install!((self, builder, _config), RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, { if let Some(tarball) = builder.ensure(dist::CodegenBackend { compiler: self.compiler, - backend: INTERNER.intern_str("cranelift"), + backend: "cranelift".to_string(), }) { install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball); } else { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 4a4497e57db14..659c992d59705 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -26,7 +26,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::flags::get_completion; use crate::core::config::flags::Subcommand; use crate::core::config::TargetSelection; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, @@ -38,9 +37,9 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { - path: Interned, + path: PathBuf, host: TargetSelection, } @@ -58,7 +57,7 @@ impl Step for CrateBootstrap { fn make_run(run: RunConfig<'_>) { for path in run.paths { - let path = INTERNER.intern_path(path.assert_single_path().path.clone()); + let path = path.assert_single_path().path.clone(); run.builder.ensure(CrateBootstrap { host: run.target, path }); } } @@ -623,7 +622,7 @@ impl Step for Miri { // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); - cargo.env("MIRI_HOST_SYSROOT", sysroot); + cargo.env("MIRI_HOST_SYSROOT", &sysroot); cargo.env("MIRI", &miri); if builder.config.locked_deps { // enforce lockfiles @@ -1646,8 +1645,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if suite == "debuginfo" { - builder - .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target }); + builder.ensure(dist::DebuggerScripts { + sysroot: builder.sysroot(compiler).to_path_buf(), + host: target, + }); } // Also provide `rust_test_helpers` for the host. @@ -2378,7 +2379,7 @@ impl Step for RustcGuide { pub struct CrateLibrustc { compiler: Compiler, target: TargetSelection, - crates: Vec>, + crates: Vec, } impl Step for CrateLibrustc { @@ -2394,8 +2395,11 @@ impl Step for CrateLibrustc { let builder = run.builder; let host = run.build_triple(); let compiler = builder.compiler_for(builder.top_stage, host, host); - let crates = - run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect(); + let crates = run + .paths + .iter() + .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) + .collect(); builder.ensure(CrateLibrustc { compiler, target: run.target, crates }); } @@ -2418,7 +2422,7 @@ impl Step for CrateLibrustc { fn run_cargo_test<'a>( cargo: impl Into, libtest_args: &[&str], - crates: &[Interned], + crates: &[String], primary_crate: &str, description: impl Into>, compiler: Compiler, @@ -2449,7 +2453,7 @@ fn run_cargo_test<'a>( fn prepare_cargo_test( cargo: impl Into, libtest_args: &[&str], - crates: &[Interned], + crates: &[String], primary_crate: &str, compiler: Compiler, target: TargetSelection, @@ -2477,7 +2481,7 @@ fn prepare_cargo_test( DocTests::No => { let krate = &builder .crates - .get(&INTERNER.intern_str(primary_crate)) + .get(primary_crate) .unwrap_or_else(|| panic!("missing crate {primary_crate}")); if krate.has_lib { cargo.arg("--lib"); @@ -2487,7 +2491,7 @@ fn prepare_cargo_test( DocTests::Yes => {} } - for &krate in crates { + for krate in crates { cargo.arg("-p").arg(krate); } @@ -2529,7 +2533,7 @@ pub struct Crate { pub compiler: Compiler, pub target: TargetSelection, pub mode: Mode, - pub crates: Vec>, + pub crates: Vec, } impl Step for Crate { @@ -2544,8 +2548,11 @@ impl Step for Crate { let builder = run.builder; let host = run.build_triple(); let compiler = builder.compiler_for(builder.top_stage, host, host); - let crates = - run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect(); + let crates = run + .paths + .iter() + .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) + .collect(); builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates }); } @@ -2707,7 +2714,7 @@ impl Step for CrateRustdoc { run_cargo_test( cargo, &[], - &[INTERNER.intern_str("rustdoc:0.0.0")], + &["rustdoc:0.0.0".to_string()], "rustdoc", "rustdoc", compiler, @@ -2768,7 +2775,7 @@ impl Step for CrateRustdocJsonTypes { run_cargo_test( cargo, libtest_args, - &[INTERNER.intern_str("rustdoc-json-types")], + &["rustdoc-json-types".to_string()], "rustdoc-json-types", "rustdoc-json-types", compiler, @@ -3194,8 +3201,7 @@ impl Step for CodegenCranelift { return; } - if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("cranelift")) - { + if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) { builder.info("cranelift not in rust.codegen-backends. skipping"); return; } @@ -3319,7 +3325,7 @@ impl Step for CodegenGCC { return; } - if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("gcc")) { + if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) { builder.info("gcc not in rust.codegen-backends. skipping"); return; } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 8223a80c93107..4927c83760808 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -19,7 +19,7 @@ use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, s use crate::core::config::flags::{Color, Subcommand}; use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; use crate::prepare_behaviour_dump_dir; -use crate::utils::cache::{Cache, Interned, INTERNER}; +use crate::utils::cache::Cache; use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args}; use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldThreads}; use crate::EXTRA_CHECK_CFGS; @@ -102,7 +102,7 @@ impl RunConfig<'_> { /// Return a list of crate names selected by `run.paths`. #[track_caller] - pub fn cargo_crates_in_set(&self) -> Interned> { + pub fn cargo_crates_in_set(&self) -> Vec { let mut crates = Vec::new(); for krate in &self.paths { let path = krate.assert_single_path(); @@ -111,7 +111,7 @@ impl RunConfig<'_> { }; crates.push(crate_name.to_string()); } - INTERNER.intern_list(crates) + crates } /// Given an `alias` selected by the `Step` and the paths passed on the command line, @@ -120,7 +120,7 @@ impl RunConfig<'_> { /// Normally, people will pass *just* `library` if they pass it. /// But it's possible (although strange) to pass something like `library std core`. /// Build all crates anyway, as if they hadn't passed the other args. - pub fn make_run_crates(&self, alias: Alias) -> Interned> { + pub fn make_run_crates(&self, alias: Alias) -> Vec { let has_alias = self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str())); if !has_alias { @@ -133,7 +133,7 @@ impl RunConfig<'_> { }; let crate_names = crates.into_iter().map(|krate| krate.name.to_string()).collect(); - INTERNER.intern_list(crate_names) + crate_names } } @@ -1062,26 +1062,26 @@ impl<'a> Builder<'a> { } } - pub fn sysroot(&self, compiler: Compiler) -> Interned { + pub fn sysroot(&self, compiler: Compiler) -> PathBuf { self.ensure(compile::Sysroot::new(compiler)) } /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> Interned { + pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf { #[derive(Debug, Clone, Hash, PartialEq, Eq)] struct Libdir { compiler: Compiler, target: TargetSelection, } impl Step for Libdir { - type Output = Interned; + type Output = PathBuf; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() } - fn run(self, builder: &Builder<'_>) -> Interned { + fn run(self, builder: &Builder<'_>) -> PathBuf { let lib = builder.sysroot_libdir_relative(self.compiler); let sysroot = builder .sysroot(self.compiler) @@ -1110,7 +1110,7 @@ impl<'a> Builder<'a> { ); } - INTERNER.intern_path(sysroot) + sysroot } } self.ensure(Libdir { compiler, target }) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 2cbebbcf4e2af..6a1dde51603be 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -608,7 +608,7 @@ mod dist { compiler: Compiler { host, stage: 0 }, target: host, mode: Mode::Std, - crates: vec![INTERNER.intern_str("std")], + crates: vec!["std".to_owned()], },] ); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 47b13c26711b6..4766f9d426c30 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -264,7 +264,7 @@ pub struct Config { pub rustc_default_linker: Option, pub rust_optimize_tests: bool, pub rust_dist_src: bool, - pub rust_codegen_backends: Vec>, + pub rust_codegen_backends: Vec, pub rust_verify_llvm_ir: bool, pub rust_thin_lto_import_instr_limit: Option, pub rust_remap_debuginfo: bool, @@ -458,6 +458,8 @@ impl std::str::FromStr for RustcLto { } #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +// N.B.: This type is used everywhere, and the entire codebase relies on it being Copy. +// Making !Copy is highly nontrivial! pub struct TargetSelection { pub triple: Interned, file: Option>, @@ -580,7 +582,7 @@ pub struct Target { pub wasi_root: Option, pub qemu_rootfs: Option, pub no_std: bool, - pub codegen_backends: Option>>, + pub codegen_backends: Option>, } impl Target { @@ -1163,7 +1165,7 @@ impl Config { channel: "dev".to_string(), codegen_tests: true, rust_dist_src: true, - rust_codegen_backends: vec![INTERNER.intern_str("llvm")], + rust_codegen_backends: vec!["llvm".to_owned()], deny_warnings: true, bindir: "bin".into(), dist_include_mingw_linker: true, @@ -1693,7 +1695,7 @@ impl Config { } } - INTERNER.intern_str(s) + s.clone() }).collect(); } @@ -1880,7 +1882,7 @@ impl Config { } } - INTERNER.intern_str(s) + s.clone() }).collect()); } @@ -2267,7 +2269,7 @@ impl Config { } pub fn llvm_enabled(&self, target: TargetSelection) -> bool { - self.codegen_backends(target).contains(&INTERNER.intern_str("llvm")) + self.codegen_backends(target).contains(&"llvm".to_owned()) } pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind { @@ -2286,14 +2288,14 @@ impl Config { self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) } - pub fn codegen_backends(&self, target: TargetSelection) -> &[Interned] { + pub fn codegen_backends(&self, target: TargetSelection) -> &[String] { self.target_config .get(&target) .and_then(|cfg| cfg.codegen_backends.as_deref()) .unwrap_or(&self.rust_codegen_backends) } - pub fn default_codegen_backend(&self, target: TargetSelection) -> Option> { + pub fn default_codegen_backend(&self, target: TargetSelection) -> Option { self.codegen_backends(target).first().cloned() } diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 5802082326a88..08a96407a6917 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -3,7 +3,6 @@ use std::process::Command; use serde_derive::Deserialize; -use crate::utils::cache::INTERNER; use crate::utils::helpers::output; use crate::{t, Build, Crate}; @@ -43,19 +42,19 @@ struct Target { pub fn build(build: &mut Build) { for package in workspace_members(build) { if package.source.is_none() { - let name = INTERNER.intern_string(package.name); + let name = package.name; let mut path = PathBuf::from(package.manifest_path); path.pop(); let deps = package .dependencies .into_iter() .filter(|dep| dep.source.is_none()) - .map(|dep| INTERNER.intern_string(dep.name)) + .map(|dep| dep.name) .collect(); let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib")); - let krate = Crate { name, deps, path, has_lib }; + let krate = Crate { name: name.clone(), deps, path, has_lib }; let relative_path = krate.local_path(build); - build.crates.insert(name, krate); + build.crates.insert(name.clone(), krate); let existing_path = build.crate_paths.insert(relative_path, name); assert!( existing_path.is_none(), diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 1dce8d8ac7184..81acd65d85142 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,6 +15,7 @@ use std::fs; use std::path::PathBuf; use std::process::Command; +use crate::builder::Kind; use crate::core::config::Target; use crate::utils::helpers::output; use crate::Build; @@ -64,6 +65,8 @@ pub fn check(build: &mut Build) { let mut skip_target_sanity = env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true"); + skip_target_sanity |= build.config.cmd.kind() == Kind::Check; + // Skip target sanity checks when we are doing anything with mir-opt tests or Miri let skipped_paths = [OsStr::new("mir-opt"), OsStr::new("miri")]; skip_target_sanity |= build.config.paths.iter().any(|path| { @@ -169,11 +172,7 @@ than building it. continue; } - // Some environments don't want or need these tools, such as when testing Miri. - // FIXME: it would be better to refactor this code to split necessary setup from pure sanity - // checks, and have a regular flag for skipping the latter. Also see - // . - if skip_target_sanity { + if skip_target_sanity && target != &build.build { continue; } @@ -215,11 +214,7 @@ than building it. panic!("All the *-none-* and nvptx* targets are no-std targets") } - // Some environments don't want or need these tools, such as when testing Miri. - // FIXME: it would be better to refactor this code to split necessary setup from pure sanity - // checks, and have a regular flag for skipping the latter. Also see - // . - if skip_target_sanity { + if skip_target_sanity && target != &build.build { continue; } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ab8f3c0d9e497..a252aaac97d74 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -41,7 +41,6 @@ use crate::core::builder::Kind; use crate::core::config::{flags, LldMode}; use crate::core::config::{DryRun, Target}; use crate::core::config::{LlvmLibunwind, TargetSelection}; -use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, OutputMode}; use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir}; @@ -191,8 +190,8 @@ pub struct Build { ranlib: RefCell>, // Miscellaneous // allow bidirectional lookups: both name -> path and path -> name - crates: HashMap, Crate>, - crate_paths: HashMap>, + crates: HashMap, + crate_paths: HashMap, is_sudo: bool, ci_env: CiEnv, delayed_failures: RefCell>, @@ -204,8 +203,8 @@ pub struct Build { #[derive(Debug, Clone)] struct Crate { - name: Interned, - deps: HashSet>, + name: String, + deps: HashSet, path: PathBuf, has_lib: bool, } @@ -829,8 +828,8 @@ impl Build { } /// Output directory for some generated md crate documentation for a target (temporary) - fn md_doc_out(&self, target: TargetSelection) -> Interned { - INTERNER.intern_path(self.out.join(&*target.triple).join("md-doc")) + fn md_doc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("md-doc") } /// Returns `true` if this is an external version of LLVM not managed by bootstrap. @@ -1538,7 +1537,7 @@ impl Build { /// "local" crates (those in the local source tree, not from a registry). fn in_tree_crates(&self, root: &str, target: Option) -> Vec<&Crate> { let mut ret = Vec::new(); - let mut list = vec![INTERNER.intern_str(root)]; + let mut list = vec![root.to_owned()]; let mut visited = HashSet::new(); while let Some(krate) = list.pop() { let krate = self @@ -1564,11 +1563,11 @@ impl Build { && (dep != "rustc_codegen_llvm" || self.config.hosts.iter().any(|host| self.config.llvm_enabled(*host))) { - list.push(*dep); + list.push(dep.clone()); } } } - ret.sort_unstable_by_key(|krate| krate.name); // reproducible order needed for tests + ret.sort_unstable_by_key(|krate| krate.name.clone()); // reproducible order needed for tests ret } diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs index 2b86585a9d3c0..e18dcbb47bea0 100644 --- a/src/bootstrap/src/utils/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -194,17 +194,6 @@ impl Interner { pub fn intern_str(&self, s: &str) -> Interned { self.strs.lock().unwrap().intern_borrow(s) } - pub fn intern_string(&self, s: String) -> Interned { - self.strs.lock().unwrap().intern(s) - } - - pub fn intern_path(&self, s: PathBuf) -> Interned { - self.paths.lock().unwrap().intern(s) - } - - pub fn intern_list(&self, v: Vec) -> Interned> { - self.lists.lock().unwrap().intern(v) - } } pub static INTERNER: Lazy = Lazy::new(Interner::default); diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index f1fae6549de4c..991ad7ae0ae2f 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -81,8 +81,7 @@ LL | let _m = async || { | _______________________- LL | | println!("I'm bored"); LL | | // Some more stuff -LL | | -LL | | // Finally something to await +... | LL | | CustomFutureType | | ^^^^^^^^^^^^^^^^ | | | diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr index 1b5b00a4a83bb..b43e6e30da220 100644 --- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr +++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.stderr @@ -22,8 +22,7 @@ error: found an empty line after an outer attribute. Perhaps you forgot to add a --> tests/ui/empty_line_after_outer_attribute.rs:28:1 | LL | / #[crate_type = "lib"] -LL | | -LL | | +... | LL | | fn with_two_newlines() { assert!(true) } | |_ diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index f15761354f7ab..c6a1d902eaeb9 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -680,7 +680,8 @@ pub fn line_directive<'line>( /// This is generated by collecting directives from ui tests and then extracting their directive /// names. This is **not** an exhaustive list of all possible directives. Instead, this is a /// best-effort approximation for diagnostics. -const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ +const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ + // tidy-alphabetical-start "assembly-output", "aux-build", "aux-crate", @@ -693,6 +694,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "check-stdout", "check-test-line-numbers-match", "compile-flags", + "count", "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", @@ -716,6 +718,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "ignore-compare-mode-polonius", "ignore-cross-compile", "ignore-debug", + "ignore-eabi", "ignore-emscripten", "ignore-endian-big", "ignore-freebsd", @@ -731,14 +734,30 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "ignore-lldb", "ignore-llvm-version", "ignore-loongarch64", + "ignore-macabi", "ignore-macos", + "ignore-mode-assembly", + "ignore-mode-codegen", + "ignore-mode-codegen-units", "ignore-mode-coverage-map", "ignore-mode-coverage-run", + "ignore-mode-debuginfo", + "ignore-mode-incremental", + "ignore-mode-js-doc-test", + "ignore-mode-mir-opt", + "ignore-mode-pretty", + "ignore-mode-run-make", + "ignore-mode-run-pass-valgrind", + "ignore-mode-rustdoc", + "ignore-mode-rustdoc-json", + "ignore-mode-ui", + "ignore-mode-ui-fulldeps", "ignore-msp430", "ignore-msvc", "ignore-musl", "ignore-netbsd", "ignore-nightly", + "ignore-none", "ignore-nto", "ignore-nvptx64", "ignore-openbsd", @@ -750,18 +769,27 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "ignore-spirv", "ignore-stable", "ignore-stage1", + "ignore-stage2", "ignore-test", + "ignore-thumb", "ignore-thumbv8m.base-none-eabi", "ignore-thumbv8m.main-none-eabi", + "ignore-unix", + "ignore-unknown", "ignore-uwp", "ignore-vxworks", + "ignore-wasi", "ignore-wasm", "ignore-wasm32", "ignore-wasm32-bare", + "ignore-wasm64", "ignore-windows", "ignore-windows-gnu", + "ignore-x32", "ignore-x86", + "ignore-x86_64", "ignore-x86_64-apple-darwin", + "ignore-x86_64-unknown-linux-gnu", "incremental", "known-bug", "llvm-cov-flags", @@ -769,9 +797,11 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "min-gdb-version", "min-lldb-version", "min-llvm-version", + "min-system-llvm-version", "needs-asm-support", "needs-dlltool", "needs-dynamic-linking", + "needs-git-hash", "needs-llvm-components", "needs-profiler-support", "needs-relocation-model-pic", @@ -779,6 +809,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "needs-rust-lldb", "needs-sanitizer-address", "needs-sanitizer-cfi", + "needs-sanitizer-dataflow", "needs-sanitizer-hwaddress", "needs-sanitizer-leak", "needs-sanitizer-memory", @@ -801,6 +832,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "only-aarch64", "only-arm", "only-avr", + "only-beta", "only-bpf", "only-cdb", "only-gnu", @@ -818,6 +850,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "only-riscv64", "only-sparc", "only-sparc64", + "only-stable", "only-thumb", "only-wasm32", "only-wasm32-bare", @@ -825,6 +858,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "only-x86", "only-x86_64", "only-x86_64-fortanix-unknown-sgx", + "only-x86_64-pc-windows-gnu", "only-x86_64-pc-windows-msvc", "only-x86_64-unknown-linux-gnu", "pp-exact", @@ -846,6 +880,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[ "unit-test", "unset-exec-env", "unset-rustc-env", + // tidy-alphabetical-end ]; /// The broken-down contents of a line containing a test header directive, @@ -876,6 +911,22 @@ struct HeaderLine<'ln> { directive: &'ln str, } +pub(crate) struct CheckDirectiveResult<'ln> { + is_known_directive: bool, + directive_name: &'ln str, +} + +// Returns `(is_known_directive, directive_name)`. +pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> { + let directive_name = + directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln); + + CheckDirectiveResult { + is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name), + directive_name: directive_ln, + } +} + fn iter_header( mode: Mode, _suite: &str, @@ -915,6 +966,7 @@ fn iter_header( let mut ln = String::new(); let mut line_number = 0; + // Match on error annotations like `//~ERROR`. static REVISION_MAGIC_COMMENT_RE: Lazy = Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap()); @@ -933,9 +985,38 @@ fn iter_header( if ln.starts_with("fn") || ln.starts_with("mod") { return; - // First try to accept `ui_test` style comments - } else if let Some((header_revision, directive)) = line_directive(comment, ln) { - it(HeaderLine { line_number, original_line, header_revision, directive }); + // First try to accept `ui_test` style comments (`//@`) + } else if let Some((header_revision, non_revisioned_directive_line)) = + line_directive(comment, ln) + { + // Perform unknown directive check on Rust files. + if testfile.extension().map(|e| e == "rs").unwrap_or(false) { + let directive_ln = non_revisioned_directive_line.trim(); + + let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln); + + if !is_known_directive { + *poisoned = true; + + eprintln!( + "error: detected unknown compiletest test directive `{}` in {}:{}", + directive_ln, + testfile.display(), + line_number, + ); + + return; + } + } + + it(HeaderLine { + line_number, + original_line, + header_revision, + directive: non_revisioned_directive_line, + }); + // Then we try to check for legacy-style candidates, which are not the magic ~ERROR family + // error annotations. } else if !REVISION_MAGIC_COMMENT_RE.is_match(ln) { let Some((_, rest)) = line_directive("//", ln) else { continue; @@ -949,34 +1030,18 @@ fn iter_header( let rest = rest.trim_start(); - for candidate in DIAGNOSTICS_DIRECTIVE_NAMES.iter() { - if rest.starts_with(candidate) { - let Some(prefix_removed) = rest.strip_prefix(candidate) else { - // We have a comment that's *successfully* parsed as an legacy-style - // directive. We emit an error here to warn the user. - *poisoned = true; - eprintln!( - "error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}", - testfile.display(), - line_number, - line_directive("//", ln), - ); - return; - }; + let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest); - if prefix_removed.starts_with([' ', ':']) { - // We have a comment that's *successfully* parsed as an legacy-style - // directive. We emit an error here to warn the user. - *poisoned = true; - eprintln!( - "error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}", - testfile.display(), - line_number, - line_directive("//", ln), - ); - return; - } - } + if is_known_directive { + *poisoned = true; + eprintln!( + "error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}", + directive_name, + testfile.display(), + line_number, + line_directive("//", ln), + ); + return; } } } diff --git a/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs new file mode 100644 index 0000000000000..fea66a5e07b4d --- /dev/null +++ b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs @@ -0,0 +1,6 @@ +//@ check-pass + +//~ HELP +fn main() {} //~ERROR +//~^ ERROR +//~| ERROR diff --git a/src/tools/compiletest/src/header/test-auxillary/known_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs new file mode 100644 index 0000000000000..99834b14c1ea3 --- /dev/null +++ b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs @@ -0,0 +1,4 @@ +//! ignore-wasm +//@ ignore-wasm +//@ check-pass +// regular comment diff --git a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs new file mode 100644 index 0000000000000..108ca432e1308 --- /dev/null +++ b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs @@ -0,0 +1 @@ +// ignore-wasm diff --git a/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile new file mode 100644 index 0000000000000..4b565e0e6dfd0 --- /dev/null +++ b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile @@ -0,0 +1 @@ +# ignore-owo diff --git a/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs new file mode 100644 index 0000000000000..d440603104304 --- /dev/null +++ b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs @@ -0,0 +1 @@ +//@ needs-headpat diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 815ac3839df82..433f3e8b5559c 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -5,6 +5,8 @@ use std::str::FromStr; use crate::common::{Config, Debugger, Mode}; use crate::header::{parse_normalization_string, EarlyProps, HeadersCache}; +use super::iter_header; + fn make_test_description( config: &Config, name: test::TestName, @@ -612,3 +614,63 @@ fn threads_support() { assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads) } } + +fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) { + let rdr = std::io::Cursor::new(&buf); + iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {}); +} + +#[test] +fn test_unknown_directive_check() { + let mut poisoned = false; + run_path( + &mut poisoned, + Path::new("a.rs"), + include_bytes!("./test-auxillary/unknown_directive.rs"), + ); + assert!(poisoned); +} + +#[test] +fn test_known_legacy_directive_check() { + let mut poisoned = false; + run_path( + &mut poisoned, + Path::new("a.rs"), + include_bytes!("./test-auxillary/known_legacy_directive.rs"), + ); + assert!(poisoned); +} + +#[test] +fn test_known_directive_check_no_error() { + let mut poisoned = false; + run_path( + &mut poisoned, + Path::new("a.rs"), + include_bytes!("./test-auxillary/known_directive.rs"), + ); + assert!(!poisoned); +} + +#[test] +fn test_error_annotation_no_error() { + let mut poisoned = false; + run_path( + &mut poisoned, + Path::new("a.rs"), + include_bytes!("./test-auxillary/error_annotation.rs"), + ); + assert!(!poisoned); +} + +#[test] +fn test_non_rs_unknown_directive_not_checked() { + let mut poisoned = false; + run_path( + &mut poisoned, + Path::new("a.Makefile"), + include_bytes!("./test-auxillary/not_rs.Makefile"), + ); + assert!(!poisoned); +} diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs index 67b745373f019..9803b6eab2db5 100644 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ b/src/tools/tidy/src/fluent_alphabetical.rs @@ -1,6 +1,7 @@ //! Checks that all Flunt files have messages in alphabetical order use crate::walk::{filter_dirs, walk}; +use std::collections::HashMap; use std::{fs::OpenOptions, io::Write, path::Path}; use regex::Regex; @@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool { if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } } -fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) { +fn check_alphabetic( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) { let mut matches = MESSAGE.captures_iter(fluent).peekable(); while let Some(m) = matches.next() { + let name = m.get(1).unwrap(); + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); + if let Some(next) = matches.peek() { - let name = m.get(1).unwrap(); let next = next.get(1).unwrap(); if name.as_str() > next.as_str() { tidy_error!( @@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly", } } -fn sort_messages(fluent: &str) -> String { +fn sort_messages( + filename: &str, + fluent: &str, + bad: &mut bool, + all_defined_msgs: &mut HashMap, +) -> String { let mut chunks = vec![]; let mut cur = String::new(); for line in fluent.lines() { - if MESSAGE.is_match(line) { + if let Some(name) = MESSAGE.find(line) { + if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { + tidy_error!( + bad, + "{filename}: message `{}` is already defined in {}", + name.as_str(), + defined_filename, + ); + } + + all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); chunks.push(std::mem::take(&mut cur)); } + cur += line; cur.push('\n'); } @@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String { } pub fn check(path: &Path, bless: bool, bad: &mut bool) { + let mut all_defined_msgs = HashMap::new(); walk( path, |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), &mut |ent, contents| { if bless { - let sorted = sort_messages(contents); + let sorted = sort_messages( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); if sorted != contents { let mut f = OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap(); f.write(sorted.as_bytes()).unwrap(); } } else { - check_alphabetic(ent.path().to_str().unwrap(), contents, bad); + check_alphabetic( + ent.path().to_str().unwrap(), + contents, + bad, + &mut all_defined_msgs, + ); } }, ); + + crate::fluent_used::check(path, all_defined_msgs, bad); } diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs new file mode 100644 index 0000000000000..b73e79cb38d94 --- /dev/null +++ b/src/tools/tidy/src/fluent_used.rs @@ -0,0 +1,43 @@ +//! Checks that all Fluent messages appear at least twice + +use crate::walk::{filter_dirs, walk}; +use regex::Regex; +use std::collections::HashMap; +use std::path::Path; + +lazy_static::lazy_static! { + static ref WORD: Regex = Regex::new(r"\w+").unwrap(); +} + +fn filter_used_messages( + contents: &str, + msgs_not_appeared_yet: &mut HashMap, + msgs_appeared_only_once: &mut HashMap, +) { + // we don't just check messages never appear in Rust files, + // because messages can be used as parts of other fluent messages in Fluent files, + // so we do checking messages appear only once in all Rust and Fluent files. + let mut matches = WORD.find_iter(contents); + while let Some(name) = matches.next() { + if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { + // if one msg appears for the first time, + // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`. + msgs_appeared_only_once.insert(name, filename); + } else { + // if one msg appears for the second time, + // remove it from `msgs_appeared_only_once`. + msgs_appeared_only_once.remove(name.as_str()); + } + } +} + +pub fn check(path: &Path, mut all_defined_msgs: HashMap, bad: &mut bool) { + let mut msgs_appear_only_once = HashMap::new(); + walk(path, |path, _| filter_dirs(path), &mut |_, contents| { + filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once); + }); + + for (name, filename) in msgs_appear_only_once { + tidy_error!(bad, "{filename}: message `{}` is not used", name,); + } +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 6f3ade0ab58c7..670b7eb2be995 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -65,6 +65,7 @@ pub mod ext_tool_checks; pub mod extdeps; pub mod features; pub mod fluent_alphabetical; +mod fluent_used; pub(crate) mod iter_header; pub mod mir_opt_tests; pub mod pal; diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh index a36ad916bebe3..a7c4ae13ecb38 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh @@ -1,20 +1,20 @@ -#!/bin/sh +#!/bin/bash set -exuo pipefail function build { CRATE=enclave - mkdir -p $WORK_DIR - pushd $WORK_DIR - rm -rf $CRATE - cp -a $TEST_DIR/enclave . + mkdir -p "${WORK_DIR}" + pushd "${WORK_DIR}" + rm -rf "${CRATE}" + cp -a "${TEST_DIR}"/enclave . pushd $CRATE - echo ${WORK_DIR} + echo "${WORK_DIR}" # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features. # These come from the top-level Rust workspace, that this crate is not a # member of, but Cargo tries to load the workspace `Cargo.toml` anyway. env RUSTC_BOOTSTRAP=1 - cargo -v run --target $TARGET + cargo -v run --target "${TARGET}" popd popd } @@ -22,17 +22,18 @@ function build { function check { local func_re="$1" local checks="${TEST_DIR}/$2" - local asm=$(mktemp) + local asm="" local objdump="${LLVM_BIN_DIR}/llvm-objdump" local filecheck="${LLVM_BIN_DIR}/FileCheck" local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave - func="$(${objdump} --syms --demangle ${enclave} | \ + asm=$(mktemp) + func="$(${objdump} --syms --demangle "${enclave}" | \ grep --only-matching -E "[[:blank:]]+${func_re}\$" | \ sed -e 's/^[[:space:]]*//' )" ${objdump} --disassemble-symbols="${func}" --demangle \ - ${enclave} > ${asm} - ${filecheck} --input-file ${asm} ${checks} + "${enclave}" > "${asm}" + ${filecheck} --input-file "${asm}" "${checks}" if [ "${func_re}" != "rust_plus_one_global_asm" ] && [ "${func_re}" != "cmake_plus_one_c_global_asm" ] && @@ -41,7 +42,7 @@ function check { # of `shlq $0x0, (%rsp); lfence; retq` are used instead. # https://www.intel.com/content/www/us/en/developer/articles/technical/ # software-security-guidance/technical-documentation/load-value-injection.html - ${filecheck} --implicit-check-not ret --input-file ${asm} ${checks} + ${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}" fi } diff --git a/tests/rustdoc-ui/lints/check.stderr b/tests/rustdoc-ui/lints/check.stderr index c5ed5d0c3efbe..acdb8128443fd 100644 --- a/tests/rustdoc-ui/lints/check.stderr +++ b/tests/rustdoc-ui/lints/check.stderr @@ -4,7 +4,6 @@ warning: missing documentation for the crate LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | -LL | | ... | LL | | LL | | pub fn foo() {} @@ -39,7 +38,6 @@ warning: missing code example in this documentation LL | / #![feature(rustdoc_missing_doc_code_examples)] LL | | LL | | -LL | | ... | LL | | LL | | pub fn foo() {} diff --git a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr index 4e3bf1d70429d..a66281a188d72 100644 --- a/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr +++ b/tests/ui/borrowck/issue-109271-pass-self-into-closure.stderr @@ -42,8 +42,7 @@ LL | v.call(|(), this: &mut S| { | | LL | | LL | | -LL | | -LL | | _ = v; +... | LL | | v.set(); | | - first borrow occurs due to use of `v` in closure ... | diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs index ac0d4f6e09975..b6bcf7b66173e 100644 --- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs +++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs @@ -2,7 +2,7 @@ // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref -//[nll_beyond]should-fail +//@[nll_beyond]should-fail // This is a corner case that the current implementation is (probably) // treating more conservatively than is necessary. But it also does diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.rs b/tests/ui/codemap_tests/huge_multispan_highlight.rs index 623c59081d0fe..c2bd393589e01 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.rs +++ b/tests/ui/codemap_tests/huge_multispan_highlight.rs @@ -1,5 +1,11 @@ +//@ compile-flags: --error-format=human --color=always +//@ ignore-windows +// Temporary until next release: +//@ ignore-stage2 fn main() { - let x = "foo"; + let _ = match true { + true => ( + // last line shown in multispan header @@ -87,5 +93,148 @@ fn main() { - let y = &mut x; //~ ERROR cannot borrow + + ), + false => " + + + + + + + + + + + + + + + + + + + + + + ", + }; + let _ = match true { + true => ( + + 1 // last line shown in multispan header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), + false => " + + + 1 last line shown in multispan + + + + + + + + + + + + + + + + + + + + ", + }; } diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.stderr b/tests/ui/codemap_tests/huge_multispan_highlight.stderr deleted file mode 100644 index d2923875c94cf..0000000000000 --- a/tests/ui/codemap_tests/huge_multispan_highlight.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/huge_multispan_highlight.rs:90:13 - | -LL | let y = &mut x; - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to be mutable - | -LL | let mut x = "foo"; - | +++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg new file mode 100644 index 0000000000000..403e9961102d5 --- /dev/null +++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg @@ -0,0 +1,116 @@ + + + + + + + error[E0308]: `match` arms have incompatible types + + --> $DIR/huge_multispan_highlight.rs:98:18 + + | + + LL | let _ = match true { + + | ---------- `match` arms have incompatible types + + LL | true => ( + + | _________________- + + LL | | // last line shown in multispan header + + ... | + + LL | | + + LL | | ), + + | |_________- this is found to be of type `()` + + LL | false => " + + | __________________^ + + ... | + + LL | | + + LL | | ", + + | |_________^ expected `()`, found `&str` + + + + error[E0308]: `match` arms have incompatible types + + --> $DIR/huge_multispan_highlight.rs:215:18 + + | + + LL | let _ = match true { + + | ---------- `match` arms have incompatible types + + LL | true => ( + + | _________________- + + LL | | + + LL | | 1 // last line shown in multispan header + + ... | + + LL | | + + LL | | ), + + | |_________- this is found to be of type `{integer}` + + LL | false => " + + | __________________^ + + LL | | + + LL | | + + LL | | 1 last line shown in multispan + + ... | + + LL | | + + LL | | ", + + | |_________^ expected integer, found `&str` + + + + error: aborting due to 2 previous errors + + + + For more information about this error, try `rustc --explain E0308`. + + + + + + diff --git a/tests/ui/include-macros/parent_dir.rs b/tests/ui/include-macros/parent_dir.rs new file mode 100644 index 0000000000000..321baf77025d2 --- /dev/null +++ b/tests/ui/include-macros/parent_dir.rs @@ -0,0 +1,12 @@ +//@ normalize-stderr-test: "`: .*\(os error" -> "`: $$FILE_NOT_FOUND_MSG (os error" + +fn main() { + let _ = include_str!("include-macros/file.txt"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_str!("hello.rs"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_bytes!("../../data.bin"); //~ ERROR couldn't read + //~^HELP different directory + let _ = include_str!("tests/ui/include-macros/file.txt"); //~ ERROR couldn't read + //~^HELP different directory +} diff --git a/tests/ui/include-macros/parent_dir.stderr b/tests/ui/include-macros/parent_dir.stderr new file mode 100644 index 0000000000000..7610360815b7a --- /dev/null +++ b/tests/ui/include-macros/parent_dir.stderr @@ -0,0 +1,50 @@ +error: couldn't read `$DIR/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:4:13 + | +LL | let _ = include_str!("include-macros/file.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("file.txt"); + | ~~~~~~~~~~ + +error: couldn't read `$DIR/hello.rs`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:6:13 + | +LL | let _ = include_str!("hello.rs"); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("../hello.rs"); + | ~~~~~~~~~~~~~ + +error: couldn't read `$DIR/../../data.bin`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:8:13 + | +LL | let _ = include_bytes!("../../data.bin"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_bytes!("data.bin"); + | ~~~~~~~~~~ + +error: couldn't read `$DIR/tests/ui/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2) + --> $DIR/parent_dir.rs:10:13 + | +LL | let _ = include_str!("tests/ui/include-macros/file.txt"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) +help: there is a file with the same name in a different directory + | +LL | let _ = include_str!("file.txt"); + | ~~~~~~~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/macros/derive-in-eager-expansion-hang.stderr b/tests/ui/macros/derive-in-eager-expansion-hang.stderr index e0f6d5b2de009..b61ef2a9babe8 100644 --- a/tests/ui/macros/derive-in-eager-expansion-hang.stderr +++ b/tests/ui/macros/derive-in-eager-expansion-hang.stderr @@ -4,8 +4,7 @@ error: format argument must be a string literal LL | / { LL | | #[derive(Clone)] LL | | struct S; -LL | | -LL | | "" +... | LL | | } | |_____^ ... diff --git a/tests/ui/macros/macros-nonfatal-errors.rs b/tests/ui/macros/macros-nonfatal-errors.rs index 20e6d70500358..65cb899e0941b 100644 --- a/tests/ui/macros/macros-nonfatal-errors.rs +++ b/tests/ui/macros/macros-nonfatal-errors.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG (" +//@ normalize-stderr-test: "`: .*\(" -> "`: $$FILE_NOT_FOUND_MSG (" // test that errors in a (selection) of macros don't kill compilation // immediately, so that we get more errors listed at a time. diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index ca373ea6cd9e4..d02d2399bbadb 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -200,7 +200,7 @@ error: argument must be a string literal LL | include_str!(invalid); | ^^^^^^^ -error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) +error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/macros-nonfatal-errors.rs:113:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); @@ -214,7 +214,7 @@ error: argument must be a string literal LL | include_bytes!(invalid); | ^^^^^^^ -error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) +error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/macros-nonfatal-errors.rs:115:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index e9aa495becdfa..1e2d9240267da 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -202,7 +202,6 @@ LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); | | in this macro invocation LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2); LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); -LL | | ... | | = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr index fd205f4058ae0..1c19afdcdbafa 100644 --- a/tests/ui/privacy/effective_visibilities_invariants.stderr +++ b/tests/ui/privacy/effective_visibilities_invariants.stderr @@ -15,7 +15,6 @@ error: module has missing stability attribute LL | / #![feature(staged_api)] LL | | LL | | pub mod m {} -LL | | ... | LL | | LL | | fn main() {} diff --git a/tests/ui/single-use-lifetime/dedup.rs b/tests/ui/single-use-lifetime/dedup.rs new file mode 100644 index 0000000000000..16b39609a6d34 --- /dev/null +++ b/tests/ui/single-use-lifetime/dedup.rs @@ -0,0 +1,9 @@ +// Check that `unused_lifetimes` lint doesn't duplicate a "parameter is never used" error. +// Fixed in . +// Issue: . + +#![warn(unused_lifetimes)] +struct Foo<'a>; +//~^ ERROR parameter `'a` is never used + +fn main() {} diff --git a/tests/ui/single-use-lifetime/dedup.stderr b/tests/ui/single-use-lifetime/dedup.stderr new file mode 100644 index 0000000000000..6d02cb3c7148e --- /dev/null +++ b/tests/ui/single-use-lifetime/dedup.stderr @@ -0,0 +1,11 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/dedup.rs:6:12 + | +LL | struct Foo<'a>; + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr index dd2737c706d6b..d9d5dd4ece3b1 100644 --- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr @@ -5,25 +5,25 @@ LL | fn define() -> Opaque { | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` | note: previous use here - --> $DIR/normalize-hidden-types.rs:27:9 + --> $DIR/normalize-hidden-types.rs:26:9 | LL | dyn_hoops::<_>(0) | ^^^^^^^^^^^^^^^^^ error: concrete type differs from previous defining opaque type use - --> $DIR/normalize-hidden-types.rs:34:22 + --> $DIR/normalize-hidden-types.rs:33:22 | LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } | ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` | note: previous use here - --> $DIR/normalize-hidden-types.rs:34:31 + --> $DIR/normalize-hidden-types.rs:33:31 | LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } | ^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/normalize-hidden-types.rs:44:25 + --> $DIR/normalize-hidden-types.rs:42:25 | LL | type Opaque = impl Sized; | ---------- the expected opaque type @@ -39,13 +39,13 @@ LL | let _: Opaque = dyn_hoops::(0); = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: concrete type differs from previous defining opaque type use - --> $DIR/normalize-hidden-types.rs:54:25 + --> $DIR/normalize-hidden-types.rs:51:25 | LL | let _: Opaque = dyn_hoops::<_>(0); | ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` | note: previous use here - --> $DIR/normalize-hidden-types.rs:56:9 + --> $DIR/normalize-hidden-types.rs:52:9 | LL | None | ^^^^ diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs index e78e6cf7690e7..d6800694e5133 100644 --- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs @@ -3,7 +3,7 @@ //@ revisions: current next //@ [next] compile-flags: -Znext-solver //@ [next] check-pass -//@ [current]: known-bug: #112691 +//@ [current] known-bug: #112691 #![feature(type_alias_impl_trait)] @@ -23,7 +23,6 @@ mod typeof_1 { use super::*; type Opaque = impl Sized; fn define() -> Opaque { - //[current]~^ ERROR concrete type differs dyn_hoops::<_>(0) } } @@ -32,7 +31,6 @@ mod typeof_2 { use super::*; type Opaque = impl Sized; fn define_1() -> Opaque { dyn_hoops::<_>(0) } - //[current]~^ ERROR concrete type differs fn define_2() -> Opaque { dyn_hoops::(0) } } @@ -42,7 +40,6 @@ mod typeck { fn define() -> Option { let _: Opaque = dyn_hoops::<_>(0); let _: Opaque = dyn_hoops::(0); - //[current]~^ ERROR mismatched types None } } @@ -52,7 +49,6 @@ mod borrowck { type Opaque = impl Sized; fn define() -> Option { let _: Opaque = dyn_hoops::<_>(0); - //[current]~^ ERROR concrete type differs None } } diff --git a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr index 229729a9ba68d..8c23eaea62ebe 100644 --- a/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr +++ b/tests/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr @@ -5,8 +5,7 @@ LL | / match i { LL | | // Add `bool` to the overall `coercion`. LL | | 0 => true, | | ---- this is found to be of type `bool` -LL | | -LL | | // Necessary to cause the ICE: +... | LL | | 1 => true, | | ---- this is found to be of type `bool` ... |