diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5489b1bc66b64..c8a85eae252ff 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -648,6 +648,7 @@ impl<'a> Builder<'a> { pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { match self.config.libdir_relative() { Some(relative_libdir) if compiler.stage >= 1 => relative_libdir, + _ if compiler.stage == 0 => &self.build.initial_libdir, _ => Path::new("lib"), } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 15bf831a14835..c46c68e4d5682 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -243,6 +243,7 @@ pub struct Build { initial_rustc: PathBuf, initial_cargo: PathBuf, initial_lld: PathBuf, + initial_libdir: PathBuf, // Runtime state filled in later on // C/C++ compilers and archiver for all targets @@ -344,18 +345,39 @@ impl Build { // we always try to use git for LLVM builds let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project")); - let initial_sysroot = config.initial_rustc.parent().unwrap().parent().unwrap(); - let initial_lld = initial_sysroot - .join("lib") - .join("rustlib") - .join(config.build) - .join("bin") - .join("rust-lld"); + let initial_target_libdir_str = if config.dry_run { + "/dummy/lib/path/to/lib/".to_string() + } else { + output( + Command::new(&config.initial_rustc) + .arg("--target") + .arg(config.build) + .arg("--print") + .arg("target-libdir"), + ) + }; + let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap(); + let initial_lld = initial_target_dir.join("bin").join("rust-lld"); + + let initial_sysroot = if config.dry_run { + "/dummy".to_string() + } else { + output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot")) + }; + let initial_libdir = initial_target_dir + .parent() + .unwrap() + .parent() + .unwrap() + .strip_prefix(initial_sysroot.trim()) + .unwrap() + .to_path_buf(); let mut build = Build { initial_rustc: config.initial_rustc.clone(), initial_cargo: config.initial_cargo.clone(), initial_lld, + initial_libdir, local_rebuild: config.local_rebuild, fail_fast: config.cmd.fail_fast(), doc_tests: config.cmd.doc_tests(), diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index b514e0f6d9cff..316c2cd55acea 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2270,12 +2270,11 @@ impl str { self.len() == 0 } - /// Checks that `index`-th byte lies at the start and/or end of a - /// UTF-8 code point sequence. + /// Checks that `index`-th byte is the first byte in a UTF-8 code point + /// sequence or the end of the string. /// /// The start and end of the string (when `index == self.len()`) are - /// considered to be - /// boundaries. + /// considered to be boundaries. /// /// Returns `false` if `index` is greater than `self.len()`. /// diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 677c027f17b54..23bf7b35419db 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -191,6 +191,11 @@ pub struct Parser<'a> { append_newline: bool, /// Whether this formatting string is a literal or it comes from a macro. is_literal: bool, + /// Start position of the current line. + cur_line_start: usize, + /// Start and end byte offset of every line of the format string. Excludes + /// newline characters and leading whitespace. + pub line_spans: Vec, } impl<'a> Iterator for Parser<'a> { @@ -235,10 +240,15 @@ impl<'a> Iterator for Parser<'a> { None } } - '\n' => Some(String(self.string(pos))), _ => Some(String(self.string(pos))), } } else { + if self.is_literal && self.cur_line_start != self.input.len() { + let start = self.to_span_index(self.cur_line_start); + let end = self.to_span_index(self.input.len()); + self.line_spans.push(start.to(end)); + self.cur_line_start = self.input.len(); + } None } } @@ -266,6 +276,8 @@ impl<'a> Parser<'a> { last_opening_brace: None, append_newline, is_literal, + cur_line_start: 0, + line_spans: vec![], } } @@ -433,7 +445,17 @@ impl<'a> Parser<'a> { '{' | '}' => { return &self.input[start..pos]; } + '\n' if self.is_literal => { + let start = self.to_span_index(self.cur_line_start); + let end = self.to_span_index(pos); + self.line_spans.push(start.to(end)); + self.cur_line_start = pos + 1; + self.cur.next(); + } _ => { + if self.is_literal && pos == self.cur_line_start && c.is_whitespace() { + self.cur_line_start = pos + c.len_utf8(); + } self.cur.next(); } } diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 30bb5c0bffa6a..efcf95ec706b8 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -1252,7 +1252,7 @@ pub enum ExprKind { Ret(Option>), /// Output of the `asm!()` macro. - InlineAsm(InlineAsm), + InlineAsm(P), /// Output of the `llvm_asm!()` macro. LlvmInlineAsm(P), @@ -1971,6 +1971,7 @@ pub struct InlineAsm { pub template: Vec, pub operands: Vec<(InlineAsmOperand, Span)>, pub options: InlineAsmOptions, + pub line_spans: Vec, } /// Inline assembly dialect. diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index b7f2e9a9050df..c9037da377ebb 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -1267,7 +1267,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let operands = self.arena.alloc_from_iter(operands); let template = self.arena.alloc_from_iter(asm.template.iter().cloned()); - let hir_asm = hir::InlineAsm { template, operands, options: asm.options }; + let line_spans = self.arena.alloc_slice(&asm.line_spans[..]); + let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans }; hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm)) } diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index 224b52b239f43..19fae63557289 100644 --- a/src/librustc_builtin_macros/asm.rs +++ b/src/librustc_builtin_macros/asm.rs @@ -513,10 +513,16 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P( return DummyResult::any(sp); } + let sp = cx.with_def_site_ctxt(sp); let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index f3b46dd322a39..9d4a30f23a209 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; -use rustc_span::Span; +use rustc_span::{Pos, Span}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -97,7 +97,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { ia.volatile, ia.alignstack, ia.dialect, - span, + &[span], ); if r.is_none() { return false; @@ -119,7 +119,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { template: &[InlineAsmTemplatePiece], operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, - span: Span, + line_spans: &[Span], ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -287,9 +287,9 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { volatile, alignstack, dialect, - span, + line_spans, ) - .unwrap_or_else(|| span_bug!(span, "LLVM asm constraint validation failed")); + .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed")); if options.contains(InlineAsmOptions::PURE) { if options.contains(InlineAsmOptions::NOMEM) { @@ -341,7 +341,7 @@ fn inline_asm_call( volatile: bool, alignstack: bool, dia: LlvmAsmDialect, - span: Span, + line_spans: &[Span], ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; let alignstack = if alignstack { llvm::True } else { llvm::False }; @@ -382,8 +382,24 @@ fn inline_asm_call( key.len() as c_uint, ); - let val: &'ll Value = bx.const_i32(span.ctxt().outer_expn().as_u32() as i32); - llvm::LLVMSetMetadata(call, kind, llvm::LLVMMDNodeInContext(bx.llcx, &val, 1)); + // srcloc contains one integer for each line of assembly code. + // Unfortunately this isn't enough to encode a full span so instead + // we just encode the start position of each line. + // FIXME: Figure out a way to pass the entire line spans. + let mut srcloc = vec![]; + if dia == LlvmAsmDialect::Intel && line_spans.len() > 1 { + // LLVM inserts an extra line to add the ".intel_syntax", so add + // a dummy srcloc entry for it. + // + // Don't do this if we only have 1 line span since that may be + // due to the asm template string coming from a macro. LLVM will + // default to the first srcloc for lines that don't have an + // associated srcloc. + srcloc.push(bx.const_i32(0)); + } + srcloc.extend(line_spans.iter().map(|span| bx.const_i32(span.lo().to_u32() as i32))); + let md = llvm::LLVMMDNodeInContext(bx.llcx, srcloc.as_ptr(), srcloc.len() as u32); + llvm::LLVMSetMetadata(call, kind, md); Some(call) } else { diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 57e018bba6a1a..02a9294930d2b 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -23,6 +23,7 @@ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; use rustc_session::Session; +use rustc_span::InnerSpan; use rustc_target::spec::{CodeModel, RelocModel}; use libc::{c_char, c_int, c_uint, c_void, size_t}; @@ -238,12 +239,19 @@ impl<'a> Drop for DiagnosticHandlers<'a> { } } -unsafe extern "C" fn report_inline_asm( +fn report_inline_asm( cgcx: &CodegenContext, - msg: &str, - cookie: c_uint, + msg: String, + mut cookie: c_uint, + source: Option<(String, Vec)>, ) { - cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned()); + // In LTO build we may get srcloc values from other crates which are invalid + // since they use a different source map. To be safe we just suppress these + // in LTO builds. + if matches!(cgcx.lto, Lto::Fat | Lto::Thin) { + cookie = 0; + } + cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source); } unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) { @@ -252,10 +260,37 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void } let (cgcx, _) = *(user as *const (&CodegenContext, &Handler)); - let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s)) - .expect("non-UTF8 SMDiagnostic"); + // Recover the post-substitution assembly code from LLVM for better + // diagnostics. + let mut have_source = false; + let mut buffer = String::new(); + let mut loc = 0; + let mut ranges = [0; 8]; + let mut num_ranges = ranges.len() / 2; + let msg = llvm::build_string(|msg| { + buffer = llvm::build_string(|buffer| { + have_source = llvm::LLVMRustUnpackSMDiagnostic( + diag, + msg, + buffer, + &mut loc, + ranges.as_mut_ptr(), + &mut num_ranges, + ); + }) + .expect("non-UTF8 inline asm"); + }) + .expect("non-UTF8 SMDiagnostic"); + + let source = have_source.then(|| { + let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)]; + for i in 0..num_ranges { + spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize)); + } + (buffer, spans) + }); - report_inline_asm(cgcx, &msg, cookie); + report_inline_asm(cgcx, msg, cookie, source); } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { @@ -266,7 +301,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void match llvm::diagnostic::Diagnostic::unpack(info) { llvm::diagnostic::InlineAsm(inline) => { - report_inline_asm(cgcx, &llvm::twine_to_string(inline.message), inline.cookie); + report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None); } llvm::diagnostic::Optimization(opt) => { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0cce0b25e5893..333eb805221ff 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -959,16 +959,16 @@ pub fn compile_unit_metadata( if tcx.sess.opts.debugging_opts.profile { let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata); + let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda"); + let gcda_path = + tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); let gcov_cu_info = [ path_to_mdstring( debug_context.llcontext, &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"), ), - path_to_mdstring( - debug_context.llcontext, - &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda"), - ), + path_to_mdstring(debug_context.llcontext, &gcda_path), cu_desc_metadata, ]; let gcov_metadata = llvm::LLVMMDNodeInContext( diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 3fb7ff3cb8dfd..759c2bf1b85f4 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -2070,7 +2070,14 @@ extern "C" { ); #[allow(improper_ctypes)] - pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString); + pub fn LLVMRustUnpackSMDiagnostic( + d: &SMDiagnostic, + message_out: &RustString, + buffer_out: &RustString, + loc_out: &mut c_uint, + ranges_out: *mut c_uint, + num_ranges: &mut usize, + ) -> bool; pub fn LLVMRustWriteArchive( Dst: *const c_char, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 9e03c283cfb5c..cb5c95c11fad8 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -31,9 +31,9 @@ use rustc_session::cgu_reuse_tracker::CguReuseTracker; use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType}; use rustc_session::config::{Passes, Sanitizer, SwitchWithOptPath}; use rustc_session::Session; -use rustc_span::hygiene::ExpnId; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use std::any::Any; @@ -1551,7 +1551,7 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem enum SharedEmitterMessage { Diagnostic(Diagnostic), - InlineAsmError(u32, String), + InlineAsmError(u32, String, Option<(String, Vec)>), AbortIfErrors, Fatal(String), } @@ -1572,8 +1572,13 @@ impl SharedEmitter { (SharedEmitter { sender }, SharedEmitterMain { receiver }) } - pub fn inline_asm_error(&self, cookie: u32, msg: String) { - drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg))); + pub fn inline_asm_error( + &self, + cookie: u32, + msg: String, + source: Option<(String, Vec)>, + ) { + drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source))); } pub fn fatal(&self, msg: &str) { @@ -1626,8 +1631,30 @@ impl SharedEmitterMain { } handler.emit_diagnostic(&d); } - Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => { - sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg) + Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => { + let msg = msg.strip_prefix("error: ").unwrap_or(&msg); + + // If the cookie is 0 then we don't have span information. + let mut err = if cookie == 0 { + sess.struct_err(&msg) + } else { + let pos = BytePos::from_u32(cookie); + let span = Span::with_root_ctxt(pos, pos); + sess.struct_span_err(span, &msg) + }; + + // Point to the generated assembly if it is available. + if let Some((buffer, spans)) = source { + let source = sess + .source_map() + .new_source_file(FileName::inline_asm_source_code(&buffer), buffer); + let source_span = Span::with_root_ctxt(source.start_pos, source.end_pos); + let spans: Vec<_> = + spans.iter().map(|sp| source_span.from_inner(*sp)).collect(); + err.span_note(spans, "instantiated into assembly here"); + } + + err.emit(); } Ok(SharedEmitterMessage::AbortIfErrors) => { sess.abort_if_errors(); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 2a6d1abba9e9d..6c18e753d790b 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -831,6 +831,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { template: &[ast::InlineAsmTemplatePiece], operands: &[mir::InlineAsmOperand<'tcx>], options: ast::InlineAsmOptions, + line_spans: &[Span], destination: Option, ) { let span = terminator.source_info.span; @@ -930,7 +931,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) .collect(); - bx.codegen_inline_asm(template, &operands, options, span); + bx.codegen_inline_asm(template, &operands, options, line_spans); if let Some(target) = destination { helper.funclet_br(self, &mut bx, target); @@ -1033,7 +1034,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("borrowck false edges in codegen") } - mir::TerminatorKind::InlineAsm { template, ref operands, options, destination } => { + mir::TerminatorKind::InlineAsm { + template, + ref operands, + options, + line_spans, + destination, + } => { self.codegen_asm_terminator( helper, bx, @@ -1041,6 +1048,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { template, operands, options, + line_spans, destination, ); } diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs index 0abfdfde7801b..b6b57744f95b6 100644 --- a/src/librustc_codegen_ssa/traits/asm.rs +++ b/src/librustc_codegen_ssa/traits/asm.rs @@ -52,7 +52,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { template: &[InlineAsmTemplatePiece], operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, - span: Span, + line_spans: &[Span], ); } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 35cff668581dd..0194dc9f90bb8 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2106,6 +2106,7 @@ pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub operands: &'hir [InlineAsmOperand<'hir>], pub options: InlineAsmOptions, + pub line_spans: &'hir [Span], } #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)] diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index ae9019828170f..a59a91e3005aa 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -60,7 +60,7 @@ use rustc_errors::{pluralize, struct_span_err}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::Node; +use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, @@ -1682,49 +1682,92 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) -> DiagnosticBuilder<'a> { + let hir = &self.tcx.hir(); // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. - let type_param_span = match (self.in_progress_tables, bound_kind) { - (Some(ref table), GenericKind::Param(ref param)) => { - let table_owner = table.borrow().hir_owner; - table_owner.and_then(|table_owner| { - let generics = self.tcx.generics_of(table_owner.to_def_id()); - // Account for the case where `param` corresponds to `Self`, - // which doesn't have the expected type argument. - if !(generics.has_self && param.index == 0) { - let type_param = generics.type_param(param, self.tcx); - let hir = &self.tcx.hir(); - type_param.def_id.as_local().map(|def_id| { - // Get the `hir::Param` to verify whether it already has any bounds. - // We do this to avoid suggesting code that ends up as `T: 'a'b`, - // instead we suggest `T: 'a + 'b` in that case. - let id = hir.as_local_hir_id(def_id); - let mut has_bounds = false; - if let Node::GenericParam(param) = hir.get(id) { - has_bounds = !param.bounds.is_empty(); - } - let sp = hir.span(id); - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - let is_impl_trait = bound_kind.to_string().starts_with("impl "); - let sp = if has_bounds && !is_impl_trait { - sp.to(self - .tcx - .sess - .source_map() - .next_point(self.tcx.sess.source_map().next_point(sp))) - } else { - sp - }; - (sp, has_bounds, is_impl_trait) - }) + let generics = + self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| { + let hir_id = hir.as_local_hir_id(table_owner); + let parent_id = hir.get_parent_item(hir_id); + ( + // Parent item could be a `mod`, so we check the HIR before calling: + if let Some(Node::Item(Item { + kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, + .. + })) = hir.find(parent_id) + { + Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id())) } else { None - } - }) + }, + self.tcx.generics_of(table_owner.to_def_id()), + ) + }); + let type_param_span = match (generics, bound_kind) { + (Some((_, ref generics)), GenericKind::Param(ref param)) => { + // Account for the case where `param` corresponds to `Self`, + // which doesn't have the expected type argument. + if !(generics.has_self && param.index == 0) { + let type_param = generics.type_param(param, self.tcx); + type_param.def_id.as_local().map(|def_id| { + // Get the `hir::Param` to verify whether it already has any bounds. + // We do this to avoid suggesting code that ends up as `T: 'a'b`, + // instead we suggest `T: 'a + 'b` in that case. + let id = hir.as_local_hir_id(def_id); + let mut has_bounds = false; + if let Node::GenericParam(param) = hir.get(id) { + has_bounds = !param.bounds.is_empty(); + } + let sp = hir.span(id); + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + let is_impl_trait = bound_kind.to_string().starts_with("impl "); + let sp = if has_bounds && !is_impl_trait { + sp.to(self + .tcx + .sess + .source_map() + .next_point(self.tcx.sess.source_map().next_point(sp))) + } else { + sp + }; + (sp, has_bounds, is_impl_trait) + }) + } else { + None + } } _ => None, }; + let new_lt = generics + .as_ref() + .and_then(|(parent_g, g)| { + let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect(); + let mut lts_names = g + .params + .iter() + .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) + .map(|p| p.name.as_str()) + .collect::>(); + if let Some(g) = parent_g { + lts_names.extend( + g.params + .iter() + .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime)) + .map(|p| p.name.as_str()), + ); + } + let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); + possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str())) + }) + .unwrap_or("'lt".to_string()); + let add_lt_sugg = generics + .as_ref() + .and_then(|(_, g)| g.params.first()) + .and_then(|param| param.def_id.as_local()) + .map(|def_id| { + (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt)) + }); let labeled_user_string = match bound_kind { GenericKind::Param(ref p) => format!("the parameter type `{}`", p), @@ -1781,6 +1824,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + let new_binding_suggestion = + |err: &mut DiagnosticBuilder<'tcx>, + type_param_span: Option<(Span, bool, bool)>, + bound_kind: GenericKind<'tcx>| { + let msg = "consider introducing an explicit lifetime bound"; + if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { + let suggestion = if is_impl_trait { + (sp.shrink_to_hi(), format!(" + {}", new_lt)) + } else { + let tail = if has_lifetimes { " +" } else { "" }; + (sp, format!("{}: {}{}", bound_kind, new_lt, tail)) + }; + let mut sugg = + vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))]; + if let Some(lt) = add_lt_sugg { + sugg.push(lt); + sugg.rotate_right(1); + } + // `MaybeIncorrect` due to issue #41966. + err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect); + } + }; + let mut err = match *sub { ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. }) | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => { @@ -1822,10 +1888,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{} may not live long enough", labeled_user_string ); - err.help(&format!( - "consider adding an explicit lifetime bound for `{}`", - bound_kind - )); note_and_explain_region( self.tcx, &mut err, @@ -1833,6 +1895,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sub, "...", ); + if let Some(infer::RelateParamBound(_, t)) = origin { + let t = self.resolve_vars_if_possible(&t); + match t.kind { + // We've got: + // fn get_later(g: G, dest: &mut T) -> impl FnOnce() + '_ + // suggest: + // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + ty::Closure(_, _substs) | ty::Opaque(_, _substs) => { + new_binding_suggestion(&mut err, type_param_span, bound_kind); + } + _ => { + binding_suggestion(&mut err, type_param_span, bound_kind, new_lt); + } + } + } err } }; @@ -1861,14 +1938,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "...", ); + debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); + debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); + debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); + debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); + debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); + if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { - debug!("report_sub_sup_conflict: var_origin={:?}", var_origin); - debug!("report_sub_sup_conflict: sub_region={:?}", sub_region); - debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin); - debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); - debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index d206a30d526cb..7ab18e54f7ea2 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -121,16 +121,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { (Some(ret_span), _) => ( ty_sub.span, ret_span, - "this parameter and the return type are declared \ - with different lifetimes..." + "this parameter and the return type are declared with different lifetimes..." .to_owned(), format!("...but data{} is returned here", span_label_var1), ), (_, Some(ret_span)) => ( ty_sup.span, ret_span, - "this parameter and the return type are declared \ - with different lifetimes..." + "this parameter and the return type are declared with different lifetimes..." .to_owned(), format!("...but data{} is returned here", span_label_var1), ), diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index efe52689550c4..cc8f1816bc3f4 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -55,9 +55,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { diag.emit(); ErrorReported }) + .or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_static_impl_trait()) - .or_else(|| self.try_report_impl_not_conforming_to_trait()) } pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index b85a4cae2e470..acaf474699276 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -21,8 +21,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // where the anonymous region appears (there must always be one; we // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced - // with the named one.//scope_def_id - let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub) + // with the named one. + let (named, anon, anon_param_info, region_info) = if sub.has_name() && self.tcx().is_suitable_region(sup).is_some() && self.find_param_with_region(sup, sub).is_some() { @@ -32,7 +32,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { self.find_param_with_region(sup, sub).unwrap(), self.tcx().is_suitable_region(sup).unwrap(), ) - } else if self.is_named_region(sup) + } else if sup.has_name() && self.tcx().is_suitable_region(sub).is_some() && self.find_param_with_region(sub, sup).is_some() { @@ -74,15 +74,21 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let Some((_, fndecl)) = self.find_anon_type(anon, &br) { - if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() - || self.is_self_anon(is_first, scope_def_id) - { + let is_self_anon = self.is_self_anon(is_first, scope_def_id); + if is_self_anon { return None; } + if let FnRetTy::Return(ty) = &fndecl.output { - if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) { - // This is an impl Trait return that evaluates de need of 'static. - // We handle this case better in `static_impl_trait`. + let mut v = ty::TraitObjectVisitor(vec![]); + rustc_hir::intravisit::walk_ty(&mut v, ty); + + debug!("try_report_named_anon_conflict: ret ty {:?}", ty); + if sub == &ty::ReStatic && (matches!(ty.kind, TyKind::Def(_, _)) || v.0.len() == 1) + { + debug!("try_report_named_anon_conflict: impl Trait + 'static"); + // This is an `impl Trait` or `dyn Trait` return that evaluates de need of + // `'static`. We handle this case better in `static_impl_trait`. return None; } } @@ -114,17 +120,4 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(diag) } - - // This method returns whether the given Region is Named - pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool { - match *region { - ty::ReStatic => true, - ty::ReFree(ref free_region) => match free_region.bound_region { - ty::BrNamed(..) => true, - _ => false, - }, - ty::ReEarlyBound(ebr) => ebr.has_name(), - _ => false, - } - } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index 7f3ec852e41de..f4c86ddae604e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -4,7 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use rustc_errors::{Applicability, ErrorReported}; -use rustc_middle::ty::{BoundRegion, FreeRegion, RegionKind}; +use rustc_middle::ty::RegionKind; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. @@ -20,48 +20,59 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() { let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; - let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id); - if sub_r == &RegionKind::ReStatic && return_ty.is_some() { + let (fn_return_span, is_dyn) = + self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?; + if sub_r == &RegionKind::ReStatic { let sp = var_origin.span(); let return_sp = sub_origin.span(); let mut err = self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime"); - err.span_label( - return_sp, - "this return type evaluates to the `'static` lifetime...", - ); - err.span_label(sup_origin.span(), "...but this borrow..."); + let param_info = self.find_param_with_region(sup_r, sub_r)?; + err.span_label(param_info.param_ty_span, "data with this lifetime..."); - let (lifetime, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r); - if let Some(lifetime_sp) = lt_sp_opt { - err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime)); - } - - let lifetime_name = match sup_r { - RegionKind::ReFree(FreeRegion { - bound_region: BoundRegion::BrNamed(_, ref name), - .. - }) => name.to_string(), - _ => "'_".to_owned(), - }; - let fn_return_span = return_ty.unwrap().1; - if let Ok(snippet) = - self.tcx().sess.source_map().span_to_snippet(fn_return_span) + // We try to make the output have fewer overlapping spans if possible. + if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) + && sup_origin.span() != return_sp { - // only apply this suggestion onto functions with - // explicit non-desugar'able return. - if fn_return_span.desugaring_kind().is_none() { - err.span_suggestion( - fn_return_span, - &format!( - "you can add a bound to the return type to make it last \ - less than `'static` and match {}", - lifetime, - ), - format!("{} + {}", snippet, lifetime_name), - Applicability::Unspecified, - ); + // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` + + // Customize the spans and labels depending on their relative order so + // that split sentences flow correctly. + if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() { + err.span_label(sup_origin.span(), "...is captured here..."); + err.span_label(return_sp, "...and required to be `'static` by this"); + } else { + err.span_label(return_sp, "...is required to be `'static` by this..."); + err.span_label(sup_origin.span(), "...and is captured here"); } + } else { + err.span_label( + return_sp, + "...is captured and required to be `'static` here", + ); + } + + let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r); + + let lifetime_name = + if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; + // only apply this suggestion onto functions with + // explicit non-desugar'able return. + if fn_return_span.desugaring_kind().is_none() { + let msg = format!( + "to permit non-static references in {} `{} Trait` value, you can add \ + an explicit bound for {}", + if is_dyn { "a" } else { "an" }, + if is_dyn { "dyn" } else { "impl" }, + lifetime, + ); + // FIXME: account for the need of parens in `&(dyn Trait + '_)` + err.span_suggestion_verbose( + fn_return_span.shrink_to_hi(), + &msg, + format!(" + {}", lifetime_name), + Applicability::MaybeIncorrect, + ); } err.emit(); return Some(ErrorReported); diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 8fbb89da5af41..9ac27030adeea 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -10,10 +10,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, origin: &SubregionOrigin<'tcx>, ) { + let mut label_or_note = |span, msg| { + let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); + let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); + let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); + if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { + err.span_label(span, msg); + } else if span_is_primary && expanded_sub_count == 0 { + err.note(msg); + } else { + err.span_note(span, msg); + } + }; match *origin { infer::Subtype(ref trace) => { if let Some((expected, found)) = self.values_str(&trace.values) { - err.span_note( + label_or_note( trace.cause.span, &format!("...so that the {}", trace.cause.as_requirement_str()), ); @@ -24,27 +36,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // handling of region checking when type errors are present is // *terrible*. - err.span_note( + label_or_note( trace.cause.span, &format!("...so that {}", trace.cause.as_requirement_str()), ); } } infer::Reborrow(span) => { - err.span_note(span, "...so that reference does not outlive borrowed content"); + label_or_note(span, "...so that reference does not outlive borrowed content"); } infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - err.span_note(span, &format!("...so that closure can access `{}`", var_name)); + label_or_note(span, &format!("...so that closure can access `{}`", var_name)); } infer::RelateObjectBound(span) => { - err.span_note(span, "...so that it can be closed over into an object"); + label_or_note(span, "...so that it can be closed over into an object"); } infer::CallReturn(span) => { - err.span_note(span, "...so that return value is valid for the call"); + label_or_note(span, "...so that return value is valid for the call"); } infer::DataBorrowed(ty, span) => { - err.span_note( + label_or_note( span, &format!( "...so that the type `{}` is not borrowed for too long", @@ -53,36 +65,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } infer::ReferenceOutlivesReferent(ty, span) => { - err.span_note( + label_or_note( span, &format!( - "...so that the reference type `{}` does not outlive the \ - data it points at", + "...so that the reference type `{}` does not outlive the data it points at", self.ty_to_string(ty) ), ); } infer::RelateParamBound(span, t) => { - err.span_note( + label_or_note( span, &format!( - "...so that the type `{}` will meet its required \ - lifetime bounds", + "...so that the type `{}` will meet its required lifetime bounds", self.ty_to_string(t) ), ); } infer::RelateRegionParamBound(span) => { - err.span_note( + label_or_note( span, "...so that the declared lifetime parameter bounds are satisfied", ); } infer::CompareImplMethodObligation { span, .. } => { - err.span_note( + label_or_note( span, - "...so that the definition in impl matches the definition from the \ - trait", + "...so that the definition in impl matches the definition from the trait", ); } } @@ -113,8 +122,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0312, - "lifetime of reference outlives lifetime of \ - borrowed content..." + "lifetime of reference outlives lifetime of borrowed content..." ); note_and_explain_region( self.tcx, @@ -138,8 +146,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0313, - "lifetime of borrowed pointer outlives lifetime \ - of captured variable `{}`...", + "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", var_name ); note_and_explain_region( @@ -163,8 +170,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0476, - "lifetime of the source pointer does not outlive \ - lifetime bound of the object type" + "lifetime of the source pointer does not outlive lifetime bound of the \ + object type" ); note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, ""); note_and_explain_region( @@ -181,8 +188,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0477, - "the type `{}` does not fulfill the required \ - lifetime", + "the type `{}` does not fulfill the required lifetime", self.ty_to_string(ty) ); match *sub { @@ -217,8 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0482, - "lifetime of return value does not outlive the \ - function call" + "lifetime of return value does not outlive the function call" ); note_and_explain_region( self.tcx, diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 55f825e150e5e..f127a239eea2c 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -18,7 +18,7 @@ use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; use rustc_session::{DiagnosticOutput, Session}; use rustc_span::edition; -use rustc_span::source_map::{FileLoader, FileName, SourceMap}; +use rustc_span::source_map::{FileLoader, FileName}; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -31,7 +31,6 @@ pub type Result = result::Result; pub struct Compiler { pub(crate) sess: Lrc, codegen_backend: Lrc>, - source_map: Lrc, pub(crate) input: Input, pub(crate) input_path: Option, pub(crate) output_dir: Option, @@ -49,9 +48,6 @@ impl Compiler { pub fn codegen_backend(&self) -> &Lrc> { &self.codegen_backend } - pub fn source_map(&self) -> &Lrc { - &self.source_map - } pub fn input(&self) -> &Input { &self.input } @@ -168,7 +164,7 @@ pub fn run_compiler_in_existing_thread_pool( f: impl FnOnce(&Compiler) -> R, ) -> R { let registry = &config.registry; - let (sess, codegen_backend, source_map) = util::create_session( + let (sess, codegen_backend) = util::create_session( config.opts, config.crate_cfg, config.diagnostic_output, @@ -181,7 +177,6 @@ pub fn run_compiler_in_existing_thread_pool( let compiler = Compiler { sess, codegen_backend, - source_map, input: config.input, input_path: config.input_path, output_dir: config.output_dir, diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index d573e11fc4b24..18cbea858d47a 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -7,11 +7,10 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; use rustc_session::config::{Externs, OutputType, OutputTypes, Sanitizer, SymbolManglingVersion}; -use rustc_session::getopts; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::NativeLibKind; -use rustc_session::{build_session, Session}; +use rustc_session::{build_session, getopts, DiagnosticOutput, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::SourceFileHashAlgorithm; @@ -32,7 +31,14 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { let registry = registry::Registry::new(&[]); let (sessopts, cfg) = build_session_options_and_crate_config(matches); - let sess = build_session(sessopts, None, registry); + let sess = build_session( + sessopts, + None, + registry, + DiagnosticOutput::Default, + Default::default(), + None, + ); (sess, cfg) } @@ -557,6 +563,7 @@ fn test_debugging_options_tracking_hash() { tracked!(plt, Some(true)); tracked!(print_fuel, Some("abc".to_string())); tracked!(profile, true); + tracked!(profile_emit, Some(PathBuf::from("abc"))); tracked!(relro_level, Some(RelroLevel::Full)); tracked!(report_delayed_bugs, true); tracked!(run_dsymutil, false); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 7eaaff05fb5f0..924908e572487 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -23,7 +23,7 @@ use rustc_session::parse::CrateConfig; use rustc_session::CrateDisambiguator; use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session}; use rustc_span::edition::Edition; -use rustc_span::source_map::{FileLoader, SourceMap}; +use rustc_span::source_map::FileLoader; use rustc_span::symbol::{sym, Symbol}; use smallvec::SmallVec; use std::env; @@ -65,8 +65,8 @@ pub fn create_session( input_path: Option, lint_caps: FxHashMap, descriptions: Registry, -) -> (Lrc, Lrc>, Lrc) { - let (mut sess, source_map) = session::build_session_with_source_map( +) -> (Lrc, Lrc>) { + let mut sess = session::build_session( sopts, input_path, descriptions, @@ -81,7 +81,7 @@ pub fn create_session( add_configuration(&mut cfg, &mut sess, &*codegen_backend); sess.parse_sess.config = cfg; - (Lrc::new(sess), Lrc::new(codegen_backend), source_map) + (Lrc::new(sess), Lrc::new(codegen_backend)) } const STACK_SIZE: usize = 8 * 1024 * 1024; diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index fe6785de009a1..c2139d07f378a 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -238,26 +238,25 @@ pub enum Base { /// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun", /// but shebang isn't a part of rust syntax. pub fn strip_shebang(input: &str) -> Option { - let first_line = input.lines().next()?; - // A shebang is intentionally loosely defined as `#! [non whitespace]` on the first line. - let could_be_shebang = - first_line.starts_with("#!") && first_line[2..].contains(|c| !is_whitespace(c)); - if !could_be_shebang { - return None; - } - let non_whitespace_tokens = tokenize(input).map(|tok| tok.kind).filter(|tok| - !matches!(tok, TokenKind::LineComment | TokenKind::BlockComment { .. } | TokenKind::Whitespace) - ); - let prefix = [TokenKind::Pound, TokenKind::Not, TokenKind::OpenBracket]; - let starts_with_attribute = non_whitespace_tokens.take(3).eq(prefix.iter().copied()); - if starts_with_attribute { - // If the file starts with #![ then it's definitely not a shebang -- it couldn't be - // a rust program since a Rust program can't start with `[` - None - } else { - // It's a #!... and there isn't a `[` in sight, must be a shebang - Some(first_line.len()) + // Shebang must start with `#!` literally, without any preceding whitespace. + if input.starts_with("#!") { + let input_tail = &input[2..]; + // Shebang must have something non-whitespace after `#!` on the first line. + let first_line_tail = input_tail.lines().next()?; + if first_line_tail.contains(|c| !is_whitespace(c)) { + // Ok, this is a shebang but if the next non-whitespace token is `[` or maybe + // a doc comment (due to `TokenKind::(Line,Block)Comment` ambiguity at lexer level), + // then it may be valid Rust code, so consider it Rust code. + let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).filter(|tok| + !matches!(tok, TokenKind::Whitespace | TokenKind::LineComment | TokenKind::BlockComment { .. }) + ).next(); + if next_non_whitespace_token != Some(TokenKind::OpenBracket) { + // No other choice than to consider this a shebang. + return Some(2 + first_line_tail.len()); + } + } } + None } /// Parses the first token from the provided input string. diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs index 9b9207312e8dd..d5212ec5c3081 100644 --- a/src/librustc_middle/arena.rs +++ b/src/librustc_middle/arena.rs @@ -82,6 +82,8 @@ macro_rules! arena_types { // (during lowering) and the `librustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, + // This is used to decode the &'tcx [Span] for InlineAsm's line_spans. + [decode] span: rustc_span::Span, ], $tcx); ) } diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 0e9c133e2c322..b54b09918abe1 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -1194,6 +1194,10 @@ pub enum TerminatorKind<'tcx> { /// Miscellaneous options for the inline assembly. options: InlineAsmOptions, + /// Source spans for each line of the inline assembly code. These are + /// used to map assembler errors back to the line in the source code. + line_spans: &'tcx [Span], + /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option, @@ -1596,7 +1600,7 @@ impl<'tcx> TerminatorKind<'tcx> { } FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"), - InlineAsm { template, ref operands, options, destination: _ } => { + InlineAsm { template, ref operands, options, .. } => { write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?; for op in operands { write!(fmt, ", ")?; diff --git a/src/librustc_middle/mir/type_foldable.rs b/src/librustc_middle/mir/type_foldable.rs index bb7001c1207bf..b0207b469fa64 100644 --- a/src/librustc_middle/mir/type_foldable.rs +++ b/src/librustc_middle/mir/type_foldable.rs @@ -78,9 +78,13 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { FalseEdges { real_target, imaginary_target } } FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, - InlineAsm { template, ref operands, options, destination } => { - InlineAsm { template, operands: operands.fold_with(folder), options, destination } - } + InlineAsm { template, ref operands, options, line_spans, destination } => InlineAsm { + template, + operands: operands.fold_with(folder), + options, + line_spans, + destination, + }, }; Terminator { source_info: self.source_info, kind } } diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index a29b7b75294b7..035e6e55a975d 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -535,6 +535,7 @@ macro_rules! make_mir_visitor { template: _, operands, options: _, + line_spans: _, destination: _, } => { for op in operands { diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 3a08d202ea385..c9d240a5da91e 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1,38 +1,27 @@ //! Type context book-keeping. use crate::arena::Arena; -use crate::dep_graph::DepGraph; -use crate::dep_graph::{self, DepConstructor}; +use crate::dep_graph::{self, DepConstructor, DepGraph}; use crate::hir::exports::Export; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; -use crate::lint::LintDiagnosticBuilder; -use crate::lint::{struct_lint_level, LintSource}; +use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintSource}; use crate::middle; -use crate::middle::cstore::CrateStoreDyn; -use crate::middle::cstore::EncodedMetadata; +use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata}; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::interpret::{Allocation, ConstValue, Scalar}; -use crate::mir::{interpret, Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; +use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; use crate::traits; -use crate::ty::query; use crate::ty::steal::Steal; -use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; -use crate::ty::subst::{GenericArgKind, UserSubsts}; -use crate::ty::CanonicalPolyFnSig; -use crate::ty::GenericParamDefKind; -use crate::ty::RegionKind; -use crate::ty::ReprOptions; +use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts}; use crate::ty::TyKind::*; -use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; -use crate::ty::{AdtDef, AdtKind, Const, Region}; -use crate::ty::{BindingMode, BoundVar}; -use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid}; -use crate::ty::{ExistentialPredicate, Predicate, PredicateKind}; -use crate::ty::{InferConst, ParamConst}; -use crate::ty::{InferTy, ParamTy, PolyFnSig, ProjectionTy}; -use crate::ty::{List, TyKind, TyS}; +use crate::ty::{ + self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, + DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, + IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, ProjectionTy, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, +}; use rustc_ast::ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_attr as attr; @@ -48,10 +37,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathHash, Definitions}; -use rustc_hir::lang_items; -use rustc_hir::lang_items::PanicLocationLangItem; -use rustc_hir::{HirId, Node, TraitCandidate}; -use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet}; +use rustc_hir::lang_items::{self, PanicLocationLangItem}; +use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; @@ -1396,6 +1383,66 @@ impl<'tcx> TyCtxt<'tcx> { }) } + pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> { + let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); + let hir_output = match self.hir().get(hir_id) { + Node::Item(hir::Item { + kind: + ItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + .., + ), + .. + }) + | Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + _, + ), + .. + }) + | Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { + decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, + .. + }, + _, + ), + .. + }) => ty, + _ => return None, + }; + + let ret_ty = self.type_of(scope_def_id); + match ret_ty.kind { + ty::FnDef(_, _) => { + let sig = ret_ty.fn_sig(*self); + let output = self.erase_late_bound_regions(&sig.output()); + if output.is_impl_trait() { + let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); + Some((fn_decl.output.span(), false)) + } else { + let mut v = TraitObjectVisitor(vec![]); + rustc_hir::intravisit::walk_ty(&mut v, hir_output); + if v.0.len() == 1 { + return Some((v.0[0], true)); + } + None + } + } + _ => None, + } + } + pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> { // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local()); diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs index 613d66d59c55b..1403efb745b15 100644 --- a/src/librustc_middle/ty/diagnostics.rs +++ b/src/librustc_middle/ty/diagnostics.rs @@ -249,3 +249,22 @@ pub fn suggest_constraining_type_param( true } } + +pub struct TraitObjectVisitor(pub Vec); +impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + if let hir::TyKind::TraitObject( + _, + hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. }, + ) = ty.kind + { + self.0.push(ty.span); + } + } +} diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 178e3db17cd32..0b59e29b66c74 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -183,7 +183,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } } } - TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => { + TerminatorKind::InlineAsm { + template: _, + ref operands, + options: _, + line_spans: _, + destination: _, + } => { for op in operands { match *op { InlineAsmOperand::In { reg: _, ref value } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index e3098fc1cfc54..268fbfcf39525 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -722,7 +722,13 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc self.mutate_place(loc, (resume_arg, span), Deep, JustWrite, flow_state); } - TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => { + TerminatorKind::InlineAsm { + template: _, + ref operands, + options: _, + line_spans: _, + destination: _, + } => { for op in operands { match *op { InlineAsmOperand::In { reg: _, ref value } diff --git a/src/librustc_mir/dataflow/framework/direction.rs b/src/librustc_mir/dataflow/framework/direction.rs index 97b14ea771b2f..9e2a28853e151 100644 --- a/src/librustc_mir/dataflow/framework/direction.rs +++ b/src/librustc_mir/dataflow/framework/direction.rs @@ -482,7 +482,7 @@ impl Direction for Forward { } } - InlineAsm { template: _, operands: _, options: _, destination } => { + InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => { if let Some(target) = destination { propagate(target, exit_state); } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 427ab1ca5cd22..e35d853c92815 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -411,7 +411,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly); } } - TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => { + TerminatorKind::InlineAsm { + template: _, + ref operands, + options: _, + line_spans: _, + destination: _ + } => { for op in operands { match *op { InlineAsmOperand::In { reg: _, ref value } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index e962dfb2b3e86..d5f4a63baaa83 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -485,7 +485,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' try_validation!( value.to_char(), self.path, - err_ub!(InvalidChar(..)) => { "{}", value } expected { "a valid unicode codepoint" }, + err_ub!(InvalidChar(..)) => { "{}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" }, ); Ok(true) } diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs index ff3c7ee3ee823..e7733deee4dd3 100644 --- a/src/librustc_mir_build/build/expr/into.rs +++ b/src/librustc_mir_build/build/expr/into.rs @@ -310,7 +310,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); block.unit() } - ExprKind::InlineAsm { template, operands, options } => { + ExprKind::InlineAsm { template, operands, options, line_spans } => { use crate::hair; use rustc_middle::mir; let operands = operands @@ -368,6 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { template, operands, options, + line_spans, destination: if options.contains(InlineAsmOptions::NORETURN) { None } else { diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index fd3c48b38badb..969bb4f72597e 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -513,6 +513,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( }) .collect(), options: asm.options, + line_spans: asm.line_spans, }, hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm { diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs index aba7a7a1b420c..0a1c68e83a94c 100644 --- a/src/librustc_mir_build/hair/mod.rs +++ b/src/librustc_mir_build/hair/mod.rs @@ -283,6 +283,7 @@ crate enum ExprKind<'tcx> { template: &'tcx [InlineAsmTemplatePiece], operands: Vec>, options: InlineAsmOptions, + line_spans: &'tcx [Span], }, LlvmInlineAsm { asm: &'tcx hir::LlvmInlineAsmInner, diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs index b16d513d9239f..8a66fac1e3634 100644 --- a/src/librustc_session/lint.rs +++ b/src/librustc_session/lint.rs @@ -347,14 +347,14 @@ pub trait LintPass { fn name(&self) -> &'static str; } -/// Implements `LintPass for $name` with the given list of `Lint` statics. +/// Implements `LintPass for $ty` with the given list of `Lint` statics. #[macro_export] macro_rules! impl_lint_pass { - ($name:ident => [$($lint:expr),* $(,)?]) => { - impl $crate::lint::LintPass for $name { - fn name(&self) -> &'static str { stringify!($name) } + ($ty:ty => [$($lint:expr),* $(,)?]) => { + impl $crate::lint::LintPass for $ty { + fn name(&self) -> &'static str { stringify!($ty) } } - impl $name { + impl $ty { pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) } } }; diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 95f9ff00fb8d4..a38e7f063d79a 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -955,6 +955,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print layout information for each type encountered (default: no)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code (default: no)"), + profile_emit: Option = (None, parse_opt_pathbuf, [TRACKED], + "file path to emit profiling data at runtime when using 'profile' \ + (default based on relative source path)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing (default: no)"), query_stats: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 746e3536ce908..233761dbed7de 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -174,6 +174,10 @@ impl ParseSess { &self.source_map } + pub fn clone_source_map(&self) -> Lrc { + self.source_map.clone() + } + pub fn buffer_lint( &self, lint: &'static Lint, diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index a943cf3b67497..048033846a138 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_span::edition::Edition; -use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; +use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; use rustc_span::{SourceFileHashAlgorithm, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel}; @@ -523,7 +523,7 @@ impl Session { } #[inline] - pub fn source_map(&self) -> &source_map::SourceMap { + pub fn source_map(&self) -> &SourceMap { self.parse_sess.source_map() } pub fn verbose(&self) -> bool { @@ -1026,26 +1026,10 @@ impl Session { } } -pub fn build_session( - sopts: config::Options, - local_crate_source_file: Option, - registry: rustc_errors::registry::Registry, -) -> Session { - build_session_with_source_map( - sopts, - local_crate_source_file, - registry, - DiagnosticOutput::Default, - Default::default(), - None, - ) - .0 -} - fn default_emitter( sopts: &config::Options, registry: rustc_errors::registry::Registry, - source_map: &Lrc, + source_map: Lrc, emitter_dest: Option>, ) -> Box { let macro_backtrace = sopts.debugging_opts.macro_backtrace; @@ -1054,17 +1038,14 @@ fn default_emitter( let (short, color_config) = kind.unzip(); if let HumanReadableErrorType::AnnotateSnippet(_) = kind { - let emitter = AnnotateSnippetEmitterWriter::new( - Some(source_map.clone()), - short, - macro_backtrace, - ); + let emitter = + AnnotateSnippetEmitterWriter::new(Some(source_map), short, macro_backtrace); Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) } else { let emitter = match dst { None => EmitterWriter::stderr( color_config, - Some(source_map.clone()), + Some(source_map), short, sopts.debugging_opts.teach, sopts.debugging_opts.terminal_width, @@ -1072,7 +1053,7 @@ fn default_emitter( ), Some(dst) => EmitterWriter::new( dst, - Some(source_map.clone()), + Some(source_map), short, false, // no teach messages when writing to a buffer false, // no colors when writing to a buffer @@ -1084,20 +1065,14 @@ fn default_emitter( } } (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new( - JsonEmitter::stderr( - Some(registry), - source_map.clone(), - pretty, - json_rendered, - macro_backtrace, - ) - .ui_testing(sopts.debugging_opts.ui_testing), + JsonEmitter::stderr(Some(registry), source_map, pretty, json_rendered, macro_backtrace) + .ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new( JsonEmitter::new( dst, Some(registry), - source_map.clone(), + source_map, pretty, json_rendered, macro_backtrace, @@ -1112,14 +1087,14 @@ pub enum DiagnosticOutput { Raw(Box), } -pub fn build_session_with_source_map( +pub fn build_session( sopts: config::Options, local_crate_source_file: Option, registry: rustc_errors::registry::Registry, diagnostics_output: DiagnosticOutput, driver_lint_caps: FxHashMap, file_loader: Option>, -) -> (Session, Lrc) { +) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed // later via the source code. @@ -1157,7 +1132,7 @@ pub fn build_session_with_source_map( sopts.file_path_mapping(), hash_kind, )); - let emitter = default_emitter(&sopts, registry, &source_map, write_dest); + let emitter = default_emitter(&sopts, registry, source_map.clone(), write_dest); let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags( emitter, @@ -1185,7 +1160,7 @@ pub fn build_session_with_source_map( None }; - let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map.clone()); + let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map); let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), None => filesearch::get_or_default_sysroot(), @@ -1308,7 +1283,7 @@ pub fn build_session_with_source_map( validate_commandline_args_with_session_available(&sess); - (sess, source_map) + sess } // If it is useful to have a Session available already for validating a diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 58cdb87158afe..616876d4b02a8 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -101,6 +101,8 @@ pub enum FileName { /// Custom sources for explicit parser calls from plugins and drivers. Custom(String), DocTest(PathBuf, isize), + /// Post-substitution inline assembly from LLVM + InlineAsm(u64), } impl std::fmt::Display for FileName { @@ -116,6 +118,7 @@ impl std::fmt::Display for FileName { CliCrateAttr(_) => write!(fmt, ""), Custom(ref s) => write!(fmt, "<{}>", s), DocTest(ref path, _) => write!(fmt, "{}", path.display()), + InlineAsm(_) => write!(fmt, ""), } } } @@ -139,7 +142,8 @@ impl FileName { | CliCrateAttr(_) | Custom(_) | QuoteExpansion(_) - | DocTest(_, _) => false, + | DocTest(_, _) + | InlineAsm(_) => false, } } @@ -182,6 +186,12 @@ impl FileName { pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName { FileName::DocTest(path, line) } + + pub fn inline_asm_source_code(src: &str) -> FileName { + let mut hasher = StableHasher::new(); + src.hash(&mut hasher); + FileName::InlineAsm(hasher.finish()) + } } /// Spans represent a region of code, used for error reporting. Positions in spans diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 12edfed19c07e..ab9db159038af 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1151,9 +1151,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .as_ref() .and_then(|args| args.args.get(0)) .and_then(|arg| match arg { - hir::GenericArg::Type(ty) => { - sess.source_map().span_to_snippet(ty.span).ok() + hir::GenericArg::Type(ty) => match ty.kind { + hir::TyKind::Tup(t) => t + .iter() + .map(|e| sess.source_map().span_to_snippet(e.span)) + .collect::, _>>() + .map(|a| a.join(", ")), + _ => sess.source_map().span_to_snippet(ty.span), } + .map(|s| format!("({})", s)) + .ok(), _ => None, }) .unwrap_or_else(|| "()".to_string()), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 4bf3649dcc2e2..08e04f719e9ba 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -6,7 +6,7 @@ use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::Mutability; use rustc_metadata::creader::LoadedMacro; use rustc_middle::ty; @@ -454,11 +454,7 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) name: None, attrs: clean::Attributes::default(), source: clean::Span::empty(), - def_id: cx - .tcx - .hir() - .local_def_id_from_node_id(ast::CRATE_NODE_ID) - .to_def_id(), + def_id: DefId::local(CRATE_DEF_INDEX), visibility: clean::Public, stability: None, deprecation: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 702c7d1e0f120..371df7444b004 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1549,11 +1549,11 @@ impl<'tcx> Clean for Ty<'tcx> { ty::FnDef(..) | ty::FnPtr(_) => { let ty = cx.tcx.lift(self).expect("FnPtr lift failed"); let sig = ty.fn_sig(cx.tcx); - let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID); + let def_id = DefId::local(CRATE_DEF_INDEX); BareFunction(box BareFunctionDecl { unsafety: sig.unsafety(), generic_params: Vec::new(), - decl: (local_def_id.to_def_id(), sig).clean(cx), + decl: (def_id, sig).clean(cx), abi: sig.abi(), }) } @@ -2255,7 +2255,7 @@ impl Clean> for doctree::Import<'_> { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID).to_def_id(), + def_id: DefId::local(CRATE_DEF_INDEX), visibility: self.vis.clean(cx), stability: None, deprecation: None, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index cd49da88d9652..5b364ed95cf59 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4067,9 +4067,9 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter(|i| i.inner_impl().trait_.is_none()) .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false)) .collect::>(); - // We want links' order to be reproducible so we don't use unstable sort. - ret.sort(); if !ret.is_empty() { + // We want links' order to be reproducible so we don't use unstable sort. + ret.sort(); out.push_str(&format!( "Methods\
{}
", @@ -4240,7 +4240,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool { fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { let mut sidebar = String::new(); - let types = t + let mut types = t .items .iter() .filter_map(|m| match m.name { @@ -4249,8 +4249,8 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { } _ => None, }) - .collect::(); - let consts = t + .collect::>(); + let mut consts = t .items .iter() .filter_map(|m| match m.name { @@ -4259,7 +4259,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { } _ => None, }) - .collect::(); + .collect::>(); let mut required = t .items .iter() @@ -4282,24 +4282,26 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { .collect::>(); if !types.is_empty() { + types.sort(); sidebar.push_str(&format!( "\ - Associated Types
{}
", - types + Associated Types
{}
", + types.join("") )); } if !consts.is_empty() { + consts.sort(); sidebar.push_str(&format!( "\ - Associated Constants
{}
", - consts + Associated Constants
{}
", + consts.join("") )); } if !required.is_empty() { required.sort(); sidebar.push_str(&format!( "\ - Required Methods
{}
", + Required Methods
{}
", required.join("") )); } @@ -4307,7 +4309,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { provided.sort(); sidebar.push_str(&format!( "\ - Provided Methods
{}
", + Provided Methods
{}
", provided.join("") )); } @@ -4325,8 +4327,8 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { res.sort(); sidebar.push_str(&format!( "\ - Implementations on Foreign Types
{}
", + Implementations on Foreign Types
{}
", res.into_iter() .map(|(name, id)| format!("{}", id, Escape(&name))) .collect::>() @@ -4339,7 +4341,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { if t.auto { sidebar.push_str( "Auto Implementors", + href=\"#synthetic-implementors\">Auto Implementors", ); } @@ -4365,18 +4367,18 @@ fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) { } fn get_struct_fields_name(fields: &[clean::Item]) -> String { - fields + let mut fields = fields .iter() .filter(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) .filter_map(|f| match f.name { - Some(ref name) => Some(format!( - "\ - {name}", - name = name - )), + Some(ref name) => { + Some(format!("{name}", name = name)) + } _ => None, }) - .collect() + .collect::>(); + fields.sort(); + fields.join("") } fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { @@ -4386,7 +4388,7 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { if !fields.is_empty() { sidebar.push_str(&format!( "Fields\ -
{}
", +
{}
", fields )); } @@ -4401,23 +4403,20 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) { fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) { let mut sidebar = String::new(); - let variants = e + let mut variants = e .variants .iter() .filter_map(|v| match v.name { - Some(ref name) => Some(format!( - "{name}\ - ", - name = name - )), + Some(ref name) => Some(format!("{name}", name = name)), _ => None, }) - .collect::(); + .collect::>(); if !variants.is_empty() { + variants.sort_unstable(); sidebar.push_str(&format!( "Variants\ -
{}
", - variants +
{}
", + variants.join(""), )); } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 284e6d421ee2f..85ba4cbdc7e1b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -114,7 +114,7 @@ pub fn run(options: Options) -> Result<(), String> { options, false, opts, - Some(compiler.source_map().clone()), + Some(compiler.session().parse_sess.clone_source_map()), None, enable_per_target_ignores, ); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 24f35627d10e5..6fac2662506a1 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1216,10 +1216,33 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler( unwrap(C)->setInlineAsmDiagnosticHandler(H, CX); } -extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef D, - RustStringRef Str) { - RawRustStringOstream OS(Str); - unwrap(D)->print("", OS); +extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, + RustStringRef MessageOut, + RustStringRef BufferOut, + unsigned* LocOut, + unsigned* RangesOut, + size_t* NumRanges) { + SMDiagnostic& D = *unwrap(DRef); + RawRustStringOstream MessageOS(MessageOut); + MessageOS << D.getMessage(); + + if (D.getLoc() == SMLoc()) + return false; + + const SourceMgr &LSM = *D.getSourceMgr(); + const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize()); + + *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart(); + + *NumRanges = std::min(*NumRanges, D.getRanges().size()); + size_t LineStart = *LocOut - (size_t)D.getColumnNo(); + for (size_t i = 0; i < *NumRanges; i++) { + RangesOut[i * 2] = LineStart + D.getRanges()[i].first; + RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second; + } + + return true; } extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B, diff --git a/src/test/run-make-fulldeps/profile/Makefile b/src/test/run-make-fulldeps/profile/Makefile index c12712590e48f..04d382b475ed2 100644 --- a/src/test/run-make-fulldeps/profile/Makefile +++ b/src/test/run-make-fulldeps/profile/Makefile @@ -7,3 +7,6 @@ all: $(call RUN,test) || exit 1 [ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1) [ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1) + $(RUSTC) -g -Z profile -Z profile-emit=$(TMPDIR)/abc/abc.gcda test.rs + $(call RUN,test) || exit 1 + [ -e "$(TMPDIR)/abc/abc.gcda" ] || (echo "gcda file not emitted to defined path"; exit 1) diff --git a/src/test/ui-fulldeps/lint-pass-macros.rs b/src/test/ui-fulldeps/lint-pass-macros.rs new file mode 100644 index 0000000000000..b3c2a542792f0 --- /dev/null +++ b/src/test/ui-fulldeps/lint-pass-macros.rs @@ -0,0 +1,26 @@ +// compile-flags: -Z unstable-options +// check-pass + +#![feature(rustc_private)] + +extern crate rustc_session; + +use rustc_session::lint::{LintArray, LintPass}; +use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; + +declare_lint! { + pub TEST_LINT, + Allow, + "test" +} + +struct Foo; + +struct Bar<'a>(&'a u32); + +impl_lint_pass!(Foo => [TEST_LINT]); +impl_lint_pass!(Bar<'_> => [TEST_LINT]); + +declare_lint_pass!(Baz => [TEST_LINT]); + +fn main() {} diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs new file mode 100644 index 0000000000000..7af6f620a9858 --- /dev/null +++ b/src/test/ui/asm/srcloc.rs @@ -0,0 +1,41 @@ +// no-system-llvm +// only-x86_64 +// build-fail + +#![feature(asm)] + +// Checks that inline asm errors are mapped to the correct line in the source code. + +fn main() { + unsafe { + asm!("invalid_instruction"); + //~^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(" + invalid_instruction + "); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(r#" + invalid_instruction + "#); + //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(" + mov eax, eax + invalid_instruction + mov eax, eax + "); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(r#" + mov eax, eax + invalid_instruction + mov eax, eax + "#); + //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction' + + asm!(concat!("invalid", "_", "instruction")); + //~^ ERROR: invalid instruction mnemonic 'invalid_instruction' + } +} diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/srcloc.stderr new file mode 100644 index 0000000000000..57a4fbb974228 --- /dev/null +++ b/src/test/ui/asm/srcloc.stderr @@ -0,0 +1,74 @@ +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:11:15 + | +LL | asm!("invalid_instruction"); + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:15:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:20:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :3:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:26:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :4:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:33:13 + | +LL | invalid_instruction + | ^ + | +note: instantiated into assembly here + --> :4:13 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: invalid instruction mnemonic 'invalid_instruction' + --> $DIR/srcloc.rs:38:14 + | +LL | asm!(concat!("invalid", "_", "instruction")); + | ^ + | +note: instantiated into assembly here + --> :2:2 + | +LL | invalid_instruction + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr index 94afccc06a9e7..af8fc2cd2ab45 100644 --- a/src/test/ui/async-await/issues/issue-62097.stderr +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -2,15 +2,12 @@ error: cannot infer an appropriate lifetime --> $DIR/issue-62097.rs:12:31 | LL | pub async fn run_dummy_fn(&self) { - | ^^^^^ ...but this borrow... + | ^^^^^ + | | + | data with this lifetime... + | ...is captured here... LL | foo(|| self.bar()).await; - | --- this return type evaluates to the `'static` lifetime... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31 - --> $DIR/issue-62097.rs:12:31 - | -LL | pub async fn run_dummy_fn(&self) { - | ^ + | --- ...and required to be `'static` by this error: aborting due to previous error diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index 999a5839ba690..2dac4a22ae713 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/builtin-superkinds-self-type.rs:10:16 | LL | impl Foo for T { } - | -- ^^^ + | -- ^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/builtin-superkinds-self-type.rs:10:16 - | -LL | impl Foo for T { } - | ^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index d8dafac3e70a1..e49fd3e0b970b 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -82,7 +82,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:87:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at ..0.1, but expected a valid unicode codepoint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at ..0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/extenv/extenv-not-defined-custom.stderr b/src/test/ui/extenv/extenv-not-defined-custom.stderr index 523982dd0196b..56415fd1f0dd0 100644 --- a/src/test/ui/extenv/extenv-not-defined-custom.stderr +++ b/src/test/ui/extenv/extenv-not-defined-custom.stderr @@ -3,6 +3,8 @@ error: my error message | LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/extenv/extenv-not-defined-default.stderr b/src/test/ui/extenv/extenv-not-defined-default.stderr index 4bfe330f59235..1a9332c4f1c9f 100644 --- a/src/test/ui/extenv/extenv-not-defined-default.stderr +++ b/src/test/ui/extenv/extenv-not-defined-default.stderr @@ -3,6 +3,8 @@ error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined | LL | env!("__HOPEFULLY_NOT_DEFINED__"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr index c57a467cdba56..b62f06e33e531 100644 --- a/src/test/ui/extenv/issue-55897.stderr +++ b/src/test/ui/extenv/issue-55897.stderr @@ -3,6 +3,8 @@ error: environment variable `NON_EXISTENT` not defined | LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on a string literal are invalid --> $DIR/issue-55897.rs:16:22 diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr index fbc4e8abc42fd..2beeba8184a7d 100644 --- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr +++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar - | ^^^^^^^^^^^ - | -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5 - | -LL | bar: Bar - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index d5560c8133773..e06977ebbe3df 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -5,11 +5,7 @@ LL | type A<'a> where Self: 'static = (&'a ()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `T: 'static`... -note: ...so that the type `Fooy` will meet its required lifetime bounds - --> $DIR/impl_bounds.rs:15:5 - | -LL | type A<'a> where Self: 'static = (&'a ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the type `Fooy` will meet its required lifetime bounds error[E0478]: lifetime bound not satisfied --> $DIR/impl_bounds.rs:17:5 diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index cffa5ee8f1461..d7dae6a08a7b9 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -2,55 +2,43 @@ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:3:35 | LL | fn elided(x: &i32) -> impl Copy { x } - | --------- ^ ...but this borrow... - | | - | this return type evaluates to the `'static` lifetime... + | ---- --------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1 - --> $DIR/must_outlive_least_region_or_bound.rs:3:1 - | -LL | fn elided(x: &i32) -> impl Copy { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 | LL | fn elided(x: &i32) -> impl Copy + '_ { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:6:44 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | --------- ^ ...but this borrow... - | | - | this return type evaluates to the `'static` lifetime... + | ------- --------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 - --> $DIR/must_outlive_least_region_or_bound.rs:6:13 - | -LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } - | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } - | ^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/must_outlive_least_region_or_bound.rs:12:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | -------------------------------- ^ ...but this borrow... - | | - | this return type evaluates to the `'static` lifetime... - | -note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 - --> $DIR/must_outlive_least_region_or_bound.rs:12:15 + | ------- -------------------------------- ^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } - | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error[E0623]: lifetime mismatch --> $DIR/must_outlive_least_region_or_bound.rs:17:61 @@ -65,15 +53,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/must_outlive_least_region_or_bound.rs:22:51 | LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | -- ^^^^^^^^^^^^^^^^^^^^ + | -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static +` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/must_outlive_least_region_or_bound.rs:22:51 - | -LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index e550be1917474..1c3a5979ee55b 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -2,43 +2,35 @@ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:7:16 | LL | fn iter_values_anon(&self) -> impl Iterator { - | ----------------------- this return type evaluates to the `'static` lifetime... + | ----- ----------------------- ...is required to be `'static` by this... + | | + | data with this lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...but this borrow... + | ...and is captured here | -note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 - --> $DIR/static-return-lifetime-infered.rs:6:5 - | -LL | / fn iter_values_anon(&self) -> impl Iterator { -LL | | self.x.iter().map(|a| a.0) -LL | | } - | |_____^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn iter_values_anon(&self) -> impl Iterator + '_ { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: cannot infer an appropriate lifetime --> $DIR/static-return-lifetime-infered.rs:11:16 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ----------------------- this return type evaluates to the `'static` lifetime... + | -------- ----------------------- ...is required to be `'static` by this... + | | + | data with this lifetime... LL | self.x.iter().map(|a| a.0) | ------ ^^^^ | | - | ...but this borrow... - | -note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20 - --> $DIR/static-return-lifetime-infered.rs:10:20 + | ...and is captured here | -LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | ^^ -help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index 34f0f7f1d731c..40e50b9922f8d 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/type_parameters_captured.rs:7:20 | LL | fn foo(x: T) -> impl Any + 'static { - | - ^^^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds | | | help: consider adding an explicit lifetime bound...: `T: 'static` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/type_parameters_captured.rs:7:20 - | -LL | fn foo(x: T) -> impl Any + 'static { - | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16922.nll.stderr b/src/test/ui/issues/issue-16922.nll.stderr new file mode 100644 index 0000000000000..7f4f5b22eb302 --- /dev/null +++ b/src/test/ui/issues/issue-16922.nll.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-16922.rs:4:5 + | +LL | fn foo(value: &T) -> Box { + | - let's call the lifetime of this reference `'1` +LL | Box::new(value) as Box + | ^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs index 10a5cccbceef0..827163ef83cf7 100644 --- a/src/test/ui/issues/issue-16922.rs +++ b/src/test/ui/issues/issue-16922.rs @@ -2,7 +2,7 @@ use std::any::Any; fn foo(value: &T) -> Box { Box::new(value) as Box - //~^ ERROR explicit lifetime required in the type of `value` [E0621] + //~^ ERROR cannot infer an appropriate lifetime } fn main() { diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index 4e3d3ecb9c03a..02d33aae023ff 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -1,11 +1,18 @@ -error[E0621]: explicit lifetime required in the type of `value` - --> $DIR/issue-16922.rs:4:5 +error: cannot infer an appropriate lifetime + --> $DIR/issue-16922.rs:4:14 | LL | fn foo(value: &T) -> Box { - | -- help: add explicit lifetime `'static` to the type of `value`: `&'static T` + | -- data with this lifetime... LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^ lifetime `'static` required + | ---------^^^^^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1 + | +LL | fn foo(value: &T) -> Box { + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr index 81f06e6397542..a6500b9bb4c24 100644 --- a/src/test/ui/issues/issue-23458.stderr +++ b/src/test/ui/issues/issue-23458.stderr @@ -2,16 +2,19 @@ error: invalid operand in inline asm: 'int $3' --> $DIR/issue-23458.rs:8:9 | LL | llvm_asm!("int $3"); - | ^^^^^^^^^^^^^^^^^^^^ - -error: :1:2: error: too few operands for instruction - int - ^ + | ^ +error: too few operands for instruction --> $DIR/issue-23458.rs:8:9 | LL | llvm_asm!("int $3"); - | ^^^^^^^^^^^^^^^^^^^^ + | ^ + | +note: instantiated into assembly here + --> :1:2 + | +LL | int + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index e60c461743c8f..d682478db0eef 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `T` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | foo: &'static T - | ^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5 - | -LL | foo: &'static T - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `K` may not live long enough LL | trait X: Sized { | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn foo<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 - | -LL | fn foo<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `Self` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 @@ -33,25 +21,15 @@ LL | fn bar<'a, L: X<&'a Nested>>(); | ^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `Self: 'a`... -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19 - | -LL | fn bar<'a, L: X<&'a Nested>>(); - | ^^^^^^^^^^^^^^^^^^^ + = note: ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `L` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 | LL | fn baz<'a, L, M: X<&'a Nested>>() { - | - ^^^^^^^^^^^^^^^^ + | - ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at | | | help: consider adding an explicit lifetime bound...: `L: 'a` - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 - | -LL | fn baz<'a, L, M: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 @@ -59,25 +37,15 @@ error[E0309]: the parameter type `K` may not live long enough LL | impl Nested { | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 - | -LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested` does not outlive the data it points at error[E0309]: the parameter type `M` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 | LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { | ^^^^^^^^^^^^^^^^ -- help: consider adding an explicit lifetime bound...: `M: 'a +` - | -note: ...so that the reference type `&'a Nested` does not outlive the data it points at - --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 - | -LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { - | ^^^^^^^^^^^^^^^^ + | | + | ...so that the reference type `&'a Nested` does not outlive the data it points at error: aborting due to 6 previous errors diff --git a/src/test/ui/llvm-asm/issue-69092.rs b/src/test/ui/llvm-asm/issue-69092.rs index ecce7bfdf5bba..96c019b760e95 100644 --- a/src/test/ui/llvm-asm/issue-69092.rs +++ b/src/test/ui/llvm-asm/issue-69092.rs @@ -6,5 +6,5 @@ fn main() { unsafe { llvm_asm!(".ascii \"Xen\0\""); } - //~^ ERROR: :1:9: error: expected string in '.ascii' directive + //~^ ERROR: expected string in '.ascii' directive } diff --git a/src/test/ui/llvm-asm/issue-69092.stderr b/src/test/ui/llvm-asm/issue-69092.stderr index 35f77edc3c402..2ca86cf7c1b99 100644 --- a/src/test/ui/llvm-asm/issue-69092.stderr +++ b/src/test/ui/llvm-asm/issue-69092.stderr @@ -1,11 +1,14 @@ -error: :1:9: error: expected string in '.ascii' directive - .ascii "Xen - ^ - +error: expected string in '.ascii' directive --> $DIR/issue-69092.rs:8:14 | LL | unsafe { llvm_asm!(".ascii \"Xen\0\""); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ + | +note: instantiated into assembly here + --> :1:9 + | +LL | .ascii "Xen + | ^ error: aborting due to previous error diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index 6ef757a55b8fb..42954ebcdc1cd 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -47,6 +47,8 @@ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal --> $DIR/macros-nonfatal-errors.rs:23:13 diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index 1a5a3719fd86d..eba00c5a9454e 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -5,11 +5,7 @@ LL | bar::() | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -note: ...so that the type `>::Output` will meet its required lifetime bounds - --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5 - | -LL | bar::() - | ^^^^^^^^^^^^^^^^ + = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr index d6ade2a603e82..34b83859a6bd2 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -5,11 +5,7 @@ LL | bar::<>::Output>() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... -note: ...so that the type `>::Output` will meet its required lifetime bounds - --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5 - | -LL | bar::<>::Output>() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the type `>::Output` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr index f6252f4ed7977..9563c0dff3644 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr @@ -1,11 +1,11 @@ -error[E0621]: explicit lifetime required in the type of `ss` +error: lifetime may not live long enough --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>` + | -- has type `&mut SomeStruct<'1>` ... LL | ss.r - | ^^^^ lifetime `'static` required + | ^^^^ returning this value requires that `'1` must outlive `'static` error[E0507]: cannot move out of `ss.r` which is behind a mutable reference --> $DIR/object-lifetime-default-from-box-error.rs:18:5 diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs index 587aab1edce38..708ab1cf38297 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box { // `Box` defaults to a `'static` bound, so this return // is illegal. - ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621] + ss.r //~ ERROR cannot infer an appropriate lifetime } fn store(ss: &mut SomeStruct, b: Box) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr index 78e4bdd374da9..70a9bf22b8db3 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -1,11 +1,16 @@ -error[E0621]: explicit lifetime required in the type of `ss` +error: cannot infer an appropriate lifetime --> $DIR/object-lifetime-default-from-box-error.rs:18:5 | LL | fn load(ss: &mut SomeStruct) -> Box { - | --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>` + | --------------- data with this lifetime... ... LL | ss.r - | ^^^^ lifetime `'static` required + | ^^^^ ...is captured and required to be `'static` here + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1 + | +LL | fn load(ss: &mut SomeStruct) -> Box { + | ^^^^ error[E0621]: explicit lifetime required in the type of `ss` --> $DIR/object-lifetime-default-from-box-error.rs:31:12 diff --git a/src/test/ui/parser/shebang/shebang-doc-comment.rs b/src/test/ui/parser/shebang/shebang-doc-comment.rs new file mode 100644 index 0000000000000..7dbb9eebc7571 --- /dev/null +++ b/src/test/ui/parser/shebang/shebang-doc-comment.rs @@ -0,0 +1,6 @@ +#!///bin/bash +[allow(unused_variables)] +//~^^ ERROR expected `[`, found doc comment + +// Doc comment is misinterpreted as a whitespace (regular comment) during shebang detection. +// Even if it wasn't, it would still result in an error, just a different one. diff --git a/src/test/ui/parser/shebang/shebang-doc-comment.stderr b/src/test/ui/parser/shebang/shebang-doc-comment.stderr new file mode 100644 index 0000000000000..f524f556837fb --- /dev/null +++ b/src/test/ui/parser/shebang/shebang-doc-comment.stderr @@ -0,0 +1,8 @@ +error: expected `[`, found doc comment `///bin/bash` + --> $DIR/shebang-doc-comment.rs:1:3 + | +LL | #!///bin/bash + | ^^^^^^^^^^^ expected `[` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr index 767853d81480e..bf02ba8eb9199 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr @@ -14,17 +14,17 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^^^^^^^^^^^ lifetime `'static` required -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:21:5 +error: lifetime may not live long enough + --> $DIR/region-object-lifetime-in-coercion.rs:20:5 | LL | fn c(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | - let's call the lifetime of this reference `'1` ... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` error: lifetime may not live long enough - --> $DIR/region-object-lifetime-in-coercion.rs:26:5 + --> $DIR/region-object-lifetime-in-coercion.rs:24:5 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs index 2dc67599913a6..d56eaf77b6646 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs @@ -11,20 +11,17 @@ fn a(v: &[u8]) -> Box { } fn b(v: &[u8]) -> Box { - Box::new(v) - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621] } fn c(v: &[u8]) -> Box { // same as previous case due to RFC 599 - Box::new(v) - //~^ ERROR explicit lifetime required in the type of `v` [E0621] + Box::new(v) //~ ERROR cannot infer an appropriate lifetime } fn d<'a,'b>(v: &'a [u8]) -> Box { - Box::new(v) - //~^ ERROR cannot infer an appropriate lifetime due to conflicting + Box::new(v) //~ ERROR cannot infer an appropriate lifetime due to conflicting } fn e<'a:'b,'b>(v: &'a [u8]) -> Box { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 069b897603cb9..1462af44cb15a 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -14,40 +14,48 @@ LL | fn b(v: &[u8]) -> Box { LL | Box::new(v) | ^^^^^^^^^^^ lifetime `'static` required -error[E0621]: explicit lifetime required in the type of `v` - --> $DIR/region-object-lifetime-in-coercion.rs:21:5 +error: cannot infer an appropriate lifetime + --> $DIR/region-object-lifetime-in-coercion.rs:20:14 | LL | fn c(v: &[u8]) -> Box { - | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]` + | ----- data with this lifetime... ... LL | Box::new(v) - | ^^^^^^^^^^^ lifetime `'static` required + | ---------^- + | | | + | | ...and is captured here + | ...is required to be `'static` by this... + | +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1 + | +LL | fn c(v: &[u8]) -> Box { + | ^^^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/region-object-lifetime-in-coercion.rs:26:14 + --> $DIR/region-object-lifetime-in-coercion.rs:24:14 | LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6... - --> $DIR/region-object-lifetime-in-coercion.rs:25:6 +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6... + --> $DIR/region-object-lifetime-in-coercion.rs:23:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:26:14 + --> $DIR/region-object-lifetime-in-coercion.rs:24:14 | LL | Box::new(v) | ^ = note: expected `&[u8]` found `&'a [u8]` -note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9... - --> $DIR/region-object-lifetime-in-coercion.rs:25:9 +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9... + --> $DIR/region-object-lifetime-in-coercion.rs:23:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { | ^^ note: ...so that the expression is assignable - --> $DIR/region-object-lifetime-in-coercion.rs:26:5 + --> $DIR/region-object-lifetime-in-coercion.rs:24:5 | LL | Box::new(v) | ^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.stderr b/src/test/ui/regions/regions-close-associated-type-into-object.stderr index 2401f549a5604..9303e0f8e6643 100644 --- a/src/test/ui/regions/regions-close-associated-type-into-object.stderr +++ b/src/test/ui/regions/regions-close-associated-type-into-object.stderr @@ -5,11 +5,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'static`... -note: ...so that the type `::Item` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:15:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0310]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:22:5 @@ -18,11 +14,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'static`... -note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:22:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:28:5 @@ -31,11 +23,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... -note: ...so that the type `::Item` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:28:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `::Item` will meet its required lifetime bounds error[E0309]: the associated type `::Item` may not live long enough --> $DIR/regions-close-associated-type-into-object.rs:35:5 @@ -44,11 +32,7 @@ LL | Box::new(item) | ^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `::Item: 'a`... -note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds - --> $DIR/regions-close-associated-type-into-object.rs:35:5 - | -LL | Box::new(item) - | ^^^^^^^^^^^^^^ + = note: ...so that the type `std::boxed::Box<::Item>` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 2bcdcd1864e2f..e5a80cbd54758 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr @@ -5,13 +5,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^^^^^^^^ - | -note: ...so that the type `B<'_, T>` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:5 - | -LL | box B(&*v) as Box - | ^^^^^^^^^^ + | ^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 @@ -20,13 +14,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | box B(&*v) as Box - | ^ + | ^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 @@ -35,13 +23,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-object-into-object-5.rs:17:9 - | -LL | box B(&*v) as Box - | ^^^^^^ + | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -50,13 +32,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the reference type `&dyn A` does not outlive the data it points at - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the reference type `&dyn A` does not outlive the data it points at error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -65,13 +41,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the type `(dyn A + 'static)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 @@ -80,13 +50,7 @@ LL | fn f<'a, T, U>(v: Box + 'static>) -> Box { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box - | ^^^ - | -note: ...so that the type `(dyn A + 'static)` is not borrowed for too long - --> $DIR/regions-close-object-into-object-5.rs:17:11 - | -LL | box B(&*v) as Box - | ^^^ + | ^^^ ...so that the type `(dyn A + 'static)` is not borrowed for too long error: aborting due to 6 previous errors diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr index a7509cb608c6b..50274b066df60 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `A` may not live long enough LL | fn make_object1(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'static +` LL | box v as Box - | ^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-close-over-type-parameter-1.rs:12:5 - | -LL | box v as Box - | ^^^^^ + | ^^^^^ ...so that the type `A` will meet its required lifetime bounds error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:21:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box { | -- help: consider adding an explicit lifetime bound...: `A: 'b +` LL | box v as Box - | ^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-close-over-type-parameter-1.rs:21:5 - | -LL | box v as Box - | ^^^^^ + | ^^^^^ ...so that the type `A` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr index 3b1a89d9ced77..705d21078ecd7 100644 --- a/src/test/ui/regions/regions-close-param-into-object.stderr +++ b/src/test/ui/regions/regions-close-param-into-object.stderr @@ -5,13 +5,7 @@ LL | fn p1(v: T) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:6:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:12:5 @@ -20,13 +14,7 @@ LL | fn p2(v: Box) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `std::boxed::Box` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:12:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `std::boxed::Box` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:18:5 @@ -35,13 +23,7 @@ LL | fn p3<'a,T>(v: T) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:18:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:24:5 @@ -50,13 +32,7 @@ LL | fn p4<'a,T>(v: Box) -> Box | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) - | ^^^^^^^^^^^ - | -note: ...so that the type `std::boxed::Box` will meet its required lifetime bounds - --> $DIR/regions-close-param-into-object.rs:24:5 - | -LL | Box::new(v) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `std::boxed::Box` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index 297fcb088d2bf..e32a36f72cd14 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:18:18 - | -LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 @@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:23:25 - | -LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 @@ -37,16 +25,7 @@ LL | enum RefDouble<'a, 'b, T> { LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) LL | | LL | | } - | |_^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | / enum RefDouble<'a, 'b, T> { -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ + | |_^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 @@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:36:23 - | -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr index 2f1a4cea8e9ac..ea59ea11a143c 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -5,13 +5,7 @@ LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) | -- help: consider adding an explicit lifetime bound...: `T: 'x +` LL | { LL | wf::<&'x T>(); - | ^^^^^ - | -note: ...so that the reference type `&'x T` does not outlive the data it points at - --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10 - | -LL | wf::<&'x T>(); - | ^^^^^ + | ^^^^^ ...so that the reference type `&'x T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr index bcdadd7a73d6c..4ca5ac291d5be 100644 --- a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr +++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr @@ -5,11 +5,7 @@ LL | check_bound(x, self) | ^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `Self: 'a`... -note: ...so that the type `Self` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait-self.rs:46:9 - | -LL | check_bound(x, self) - | ^^^^^^^^^^^ + = note: ...so that the type `Self` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr index a5a0ff52fac12..196ee8ca7c0b5 100644 --- a/src/test/ui/regions/regions-infer-bound-from-trait.stderr +++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn bar1<'a,A>(x: Inv<'a>, a: A) { | - help: consider adding an explicit lifetime bound...: `A: 'a` LL | check_bound(x, a) - | ^^^^^^^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait.rs:33:5 - | -LL | check_bound(x, a) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:37:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) { | -- help: consider adding an explicit lifetime bound...: `A: 'a +` LL | check_bound(x, a) - | ^^^^^^^^^^^ - | -note: ...so that the type `A` will meet its required lifetime bounds - --> $DIR/regions-infer-bound-from-trait.rs:37:5 - | -LL | check_bound(x, a) - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr index c3cfc5a4d97c8..2bb51731583a6 100644 --- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar - | ^^^^^^^^^^^ - | -note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/dont-infer-static.rs:8:5 - | -LL | bar: Bar - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index 297fcb088d2bf..e32a36f72cd14 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum Ref1<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:18:18 - | -LL | Ref1Variant1(RequireOutlives<'a, T>) - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 @@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:23:25 - | -LL | Ref2Variant2(isize, RequireOutlives<'a, T>), - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 @@ -37,16 +25,7 @@ LL | enum RefDouble<'a, 'b, T> { LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) LL | | LL | | } - | |_^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:35:1 - | -LL | / enum RefDouble<'a, 'b, T> { -LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) -LL | | -LL | | } - | |_^ + | |_^ ...so that the type `T` will meet its required lifetime bounds error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 @@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | enum RefDouble<'a, 'b, T> { | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-enum-not-wf.rs:36:23 - | -LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index f6658891fa622..44812a51778a7 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for usize { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a T; - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a T` does not outlive the data it points at - --> $DIR/regions-struct-not-wf.rs:13:5 - | -LL | type Out = &'a T; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:21:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for u32 { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = RefOk<'a, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/regions-struct-not-wf.rs:21:5 - | -LL | type Out = RefOk<'a, T>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references --> $DIR/regions-struct-not-wf.rs:25:5 diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 91075ffbdb605..1aeabce5e8aaf 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -2,15 +2,10 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^ ---------- this return type evaluates to the `'static` lifetime... - | | - | ...but this borrow... - | -note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26 - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone { self } - | ^ + | ^^^^ ---------- ---------- ...and required to be `'static` by this + | | | + | | data with this lifetime... + | ...is captured here... error: aborting due to previous error diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr index 47ab6fff83878..04c475be787b8 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr @@ -2,19 +2,15 @@ error: cannot infer an appropriate lifetime --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44 | LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ---------- ^^^^ ...but this borrow... - | | - | this return type evaluates to the `'static` lifetime... + | ---------- ---------- ^^^^ ...and is captured here + | | | + | | ...is required to be `'static` by this... + | data with this lifetime... | -note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5 - --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:5 - | -LL | fn f(self: Pin<&Self>) -> impl Clone { self } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5 +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5 | LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ^^^^^^^^^^^^^^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/fn-trait-notation.fixed b/src/test/ui/suggestions/fn-trait-notation.fixed new file mode 100644 index 0000000000000..cf940f4e9267a --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.fixed @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658(f: F, g: G, h: H) -> i32 +where + F: Fn(i32) -> i32, //~ ERROR E0658 + G: Fn(i32, i32) -> (i32, i32), //~ ERROR E0658 + H: Fn(i32) -> i32, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/src/test/ui/suggestions/fn-trait-notation.rs b/src/test/ui/suggestions/fn-trait-notation.rs new file mode 100644 index 0000000000000..f0bb03315d987 --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.rs @@ -0,0 +1,19 @@ +// run-rustfix +fn e0658(f: F, g: G, h: H) -> i32 +where + F: Fn, //~ ERROR E0658 + G: Fn<(i32, i32, ), Output = (i32, i32)>, //~ ERROR E0658 + H: Fn<(i32,), Output = i32>, //~ ERROR E0658 +{ + f(3); + g(3, 4); + h(3) +} + +fn main() { + e0658( + |a| a, + |a, b| (b, a), + |a| a, + ); +} diff --git a/src/test/ui/suggestions/fn-trait-notation.stderr b/src/test/ui/suggestions/fn-trait-notation.stderr new file mode 100644 index 0000000000000..3e3b541744017 --- /dev/null +++ b/src/test/ui/suggestions/fn-trait-notation.stderr @@ -0,0 +1,30 @@ +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:4:8 + | +LL | F: Fn, + | ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:5:8 + | +LL | G: Fn<(i32, i32, ), Output = (i32, i32)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change + --> $DIR/fn-trait-notation.rs:6:8 + | +LL | H: Fn<(i32,), Output = i32>, + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | + = note: see issue #29625 for more information + = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr new file mode 100644 index 0000000000000..2072b00f7b2cb --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr @@ -0,0 +1,115 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error: lifetime may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:15:37 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | - ^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1... + --> $DIR/missing-lifetimes-in-signature.rs:25:1 + | +LL | / fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1... + --> $DIR/missing-lifetimes-in-signature.rs:47:1 + | +LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5... + --> $DIR/missing-lifetimes-in-signature.rs:59:5 + | +LL | / fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { +LL | | +LL | | move || { +LL | | *dest = g.get(); +LL | | } +LL | | } + | |_____^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:68:45 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 68:1... + --> $DIR/missing-lifetimes-in-signature.rs:68:1 + | +LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ + +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:73:5 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` +... +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ lifetime `'a` required + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:79:44 + | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `G: 'a`... + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0261, E0309, E0621. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs new file mode 100644 index 0000000000000..d3853445dfdfe --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -0,0 +1,110 @@ +pub trait Get { + fn get(self) -> T; +} + +struct Foo { + x: usize, +} + +impl Get for Foo { + fn get(self) -> usize { + self.x + } +} + +fn foo(g: G, dest: &mut T) -> impl FnOnce() +where + G: Get +{ + move || { //~ ERROR cannot infer an appropriate lifetime + *dest = g.get(); + } +} + +// After applying suggestion for `foo`: +fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + + +// After applying suggestion for `bar`: +fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// After applying suggestion for `baz`: +fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// Same as above, but show that we pay attention to lifetime names from parent item +impl<'a> Foo { + fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + //~^ ERROR the parameter type `G` may not live long enough + move || { + *dest = g.get(); + } + } +} + +// After applying suggestion for `qux`: +fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a +//~^ ERROR explicit lifetime required in the type of `dest` +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// Potential incorrect attempt: +fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +//~^ ERROR the parameter type `G` may not live long enough +where + G: Get +{ + move || { + *dest = g.get(); + } +} + + +// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure: +fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: +fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +where + G: Get +{ + move || { + *dest = g.get(); + } +} + +fn main() {} diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr new file mode 100644 index 0000000000000..5cf170d566ca9 --- /dev/null +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -0,0 +1,126 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/missing-lifetimes-in-signature.rs:37:11 + | +LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `'a,` + +error: cannot infer an appropriate lifetime + --> $DIR/missing-lifetimes-in-signature.rs:19:5 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + | ------ ------------- ...is required to be `'static` by this... + | | + | data with this lifetime... +... +LL | / move || { +LL | | *dest = g.get(); +LL | | } + | |_____^ ...and is captured here + | +help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1 + | +LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1... + --> $DIR/missing-lifetimes-in-signature.rs:25:1 + | +LL | / fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:25:37 + | +LL | fn bar(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound + | +LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ^^^^^ ^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1... + --> $DIR/missing-lifetimes-in-signature.rs:47:1 + | +LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | | +LL | | where +LL | | G: Get +... | +LL | | } +LL | | } + | |_^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:47:45 + | +LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound + | +LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b + | ^^^ ^^^^^^^ ^^^^ + +error[E0311]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5... + --> $DIR/missing-lifetimes-in-signature.rs:59:5 + | +LL | / fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { +LL | | +LL | | move || { +LL | | *dest = g.get(); +LL | | } +LL | | } + | |_____^ +note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds + --> $DIR/missing-lifetimes-in-signature.rs:59:58 + | +LL | fn qux<'b, G: Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | ^^^^^^^^^^^^^^^^^^ +help: consider introducing an explicit lifetime bound + | +LL | fn qux<'c, 'b, G: 'c + Get + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c { + | ^^^ ^^^^^^^ ^^^^ + +error[E0621]: explicit lifetime required in the type of `dest` + --> $DIR/missing-lifetimes-in-signature.rs:68:45 + | +LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | | + | help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T` + +error[E0309]: the parameter type `G` may not live long enough + --> $DIR/missing-lifetimes-in-signature.rs:79:44 + | +LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + | - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6 g:G, dest:&mut T]` will meet its required lifetime bounds + | | + | help: consider adding an explicit lifetime bound...: `G: 'a` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0261, E0309, E0621. +For more information about an error, try `rustc --explain E0261`. diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr index b6e6c0bbf32df..643dac2572497 100644 --- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -5,13 +5,7 @@ LL | fn foo(d: impl Debug) { | ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static` LL | LL | bar(d); - | ^^^ - | -note: ...so that the type `impl Debug` will meet its required lifetime bounds - --> $DIR/suggest-impl-trait-lifetime.rs:7:5 - | -LL | bar(d); - | ^^^ + | ^^^ ...so that the type `impl Debug` will meet its required lifetime bounds error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 22e2391f8380b..e2540e424cb19 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -22,16 +22,10 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/generic_type_does_not_live_long_enough.rs:9:1 | LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds ... LL | fn wrong_generic(t: T) -> WrongGeneric { | - help: consider adding an explicit lifetime bound...: `T: 'static` - | -note: ...so that the type `T` will meet its required lifetime bounds - --> $DIR/generic_type_does_not_live_long_enough.rs:9:1 - | -LL | type WrongGeneric = impl 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index e3c9d50dfe5b3..3577dd59289e5 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,31 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements +error: cannot infer an appropriate lifetime --> $DIR/dyn-trait-underscore.rs:8:20 | +LL | fn a(items: &[T]) -> Box> { + | ---- data with this lifetime... +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) - | ^^^^ + | ---------------^^^^--- ...is captured and required to be `'static` here | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 6:1... - --> $DIR/dyn-trait-underscore.rs:6:1 +help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1 | -LL | / fn a(items: &[T]) -> Box> { -LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` -LL | | Box::new(items.iter()) -LL | | } - | |_^ -note: ...so that reference does not outlive borrowed content - --> $DIR/dyn-trait-underscore.rs:8:14 - | -LL | Box::new(items.iter()) - | ^^^^^ - = note: but, the lifetime must be valid for the static lifetime... -note: ...so that the expression is assignable - --> $DIR/dyn-trait-underscore.rs:8:5 - | -LL | Box::new(items.iter()) - | ^^^^^^^^^^^^^^^^^^^^^^ - = note: expected `std::boxed::Box<(dyn std::iter::Iterator + 'static)>` - found `std::boxed::Box>` +LL | fn a(items: &[T]) -> Box + '_> { + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr index 9942c80effe4b..f3b32ad3f7e85 100644 --- a/src/test/ui/wf/wf-impl-associated-type-region.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Foo<'a> for T { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Bar = &'a T; - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a T` does not outlive the data it points at - --> $DIR/wf-impl-associated-type-region.rs:10:5 - | -LL | type Bar = &'a T; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr index 7dc8f5a96611b..a79c446247794 100644 --- a/src/test/ui/wf/wf-in-fn-type-static.stderr +++ b/src/test/ui/wf/wf-in-fn-type-static.stderr @@ -5,13 +5,7 @@ LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: fn() -> &'static T - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-fn-type-static.rs:13:5 - | -LL | x: fn() -> &'static T - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:18:5 @@ -20,13 +14,7 @@ LL | struct Bar { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: Copy LL | x: fn(&'static T) - | ^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-fn-type-static.rs:18:5 - | -LL | x: fn(&'static T) - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr index 32c3198d55be4..c0057f3c82977 100644 --- a/src/test/ui/wf/wf-in-obj-type-static.stderr +++ b/src/test/ui/wf/wf-in-obj-type-static.stderr @@ -5,13 +5,7 @@ LL | struct Foo { | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: dyn Object<&'static T> - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'static T` does not outlive the data it points at - --> $DIR/wf-in-obj-type-static.rs:14:5 - | -LL | x: dyn Object<&'static T> - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at error: aborting due to previous error diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr index 52786fb3bca96..4c25ab9593958 100644 --- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr +++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for usize { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a fn(T); - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a fn(T)` does not outlive the data it points at - --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5 - | -LL | type Out = &'a fn(T); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5 @@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough LL | impl<'a, T> Trait<'a, T> for u32 { | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a dyn Baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at - --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5 - | -LL | type Out = &'a dyn Baz; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz + 'a)` does not outlive the data it points at error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-trait-associated-type-region.stderr b/src/test/ui/wf/wf-trait-associated-type-region.stderr index 9bbfad90cdb85..ae681ba6c9bb5 100644 --- a/src/test/ui/wf/wf-trait-associated-type-region.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-region.stderr @@ -5,11 +5,7 @@ LL | type Type2 = &'a Self::Type1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Type1: 'a`... -note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at - --> $DIR/wf-trait-associated-type-region.rs:9:5 - | -LL | type Type2 = &'a Self::Type1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...so that the reference type `&'a >::Type1` does not outlive the data it points at error: aborting due to previous error