diff --git a/.gitmodules b/.gitmodules index 984113151de4d..40e6fc2c19db0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,7 +37,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/11.0-2020-10-12 + branch = rustc/11.0-2021-01-05 [submodule "src/doc/embedded-book"] path = src/doc/embedded-book url = https://github.com/rust-embedded/book.git diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 305fa838afad2..b7edc24bc4a1a 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -363,8 +363,15 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> { fn get_source(input: &Input, sess: &Session) -> (String, FileName) { let src_name = input.source_name(); - let src = - String::clone(&sess.source_map().get_source_file(&src_name).unwrap().src.as_ref().unwrap()); + let src = String::clone( + &sess + .source_map() + .get_source_file(&src_name) + .expect("get_source_file") + .src + .as_ref() + .expect("src"), + ); (src, src_name) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7b0a91986b3a3..5d56744805f89 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -98,7 +98,7 @@ pub(super) fn note_and_explain_region( // uh oh, hope no user ever sees THIS ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None), - ty::RePlaceholder(_) => ("any other region".to_string(), None), + ty::RePlaceholder(_) => return, // FIXME(#13998) RePlaceholder should probably print like // ReFree rather than dumping Debug output on the user. @@ -1675,6 +1675,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.check_and_note_conflicting_crates(diag, terr); self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id()); + if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values { + if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() { + if let Some(def_id) = def_id.as_local() { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let span = self.tcx.hir().span(hir_id); + diag.span_note(span, "this closure does not fulfill the lifetime requirements"); + } + } + } + // It reads better to have the error origin as the final // thing. self.note_error_origin(diag, cause, exp_found); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 7fb94332cad5c..c88869abc29e4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -1,6 +1,7 @@ use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; use crate::infer::{self, InferCtxt, SubregionOrigin}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Region}; @@ -107,14 +108,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); let mut err = self.report_and_explain_type_error(trace, &terr); - note_and_explain_region(self.tcx, &mut err, "", sup, "..."); - note_and_explain_region( - self.tcx, - &mut err, - "...does not necessarily outlive ", - sub, - "", - ); + match (sub, sup) { + (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} + (ty::RePlaceholder(_), _) => { + note_and_explain_region( + self.tcx, + &mut err, + "", + sup, + " doesn't meet the lifetime requirements", + ); + } + (_, ty::RePlaceholder(_)) => { + note_and_explain_region( + self.tcx, + &mut err, + "the required lifetime does not necessarily outlive ", + sub, + "", + ); + } + _ => { + note_and_explain_region(self.tcx, &mut err, "", sup, "..."); + note_and_explain_region( + self.tcx, + &mut err, + "...does not necessarily outlive ", + sub, + "", + ); + } + } err } infer::Reborrow(span) => { @@ -286,13 +310,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sup: Region<'tcx>, ) -> DiagnosticBuilder<'tcx> { // I can't think how to do better than this right now. -nikomatsakis + debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); match placeholder_origin { + infer::Subtype(box ref trace) + if matches!( + &trace.cause.code.peel_derives(), + ObligationCauseCode::BindingObligation(..) + ) => + { + // Hack to get around the borrow checker because trace.cause has an `Rc`. + if let ObligationCauseCode::BindingObligation(_, span) = + &trace.cause.code.peel_derives() + { + let span = *span; + let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); + err.span_note(span, "the lifetime requirement is introduced here"); + err + } else { + unreachable!() + } + } infer::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; - self.report_and_explain_type_error(trace, &terr) + return self.report_and_explain_type_error(trace, &terr); } - - _ => self.report_concrete_failure(placeholder_origin, sub, sup), + _ => return self.report_concrete_failure(placeholder_origin, sub, sup), } } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5cece569903c7..37bdc878b16cd 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -10,7 +10,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::map::Map; -use rustc_middle::lint::LevelSource; +use rustc_middle::lint::LevelAndSource; use rustc_middle::lint::LintDiagnosticBuilder; use rustc_middle::lint::{ struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet, @@ -106,9 +106,9 @@ impl<'s> LintLevelsBuilder<'s> { /// diagnostic with no change to `specs`. fn insert_spec( &mut self, - specs: &mut FxHashMap, + specs: &mut FxHashMap, id: LintId, - (level, src): LevelSource, + (level, src): LevelAndSource, ) { // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 64d850192f449..80c87dddd5614 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -46,7 +46,7 @@ impl LintLevelSource { } /// A tuple of a lint level and its source. -pub type LevelSource = (Level, LintLevelSource); +pub type LevelAndSource = (Level, LintLevelSource); pub struct LintLevelSets { pub list: Vec, @@ -57,11 +57,11 @@ pub enum LintSet { CommandLine { // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which // flag. - specs: FxHashMap, + specs: FxHashMap, }, Node { - specs: FxHashMap, + specs: FxHashMap, parent: u32, }, } @@ -75,9 +75,9 @@ impl LintLevelSets { &self, lint: &'static Lint, idx: u32, - aux: Option<&FxHashMap>, + aux: Option<&FxHashMap>, sess: &Session, - ) -> LevelSource { + ) -> LevelAndSource { let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); // If `level` is none then we actually assume the default level for this @@ -113,7 +113,7 @@ impl LintLevelSets { &self, id: LintId, mut idx: u32, - aux: Option<&FxHashMap>, + aux: Option<&FxHashMap>, ) -> (Option, LintLevelSource) { if let Some(specs) = aux { if let Some(&(level, src)) = specs.get(&id) { @@ -157,7 +157,7 @@ impl LintLevelMap { lint: &'static Lint, id: HirId, session: &Session, - ) -> Option { + ) -> Option { self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session)) } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 698c25215968b..f810f6a56a520 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,6 +1,7 @@ use crate::dep_graph::{dep_constructor, DepNode, WorkProduct, WorkProductId}; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; +use rustc_attr::InlineAttr; use rustc_data_structures::base_n; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -78,6 +79,14 @@ impl<'tcx> MonoItem<'tcx> { } pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode { + let generate_cgu_internal_copies = tcx + .sess + .opts + .debugging_opts + .inline_in_all_cgus + .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No) + && !tcx.sess.link_dead_code(); + match *self { MonoItem::Fn(ref instance) => { let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); @@ -90,26 +99,21 @@ impl<'tcx> MonoItem<'tcx> { return InstantiationMode::GloballyShared { may_conflict: false }; } - let generate_cgu_internal_copies = tcx - .sess - .opts - .debugging_opts - .inline_in_all_cgus - .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No) - && !tcx.sess.link_dead_code(); - // At this point we don't have explicit linkage and we're an - // inlined function. If we should generate local copies for each CGU, - // then return `LocalCopy`, otherwise we'll just generate one copy - // and share it with all CGUs in this crate. + // inlined function. If we're inlining into all CGUs then we'll + // be creating a local copy per CGU. if generate_cgu_internal_copies { - InstantiationMode::LocalCopy - } else { - // Finally, if we've reached this point, then we should optimize for - // compilation speed. In that regard, we will ignore any `#[inline]` - // annotations on the function and simply codegen it as usual. This could - // conflict with upstream crates as it could be an exported symbol. - InstantiationMode::GloballyShared { may_conflict: true } + return InstantiationMode::LocalCopy; + } + + // Finally, if this is `#[inline(always)]` we're sure to respect + // that with an inline copy per CGU, but otherwise we'll be + // creating one copy of this `#[inline]` function which may + // conflict with upstream crates as it could be an exported + // symbol. + match tcx.codegen_fn_attrs(instance.def_id()).inline { + InlineAttr::Always => InstantiationMode::LocalCopy, + _ => InstantiationMode::GloballyShared { may_conflict: true }, } } MonoItem::Static(..) | MonoItem::GlobalAsm(..) => { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 0af884a286d6e..041c040f0b7e2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -92,8 +92,7 @@ impl<'tcx> Const<'tcx> { let item_id = tcx.hir().get_parent_node(hir_id); let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id.to_def_id()); - let index = - generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id).to_def_id()]; + let index = generics.param_def_id_to_index[&def_id]; let name = tcx.hir().name(hir_id); ty::ConstKind::Param(ty::ParamConst::new(index, name)) } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 417f9bded0988..625a0989ab353 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -813,8 +813,7 @@ fn convert_path_expr<'a, 'tcx>( let item_id = cx.tcx.hir().get_parent_node(hir_id); let item_def_id = cx.tcx.hir().local_def_id(item_id); let generics = cx.tcx.generics_of(item_def_id); - let local_def_id = cx.tcx.hir().local_def_id(hir_id); - let index = generics.param_def_id_to_index[&local_def_id.to_def_id()]; + let index = generics.param_def_id_to_index[&def_id]; let name = cx.tcx.hir().name(hir_id); let val = ty::ConstKind::Param(ty::ParamConst::new(index, name)); ExprKind::Literal { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 6635d44496c03..a7b8c8ba1d492 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -872,8 +872,10 @@ impl SourceMap { } pub fn get_source_file(&self, filename: &FileName) -> Option> { + // Remap filename before lookup + let filename = self.path_mapping().map_filename_prefix(filename).0; for sf in self.files.borrow().source_files.iter() { - if *filename == sf.name { + if filename == sf.name { return Some(sf.clone()); } } @@ -1041,4 +1043,15 @@ impl FilePathMapping { (path, false) } + + fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) { + match file { + FileName::Real(realfile) => { + let path = realfile.local_path(); + let (path, mapped) = self.map_prefix(path.to_path_buf()); + (FileName::Real(RealFileName::Named(path)), mapped) + } + other => (other.clone(), false), + } + } } diff --git a/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs new file mode 100644 index 0000000000000..f329b2d2c8858 --- /dev/null +++ b/compiler/rustc_target/src/spec/i386_unknown_linux_gnu.rs @@ -0,0 +1,8 @@ +use crate::spec::Target; + +pub fn target() -> Target { + let mut base = super::i686_unknown_linux_gnu::target(); + base.cpu = "i386".to_string(); + base.llvm_target = "i386-unknown-linux-gnu".to_string(); + base +} diff --git a/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs new file mode 100644 index 0000000000000..5d96a558cb72a --- /dev/null +++ b/compiler/rustc_target/src/spec/i486_unknown_linux_gnu.rs @@ -0,0 +1,8 @@ +use crate::spec::Target; + +pub fn target() -> Target { + let mut base = super::i686_unknown_linux_gnu::target(); + base.cpu = "i486".to_string(); + base.llvm_target = "i486-unknown-linux-gnu".to_string(); + base +} diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 2728e03171a75..c22f001744639 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -32,6 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { return; } + self.suggest_no_capture_closure(err, expected, expr_ty); self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty); self.suggest_missing_parentheses(err, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 17dbf989d6683..9fbf330fe0208 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -2,7 +2,7 @@ use super::FnCtxt; use crate::astconv::AstConv; use rustc_ast::util::parser::ExprPrecedence; -use rustc_span::{self, Span}; +use rustc_span::{self, MultiSpan, Span}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -287,6 +287,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// When encountering a closure that captures variables, where a FnPtr is expected, + /// suggest a non-capturing closure + pub(in super::super) fn suggest_no_capture_closure( + &self, + err: &mut DiagnosticBuilder<'_>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) { + if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) { + if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) { + // Report upto four upvars being captured to reduce the amount error messages + // reported back to the user. + let spans_and_labels = upvars + .iter() + .take(4) + .map(|(var_hir_id, upvar)| { + let var_name = self.tcx.hir().name(*var_hir_id).to_string(); + let msg = format!("`{}` captured here", var_name); + (upvar.span, msg) + }) + .collect::>(); + + let mut multi_span: MultiSpan = + spans_and_labels.iter().map(|(sp, _)| *sp).collect::>().into(); + for (sp, label) in spans_and_labels { + multi_span.push_span_label(sp, label); + } + err.span_note(multi_span, "closures can only be coerced to `fn` types if they do not capture any variables"); + } + } + } + /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`. pub(in super::super) fn suggest_calling_boxed_future_when_appropriate( &self, diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 7e8e0a621e31c..95e18ef2a6543 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -95,11 +95,12 @@ mod tests; // a backtrace or actually symbolizing it. use crate::backtrace_rs::{self, BytesOrWideString}; +use crate::cell::UnsafeCell; use crate::env; use crate::ffi::c_void; use crate::fmt; use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; -use crate::sync::Mutex; +use crate::sync::Once; use crate::sys_common::backtrace::{lock, output_filename}; use crate::vec::Vec; @@ -132,7 +133,7 @@ pub enum BacktraceStatus { enum Inner { Unsupported, Disabled, - Captured(Mutex), + Captured(LazilyResolvedCapture), } struct Capture { @@ -171,12 +172,11 @@ enum BytesOrWide { impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut capture = match &self.inner { + let capture = match &self.inner { Inner::Unsupported => return fmt.write_str(""), Inner::Disabled => return fmt.write_str(""), - Inner::Captured(c) => c.lock().unwrap(), + Inner::Captured(c) => c.force(), }; - capture.resolve(); let frames = &capture.frames[capture.actual_start..]; @@ -331,7 +331,7 @@ impl Backtrace { let inner = if frames.is_empty() { Inner::Unsupported } else { - Inner::Captured(Mutex::new(Capture { + Inner::Captured(LazilyResolvedCapture::new(Capture { actual_start: actual_start.unwrap_or(0), frames, resolved: false, @@ -355,12 +355,11 @@ impl Backtrace { impl fmt::Display for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut capture = match &self.inner { + let capture = match &self.inner { Inner::Unsupported => return fmt.write_str("unsupported backtrace"), Inner::Disabled => return fmt.write_str("disabled backtrace"), - Inner::Captured(c) => c.lock().unwrap(), + Inner::Captured(c) => c.force(), }; - capture.resolve(); let full = fmt.alternate(); let (frames, style) = if full { @@ -404,6 +403,33 @@ impl fmt::Display for Backtrace { } } +struct LazilyResolvedCapture { + sync: Once, + capture: UnsafeCell, +} + +impl LazilyResolvedCapture { + fn new(capture: Capture) -> Self { + LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) } + } + + fn force(&self) -> &Capture { + self.sync.call_once(|| { + // SAFETY: This exclusive reference can't overlap with any others + // `Once` guarantees callers will block until this closure returns + // `Once` also guarantees only a single caller will enter this closure + unsafe { &mut *self.capture.get() }.resolve(); + }); + + // SAFETY: This shared reference can't overlap with the exclusive reference above + unsafe { &*self.capture.get() } + } +} + +// SAFETY: Access to the inner value is synchronized using a thread-safe `Once` +// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too +unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} + impl Capture { fn resolve(&mut self) { // If we're already resolved, nothing to do! diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs index f5f74d1eb9ae6..31cf0f702185c 100644 --- a/library/std/src/backtrace/tests.rs +++ b/library/std/src/backtrace/tests.rs @@ -3,7 +3,7 @@ use super::*; #[test] fn test_debug() { let backtrace = Backtrace { - inner: Inner::Captured(Mutex::new(Capture { + inner: Inner::Captured(LazilyResolvedCapture::new(Capture { actual_start: 1, resolved: true, frames: vec![ @@ -54,4 +54,7 @@ fn test_debug() { \n]"; assert_eq!(format!("{:#?}", backtrace), expected); + + // Format the backtrace a second time, just to make sure lazily resolved state is stable + assert_eq!(format!("{:#?}", backtrace), expected); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7ed64c5813fcd..efcb006870c5a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -412,11 +412,7 @@ fn opts() -> Vec { ) }), unstable("test-builder", |o| { - o.optflag( - "", - "test-builder", - "specified the rustc-like binary to use as the test builder", - ) + o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") }), unstable("check", |o| o.optflag("", "check", "Run rustdoc checks")), ] diff --git a/src/llvm-project b/src/llvm-project index fb115ee43b776..f9a8d70b6e036 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit fb115ee43b77601b237717c21ab0a8f5b5b9d50a +Subproject commit f9a8d70b6e0365ac2172ca6b7f1de0341297458d diff --git a/src/test/incremental/hygiene/load_cached_hygiene.rs b/src/test/incremental/hygiene/load_cached_hygiene.rs index d6a5cb993a467..8124141418bc3 100644 --- a/src/test/incremental/hygiene/load_cached_hygiene.rs +++ b/src/test/incremental/hygiene/load_cached_hygiene.rs @@ -1,5 +1,5 @@ // revisions:rpass1 rpass2 -// compile-flags: -Z query-dep-graph -O +// compile-flags: -Z query-dep-graph // aux-build:cached_hygiene.rs // This tests the folllowing scenario @@ -19,12 +19,7 @@ // the metadata. Specifically, we were not resetting `orig_id` // for an `EpxnData` generate in the current crate, which would cause // us to serialize the `ExpnId` pointing to a garbage location in -// the metadata.o - -// NOTE: We're explicitly passing the `-O` optimization flag because if optimizations are not -// enabled, then rustc will ignore the `#[inline(always)]` attribute which means we do not load -// the optimized mir for the unmodified function to be loaded and so the CGU containing that -// function will be reused. +// the metadata. #![feature(rustc_attrs)] diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs index 735635029dac9..b01f02444eae8 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -1,18 +1,11 @@ // revisions:rpass1 rpass2 rpass3 -// compile-flags: -Z query-dep-graph -g -O +// compile-flags: -Z query-dep-graph -g // aux-build:extern_crate.rs // ignore-asmjs wasm2js does not support source maps yet - // This test case makes sure that we detect if paths emitted into debuginfo // are changed, even when the change happens in an external crate. -// NOTE: We're explicitly passing the `-O` optimization flag because if no optimizations are -// requested, rustc will ignore the `#[inline]` attribute. This is a performance optimization for -// non-optimized builds which causes us to generate fewer copies of inlined functions when -// runtime performance doesn't matter. Without this flag, the function will go into a different -// CGU which can be reused by this crate. - #![feature(rustc_attrs)] #![rustc_partition_reused(module="main", cfg="rpass2")] diff --git a/src/test/pretty/expanded-and-path-remap-80832.pp b/src/test/pretty/expanded-and-path-remap-80832.pp new file mode 100644 index 0000000000000..6dbc19e9d9c6c --- /dev/null +++ b/src/test/pretty/expanded-and-path-remap-80832.pp @@ -0,0 +1,13 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::v1::*; +#[macro_use] +extern crate std; +// Test for issue 80832 +// +// pretty-mode:expanded +// pp-exact:expanded-and-path-remap-80832.pp +// compile-flags: --remap-path-prefix {{src-base}}=the/src + +fn main() { } diff --git a/src/test/pretty/expanded-and-path-remap-80832.rs b/src/test/pretty/expanded-and-path-remap-80832.rs new file mode 100644 index 0000000000000..f48441fbc5755 --- /dev/null +++ b/src/test/pretty/expanded-and-path-remap-80832.rs @@ -0,0 +1,7 @@ +// Test for issue 80832 +// +// pretty-mode:expanded +// pp-exact:expanded-and-path-remap-80832.pp +// compile-flags: --remap-path-prefix {{src-base}}=the/src + +fn main() {} diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile index d12a23fbbf013..0cab955f6442b 100644 --- a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile +++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile @@ -1,12 +1,7 @@ -include ../tools.mk all: - $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=0 - if ![cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b']; then \ - echo "not found call instruction when one was expected"; \ - exit 1; \ - fi - $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=1 + $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \ echo "found call instruction when one wasn't expected"; \ exit 1; \ diff --git a/src/test/rustdoc/issue-80893.rs b/src/test/rustdoc/issue-80893.rs new file mode 100644 index 0000000000000..7c958a80be395 --- /dev/null +++ b/src/test/rustdoc/issue-80893.rs @@ -0,0 +1,6 @@ +// compile-flags: --test -Z unstable-options --test-builder true + +/// ```no_run +/// This tests that `--test-builder` is accepted as a flag by rustdoc. +/// ``` +pub struct Foo; diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 811c9a8f5e12b..e2847b6b72b86 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -2,10 +2,15 @@ error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `&'a ()` found type `&()` +note: the lifetime requirement is introduced here + --> $DIR/higher-ranked-projection.rs:15:33 + | +LL | where for<'a> &'a T: Mirror + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/closures/closure-no-fn-1.stderr b/src/test/ui/closures/closure-no-fn-1.stderr index 76136315a1b8b..2b53802fea793 100644 --- a/src/test/ui/closures/closure-no-fn-1.stderr +++ b/src/test/ui/closures/closure-no-fn-1.stderr @@ -8,6 +8,11 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | = note: expected fn pointer `fn(u8) -> u8` found closure `[closure@$DIR/closure-no-fn-1.rs:6:29: 6:50]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-1.rs:6:39 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ^ `a` captured here error: aborting due to previous error diff --git a/src/test/ui/closures/closure-no-fn-2.stderr b/src/test/ui/closures/closure-no-fn-2.stderr index 85cbdbe7c18e1..ed9f87a2c94a8 100644 --- a/src/test/ui/closures/closure-no-fn-2.stderr +++ b/src/test/ui/closures/closure-no-fn-2.stderr @@ -8,6 +8,11 @@ LL | let bar: fn() -> u8 = || { b }; | = note: expected fn pointer `fn() -> u8` found closure `[closure@$DIR/closure-no-fn-2.rs:6:27: 6:35]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-2.rs:6:32 + | +LL | let bar: fn() -> u8 = || { b }; + | ^ `b` captured here error: aborting due to previous error diff --git a/src/test/ui/closures/closure-no-fn-4.rs b/src/test/ui/closures/closure-no-fn-4.rs new file mode 100644 index 0000000000000..275bff645dba6 --- /dev/null +++ b/src/test/ui/closures/closure-no-fn-4.rs @@ -0,0 +1,8 @@ +fn main() { + let b = 2; + let _: fn(usize) -> usize = match true { + true => |a| a + 1, + false => |a| a - b, + //~^ ERROR `match` arms have incompatible types + }; +} diff --git a/src/test/ui/closures/closure-no-fn-4.stderr b/src/test/ui/closures/closure-no-fn-4.stderr new file mode 100644 index 0000000000000..89798ec5dd34f --- /dev/null +++ b/src/test/ui/closures/closure-no-fn-4.stderr @@ -0,0 +1,24 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/closure-no-fn-4.rs:5:18 + | +LL | let _: fn(usize) -> usize = match true { + | _________________________________- +LL | | true => |a| a + 1, + | | --------- this is found to be of type `fn(usize) -> usize` +LL | | false => |a| a - b, + | | ^^^^^^^^^ expected fn pointer, found closure +LL | | +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn pointer `fn(usize) -> usize` + found closure `[closure@$DIR/closure-no-fn-4.rs:5:18: 5:27]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-4.rs:5:26 + | +LL | false => |a| a - b, + | ^ `b` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/closure-no-fn-5.rs b/src/test/ui/closures/closure-no-fn-5.rs new file mode 100644 index 0000000000000..43e3e977e34ab --- /dev/null +++ b/src/test/ui/closures/closure-no-fn-5.rs @@ -0,0 +1,12 @@ +// When providing diagnostics about not being able to coerce a capturing-closure +// to fn type, we want to report only upto 4 captures. + +fn main() { + let a = 0u8; + let b = 0u8; + let c = 0u8; + let d = 0u8; + let e = 0u8; + let bar: fn() -> u8 = || { a; b; c; d; e }; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/closures/closure-no-fn-5.stderr b/src/test/ui/closures/closure-no-fn-5.stderr new file mode 100644 index 0000000000000..1f373f10489e6 --- /dev/null +++ b/src/test/ui/closures/closure-no-fn-5.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/closure-no-fn-5.rs:10:27 + | +LL | let bar: fn() -> u8 = || { a; b; c; d; e }; + | ---------- ^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure + | | + | expected due to this + | + = note: expected fn pointer `fn() -> u8` + found closure `[closure@$DIR/closure-no-fn-5.rs:10:27: 10:47]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-no-fn-5.rs:10:32 + | +LL | let bar: fn() -> u8 = || { a; b; c; d; e }; + | ^ ^ ^ ^ `d` captured here + | | | | + | | | `c` captured here + | | `b` captured here + | `a` captured here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr index 77c8c7ab7948d..37813879ce752 100644 --- a/src/test/ui/closures/closure-reform-bad.stderr +++ b/src/test/ui/closures/closure-reform-bad.stderr @@ -8,6 +8,11 @@ LL | call_bare(f) | = note: expected fn pointer `for<'r> fn(&'r str)` found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:50]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-reform-bad.rs:10:43 + | +LL | let f = |s: &str| println!("{}{}", s, string); + | ^^^^^^ `string` captured here error: aborting due to previous error diff --git a/src/test/ui/closures/print/closure-print-verbose.stderr b/src/test/ui/closures/print/closure-print-verbose.stderr index 9e07137a24195..d19b07acbf175 100644 --- a/src/test/ui/closures/print/closure-print-verbose.stderr +++ b/src/test/ui/closures/print/closure-print-verbose.stderr @@ -8,6 +8,11 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | = note: expected fn pointer `fn(u8) -> u8` found closure `[main::{closure#0} closure_substs=(unavailable)]` +note: closures can only be coerced to `fn` types if they do not capture any variables + --> $DIR/closure-print-verbose.rs:10:39 + | +LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; + | ^ `a` captured here error: aborting due to previous error diff --git a/src/test/ui/extern/extern-compare-with-return-type.rs b/src/test/ui/extern/extern-compare-with-return-type.rs index 6c9ed3760f6e4..52b51bb943aa6 100644 --- a/src/test/ui/extern/extern-compare-with-return-type.rs +++ b/src/test/ui/extern/extern-compare-with-return-type.rs @@ -2,8 +2,9 @@ // Tests that we can compare various kinds of extern fn signatures. #![allow(non_camel_case_types)] -extern fn voidret1() {} -extern fn voidret2() {} +// `dbg!()` differentiates these functions to ensure they won't be merged. +extern fn voidret1() { dbg!() } +extern fn voidret2() { dbg!() } extern fn uintret() -> usize { 22 } diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index dc0864165abf4..63411b59280bb 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -2,19 +2,47 @@ error[E0308]: mismatched types --> $DIR/resume-arg-late-bound.rs:15:5 | LL | test(gen); - | ^^^^ one type is more general than the other + | ^^^^ lifetime mismatch | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` +note: the required lifetime does not necessarily outlive the anonymous lifetime #1 defined on the body at 11:15 + --> $DIR/resume-arg-late-bound.rs:11:15 + | +LL | let gen = |arg: &mut bool| { + | _______________^ +LL | | yield (); +LL | | *arg = true; +LL | | }; + | |_____^ +note: the lifetime requirement is introduced here + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/resume-arg-late-bound.rs:15:5 | LL | test(gen); - | ^^^^ one type is more general than the other + | ^^^^ lifetime mismatch | = note: expected type `for<'a> Generator<&'a mut bool>` found type `Generator<&mut bool>` +note: the anonymous lifetime #1 defined on the body at 11:15 doesn't meet the lifetime requirements + --> $DIR/resume-arg-late-bound.rs:11:15 + | +LL | let gen = |arg: &mut bool| { + | _______________^ +LL | | yield (); +LL | | *arg = true; +LL | | }; + | |_____^ +note: the lifetime requirement is introduced here + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 1ceb0c99e90e9..ed810d443bef7 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -2,19 +2,39 @@ error[E0308]: mismatched types --> $DIR/hrtb-perfect-forwarding.rs:46:5 | LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected type `Bar<&'a isize>` found type `Bar<&'b isize>` +note: the required lifetime does not necessarily outlive the lifetime `'b` as defined on the function body at 39:21 + --> $DIR/hrtb-perfect-forwarding.rs:39:21 + | +LL | fn foo_hrtb_bar_not<'b,T>(mut t: T) + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/hrtb-perfect-forwarding.rs:40:15 + | +LL | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/hrtb-perfect-forwarding.rs:46:5 | LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^ one type is more general than the other + | ^^^^^^^^^^^^^^^^ lifetime mismatch | = note: expected type `Bar<&'a isize>` found type `Bar<&'b isize>` +note: the lifetime `'b` as defined on the function body at 39:21 doesn't meet the lifetime requirements + --> $DIR/hrtb-perfect-forwarding.rs:39:21 + | +LL | fn foo_hrtb_bar_not<'b,T>(mut t: T) + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/hrtb-perfect-forwarding.rs:40:15 + | +LL | where T : for<'a> Foo<&'a isize> + Bar<&'b isize> + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-26217.stderr b/src/test/ui/issues/issue-26217.stderr index b1625536d4202..f5c641be2d47c 100644 --- a/src/test/ui/issues/issue-26217.stderr +++ b/src/test/ui/issues/issue-26217.stderr @@ -3,8 +3,6 @@ error[E0477]: the type `&'a i32` does not fulfill the required lifetime | LL | foo::<&'a i32>(); | ^^^^^^^^^^^^^^ - | - = note: type must outlive any other region error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57843.stderr b/src/test/ui/issues/issue-57843.stderr index 01edb9507a3a7..7699e97da99ad 100644 --- a/src/test/ui/issues/issue-57843.stderr +++ b/src/test/ui/issues/issue-57843.stderr @@ -6,6 +6,11 @@ LL | Foo(Box::new(|_| ())); | = note: expected type `FnOnce<(&'a bool,)>` found type `FnOnce<(&bool,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57843.rs:23:18 + | +LL | Foo(Box::new(|_| ())); + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr new file mode 100644 index 0000000000000..4970c579e7b98 --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr @@ -0,0 +1,44 @@ +error: lifetime may not live long enough + --> $DIR/issue-79187-2.rs:9:24 + | +LL | take_foo(|a: &i32| a); + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is &'2 i32 + | let's call the lifetime of this reference `'1` + +error: lifetime may not live long enough + --> $DIR/issue-79187-2.rs:10:34 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | - - ^ returning this value requires that `'1` must outlive `'2` + | | | + | | let's call the lifetime of this reference `'2` + | let's call the lifetime of this reference `'1` + +error: higher-ranked subtype error + --> $DIR/issue-79187-2.rs:8:5 + | +LL | take_foo(|a| a); + | ^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-79187-2.rs:8:5 + | +LL | take_foo(|a| a); + | ^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-79187-2.rs:9:5 + | +LL | take_foo(|a: &i32| a); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-79187-2.rs:10:5 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/lifetimes/issue-79187-2.rs b/src/test/ui/lifetimes/issue-79187-2.rs new file mode 100644 index 0000000000000..29d108facab3f --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187-2.rs @@ -0,0 +1,23 @@ +trait Foo {} + +impl Foo for F where F: Fn(&i32) -> &i32 {} + +fn take_foo(_: impl Foo) {} + +fn main() { + take_foo(|a| a); //~ ERROR mismatched types + take_foo(|a: &i32| a); //~ ERROR mismatched types + take_foo(|a: &i32| -> &i32 { a }); //~ ERROR mismatched types + + // OK + take_foo(identity(|a| a)); + take_foo(identity(|a: &i32| a)); + take_foo(identity(|a: &i32| -> &i32 { a })); + + fn identity(t: F) -> F + where + F: Fn(&i32) -> &i32, + { + t + } +} diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr new file mode 100644 index 0000000000000..a156c74fb3304 --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187-2.stderr @@ -0,0 +1,60 @@ +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:8:5 + | +LL | take_foo(|a| a); + | ^^^^^^^^ lifetime mismatch + | + = note: expected type `for<'r> Fn<(&'r i32,)>` + found type `Fn<(&i32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187-2.rs:8:14 + | +LL | take_foo(|a| a); + | ^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:9:5 + | +LL | take_foo(|a: &i32| a); + | ^^^^^^^^ lifetime mismatch + | + = note: expected reference `&i32` + found reference `&i32` +note: the anonymous lifetime #1 defined on the body at 9:14 doesn't meet the lifetime requirements + --> $DIR/issue-79187-2.rs:9:14 + | +LL | take_foo(|a: &i32| a); + | ^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error[E0308]: mismatched types + --> $DIR/issue-79187-2.rs:10:5 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | ^^^^^^^^ lifetime mismatch + | + = note: expected reference `&i32` + found reference `&i32` +note: the anonymous lifetime #1 defined on the body at 10:14 doesn't meet the lifetime requirements + --> $DIR/issue-79187-2.rs:10:14 + | +LL | take_foo(|a: &i32| -> &i32 { a }); + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr new file mode 100644 index 0000000000000..aa8809dbc95f7 --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/issue-79187.rs:5:5 + | +LL | thing(f); + | ^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-79187.rs:5:5 + | +LL | thing(f); + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lifetimes/issue-79187.rs b/src/test/ui/lifetimes/issue-79187.rs new file mode 100644 index 0000000000000..bf331d8a6068e --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187.rs @@ -0,0 +1,6 @@ +fn thing(x: impl FnOnce(&u32)) {} + +fn main() { + let f = |_| (); + thing(f); //~ERROR mismatched types +} diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr new file mode 100644 index 0000000000000..63f501e08fce4 --- /dev/null +++ b/src/test/ui/lifetimes/issue-79187.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/issue-79187.rs:5:5 + | +LL | thing(f); + | ^^^^^ lifetime mismatch + | + = note: expected type `FnOnce<(&u32,)>` + found type `FnOnce<(&u32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187.rs:4:13 + | +LL | let f = |_| (); + | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 0af44d21196db..02ba60f7f4b73 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -26,37 +26,77 @@ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `for<'r> Fn<(*mut &'r u32,)>` found type `Fn<(*mut &'a u32,)>` +note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10 + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `FnOnce<(*mut &u32,)>` found type `FnOnce<(*mut &'a u32,)>` +note: the required lifetime does not necessarily outlive the lifetime `'a` as defined on the function body at 9:10 + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `for<'r> Fn<(*mut &'r u32,)>` found type `Fn<(*mut &'a u32,)>` +note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | baz(f); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `FnOnce<(*mut &u32,)>` found type `FnOnce<(*mut &'a u32,)>` +note: the lifetime `'a` as defined on the function body at 9:10 doesn't meet the lifetime requirements + --> $DIR/closure-arg-type-mismatch.rs:9:10 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | ^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 149f505dc6f57..c41bece3c196f 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -2,10 +2,20 @@ error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | LL | baz(|_| ()); - | ^^^ one type is more general than the other + | ^^^ lifetime mismatch | = note: expected type `for<'r> Fn<(&'r (),)>` found type `Fn<(&(),)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/closure-mismatch.rs:8:9 + | +LL | baz(|_| ()); + | ^^^^^^ +note: the lifetime requirement is introduced here + --> $DIR/closure-mismatch.rs:5:11 + | +LL | fn baz(_: T) {} + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr index 790aea87510e6..be1dd1a8524c8 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -18,6 +18,11 @@ LL | type Bar = impl Baz; | = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&'static X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -27,6 +32,11 @@ LL | type Bar = impl Baz; | = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&'static X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index 5e2a8db02867f..9d9293e958eeb 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -6,6 +6,11 @@ LL | type Bar = impl Baz; | = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -15,6 +20,11 @@ LL | type Bar = impl Baz; | = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&' X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -24,6 +34,11 @@ LL | type Bar = impl Baz; | = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&' X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -33,6 +48,11 @@ LL | type Bar = impl Baz; | = note: expected type `for<'r> Fn<(&'r X,)>` found type `Fn<(&' X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 @@ -42,6 +62,11 @@ LL | type Bar = impl Baz; | = note: expected type `FnOnce<(&X,)>` found type `FnOnce<(&' X,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-57611-trait-alias.rs:25:9 + | +LL | |x| x + | ^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/unboxed-closures/issue-30906.stderr b/src/test/ui/unboxed-closures/issue-30906.stderr index 5f343ff74a1c5..ecf3a96b5a8dc 100644 --- a/src/test/ui/unboxed-closures/issue-30906.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.stderr @@ -2,10 +2,15 @@ error[E0308]: mismatched types --> $DIR/issue-30906.rs:15:5 | LL | test(Compose(f, |_| {})); - | ^^^^ one type is more general than the other + | ^^^^ lifetime mismatch | = note: expected type `FnOnce<(&'x str,)>` found type `FnOnce<(&str,)>` +note: the lifetime requirement is introduced here + --> $DIR/issue-30906.rs:3:12 + | +LL | fn test FnOnce<(&'x str,)>>(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error