diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 368a23e34290d..3c6ea56799e08 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1380,7 +1380,17 @@ pub fn noop_flat_map_stmt( ) -> SmallVec<[Stmt; 1]> { vis.visit_id(&mut id); vis.visit_span(&mut span); - noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect() + let stmts: SmallVec<_> = noop_flat_map_stmt_kind(kind, vis) + .into_iter() + .map(|kind| Stmt { id, kind, span }) + .collect(); + if stmts.len() > 1 { + panic!( + "cloning statement `NodeId`s is prohibited by default, \ + the visitor should implement custom statement visiting" + ); + } + stmts } pub fn noop_flat_map_stmt_kind( diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 95216f1c3d787..cabe3e43b342c 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -66,7 +66,7 @@ impl<'tcx> DebugContext<'tcx> { rustc_interface::util::version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ); - let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(false).into_owned(); + let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped).into_owned(); let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { Some(path) => { let name = path.to_string_lossy().into_owned(); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 4ef53663ca0d9..6c7c8cbc311f9 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -74,7 +74,7 @@ mod vtable; mod prelude { pub(crate) use std::convert::{TryFrom, TryInto}; - pub(crate) use rustc_span::Span; + pub(crate) use rustc_span::{Span, FileNameDisplayPreference}; pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub(crate) use rustc_middle::bug; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 8ff2f1cc6520f..346c51c5426d8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -35,6 +35,7 @@ use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; +use rustc_span::FileNameDisplayPreference; use rustc_span::{self, SourceFile, SourceFileHash, Span}; use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding}; use rustc_target::abi::{Int, Pointer, F32, F64}; @@ -771,7 +772,13 @@ pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll let hash = Some(&source_file.src_hash); let file_name = Some(source_file.name.prefer_remapped().to_string()); let directory = if source_file.is_real_file() && !source_file.is_imported() { - Some(cx.sess().opts.working_dir.to_string_lossy(false).to_string()) + Some( + cx.sess() + .opts + .working_dir + .to_string_lossy(FileNameDisplayPreference::Remapped) + .to_string(), + ) } else { // If the path comes from an upstream crate we assume it has been made // independent of the compiler's working directory one way or another. @@ -999,7 +1006,7 @@ pub fn compile_unit_metadata( let producer = format!("clang LLVM ({})", rustc_producer); let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); - let work_dir = tcx.sess.opts.working_dir.to_string_lossy(false); + let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped); let flags = "\0"; let output_filenames = tcx.output_filenames(()); let out_dir = &output_filenames.out_directory; diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 2253007ce3027..1eb497460e63c 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -126,7 +126,7 @@ impl AnnotateSnippetEmitterWriter { } // owned: line source, line index, annotations type Owned = (String, usize, Vec); - let filename = primary_lo.file.name.prefer_local(); + let filename = source_map.filename_for_diagnostics(&primary_lo.file.name); let origin = filename.to_string_lossy(); let annotated_files: Vec = annotated_files .into_iter() diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 25777f4133b94..29f352ae58559 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1320,7 +1320,7 @@ impl EmitterWriter { buffer_msg_line_offset, &format!( "{}:{}:{}", - loc.file.name.prefer_local(), + sm.filename_for_diagnostics(&loc.file.name), sm.doctest_offset_line(&loc.file.name, loc.line), loc.col.0 + 1, ), @@ -1334,7 +1334,7 @@ impl EmitterWriter { 0, &format!( "{}:{}:{}: ", - loc.file.name.prefer_local(), + sm.filename_for_diagnostics(&loc.file.name), sm.doctest_offset_line(&loc.file.name, loc.line), loc.col.0 + 1, ), @@ -1362,12 +1362,12 @@ impl EmitterWriter { }; format!( "{}:{}{}", - annotated_file.file.name.prefer_local(), + sm.filename_for_diagnostics(&annotated_file.file.name), sm.doctest_offset_line(&annotated_file.file.name, first_line.line_index), col ) } else { - format!("{}", annotated_file.file.name.prefer_local()) + format!("{}", sm.filename_for_diagnostics(&annotated_file.file.name)) }; buffer.append(buffer_msg_line_offset + 1, &loc, Style::LineAndColumn); for _ in 0..max_line_num_len { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 1b6cd04cca642..dde978cd8c6ce 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -464,7 +464,7 @@ impl DiagnosticSpan { }); DiagnosticSpan { - file_name: start.file.name.prefer_local().to_string(), + file_name: je.sm.filename_for_diagnostics(&start.file.name).to_string(), byte_start: start.file.original_relative_byte_pos(span.lo()).0, byte_end: start.file.original_relative_byte_pos(span.hi()).0, line_start: start.line, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index a4b7bdd9155cc..1fd48309af976 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1113,7 +1113,7 @@ impl<'a> ExtCtxt<'a> { span, &format!( "cannot resolve relative path in non-file source `{}`", - other.prefer_local() + self.source_map().filename_for_diagnostics(&other) ), )); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 16e086e32f63d..3ccf9f446a63e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -12,7 +12,7 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; -use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs, MacCall}; +use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; @@ -559,7 +559,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = orig_force_mode; // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); + let mut placeholder_expander = PlaceholderExpander::default(); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { placeholder_expander @@ -1061,13 +1061,51 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr } + fn take_stmt_bang( + &mut self, + stmt: ast::Stmt, + ) -> Result<(bool, MacCall, Vec), ast::Stmt> { + match stmt.kind { + StmtKind::MacCall(mac) => { + let MacCallStmt { mac, style, attrs, .. } = mac.into_inner(); + Ok((style == MacStmtStyle::Semicolon, mac, attrs.into())) + } + StmtKind::Item(ref item) if matches!(item.kind, ItemKind::MacCall(..)) => { + match stmt.kind { + StmtKind::Item(item) => match item.into_inner() { + ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => { + Ok((mac.args.need_semicolon(), mac, attrs)) + } + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + StmtKind::Semi(ref expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => { + match stmt.kind { + StmtKind::Semi(expr) => match expr.into_inner() { + ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => { + Ok((mac.args.need_semicolon(), mac, attrs.into())) + } + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + StmtKind::Local(..) | StmtKind::Empty | StmtKind::Item(..) | StmtKind::Semi(..) => { + Err(stmt) + } + StmtKind::Expr(..) => unreachable!(), + } + } + fn configure(&mut self, node: T) -> Option { self.cfg.configure(node) } // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. - fn check_attributes(&mut self, attrs: &[ast::Attribute], call: &MacCall) { + fn check_attributes(&self, attrs: &[ast::Attribute], call: &MacCall) { let features = self.cx.ecfg.features.unwrap(); let mut attrs = attrs.iter().peekable(); let mut span: Option = None; @@ -1177,11 +1215,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }); } - // This is needed in order to set `lint_node_id` for `let` statements - fn visit_local(&mut self, local: &mut P) { - assign_id!(self, &mut local.id, || noop_visit_local(local, self)); - } - fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { let mut arm = configure!(self, arm); @@ -1299,31 +1332,39 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { let mut stmt = configure!(self, stmt); - // we'll expand attributes on expressions separately - if !stmt.is_expr() { + // We pull macro invocations (both attributes and fn-like macro calls) out of their + // `StmtKind`s and treat them as statement macro invocations, not as items or expressions. + // FIXME: invocations in semicolon-less expressions positions are expanded as expressions, + // changing that requires some compatibility measures. + let mut stmt = if !stmt.is_expr() { if let Some(attr) = self.take_first_attr(&mut stmt) { return self .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts) .make_stmts(); } - } - if let StmtKind::MacCall(mac) = stmt.kind { - let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner(); - self.check_attributes(&attrs, &mac); - let mut placeholder = - self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts(); - - // If this is a macro invocation with a semicolon, then apply that - // semicolon to the final statement produced by expansion. - if style == MacStmtStyle::Semicolon { - if let Some(stmt) = placeholder.pop() { - placeholder.push(stmt.add_trailing_semicolon()); + let span = stmt.span; + match self.take_stmt_bang(stmt) { + Ok((add_semicolon, mac, attrs)) => { + self.check_attributes(&attrs, &mac); + let mut stmts = + self.collect_bang(mac, span, AstFragmentKind::Stmts).make_stmts(); + + // If this is a macro invocation with a semicolon, then apply that + // semicolon to the final statement produced by expansion. + if add_semicolon { + if let Some(stmt) = stmts.pop() { + stmts.push(stmt.add_trailing_semicolon()); + } + } + + return stmts; } + Err(stmt) => stmt, } - - return placeholder; - } + } else { + stmt + }; // The only way that we can end up with a `MacCall` expression statement, // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the @@ -1338,14 +1379,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - // The placeholder expander gives ids to statements, so we avoid folding the id here. - // We don't use `assign_id!` - it will be called when we visit statement's contents - // (e.g. an expression, item, or local) - let ast::Stmt { id, kind, span } = stmt; - let res = noop_flat_map_stmt_kind(kind, self) - .into_iter() - .map(|kind| ast::Stmt { id, kind, span }) - .collect(); + let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)); self.cx.current_expansion.is_trailing_mac = false; res diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 6586ba138fb99..8e78fcbb8dbc1 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -1,4 +1,3 @@ -use crate::base::ExtCtxt; use crate::expand::{AstFragment, AstFragmentKind}; use rustc_ast as ast; @@ -175,17 +174,12 @@ pub fn placeholder( } } -pub struct PlaceholderExpander<'a, 'b> { +#[derive(Default)] +pub struct PlaceholderExpander { expanded_fragments: FxHashMap, - cx: &'a mut ExtCtxt<'b>, - monotonic: bool, } -impl<'a, 'b> PlaceholderExpander<'a, 'b> { - pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { - PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic } - } - +impl PlaceholderExpander { pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); @@ -196,7 +190,7 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } -impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { +impl MutVisitor for PlaceholderExpander { fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { if arm.is_placeholder { self.remove(arm.id).make_arms() @@ -360,15 +354,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { _ => noop_visit_ty(ty, self), } } - - fn visit_block(&mut self, block: &mut P) { - noop_visit_block(block, self); - - for stmt in block.stmts.iter_mut() { - if self.monotonic { - assert_eq!(stmt.id, ast::DUMMY_NODE_ID); - stmt.id = self.cx.resolver.next_node_id(); - } - } - } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d54933841fd4e..32150c7f4c615 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1630,14 +1630,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { (TypeError::Sorts(values), extra) => { let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { (true, ty::Opaque(def_id, _)) => { - let pos = self - .tcx - .sess - .source_map() - .lookup_char_pos(self.tcx.def_span(*def_id).lo()); + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); format!( " (opaque type at <{}:{}:{}>)", - pos.file.name.prefer_local(), + sm.filename_for_diagnostics(&pos.file.name), pos.line, pos.col.to_usize() + 1, ) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f04ac8dd9426f..7a42e8c1037ba 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -461,13 +461,16 @@ trait UnusedDelimLint { let lhs_needs_parens = { let mut innermost = inner; loop { - if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind { - innermost = lhs; - if !classify::expr_requires_semi_to_be_stmt(innermost) { - break true; - } - } else { - break false; + innermost = match &innermost.kind { + ExprKind::Binary(_, lhs, _rhs) => lhs, + ExprKind::Call(fn_, _params) => fn_, + ExprKind::Cast(expr, _ty) => expr, + ExprKind::Type(expr, _ty) => expr, + ExprKind::Index(base, _subscript) => base, + _ => break false, + }; + if !classify::expr_requires_semi_to_be_stmt(innermost) { + break true; } } }; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 346a9e8021731..83f6e79d5fcf6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -411,8 +411,7 @@ impl<'tcx> Body<'tcx> { /// Returns an iterator over all function arguments. #[inline] pub fn args_iter(&self) -> impl Iterator + ExactSizeIterator { - let arg_count = self.arg_count; - (1..arg_count + 1).map(Local::new) + (1..self.arg_count + 1).map(Local::new) } /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all @@ -421,9 +420,7 @@ impl<'tcx> Body<'tcx> { pub fn vars_and_temps_iter( &self, ) -> impl DoubleEndedIterator + ExactSizeIterator { - let arg_count = self.arg_count; - let local_count = self.local_decls.len(); - (arg_count + 1..local_count).map(Local::new) + (self.arg_count + 1..self.local_decls.len()).map(Local::new) } #[inline] diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index bfb3de04c59fb..c6003d87f3ac6 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -272,11 +272,12 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> { write!(f, "inside `{}`", self.instance)?; } if !self.span.is_dummy() { - let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo()); + let sm = tcx.sess.source_map(); + let lo = sm.lookup_char_pos(self.span.lo()); write!( f, " at {}:{}:{}", - lo.file.name.prefer_local(), + sm.filename_for_diagnostics(&lo.file.name), lo.line, lo.col.to_usize() + 1 )?; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 73e05a35277ec..bf76dedd252ca 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -190,7 +190,7 @@ pub fn maybe_file_to_stream( let src = source_file.src.as_ref().unwrap_or_else(|| { sess.span_diagnostic.bug(&format!( "cannot lex `source_file` without source: {}", - source_file.name.prefer_local() + sess.source_map().filename_for_diagnostics(&source_file.name) )); }); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 273fbea358021..cdc1d1cf99f3c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1432,12 +1432,22 @@ impl<'a> Parser<'a> { // the most sense, which is immediately after the last token: // // {foo(bar {}} - // - ^ + // ^ ^ // | | // | help: `)` may belong here // | // unclosed delimiter if let Some(sp) = unmatched.unclosed_span { + let mut primary_span: Vec = + err.span.primary_spans().iter().cloned().collect(); + primary_span.push(sp); + let mut primary_span: MultiSpan = primary_span.into(); + for span_label in err.span.span_labels() { + if let Some(label) = span_label.label { + primary_span.push_span_label(span_label.span, label); + } + } + err.set_span(primary_span); err.span_label(sp, "unclosed delimiter"); } // Backticks should be removed to apply suggestions. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c34fd02e8066d..c4419e995edac 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -33,7 +33,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::PResult; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_span::source_map::{MultiSpan, Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use tracing::debug; @@ -1335,8 +1335,13 @@ crate fn make_unclosed_delims_error( // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `unmatched_braces` only for error recovery in the `Parser`. let found_delim = unmatched.found_delim?; + let span: MultiSpan = if let Some(sp) = unmatched.unclosed_span { + vec![unmatched.found_span, sp].into() + } else { + unmatched.found_span.into() + }; let mut err = sess.span_diagnostic.struct_span_err( - unmatched.found_span, + span, &format!( "mismatched closing delimiter: `{}`", pprust::token_kind_to_string(&token::CloseDelim(found_delim)), diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 10e9bde0d972b..b4cc8b2b4a3ed 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -260,11 +260,12 @@ impl RealFileName { } } - pub fn to_string_lossy(&self, prefer_local: bool) -> Cow<'_, str> { - if prefer_local { - self.local_path_if_available().to_string_lossy() - } else { - self.remapped_path_if_available().to_string_lossy() + pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> { + match display_pref { + FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(), + FileNameDisplayPreference::Remapped => { + self.remapped_path_if_available().to_string_lossy() + } } } } @@ -300,9 +301,15 @@ impl From for FileName { } } +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum FileNameDisplayPreference { + Remapped, + Local, +} + pub struct FileNameDisplay<'a> { inner: &'a FileName, - prefer_local: bool, + display_pref: FileNameDisplayPreference, } impl fmt::Display for FileNameDisplay<'_> { @@ -310,7 +317,7 @@ impl fmt::Display for FileNameDisplay<'_> { use FileName::*; match *self.inner { Real(ref name) => { - write!(fmt, "{}", name.to_string_lossy(self.prefer_local)) + write!(fmt, "{}", name.to_string_lossy(self.display_pref)) } QuoteExpansion(_) => write!(fmt, ""), MacroExpansion(_) => write!(fmt, ""), @@ -328,7 +335,7 @@ impl fmt::Display for FileNameDisplay<'_> { impl FileNameDisplay<'_> { pub fn to_string_lossy(&self) -> Cow<'_, str> { match self.inner { - FileName::Real(ref inner) => inner.to_string_lossy(self.prefer_local), + FileName::Real(ref inner) => inner.to_string_lossy(self.display_pref), _ => Cow::from(format!("{}", self)), } } @@ -352,13 +359,17 @@ impl FileName { } pub fn prefer_remapped(&self) -> FileNameDisplay<'_> { - FileNameDisplay { inner: self, prefer_local: false } + FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped } } // This may include transient local filesystem information. // Must not be embedded in build outputs. pub fn prefer_local(&self) -> FileNameDisplay<'_> { - FileNameDisplay { inner: self, prefer_local: true } + FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local } + } + + pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> { + FileNameDisplay { inner: self, display_pref } } pub fn macro_expansion_source_code(src: &str) -> FileName { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index c2de5ed2f5838..9b8c8594ee843 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -427,7 +427,7 @@ impl SourceMap { } } - fn span_to_string(&self, sp: Span, prefer_local: bool) -> String { + fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String { if self.files.borrow().source_files.is_empty() || sp.is_dummy() { return "no-location".to_string(); } @@ -436,7 +436,7 @@ impl SourceMap { let hi = self.lookup_char_pos(sp.hi()); format!( "{}:{}:{}: {}:{}", - if prefer_local { lo.file.name.prefer_local() } else { lo.file.name.prefer_remapped() }, + lo.file.name.display(filename_display_pref), lo.line, lo.col.to_usize() + 1, hi.line, @@ -446,20 +446,24 @@ impl SourceMap { /// Format the span location suitable for embedding in build artifacts pub fn span_to_embeddable_string(&self, sp: Span) -> String { - self.span_to_string(sp, false) + self.span_to_string(sp, FileNameDisplayPreference::Remapped) } /// Format the span location to be printed in diagnostics. Must not be emitted /// to build artifacts as this may leak local file paths. Use span_to_embeddable_string /// for string suitable for embedding. pub fn span_to_diagnostic_string(&self, sp: Span) -> String { - self.span_to_string(sp, true) + self.span_to_string(sp, self.path_mapping.filename_display_for_diagnostics) } pub fn span_to_filename(&self, sp: Span) -> FileName { self.lookup_char_pos(sp.lo()).file.name.clone() } + pub fn filename_for_diagnostics<'a>(&self, filename: &'a FileName) -> FileNameDisplay<'a> { + filename.display(self.path_mapping.filename_display_for_diagnostics) + } + pub fn is_multiline(&self, sp: Span) -> bool { let lo = self.lookup_source_file_idx(sp.lo()); let hi = self.lookup_source_file_idx(sp.hi()); @@ -1013,15 +1017,22 @@ impl SourceMap { #[derive(Clone)] pub struct FilePathMapping { mapping: Vec<(PathBuf, PathBuf)>, + filename_display_for_diagnostics: FileNameDisplayPreference, } impl FilePathMapping { pub fn empty() -> FilePathMapping { - FilePathMapping { mapping: vec![] } + FilePathMapping::new(Vec::new()) } pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping { - FilePathMapping { mapping } + let filename_display_for_diagnostics = if mapping.is_empty() { + FileNameDisplayPreference::Local + } else { + FileNameDisplayPreference::Remapped + }; + + FilePathMapping { mapping, filename_display_for_diagnostics } } /// Applies any path prefix substitution as defined by the mapping. diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index a25d0f8064404..702f69a9fcf0b 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -47,7 +47,7 @@ use rustc_middle::ty::{ }; use rustc_session::lint; use rustc_span::sym; -use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol, DUMMY_SP}; +use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_data_structures::stable_map::FxHashMap; @@ -680,15 +680,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { migrated_variables_concat ); - // If the body was entirely expanded from a macro - // invocation, i.e. the body is not contained inside the - // closure span, then we walk up the expansion until we - // find the span before the expansion. - let closure_body_span = self.tcx.hir().span(body_id.hir_id) - .find_ancestor_inside(closure_span) - .unwrap_or(DUMMY_SP); + let mut closure_body_span = { + // If the body was entirely expanded from a macro + // invocation, i.e. the body is not contained inside the + // closure span, then we walk up the expansion until we + // find the span before the expansion. + let s = self.tcx.hir().span(body_id.hir_id); + s.find_ancestor_inside(closure_span).unwrap_or(s) + }; + + if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) { + if s.starts_with('$') { + // Looks like a macro fragment. Try to find the real block. + if let Some(hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::Block(block, ..), .. + })) = self.tcx.hir().find(body_id.hir_id) { + // If the body is a block (with `{..}`), we use the span of that block. + // E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`. + // Since we know it's a block, we know we can insert the `let _ = ..` without + // breaking the macro syntax. + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(block.span) { + closure_body_span = block.span; + s = snippet; + } + } + } - if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) { let mut lines = s.lines(); let line1 = lines.next().unwrap_or_default(); diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 7aa24ff4afaee..9d45c5082db43 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -300,7 +300,10 @@ impl LinkedList { let tail = self.tail.take(); let len = mem::replace(&mut self.len, 0); if let Some(head) = head { - let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() }); + // SAFETY: In a LinkedList, either both the head and tail are None because + // the list is empty, or both head and tail are Some because the list is populated. + // Since we have verified the head is Some, we are sure the tail is Some too. + let tail = unsafe { tail.unwrap_unchecked() }; Some((head, tail, len)) } else { None diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 3c638e655dc91..70cccd31b92de 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -459,11 +459,8 @@ where debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX)); debug_assert!(N <= iter.size_hint().0); - match collect_into_array(iter) { - Some(array) => array, - // SAFETY: covered by the function contract. - None => unsafe { crate::hint::unreachable_unchecked() }, - } + // SAFETY: covered by the function contract. + unsafe { collect_into_array(iter).unwrap_unchecked() } } /// Pulls `N` items from `iter` and returns them as an array. If the iterator diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 1d75ac3d254bd..aff789f2afa14 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -402,7 +402,7 @@ impl<'a> Arguments<'a> { if self.args.is_empty() { pieces_length - } else if self.pieces[0] == "" && pieces_length < 16 { + } else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 { // If the format string starts with an argument, // don't preallocate anything, unless length // of pieces is significant. @@ -1163,7 +1163,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { } // SAFETY: arg and args.args come from the same Arguments, // which guarantees the indexes are always within bounds. - unsafe { run(&mut formatter, arg, &args.args) }?; + unsafe { run(&mut formatter, arg, args.args) }?; idx += 1; } } @@ -1409,7 +1409,7 @@ impl<'a> Formatter<'a> { // we know that it can't panic. Use `get` + `unwrap_or` to avoid // `unsafe` and otherwise don't emit any panic-related code // here. - s.get(..i).unwrap_or(&s) + s.get(..i).unwrap_or(s) } else { &s } @@ -1421,16 +1421,21 @@ impl<'a> Formatter<'a> { // If we're under the maximum length, and there's no minimum length // requirements, then we can just emit the string None => self.buf.write_str(s), - // If we're under the maximum width, check if we're over the minimum - // width, if so it's as easy as just emitting the string. - Some(width) if s.chars().count() >= width => self.buf.write_str(s), - // If we're under both the maximum and the minimum width, then fill - // up the minimum width with the specified string + some alignment. Some(width) => { - let align = rt::v1::Alignment::Left; - let post_padding = self.padding(width - s.chars().count(), align)?; - self.buf.write_str(s)?; - post_padding.write(self.buf) + let chars_count = s.chars().count(); + // If we're under the maximum width, check if we're over the minimum + // width, if so it's as easy as just emitting the string. + if chars_count >= width { + self.buf.write_str(s) + } + // If we're under both the maximum and the minimum width, then fill + // up the minimum width with the specified string + some alignment. + else { + let align = rt::v1::Alignment::Left; + let post_padding = self.padding(width - chars_count, align)?; + self.buf.write_str(s)?; + post_padding.write(self.buf) + } } } } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 47865240f6a6f..9d5e03dd0de79 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1198,11 +1198,8 @@ impl Option { pub fn insert(&mut self, value: T) -> &mut T { *self = Some(value); - match self { - Some(v) => v, - // SAFETY: the code above just filled the option - None => unsafe { hint::unreachable_unchecked() }, - } + // SAFETY: the code above just filled the option + unsafe { self.as_mut().unwrap_unchecked() } } /// Inserts `value` into the option if it is [`None`], then diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed new file mode 100644 index 0000000000000..f91454aa2111e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed @@ -0,0 +1,25 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_compatibility)] + +macro_rules! m { + (@ $body:expr) => {{ + let f = || $body; + //~^ WARNING: drop order + f(); + }}; + ($body:block) => {{ + m!(@ $body); + }}; +} + +fn main() { + let a = (1.to_string(), 2.to_string()); + m!({ + let _ = &a; + //~^ HELP: add a dummy + let x = a.0; + println!("{}", x); + }); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs new file mode 100644 index 0000000000000..5a1026d043319 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs @@ -0,0 +1,24 @@ +// run-rustfix +// edition:2018 +// check-pass +#![warn(rust_2021_compatibility)] + +macro_rules! m { + (@ $body:expr) => {{ + let f = || $body; + //~^ WARNING: drop order + f(); + }}; + ($body:block) => {{ + m!(@ $body); + }}; +} + +fn main() { + let a = (1.to_string(), 2.to_string()); + m!({ + //~^ HELP: add a dummy + let x = a.0; + println!("{}", x); + }); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr new file mode 100644 index 0000000000000..e6e5598f6d2a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -0,0 +1,37 @@ +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/closure-body-macro-fragment.rs:8:17 + | +LL | let f = || $body; + | _________________^ +LL | | +LL | | f(); +LL | | }}; + | | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure +LL | | ($body:block) => {{ +LL | | m!(@ $body); + | |__________________^ +... +LL | / m!({ +LL | | +LL | | let x = a.0; + | | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` +LL | | println!("{}", x); +LL | | }); + | |_______- in this macro invocation + | +note: the lint level is defined here + --> $DIR/closure-body-macro-fragment.rs:4:9 + | +LL | #![warn(rust_2021_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]` + = note: for more information, see + = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add a dummy let to cause `a` to be fully captured + | +LL ~ m!({ +LL + let _ = &a; + | + +warning: 1 warning emitted + diff --git a/src/test/ui/issues/issue-83190.rs b/src/test/ui/issues/issue-83190.rs new file mode 100644 index 0000000000000..da931c3edaf6f --- /dev/null +++ b/src/test/ui/issues/issue-83190.rs @@ -0,0 +1,49 @@ +// check-pass + +// Regression test for issue #83190, triggering an ICE in borrowck. + +pub trait Any {} +impl Any for T {} + +pub trait StreamOnce { + type Range; +} + +pub trait Parser: Sized { + type Output; + type PartialState; + fn map(self) -> Map { + todo!() + } +} + +pub struct Map

(P); +impl> Parser for Map

{ + type Output = (); + type PartialState = P::PartialState; +} + +struct TakeWhile1(Input); +impl Parser for TakeWhile1 { + type Output = I::Range; + type PartialState = (); +} +impl TakeWhile1 { + fn new() -> Self { + todo!() + } +} + +impl> Parser for (A,) { + type Output = (); + type PartialState = Map; +} + +pub fn metric_stream_parser<'a, I>() -> impl Parser +where + I: StreamOnce, +{ + (TakeWhile1::new(),).map() +} + +fn main() {} diff --git a/src/test/ui/lint/unused/issue-88519-unused-paren.rs b/src/test/ui/lint/unused/issue-88519-unused-paren.rs new file mode 100644 index 0000000000000..be02fcd3f00c7 --- /dev/null +++ b/src/test/ui/lint/unused/issue-88519-unused-paren.rs @@ -0,0 +1,94 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/88519 +#![deny(unused_parens)] +#![feature(type_ascription)] + +// binary ops are tested in issue-71290-unused-paren-binop.rs + +mod call { + fn noop() -> u8 { 0 } + fn outside() -> u8 { + ({ noop })() + } + fn inside() -> u8 { + ({ noop }()) + } + fn outside_match() -> u8 { + (match noop { x => x })() + } + fn inside_match() -> u8 { + (match noop { x => x }()) + } + fn outside_if() -> u8 { + (if false { noop } else { noop })() + } + fn inside_if() -> u8 { + (if false { noop } else { noop }()) + } +} + +mod casts { + fn outside() -> u8 { + ({ 0 }) as u8 + } + fn inside() -> u8 { + ({ 0 } as u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }) as u8 + } + fn inside_match() -> u8 { + (match 0 { x => x } as u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }) as u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 } as u8) + } +} + +mod typeascription { + fn outside() -> u8 { + ({ 0 }): u8 + } + fn inside() -> u8 { + ({ 0 }: u8) + } + fn outside_match() -> u8 { + (match 0 { x => x }): u8 + } + fn inside_match() -> u8 { + (match 0 { x => x }: u8) + } + fn outside_if() -> u8 { + (if false { 0 } else { 0 }): u8 + } + fn inside_if() -> u8 { + (if false { 0 } else { 0 }: u8) + } +} + +mod index { + fn outside(x: &[u8]) -> u8 { + ({ x })[0] + } + fn inside(x: &[u8]) -> u8 { + ({ x }[0]) + } + fn outside_match(x: &[u8]) -> u8 { + (match x { x => x })[0] + } + fn inside_match(x: &[u8]) -> u8 { + (match x { x => x }[0]) + } + fn outside_if(x: &[u8]) -> u8 { + (if false { x } else { x })[0] + } + fn inside_if(x: &[u8]) -> u8 { + (if false { x } else { x }[0]) + } +} + +fn main() {} diff --git a/src/test/ui/macros/issue-87877.rs b/src/test/ui/macros/issue-87877.rs new file mode 100644 index 0000000000000..a40e2c5f9705a --- /dev/null +++ b/src/test/ui/macros/issue-87877.rs @@ -0,0 +1,25 @@ +// check-pass + +macro_rules! two_items { + () => { + extern "C" {} + extern "C" {} + }; +} + +macro_rules! single_expr_funneler { + ($expr:expr) => { + $expr; // note the semicolon, it changes the statement kind during parsing + }; +} + +macro_rules! single_item_funneler { + ($item:item) => { + $item + }; +} + +fn main() { + single_expr_funneler! { two_items! {} } + single_item_funneler! { two_items! {} } +} diff --git a/src/test/ui/parser/issue-10636-1.stderr b/src/test/ui/parser/issue-10636-1.stderr index ff90cb97096f7..1e6294ebe1691 100644 --- a/src/test/ui/parser/issue-10636-1.stderr +++ b/src/test/ui/parser/issue-10636-1.stderr @@ -1,8 +1,8 @@ error: mismatched closing delimiter: `)` - --> $DIR/issue-10636-1.rs:4:1 + --> $DIR/issue-10636-1.rs:1:12 | LL | struct Obj { - | - unclosed delimiter + | ^ unclosed delimiter ... LL | ) | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/issue-10636-2.stderr b/src/test/ui/parser/issue-10636-2.stderr index 5b9a9b7f06c39..d4f2da9e3ab6f 100644 --- a/src/test/ui/parser/issue-10636-2.stderr +++ b/src/test/ui/parser/issue-10636-2.stderr @@ -1,8 +1,8 @@ error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` - --> $DIR/issue-10636-2.rs:5:25 + --> $DIR/issue-10636-2.rs:5:15 | LL | option.map(|some| 42; - | - ^ help: `)` may belong here + | ^ ^ help: `)` may belong here | | | unclosed delimiter diff --git a/src/test/ui/parser/issue-58856-1.stderr b/src/test/ui/parser/issue-58856-1.stderr index f1abb40ed7a73..2afb26d175834 100644 --- a/src/test/ui/parser/issue-58856-1.stderr +++ b/src/test/ui/parser/issue-58856-1.stderr @@ -1,8 +1,8 @@ error: expected one of `)`, `,`, or `:`, found `>` - --> $DIR/issue-58856-1.rs:3:14 + --> $DIR/issue-58856-1.rs:3:9 | LL | fn b(self> - | - ^ help: `)` may belong here + | ^ ^ help: `)` may belong here | | | unclosed delimiter diff --git a/src/test/ui/parser/issue-58856-2.stderr b/src/test/ui/parser/issue-58856-2.stderr index 303b5eacc3296..627dd389059cd 100644 --- a/src/test/ui/parser/issue-58856-2.stderr +++ b/src/test/ui/parser/issue-58856-2.stderr @@ -1,8 +1,8 @@ error: expected one of `)` or `,`, found `->` - --> $DIR/issue-58856-2.rs:6:26 + --> $DIR/issue-58856-2.rs:6:19 | LL | fn how_are_you(&self -> Empty { - | - -^^ + | ^ -^^ | | | | | help: `)` may belong here | unclosed delimiter diff --git a/src/test/ui/parser/issue-60075.stderr b/src/test/ui/parser/issue-60075.stderr index e3b7f4ad420e8..210ef700cd4bc 100644 --- a/src/test/ui/parser/issue-60075.stderr +++ b/src/test/ui/parser/issue-60075.stderr @@ -17,10 +17,10 @@ LL | } | - item list ends here error: mismatched closing delimiter: `)` - --> $DIR/issue-60075.rs:6:10 + --> $DIR/issue-60075.rs:4:31 | LL | fn qux() -> Option { - | - unclosed delimiter + | ^ unclosed delimiter LL | let _ = if true { LL | }); | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr index 3065d642fe105..51d835e732988 100644 --- a/src/test/ui/parser/issue-62973.stderr +++ b/src/test/ui/parser/issue-62973.stderr @@ -21,10 +21,10 @@ LL | | ^ error: expected one of `,` or `}`, found `{` - --> $DIR/issue-62973.rs:6:25 + --> $DIR/issue-62973.rs:6:8 | LL | fn p() { match s { v, E { [) {) } - | - - -^ expected one of `,` or `}` + | ^ - -^ expected one of `,` or `}` | | | | | | | help: `}` may belong here | | while parsing this struct @@ -56,18 +56,18 @@ LL | | ^ expected one of `.`, `?`, `{`, or an operator error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:28 + --> $DIR/issue-62973.rs:6:27 | LL | fn p() { match s { v, E { [) {) } - | -^ mismatched closing delimiter + | ^^ mismatched closing delimiter | | | unclosed delimiter error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:31 + --> $DIR/issue-62973.rs:6:30 | LL | fn p() { match s { v, E { [) {) } - | -^ mismatched closing delimiter + | ^^ mismatched closing delimiter | | | unclosed delimiter diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issue-63116.stderr index 4766dfafea1c9..cfdd99d1434ae 100644 --- a/src/test/ui/parser/issue-63116.stderr +++ b/src/test/ui/parser/issue-63116.stderr @@ -13,10 +13,10 @@ LL | impl W $DIR/issue-63116.rs:3:16 + --> $DIR/issue-63116.rs:3:14 | LL | impl W $DIR/issue-66357-unexpected-unreachable.rs:12:14 + --> $DIR/issue-66357-unexpected-unreachable.rs:12:13 | LL | fn f() { |[](* } - | -^ help: `)` may belong here + | ^^ help: `)` may belong here | | | unclosed delimiter diff --git a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr index f20ec75535354..34f1397ce1d5b 100644 --- a/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr +++ b/src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr @@ -1,107 +1,107 @@ error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 | LL | V = [PhantomData; { [ () ].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 | LL | V = [Vec::new; { [].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 | LL | V = [Vec::new; { [0].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 | LL | V = [PhantomData; { [ () ].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 | LL | V = [Vec::new; { [].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 | LL | V = [Vec::new; { [0].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 | LL | V = [PhantomData; { [ () ].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 | LL | V = [Vec::new; { [].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 | LL | V = [Vec::new; { [0].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27 | LL | V = [PhantomData; { [ () ].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24 | LL | V = [Vec::new; { [].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this error: mismatched closing delimiter: `]` - --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36 + --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24 | LL | V = [Vec::new; { [0].len() ].len() as isize, - | - - ^ mismatched closing delimiter + | - ^ ^ mismatched closing delimiter | | | | | unclosed delimiter | closing delimiter possibly meant for this diff --git a/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr b/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr index 93c5ab383d488..077d318004896 100644 --- a/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr +++ b/src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr @@ -1,8 +1,8 @@ error: mismatched closing delimiter: `)` - --> $DIR/macro-mismatched-delim-brace-paren.rs:6:5 + --> $DIR/macro-mismatched-delim-brace-paren.rs:4:10 | LL | foo! { - | - unclosed delimiter + | ^ unclosed delimiter LL | bar, "baz", 1, 2.0 LL | ) | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr index 424c7a60c196f..967a3e6fdc11b 100644 --- a/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr +++ b/src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr @@ -10,10 +10,10 @@ LL | } | ^ unexpected closing delimiter error: mismatched closing delimiter: `}` - --> $DIR/macro-mismatched-delim-paren-brace.rs:4:5 + --> $DIR/macro-mismatched-delim-paren-brace.rs:2:10 | LL | foo! ( - | - unclosed delimiter + | ^ unclosed delimiter LL | bar, "baz", 1, 2.0 LL | } | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/parser-recovery-2.stderr b/src/test/ui/parser/parser-recovery-2.stderr index cd3da4c71f0b5..0980d033fe73a 100644 --- a/src/test/ui/parser/parser-recovery-2.stderr +++ b/src/test/ui/parser/parser-recovery-2.stderr @@ -5,10 +5,10 @@ LL | let x = y.; | ^ error: mismatched closing delimiter: `)` - --> $DIR/parser-recovery-2.rs:6:5 + --> $DIR/parser-recovery-2.rs:4:14 | LL | fn bar() { - | - unclosed delimiter + | ^ unclosed delimiter LL | let x = foo(); LL | ) | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr index 00861a5a3d49a..1366ef1bba8bf 100644 --- a/src/test/ui/parser/unclosed-delimiter-in-dep.stderr +++ b/src/test/ui/parser/unclosed-delimiter-in-dep.stderr @@ -1,10 +1,10 @@ error: mismatched closing delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:7:1 + --> $DIR/unclosed_delim_mod.rs:5:7 | LL | pub fn new() -> Result { | - closing delimiter possibly meant for this LL | Ok(Value { - | - unclosed delimiter + | ^ unclosed delimiter LL | } LL | } | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/unclosed_delim_mod.stderr b/src/test/ui/parser/unclosed_delim_mod.stderr index 9c16707212367..a46d020b9672e 100644 --- a/src/test/ui/parser/unclosed_delim_mod.stderr +++ b/src/test/ui/parser/unclosed_delim_mod.stderr @@ -1,10 +1,10 @@ error: mismatched closing delimiter: `}` - --> $DIR/unclosed_delim_mod.rs:7:1 + --> $DIR/unclosed_delim_mod.rs:5:7 | LL | pub fn new() -> Result { | - closing delimiter possibly meant for this LL | Ok(Value { - | - unclosed delimiter + | ^ unclosed delimiter LL | } LL | } | ^ mismatched closing delimiter diff --git a/src/test/ui/parser/use-unclosed-brace.stderr b/src/test/ui/parser/use-unclosed-brace.stderr index d29a68f821481..438fe9c47eac1 100644 --- a/src/test/ui/parser/use-unclosed-brace.stderr +++ b/src/test/ui/parser/use-unclosed-brace.stderr @@ -8,10 +8,10 @@ LL | fn main() {} | ^ error: expected one of `,`, `::`, `as`, or `}`, found `;` - --> $DIR/use-unclosed-brace.rs:4:19 + --> $DIR/use-unclosed-brace.rs:4:10 | LL | use foo::{bar, baz; - | - ^ + | ^ ^ | | | | | expected one of `,`, `::`, `as`, or `}` | | help: `}` may belong here diff --git a/src/test/ui/remap-path-prefix.rs b/src/test/ui/remap-path-prefix.rs new file mode 100644 index 0000000000000..2eef970997708 --- /dev/null +++ b/src/test/ui/remap-path-prefix.rs @@ -0,0 +1,9 @@ +// compile-flags: --remap-path-prefix={{src-base}}=remapped + +fn main() { + // We cannot actually put an ERROR marker here because + // the file name in the error message is not what the + // test framework expects (since the filename gets remapped). + // We still test the expected error in the stderr file. + ferris +} diff --git a/src/test/ui/remap-path-prefix.stderr b/src/test/ui/remap-path-prefix.stderr new file mode 100644 index 0000000000000..ad6a35d1256cd --- /dev/null +++ b/src/test/ui/remap-path-prefix.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `ferris` in this scope + --> remapped/remap-path-prefix.rs:8:5 + | +LL | ferris + | ^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr index 4014af2f41b61..cca9f2dc88ca0 100644 --- a/src/test/ui/resolve/token-error-correct-2.stderr +++ b/src/test/ui/resolve/token-error-correct-2.stderr @@ -1,8 +1,8 @@ error: mismatched closing delimiter: `)` - --> $DIR/token-error-correct-2.rs:6:5 + --> $DIR/token-error-correct-2.rs:4:12 | LL | if foo { - | - unclosed delimiter + | ^ unclosed delimiter LL | LL | ) | ^ mismatched closing delimiter diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 31087e394adfe..77c87c78466b1 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -1,8 +1,8 @@ error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` - --> $DIR/token-error-correct-3.rs:13:35 + --> $DIR/token-error-correct-3.rs:13:21 | LL | callback(path.as_ref(); - | - ^ help: `)` may belong here + | ^ ^ help: `)` may belong here | | | unclosed delimiter diff --git a/src/test/ui/resolve/token-error-correct-4.stderr b/src/test/ui/resolve/token-error-correct-4.stderr index 64aff54ba7311..81e5a13369159 100644 --- a/src/test/ui/resolve/token-error-correct-4.stderr +++ b/src/test/ui/resolve/token-error-correct-4.stderr @@ -1,8 +1,8 @@ error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;` - --> $DIR/token-error-correct-4.rs:9:21 + --> $DIR/token-error-correct-4.rs:9:12 | LL | setsuna(kazusa(); - | - ^ help: `)` may belong here + | ^ ^ help: `)` may belong here | | | unclosed delimiter diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index bf300ecd78173..ca0c4c18ad4ba 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -1,10 +1,10 @@ error: mismatched closing delimiter: `}` - --> $DIR/token-error-correct.rs:6:1 + --> $DIR/token-error-correct.rs:4:12 | LL | fn main() { | - closing delimiter possibly meant for this LL | foo(bar(; - | - unclosed delimiter + | ^ unclosed delimiter LL | LL | } | ^ mismatched closing delimiter diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index a371f8bbd3cb4..39f7ade3f81f6 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -47,11 +47,8 @@ pub struct MacroRefData { impl MacroRefData { pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self { - let mut path = cx - .sess() - .source_map() - .span_to_filename(callee) - .prefer_local() + let sm = cx.sess().source_map(); + let mut path = sm.filename_for_diagnostics(&sm.span_to_filename(callee)) .to_string(); // std lib paths are <::std::module::file type>