Auto merge of #80960 - Dylan-DPC:rollup-89tri8x, r=Dylan-DPC

Rollup of 10 pull requests

Successful merges:

 - #78901 (diagnostics: Note capturing closures can't be coerced to fns)
 - #79588 (Provide more information for HRTB lifetime errors involving closures)
 - #80232 (Remove redundant def_id lookups)
 - #80662 (Added support for i386-unknown-linux-gnu and i486-unknown-linux-gnu)
 - #80736 (use Once instead of Mutex to manage capture resolution)
 - #80796 (Update to LLVM 11.0.1)
 - #80859 (Fix --pretty=expanded with --remap-path-prefix)
 - #80922 (Revert "Auto merge of #76896 - spastorino:codegen-inline-fns2)
 - #80924 (Fix rustdoc --test-builder argument parsing)
 - #80935 (Rename `rustc_middle::lint::LevelSource` to `LevelAndSource`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-13 04:29:45 +00:00
commit fc93e4719c
49 changed files with 661 additions and 101 deletions

2
.gitmodules vendored
View File

@ -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

View File

@ -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)
}

View File

@ -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);

View File

@ -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),
}
}
}

View File

@ -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<LintId, LevelSource>,
specs: &mut FxHashMap<LintId, LevelAndSource>,
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

View File

@ -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<LintSet>,
@ -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<LintId, LevelSource>,
specs: FxHashMap<LintId, LevelAndSource>,
},
Node {
specs: FxHashMap<LintId, LevelSource>,
specs: FxHashMap<LintId, LevelAndSource>,
parent: u32,
},
}
@ -75,9 +75,9 @@ impl LintLevelSets {
&self,
lint: &'static Lint,
idx: u32,
aux: Option<&FxHashMap<LintId, LevelSource>>,
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
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<LintId, LevelSource>>,
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
) -> (Option<Level>, 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<LevelSource> {
) -> Option<LevelAndSource> {
self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
}
}

View File

@ -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(..) => {

View File

@ -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))
}

View File

@ -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 {

View File

@ -872,8 +872,10 @@ impl SourceMap {
}
pub fn get_source_file(&self, filename: &FileName) -> Option<Lrc<SourceFile>> {
// 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),
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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);

View File

@ -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::<Vec<_>>();
let mut multi_span: MultiSpan =
spans_and_labels.iter().map(|(sp, _)| *sp).collect::<Vec<_>>().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,

View File

@ -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<Capture>),
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("<unsupported>"),
Inner::Disabled => return fmt.write_str("<disabled>"),
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<Capture>,
}
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!

View File

@ -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);
}

View File

@ -412,11 +412,7 @@ fn opts() -> Vec<RustcOptGroup> {
)
}),
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")),
]

@ -1 +1 @@
Subproject commit fb115ee43b77601b237717c21ab0a8f5b5b9d50a
Subproject commit f9a8d70b6e0365ac2172ca6b7f1de0341297458d

View File

@ -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)]

View File

@ -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")]

View File

@ -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() { }

View File

@ -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() {}

View File

@ -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; \

View File

@ -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;

View File

@ -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<Image=U>
| ^^^^^^^
error: aborting due to previous error

View File

@ -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

View File

@ -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

View File

@ -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
};
}

View File

@ -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`.

View File

@ -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
}

View File

@ -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`.

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,23 @@
trait Foo {}
impl<F> 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<F>(t: F) -> F
where
F: Fn(&i32) -> &i32,
{
t
}
}

View File

@ -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`.

View File

@ -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

View File

@ -0,0 +1,6 @@
fn thing(x: impl FnOnce(&u32)) {}
fn main() {
let f = |_| ();
thing(f); //~ERROR mismatched types
}

View File

@ -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`.

View File

@ -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: Fn(*mut &u32)>(_: 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: Fn(*mut &u32)>(_: 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: Fn(*mut &u32)>(_: 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: Fn(*mut &u32)>(_: F) {}
| ^^^^^^^^^^^^^
error: aborting due to 7 previous errors

View File

@ -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: Foo>(_: T) {}
| ^^^
error: aborting due to previous error

View File

@ -18,6 +18,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= 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<Self, Self>;
|
= 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

View File

@ -6,6 +6,11 @@ LL | type Bar = impl Baz<Self, Self>;
|
= 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<Self, Self>;
|
= note: expected type `for<'r> Fn<(&'r X,)>`
found type `Fn<(&'<empty> 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<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&'<empty> 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<Self, Self>;
|
= note: expected type `for<'r> Fn<(&'r X,)>`
found type `Fn<(&'<empty> 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<Self, Self>;
|
= note: expected type `FnOnce<(&X,)>`
found type `FnOnce<(&'<empty> 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

View File

@ -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<F: for<'x> FnOnce<(&'x str,)>>(_: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error