Auto merge of #99943 - compiler-errors:tuple-trait, r=jackh726
Implement `std::marker::Tuple`, use it in `extern "rust-call"` and `Fn`-family traits Implements rust-lang/compiler-team#537 I made a few opinionated decisions in this implementation, specifically: 1. Enforcing `extern "rust-call"` on fn items during wfcheck, 2. Enforcing this for all functions (not just ones that have bodies), 3. Gating this `Tuple` marker trait behind its own feature, instead of grouping it into (e.g.) `unboxed_closures`. Still needing to be done: 1. Enforce that `extern "rust-call"` `fn`-ptrs are well-formed only if they have 1/2 args and the second one implements `Tuple`. (Doing this would fix ICE in #66696.) 2. Deny all explicit/user `impl`s of the `Tuple` trait, kinda like `Sized`. 3. Fixing `Tuple` trait built-in impl for chalk, so that chalkification tests are un-broken. Open questions: 1. Does this need t-lang or t-libs signoff? Fixes #99820
This commit is contained in:
commit
7eef946fc0
@ -21,6 +21,7 @@
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
@ -1542,6 +1543,33 @@ fn check_fn_or_method<'tcx>(
|
||||
sig.output(),
|
||||
hir_decl.output.span(),
|
||||
);
|
||||
|
||||
if sig.abi == Abi::RustCall {
|
||||
let span = tcx.def_span(def_id);
|
||||
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
|
||||
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
|
||||
// Check that the argument is a tuple
|
||||
if let Some(ty) = inputs.next() {
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall),
|
||||
wfcx.param_env,
|
||||
*ty,
|
||||
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
|
||||
);
|
||||
} else {
|
||||
tcx.sess.span_err(
|
||||
hir_decl.inputs.last().map_or(span, |input| input.span),
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
// No more inputs other than the `self` type and the tuple type
|
||||
if inputs.next().is_some() {
|
||||
tcx.sess.span_err(
|
||||
hir_decl.inputs.last().map_or(span, |input| input.span),
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Basically `check_associated_type_bounds`, but separated for now and should be
|
||||
|
@ -468,6 +468,22 @@ fn confirm_builtin_call(
|
||||
def_id,
|
||||
);
|
||||
|
||||
if fn_sig.abi == abi::Abi::RustCall {
|
||||
let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
|
||||
if let Some(ty) = fn_sig.inputs().last().copied() {
|
||||
self.register_bound(
|
||||
ty,
|
||||
self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
|
||||
traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
|
||||
);
|
||||
} else {
|
||||
self.tcx.sess.span_err(
|
||||
sp,
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn_sig.output()
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,11 @@
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ImplicitSelfKind, ItemKind, Node};
|
||||
use rustc_hir_analysis::check::fn_maybe_err;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits;
|
||||
use std::cell::RefCell;
|
||||
|
||||
@ -56,41 +54,6 @@ pub(super) fn check_fn<'a, 'tcx>(
|
||||
|
||||
fn_maybe_err(tcx, span, fn_sig.abi);
|
||||
|
||||
if fn_sig.abi == Abi::RustCall {
|
||||
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
|
||||
|
||||
let err = || {
|
||||
let item = match tcx.hir().get(fn_id) {
|
||||
Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
|
||||
Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Fn(header, ..), ..
|
||||
}) => Some(header),
|
||||
Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Fn(header, ..),
|
||||
..
|
||||
}) => Some(header),
|
||||
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
|
||||
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
|
||||
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
|
||||
};
|
||||
|
||||
if let Some(header) = item {
|
||||
tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
|
||||
}
|
||||
};
|
||||
|
||||
if fn_sig.inputs().len() != expected_args {
|
||||
err()
|
||||
} else {
|
||||
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
|
||||
// This will probably require wide-scale changes to support a TupleKind obligation
|
||||
// We can't resolve this without knowing the type of the param
|
||||
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
|
||||
err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if body.generator_kind.is_some() && can_be_generator.is_some() {
|
||||
let yield_ty = fcx
|
||||
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
|
||||
|
@ -136,6 +136,7 @@ pub(in super::super) fn check_method_argument_types(
|
||||
tuple_arguments,
|
||||
Some(method.def_id),
|
||||
);
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ pub(in super::super) fn check_argument_types(
|
||||
"cannot use call notation; the first type parameter \
|
||||
for the function trait is neither a tuple nor unit"
|
||||
)
|
||||
.emit();
|
||||
.delay_as_bug();
|
||||
(self.err_args(provided_args.len()), None)
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'
|
||||
/// # fn f(x: (isize, isize)) {}
|
||||
/// f((1, 2));
|
||||
/// ```
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
enum TupleArgumentsFlag {
|
||||
DontTupleArguments,
|
||||
TupleArguments,
|
||||
|
@ -438,6 +438,8 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
},
|
||||
|
||||
AscribeUserTypeProvePredicate(Span),
|
||||
|
||||
RustCall,
|
||||
}
|
||||
|
||||
/// The 'location' at which we try to perform HIR-based wf checking.
|
||||
|
@ -700,6 +700,25 @@ fn report_selection_error(
|
||||
}
|
||||
}
|
||||
|
||||
if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
|
||||
match obligation.cause.code().peel_derives() {
|
||||
ObligationCauseCode::RustCall => {
|
||||
err.set_primary_message("functions with the \"rust-call\" ABI must take a single non-self tuple argument");
|
||||
}
|
||||
ObligationCauseCode::BindingObligation(def_id, _)
|
||||
| ObligationCauseCode::ItemObligation(def_id)
|
||||
if ty::ClosureKind::from_def_id(tcx, *def_id).is_some() =>
|
||||
{
|
||||
err.code(rustc_errors::error_code!(E0059));
|
||||
err.set_primary_message(format!(
|
||||
"type parameter to bare `{}` trait must be a tuple",
|
||||
tcx.def_path_str(*def_id)
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait()
|
||||
&& predicate_is_const
|
||||
{
|
||||
@ -848,12 +867,8 @@ fn report_selection_error(
|
||||
);
|
||||
}
|
||||
|
||||
let is_fn_trait = [
|
||||
self.tcx.lang_items().fn_trait(),
|
||||
self.tcx.lang_items().fn_mut_trait(),
|
||||
self.tcx.lang_items().fn_once_trait(),
|
||||
]
|
||||
.contains(&Some(trait_ref.def_id()));
|
||||
let is_fn_trait =
|
||||
ty::ClosureKind::from_def_id(tcx, trait_ref.def_id()).is_some();
|
||||
let is_target_feature_fn = if let ty::FnDef(def_id, _) =
|
||||
*trait_ref.skip_binder().self_ty().kind()
|
||||
{
|
||||
|
@ -2407,7 +2407,8 @@ fn note_obligation_cause_code<T>(
|
||||
| ObligationCauseCode::CheckAssociatedTypeBounds { .. }
|
||||
| ObligationCauseCode::LetElse
|
||||
| ObligationCauseCode::BinOp { .. }
|
||||
| ObligationCauseCode::AscribeUserTypeProvePredicate(..) => {}
|
||||
| ObligationCauseCode::AscribeUserTypeProvePredicate(..)
|
||||
| ObligationCauseCode::RustCall => {}
|
||||
ObligationCauseCode::SliceOrArrayElem => {
|
||||
err.note("slice and array elements must have `Sized` type");
|
||||
}
|
||||
|
@ -158,6 +158,8 @@
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::iter::FromIterator;
|
||||
use core::iter::{FusedIterator, Iterator};
|
||||
#[cfg(not(bootstrap))]
|
||||
use core::marker::Tuple;
|
||||
use core::marker::{Destruct, Unpin, Unsize};
|
||||
use core::mem;
|
||||
use core::ops::{
|
||||
@ -1979,6 +1981,7 @@ fn is_empty(&self) -> bool {
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
|
||||
type Output = <F as FnOnce<Args>>::Output;
|
||||
@ -1988,6 +1991,17 @@ extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> {
|
||||
type Output = <F as FnOnce<Args>>::Output;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
|
||||
<F as FnOnce<Args>>::call_once(*self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
|
||||
@ -1995,6 +2009,15 @@ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
|
||||
<F as FnMut<Args>>::call_mut(self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output {
|
||||
@ -2002,6 +2025,14 @@ extern "rust-call" fn call(&self, args: Args) -> Self::Output {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[stable(feature = "boxed_closure_impls", since = "1.35.0")]
|
||||
impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output {
|
||||
<F as Fn<Args>>::call(self, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}
|
||||
|
||||
|
@ -150,6 +150,7 @@
|
||||
#![feature(trusted_len)]
|
||||
#![feature(trusted_random_access)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![cfg_attr(not(bootstrap), feature(tuple_trait))]
|
||||
#![feature(unchecked_math)]
|
||||
#![feature(unicode_internals)]
|
||||
#![feature(unsize)]
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::marker::Destruct;
|
||||
#[cfg(not(bootstrap))]
|
||||
use crate::marker::Tuple;
|
||||
|
||||
/// Struct representing a closure with mutably borrowed data.
|
||||
///
|
||||
@ -44,6 +46,7 @@ pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
|
||||
|
||||
macro_rules! impl_fn_mut_tuple {
|
||||
($($var:ident)*) => {
|
||||
#[cfg(bootstrap)]
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
|
||||
FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
@ -56,6 +59,7 @@ extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Outpu
|
||||
self.call_mut(args)
|
||||
}
|
||||
}
|
||||
#[cfg(bootstrap)]
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const
|
||||
FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
@ -68,6 +72,32 @@ extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Outpu
|
||||
(self.func)(($($var),*), args)
|
||||
}
|
||||
}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
|
||||
FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
where
|
||||
Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
|
||||
{
|
||||
type Output = ClosureReturnValue;
|
||||
|
||||
extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
|
||||
self.call_mut(args)
|
||||
}
|
||||
}
|
||||
#[cfg(not(bootstrap))]
|
||||
#[allow(unused_parens)]
|
||||
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
|
||||
FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
|
||||
where
|
||||
Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
|
||||
#[allow(non_snake_case)]
|
||||
let ($($var),*) = &mut self.data;
|
||||
(self.func)(($($var),*), args)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_fn_mut_tuple!(A);
|
||||
|
@ -55,6 +55,8 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::marker::DiscriminantKind;
|
||||
#[cfg(not(bootstrap))]
|
||||
use crate::marker::Tuple;
|
||||
use crate::mem;
|
||||
|
||||
// These imports are used for simplifying intra-doc links
|
||||
@ -2169,11 +2171,75 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
|
||||
/// which violates the principle that a `const fn` must behave the same at
|
||||
/// compile-time and at run-time. The unsafe code in crate B is fine.
|
||||
#[cfg(bootstrap)]
|
||||
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
|
||||
pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
|
||||
where
|
||||
G: FnOnce<ARG, Output = RET>,
|
||||
F: FnOnce<ARG, Output = RET>;
|
||||
|
||||
/// Selects which function to call depending on the context.
|
||||
///
|
||||
/// If this function is evaluated at compile-time, then a call to this
|
||||
/// intrinsic will be replaced with a call to `called_in_const`. It gets
|
||||
/// replaced with a call to `called_at_rt` otherwise.
|
||||
///
|
||||
/// # Type Requirements
|
||||
///
|
||||
/// The two functions must be both function items. They cannot be function
|
||||
/// pointers or closures. The first function must be a `const fn`.
|
||||
///
|
||||
/// `arg` will be the tupled arguments that will be passed to either one of
|
||||
/// the two functions, therefore, both functions must accept the same type of
|
||||
/// arguments. Both functions must return RET.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The two functions must behave observably equivalent. Safe code in other
|
||||
/// crates may assume that calling a `const fn` at compile-time and at run-time
|
||||
/// produces the same result. A function that produces a different result when
|
||||
/// evaluated at run-time, or has any other observable side-effects, is
|
||||
/// *unsound*.
|
||||
///
|
||||
/// Here is an example of how this could cause a problem:
|
||||
/// ```no_run
|
||||
/// #![feature(const_eval_select)]
|
||||
/// #![feature(core_intrinsics)]
|
||||
/// use std::hint::unreachable_unchecked;
|
||||
/// use std::intrinsics::const_eval_select;
|
||||
///
|
||||
/// // Crate A
|
||||
/// pub const fn inconsistent() -> i32 {
|
||||
/// fn runtime() -> i32 { 1 }
|
||||
/// const fn compiletime() -> i32 { 2 }
|
||||
///
|
||||
/// unsafe {
|
||||
// // ⚠ This code violates the required equivalence of `compiletime`
|
||||
/// // and `runtime`.
|
||||
/// const_eval_select((), compiletime, runtime)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Crate B
|
||||
/// const X: i32 = inconsistent();
|
||||
/// let x = inconsistent();
|
||||
/// if x != X { unsafe { unreachable_unchecked(); }}
|
||||
/// ```
|
||||
///
|
||||
/// This code causes Undefined Behavior when being run, since the
|
||||
/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
|
||||
/// which violates the principle that a `const fn` must behave the same at
|
||||
/// compile-time and at run-time. The unsafe code in crate B is fine.
|
||||
#[cfg(not(bootstrap))]
|
||||
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
|
||||
pub fn const_eval_select<ARG: Tuple, F, G, RET>(
|
||||
arg: ARG,
|
||||
called_in_const: F,
|
||||
called_at_rt: G,
|
||||
) -> RET
|
||||
where
|
||||
G: FnOnce<ARG, Output = RET>,
|
||||
F: FnOnce<ARG, Output = RET>;
|
||||
}
|
||||
|
||||
// Some functions are defined here because they accidentally got made
|
||||
|
@ -1,3 +1,6 @@
|
||||
#[cfg(not(bootstrap))]
|
||||
use crate::marker::Tuple;
|
||||
|
||||
/// The version of the call operator that takes an immutable receiver.
|
||||
///
|
||||
/// Instances of `Fn` can be called repeatedly without mutating state.
|
||||
@ -51,6 +54,7 @@
|
||||
/// let double = |x| x * 2;
|
||||
/// assert_eq!(call_with_one(double), 2);
|
||||
/// ```
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "fn"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Fn"]
|
||||
@ -71,13 +75,93 @@
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[cfg_attr(not(bootstrap), const_trait)]
|
||||
pub trait Fn<Args>: FnMut<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The version of the call operator that takes an immutable receiver.
|
||||
///
|
||||
/// Instances of `Fn` can be called repeatedly without mutating state.
|
||||
///
|
||||
/// *This trait (`Fn`) is not to be confused with [function pointers]
|
||||
/// (`fn`).*
|
||||
///
|
||||
/// `Fn` is implemented automatically by closures which only take immutable
|
||||
/// references to captured variables or don't capture anything at all, as well
|
||||
/// as (safe) [function pointers] (with some caveats, see their documentation
|
||||
/// for more details). Additionally, for any type `F` that implements `Fn`, `&F`
|
||||
/// implements `Fn`, too.
|
||||
///
|
||||
/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any
|
||||
/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`]
|
||||
/// is expected.
|
||||
///
|
||||
/// Use `Fn` as a bound when you want to accept a parameter of function-like
|
||||
/// type and need to call it repeatedly and without mutating state (e.g., when
|
||||
/// calling it concurrently). If you do not need such strict requirements, use
|
||||
/// [`FnMut`] or [`FnOnce`] as bounds.
|
||||
///
|
||||
/// See the [chapter on closures in *The Rust Programming Language*][book] for
|
||||
/// some more information on this topic.
|
||||
///
|
||||
/// Also of note is the special syntax for `Fn` traits (e.g.
|
||||
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
|
||||
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
|
||||
///
|
||||
/// [book]: ../../book/ch13-01-closures.html
|
||||
/// [function pointers]: fn
|
||||
/// [nomicon]: ../../nomicon/hrtb.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Calling a closure
|
||||
///
|
||||
/// ```
|
||||
/// let square = |x| x * x;
|
||||
/// assert_eq!(square(5), 25);
|
||||
/// ```
|
||||
///
|
||||
/// ## Using a `Fn` parameter
|
||||
///
|
||||
/// ```
|
||||
/// fn call_with_one<F>(func: F) -> usize
|
||||
/// where F: Fn(usize) -> usize {
|
||||
/// func(1)
|
||||
/// }
|
||||
///
|
||||
/// let double = |x| x * 2;
|
||||
/// assert_eq!(call_with_one(double), 2);
|
||||
/// ```
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "fn"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "Fn"]
|
||||
#[rustc_paren_sugar]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
Args = "()",
|
||||
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
|
||||
),
|
||||
on(
|
||||
_Self = "unsafe fn",
|
||||
note = "unsafe function cannot be called generically without an unsafe block",
|
||||
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
|
||||
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
|
||||
),
|
||||
message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
|
||||
label = "expected an `Fn<{Args}>` closure, found `{Self}`"
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[const_trait]
|
||||
pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The version of the call operator that takes a mutable receiver.
|
||||
///
|
||||
/// Instances of `FnMut` can be called repeatedly and may mutate state.
|
||||
@ -139,6 +223,7 @@ pub trait Fn<Args>: FnMut<Args> {
|
||||
///
|
||||
/// assert_eq!(x, 5);
|
||||
/// ```
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "fn_mut"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "FnMut"]
|
||||
@ -159,13 +244,101 @@ pub trait Fn<Args>: FnMut<Args> {
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[cfg_attr(not(bootstrap), const_trait)]
|
||||
pub trait FnMut<Args>: FnOnce<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The version of the call operator that takes a mutable receiver.
|
||||
///
|
||||
/// Instances of `FnMut` can be called repeatedly and may mutate state.
|
||||
///
|
||||
/// `FnMut` is implemented automatically by closures which take mutable
|
||||
/// references to captured variables, as well as all types that implement
|
||||
/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of
|
||||
/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F`
|
||||
/// implements `FnMut`, too.
|
||||
///
|
||||
/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be
|
||||
/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of
|
||||
/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected.
|
||||
///
|
||||
/// Use `FnMut` as a bound when you want to accept a parameter of function-like
|
||||
/// type and need to call it repeatedly, while allowing it to mutate state.
|
||||
/// If you don't want the parameter to mutate state, use [`Fn`] as a
|
||||
/// bound; if you don't need to call it repeatedly, use [`FnOnce`].
|
||||
///
|
||||
/// See the [chapter on closures in *The Rust Programming Language*][book] for
|
||||
/// some more information on this topic.
|
||||
///
|
||||
/// Also of note is the special syntax for `Fn` traits (e.g.
|
||||
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
|
||||
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
|
||||
///
|
||||
/// [book]: ../../book/ch13-01-closures.html
|
||||
/// [function pointers]: fn
|
||||
/// [nomicon]: ../../nomicon/hrtb.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Calling a mutably capturing closure
|
||||
///
|
||||
/// ```
|
||||
/// let mut x = 5;
|
||||
/// {
|
||||
/// let mut square_x = || x *= x;
|
||||
/// square_x();
|
||||
/// }
|
||||
/// assert_eq!(x, 25);
|
||||
/// ```
|
||||
///
|
||||
/// ## Using a `FnMut` parameter
|
||||
///
|
||||
/// ```
|
||||
/// fn do_twice<F>(mut func: F)
|
||||
/// where F: FnMut()
|
||||
/// {
|
||||
/// func();
|
||||
/// func();
|
||||
/// }
|
||||
///
|
||||
/// let mut x: usize = 1;
|
||||
/// {
|
||||
/// let add_two_to_x = || x += 2;
|
||||
/// do_twice(add_two_to_x);
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(x, 5);
|
||||
/// ```
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "fn_mut"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "FnMut"]
|
||||
#[rustc_paren_sugar]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
Args = "()",
|
||||
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
|
||||
),
|
||||
on(
|
||||
_Self = "unsafe fn",
|
||||
note = "unsafe function cannot be called generically without an unsafe block",
|
||||
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
|
||||
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
|
||||
),
|
||||
message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
|
||||
label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[const_trait]
|
||||
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The version of the call operator that takes a by-value receiver.
|
||||
///
|
||||
/// Instances of `FnOnce` can be called, but might not be callable multiple
|
||||
@ -219,6 +392,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
|
||||
///
|
||||
/// // `consume_and_return_x` can no longer be invoked at this point
|
||||
/// ```
|
||||
#[cfg(bootstrap)]
|
||||
#[lang = "fn_once"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "FnOnce"]
|
||||
@ -239,7 +413,6 @@ pub trait FnMut<Args>: FnOnce<Args> {
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[cfg_attr(not(bootstrap), const_trait)]
|
||||
pub trait FnOnce<Args> {
|
||||
/// The returned type after the call operator is used.
|
||||
#[lang = "fn_once_output"]
|
||||
@ -251,6 +424,93 @@ pub trait FnOnce<Args> {
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
/// The version of the call operator that takes a by-value receiver.
|
||||
///
|
||||
/// Instances of `FnOnce` can be called, but might not be callable multiple
|
||||
/// times. Because of this, if the only thing known about a type is that it
|
||||
/// implements `FnOnce`, it can only be called once.
|
||||
///
|
||||
/// `FnOnce` is implemented automatically by closures that might consume captured
|
||||
/// variables, as well as all types that implement [`FnMut`], e.g., (safe)
|
||||
/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]).
|
||||
///
|
||||
/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of
|
||||
/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected.
|
||||
///
|
||||
/// Use `FnOnce` as a bound when you want to accept a parameter of function-like
|
||||
/// type and only need to call it once. If you need to call the parameter
|
||||
/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate
|
||||
/// state, use [`Fn`].
|
||||
///
|
||||
/// See the [chapter on closures in *The Rust Programming Language*][book] for
|
||||
/// some more information on this topic.
|
||||
///
|
||||
/// Also of note is the special syntax for `Fn` traits (e.g.
|
||||
/// `Fn(usize, bool) -> usize`). Those interested in the technical details of
|
||||
/// this can refer to [the relevant section in the *Rustonomicon*][nomicon].
|
||||
///
|
||||
/// [book]: ../../book/ch13-01-closures.html
|
||||
/// [function pointers]: fn
|
||||
/// [nomicon]: ../../nomicon/hrtb.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Using a `FnOnce` parameter
|
||||
///
|
||||
/// ```
|
||||
/// fn consume_with_relish<F>(func: F)
|
||||
/// where F: FnOnce() -> String
|
||||
/// {
|
||||
/// // `func` consumes its captured variables, so it cannot be run more
|
||||
/// // than once.
|
||||
/// println!("Consumed: {}", func());
|
||||
///
|
||||
/// println!("Delicious!");
|
||||
///
|
||||
/// // Attempting to invoke `func()` again will throw a `use of moved
|
||||
/// // value` error for `func`.
|
||||
/// }
|
||||
///
|
||||
/// let x = String::from("x");
|
||||
/// let consume_and_return_x = move || x;
|
||||
/// consume_with_relish(consume_and_return_x);
|
||||
///
|
||||
/// // `consume_and_return_x` can no longer be invoked at this point
|
||||
/// ```
|
||||
#[cfg(not(bootstrap))]
|
||||
#[lang = "fn_once"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_diagnostic_item = "FnOnce"]
|
||||
#[rustc_paren_sugar]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
Args = "()",
|
||||
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
|
||||
),
|
||||
on(
|
||||
_Self = "unsafe fn",
|
||||
note = "unsafe function cannot be called generically without an unsafe block",
|
||||
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
|
||||
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
|
||||
),
|
||||
message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
|
||||
label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
|
||||
)]
|
||||
#[fundamental] // so that regex can rely that `&str: !FnMut`
|
||||
#[must_use = "closures are lazy and do nothing unless called"]
|
||||
#[const_trait]
|
||||
pub trait FnOnce<Args: Tuple> {
|
||||
/// The returned type after the call operator is used.
|
||||
#[lang = "fn_once_output"]
|
||||
#[stable(feature = "fn_once_output", since = "1.12.0")]
|
||||
type Output;
|
||||
|
||||
/// Performs the call operation.
|
||||
#[unstable(feature = "fn_traits", issue = "29625")]
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[cfg(bootstrap)]
|
||||
mod impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
|
||||
@ -310,3 +570,61 @@ extern "rust-call" fn call_once(self, args: A) -> F::Output {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
mod impls {
|
||||
use crate::marker::Tuple;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Tuple, F: ?Sized> Fn<A> for &F
|
||||
where
|
||||
F: Fn<A>,
|
||||
{
|
||||
extern "rust-call" fn call(&self, args: A) -> F::Output {
|
||||
(**self).call(args)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Tuple, F: ?Sized> FnMut<A> for &F
|
||||
where
|
||||
F: Fn<A>,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
|
||||
(**self).call(args)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Tuple, F: ?Sized> FnOnce<A> for &F
|
||||
where
|
||||
F: Fn<A>,
|
||||
{
|
||||
type Output = F::Output;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: A) -> F::Output {
|
||||
(*self).call(args)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F
|
||||
where
|
||||
F: FnMut<A>,
|
||||
{
|
||||
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
|
||||
(*self).call_mut(args)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F
|
||||
where
|
||||
F: FnMut<A>,
|
||||
{
|
||||
type Output = F::Output;
|
||||
extern "rust-call" fn call_once(self, args: A) -> F::Output {
|
||||
(*self).call_mut(args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ pub trait Sized { }
|
||||
pub trait Copy { }
|
||||
#[lang = "receiver"]
|
||||
pub trait Receiver { }
|
||||
#[lang = "tuple_trait"]
|
||||
pub trait Tuple { }
|
||||
|
||||
pub struct Result<T, E> { _a: T, _b: E }
|
||||
|
||||
@ -29,7 +31,7 @@ impl Copy for &usize {}
|
||||
pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
|
||||
|
||||
#[lang = "fn_once"]
|
||||
pub trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args: Tuple> {
|
||||
#[lang = "fn_once_output"]
|
||||
type Output;
|
||||
|
||||
@ -37,24 +39,16 @@ pub trait FnOnce<Args> {
|
||||
}
|
||||
|
||||
#[lang = "fn_mut"]
|
||||
pub trait FnMut<Args> : FnOnce<Args> {
|
||||
pub trait FnMut<Args: Tuple> : FnOnce<Args> {
|
||||
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
#[lang = "fn"]
|
||||
pub trait Fn<Args>: FnOnce<Args> {
|
||||
pub trait Fn<Args: Tuple>: FnOnce<Args> {
|
||||
/// Performs the call operation.
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'a, A, R> FnOnce<A> for &'a fn(A) -> R {
|
||||
type Output = R;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: A) -> R {
|
||||
(*self)(args)
|
||||
}
|
||||
}
|
||||
|
||||
pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
|
||||
pub static mut STORAGE_BAR: u32 = 12;
|
||||
|
||||
|
@ -128,7 +128,7 @@
|
||||
// Change calling convention ---------------------------------------------------
|
||||
#[cfg(any(cfail1,cfail4))]
|
||||
extern "C" {
|
||||
pub fn change_calling_convention(c: i32);
|
||||
pub fn change_calling_convention(c: (i32,));
|
||||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
@ -137,7 +137,7 @@
|
||||
#[rustc_clean(cfg = "cfail5", except = "hir_owner,hir_owner_nodes")]
|
||||
#[rustc_clean(cfg = "cfail6")]
|
||||
extern "rust-call" {
|
||||
pub fn change_calling_convention(c: i32);
|
||||
pub fn change_calling_convention(c: (i32,));
|
||||
}
|
||||
|
||||
// Make function public --------------------------------------------------------
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![feature(unsized_locals)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(tuple_trait)]
|
||||
|
||||
pub trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args: std::marker::Tuple> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![feature(unsized_locals)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(tuple_trait)]
|
||||
|
||||
pub trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args: std::marker::Tuple> {
|
||||
type Output;
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
@ -1,32 +1,31 @@
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
extern "rust-call" fn b(_i: i32) {}
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
|
||||
trait Tr {
|
||||
extern "rust-call" fn a();
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
|
||||
extern "rust-call" fn b() {}
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
extern "rust-call" fn bar() {}
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
}
|
||||
|
||||
impl Tr for Foo {
|
||||
extern "rust-call" fn a() {}
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
}
|
||||
|
||||
fn main () {
|
||||
fn main() {
|
||||
b(10);
|
||||
|
||||
Foo::bar();
|
||||
|
||||
<Foo as Tr>::a();
|
||||
<Foo as Tr>::b();
|
||||
}
|
||||
|
@ -1,26 +1,33 @@
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/issue-22565-rust-call.rs:3:1
|
||||
|
|
||||
LL | extern "rust-call" fn b(_i: i32) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `i32`
|
||||
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
--> $DIR/issue-22565-rust-call.rs:9:5
|
||||
|
|
||||
LL | extern "rust-call" fn b() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
--> $DIR/issue-22565-rust-call.rs:16:5
|
||||
error: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/issue-22565-rust-call.rs:17:5
|
||||
|
|
||||
LL | extern "rust-call" fn bar() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
--> $DIR/issue-22565-rust-call.rs:21:5
|
||||
error: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/issue-22565-rust-call.rs:22:5
|
||||
|
|
||||
LL | extern "rust-call" fn a() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/issue-22565-rust-call.rs:7:5
|
||||
|
|
||||
LL | extern "rust-call" fn a();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/issue-22565-rust-call.rs:10:5
|
||||
|
|
||||
LL | extern "rust-call" fn b() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -2,9 +2,9 @@
|
||||
// check-pass
|
||||
//[opt] compile-flags: -Zmir-opt-level=3
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
extern "rust-call" fn foo<T>(_: T) {}
|
||||
extern "rust-call" fn foo<T: std::marker::Tuple>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
foo(());
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
// Tests that we can't assign to or mutably borrow upvars from `Fn`
|
||||
// closures (issue #17780)
|
||||
@ -7,10 +7,10 @@ fn set(x: &mut usize) {
|
||||
*x = 5;
|
||||
}
|
||||
|
||||
fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
f
|
||||
}
|
||||
fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F {
|
||||
fn to_fn_mut<A: std::marker::Tuple, F: FnMut<A>>(f: F) -> F {
|
||||
f
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:21:27
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | let _f = to_fn(|| x = 42);
|
||||
| ----- -- ^^^^^^ cannot assign
|
||||
@ -13,8 +13,8 @@ LL | let _f = to_fn(|| x = 42);
|
||||
error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:24:31
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | let _g = to_fn(|| set(&mut y));
|
||||
| ----- -- ^^^^^^ cannot borrow as mutable
|
||||
@ -25,8 +25,8 @@ LL | let _g = to_fn(|| set(&mut y));
|
||||
error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:29:22
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | to_fn(|| z = 42);
|
||||
| ----- -- ^^^^^^ cannot assign
|
||||
@ -37,8 +37,8 @@ LL | to_fn(|| z = 42);
|
||||
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:36:32
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | let _f = to_fn(move || x = 42);
|
||||
| ----- ------- ^^^^^^ cannot assign
|
||||
@ -49,8 +49,8 @@ LL | let _f = to_fn(move || x = 42);
|
||||
error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:39:36
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | let _g = to_fn(move || set(&mut y));
|
||||
| ----- ------- ^^^^^^ cannot borrow as mutable
|
||||
@ -61,8 +61,8 @@ LL | let _g = to_fn(move || set(&mut y));
|
||||
error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/borrow-immutable-upvar-mutation.rs:44:27
|
||||
|
|
||||
LL | fn to_fn<A, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A: std::marker::Tuple, F: Fn<A>>(f: F) -> F {
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | to_fn(move || z = 42);
|
||||
| ----- ------- ^^^^^^ cannot assign
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
|
||||
|
||||
pub fn main() {
|
||||
let bar: Box<_> = Box::new(3);
|
||||
|
@ -66,8 +66,8 @@ LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
|
||||
help: a trait with a similar name exists
|
||||
|
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
|
||||
|
||||
fn main() {
|
||||
let x = 1;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// check-fail
|
||||
// known-bug: unknown
|
||||
// FIXME(chalk): Chalk needs support for the Tuple trait
|
||||
// compile-flags: -Z chalk
|
||||
|
||||
fn main() -> () {
|
||||
@ -25,7 +26,7 @@ fn main() -> () {
|
||||
let mut c = b;
|
||||
|
||||
c();
|
||||
b(); //~ ERROR
|
||||
b(); // FIXME: reenable when this is fixed ~ ERROR
|
||||
|
||||
// FIXME(chalk): this doesn't quite work
|
||||
/*
|
||||
|
@ -1,22 +1,80 @@
|
||||
error[E0382]: borrow of moved value: `b`
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:7:5
|
||||
|
|
||||
LL | t();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:13:5
|
||||
|
|
||||
LL | b();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:17:5
|
||||
|
|
||||
LL | c();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:18:5
|
||||
|
|
||||
LL | b();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:24:5
|
||||
|
|
||||
LL | b();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:28:5
|
||||
|
|
||||
LL | let mut c = b;
|
||||
| - value moved here
|
||||
...
|
||||
LL | b();
|
||||
| ^ value borrowed here after move
|
||||
LL | c();
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment
|
||||
--> $DIR/closure.rs:21:9
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | a = 1;
|
||||
| ^
|
||||
help: consider mutably borrowing `b`
|
||||
|
|
||||
LL | let mut c = &mut b;
|
||||
| ++++
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0277]: `()` is not a tuple
|
||||
--> $DIR/closure.rs:29:5
|
||||
|
|
||||
LL | b(); // FIXME: reenable when this is fixed ~ ERROR
|
||||
| ^^^ the trait `Tuple` is not implemented for `()`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() -> () where (): Tuple {
|
||||
| +++++++++++++++
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -1,4 +1,5 @@
|
||||
// check-pass
|
||||
// known-bug: unknown
|
||||
// FIXME(chalk): Chalk needs support for the Tuple trait
|
||||
// compile-flags: -Z chalk
|
||||
|
||||
use std::fmt::Display;
|
||||
|
28
src/test/ui/chalkify/trait-objects.stderr
Normal file
28
src/test/ui/chalkify/trait-objects.stderr
Normal file
@ -0,0 +1,28 @@
|
||||
error: the type `&dyn Fn(i32) -> _` is not well-formed (chalk)
|
||||
--> $DIR/trait-objects.rs:11:12
|
||||
|
|
||||
LL | let f: &dyn Fn(i32) -> _ = &|x| x + x;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `(i32,)` is not a tuple
|
||||
--> $DIR/trait-objects.rs:12:5
|
||||
|
|
||||
LL | f(2);
|
||||
| ^^^^ the trait `Tuple` is not implemented for `(i32,)`
|
||||
|
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn main() where (i32,): Tuple {
|
||||
| +++++++++++++++++++
|
||||
|
||||
error[E0277]: expected a `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32`
|
||||
--> $DIR/trait-objects.rs:12:5
|
||||
|
|
||||
LL | f(2);
|
||||
| ^^^^ expected an `Fn<(i32,)>` closure, found `dyn Fn(i32) -> i32`
|
||||
|
|
||||
= help: the trait `Fn<(i32,)>` is not implemented for `dyn Fn(i32) -> i32`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -12,8 +12,8 @@ LL | _func: F,
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
|
||||
help: a trait with a similar name exists
|
||||
|
|
||||
|
@ -1,8 +1,14 @@
|
||||
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
|
||||
--> $DIR/E0059.rs:3:41
|
||||
error[E0059]: type parameter to bare `Fn` trait must be a tuple
|
||||
--> $DIR/E0059.rs:3:11
|
||||
|
|
||||
LL | fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
|
||||
| ^^^^
|
||||
| ^^^^^^^ the trait `Tuple` is not implemented for `i32`
|
||||
|
|
||||
note: required by a bound in `Fn`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| ^^^^^ required by this bound in `Fn`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
#[lang="sized"]
|
||||
trait Sized { }
|
||||
|
||||
#[lang="tuple_trait"]
|
||||
trait Tuple { }
|
||||
|
||||
// Functions
|
||||
extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
|
||||
//~^ ERROR intrinsic must be in
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:13:8
|
||||
--> $DIR/feature-gate-abi.rs:16:8
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn f1() {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {}
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:15:8
|
||||
--> $DIR/feature-gate-abi.rs:18:8
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn f2() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -16,7 +16,7 @@ LL | extern "platform-intrinsic" fn f2() {}
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:17:8
|
||||
--> $DIR/feature-gate-abi.rs:20:8
|
||||
|
|
||||
LL | extern "rust-call" fn f4(_: ()) {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -25,7 +25,7 @@ LL | extern "rust-call" fn f4(_: ()) {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:18:8
|
||||
--> $DIR/feature-gate-abi.rs:21:8
|
||||
|
|
||||
LL | extern "efiapi" fn f10() {}
|
||||
| ^^^^^^^^
|
||||
@ -34,7 +34,7 @@ LL | extern "efiapi" fn f10() {}
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:22:12
|
||||
--> $DIR/feature-gate-abi.rs:25:12
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn m1();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -42,7 +42,7 @@ LL | extern "rust-intrinsic" fn m1();
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:24:12
|
||||
--> $DIR/feature-gate-abi.rs:27:12
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn m2();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -51,7 +51,7 @@ LL | extern "platform-intrinsic" fn m2();
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:26:12
|
||||
--> $DIR/feature-gate-abi.rs:29:12
|
||||
|
|
||||
LL | extern "rust-call" fn m4(_: ());
|
||||
| ^^^^^^^^^^^
|
||||
@ -60,7 +60,7 @@ LL | extern "rust-call" fn m4(_: ());
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:27:12
|
||||
--> $DIR/feature-gate-abi.rs:30:12
|
||||
|
|
||||
LL | extern "efiapi" fn m10();
|
||||
| ^^^^^^^^
|
||||
@ -69,7 +69,7 @@ LL | extern "efiapi" fn m10();
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:29:12
|
||||
--> $DIR/feature-gate-abi.rs:32:12
|
||||
|
|
||||
LL | extern "rust-call" fn dm4(_: ()) {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -78,7 +78,7 @@ LL | extern "rust-call" fn dm4(_: ()) {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:30:12
|
||||
--> $DIR/feature-gate-abi.rs:33:12
|
||||
|
|
||||
LL | extern "efiapi" fn dm10() {}
|
||||
| ^^^^^^^^
|
||||
@ -87,7 +87,7 @@ LL | extern "efiapi" fn dm10() {}
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:37:12
|
||||
--> $DIR/feature-gate-abi.rs:40:12
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn m1() {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -95,7 +95,7 @@ LL | extern "rust-intrinsic" fn m1() {}
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:39:12
|
||||
--> $DIR/feature-gate-abi.rs:42:12
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn m2() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -104,7 +104,7 @@ LL | extern "platform-intrinsic" fn m2() {}
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:41:12
|
||||
--> $DIR/feature-gate-abi.rs:44:12
|
||||
|
|
||||
LL | extern "rust-call" fn m4(_: ()) {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -113,7 +113,7 @@ LL | extern "rust-call" fn m4(_: ()) {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:42:12
|
||||
--> $DIR/feature-gate-abi.rs:45:12
|
||||
|
|
||||
LL | extern "efiapi" fn m10() {}
|
||||
| ^^^^^^^^
|
||||
@ -122,7 +122,7 @@ LL | extern "efiapi" fn m10() {}
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:47:12
|
||||
--> $DIR/feature-gate-abi.rs:50:12
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn im1() {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -130,7 +130,7 @@ LL | extern "rust-intrinsic" fn im1() {}
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:49:12
|
||||
--> $DIR/feature-gate-abi.rs:52:12
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn im2() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -139,7 +139,7 @@ LL | extern "platform-intrinsic" fn im2() {}
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:51:12
|
||||
--> $DIR/feature-gate-abi.rs:54:12
|
||||
|
|
||||
LL | extern "rust-call" fn im4(_: ()) {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -148,7 +148,7 @@ LL | extern "rust-call" fn im4(_: ()) {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:52:12
|
||||
--> $DIR/feature-gate-abi.rs:55:12
|
||||
|
|
||||
LL | extern "efiapi" fn im10() {}
|
||||
| ^^^^^^^^
|
||||
@ -157,7 +157,7 @@ LL | extern "efiapi" fn im10() {}
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:56:18
|
||||
--> $DIR/feature-gate-abi.rs:59:18
|
||||
|
|
||||
LL | type A1 = extern "rust-intrinsic" fn();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -165,7 +165,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:57:18
|
||||
--> $DIR/feature-gate-abi.rs:60:18
|
||||
|
|
||||
LL | type A2 = extern "platform-intrinsic" fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -174,7 +174,7 @@ LL | type A2 = extern "platform-intrinsic" fn();
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:58:18
|
||||
--> $DIR/feature-gate-abi.rs:61:18
|
||||
|
|
||||
LL | type A4 = extern "rust-call" fn(_: ());
|
||||
| ^^^^^^^^^^^
|
||||
@ -183,7 +183,7 @@ LL | type A4 = extern "rust-call" fn(_: ());
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:59:19
|
||||
--> $DIR/feature-gate-abi.rs:62:19
|
||||
|
|
||||
LL | type A10 = extern "efiapi" fn();
|
||||
| ^^^^^^^^
|
||||
@ -192,7 +192,7 @@ LL | type A10 = extern "efiapi" fn();
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: intrinsics are subject to change
|
||||
--> $DIR/feature-gate-abi.rs:62:8
|
||||
--> $DIR/feature-gate-abi.rs:65:8
|
||||
|
|
||||
LL | extern "rust-intrinsic" {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -200,7 +200,7 @@ LL | extern "rust-intrinsic" {}
|
||||
= help: add `#![feature(intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: platform intrinsics are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-abi.rs:63:8
|
||||
--> $DIR/feature-gate-abi.rs:66:8
|
||||
|
|
||||
LL | extern "platform-intrinsic" {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -209,7 +209,7 @@ LL | extern "platform-intrinsic" {}
|
||||
= help: add `#![feature(platform_intrinsics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: rust-call ABI is subject to change
|
||||
--> $DIR/feature-gate-abi.rs:64:8
|
||||
--> $DIR/feature-gate-abi.rs:67:8
|
||||
|
|
||||
LL | extern "rust-call" {}
|
||||
| ^^^^^^^^^^^
|
||||
@ -218,7 +218,7 @@ LL | extern "rust-call" {}
|
||||
= help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: efiapi ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi.rs:65:8
|
||||
--> $DIR/feature-gate-abi.rs:68:8
|
||||
|
|
||||
LL | extern "efiapi" {}
|
||||
| ^^^^^^^^
|
||||
@ -227,49 +227,49 @@ LL | extern "efiapi" {}
|
||||
= help: add `#![feature(abi_efiapi)]` to the crate attributes to enable
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:22:32
|
||||
--> $DIR/feature-gate-abi.rs:25:32
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn m1();
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:24:36
|
||||
--> $DIR/feature-gate-abi.rs:27:36
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn m2();
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:13:33
|
||||
--> $DIR/feature-gate-abi.rs:16:33
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn f1() {}
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:15:37
|
||||
--> $DIR/feature-gate-abi.rs:18:37
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn f2() {}
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:37:37
|
||||
--> $DIR/feature-gate-abi.rs:40:37
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn m1() {}
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:39:41
|
||||
--> $DIR/feature-gate-abi.rs:42:41
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn m2() {}
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:47:38
|
||||
--> $DIR/feature-gate-abi.rs:50:38
|
||||
|
|
||||
LL | extern "rust-intrinsic" fn im1() {}
|
||||
| ^^
|
||||
|
||||
error: intrinsic must be in `extern "rust-intrinsic" { ... }` block
|
||||
--> $DIR/feature-gate-abi.rs:49:42
|
||||
--> $DIR/feature-gate-abi.rs:52:42
|
||||
|
|
||||
LL | extern "platform-intrinsic" fn im2() {}
|
||||
| ^^
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![feature(fn_traits)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(tuple_trait)]
|
||||
|
||||
fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
|
||||
fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
|
||||
let y = (f.unwrap()).call(t);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/unsized-ret.rs:9:27
|
||||
--> $DIR/unsized-ret.rs:10:27
|
||||
|
|
||||
LL | foo::<fn() -> str, _>(None, ());
|
||||
| --------------------- ^^^^ doesn't have a size known at compile-time
|
||||
@ -9,13 +9,13 @@ LL | foo::<fn() -> str, _>(None, ());
|
||||
= help: within `fn() -> str`, the trait `Sized` is not implemented for `str`
|
||||
= note: required because it appears within the type `fn() -> str`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/unsized-ret.rs:4:11
|
||||
--> $DIR/unsized-ret.rs:5:11
|
||||
|
|
||||
LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
|
||||
LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
|
||||
| ^^^^^ required by this bound in `foo`
|
||||
|
||||
error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time
|
||||
--> $DIR/unsized-ret.rs:12:66
|
||||
--> $DIR/unsized-ret.rs:13:66
|
||||
|
|
||||
LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),));
|
||||
| ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time
|
||||
@ -25,9 +25,9 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&()
|
||||
= help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
|
||||
= note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/unsized-ret.rs:4:11
|
||||
--> $DIR/unsized-ret.rs:5:11
|
||||
|
|
||||
LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
|
||||
LL | fn foo<F: Fn<T>, T:std::marker::Tuple>(f: Option<F>, t: T) {
|
||||
| ^^^^^ required by this bound in `foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn do_it(x: &isize) { }
|
||||
|
||||
fn main() {
|
||||
|
@ -16,7 +16,7 @@ LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3));
|
||||
note: trait defined here, with 1 generic parameter: `Args`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| ^^ ----
|
||||
help: add missing generic argument
|
||||
|
|
||||
|
@ -6,8 +6,8 @@ LL | impl Fo {
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
// error-pattern: requires `generator` lang_item
|
||||
#![feature(no_core, lang_items, unboxed_closures)]
|
||||
#![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"] pub trait Sized { }
|
||||
|
||||
#[lang = "tuple_trait"] pub trait Tuple { }
|
||||
|
||||
#[lang = "fn_once"]
|
||||
#[rustc_paren_sugar]
|
||||
pub trait FnOnce<Args> {
|
||||
pub trait FnOnce<Args: Tuple> {
|
||||
type Output;
|
||||
|
||||
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||
|
@ -1,8 +1,15 @@
|
||||
error[E0635]: unknown feature `tuple_trait`
|
||||
--> $DIR/lang-item-missing-generator.rs:2:51
|
||||
|
|
||||
LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: requires `generator` lang_item
|
||||
--> $DIR/lang-item-missing-generator.rs:15:17
|
||||
--> $DIR/lang-item-missing-generator.rs:17:17
|
||||
|
|
||||
LL | pub fn abc() -> impl FnOnce(f32) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0635`.
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures,tuple_trait)]
|
||||
|
||||
use std::ops::FnMut;
|
||||
|
||||
fn to_fn_mut<A, F: FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A:std::marker::Tuple, F:FnMut<A>>(f: F) -> F { f }
|
||||
|
||||
fn call_it<F: FnMut(isize, isize) -> isize>(y: isize, mut f: F) -> isize {
|
||||
//~^ NOTE required by this bound in `call_it`
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
|
||||
fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
|
||||
fn test(_x: Box<usize>) {}
|
||||
|
||||
|
@ -8,22 +8,23 @@ struct S {
|
||||
}
|
||||
|
||||
impl FnMut<isize> for S {
|
||||
//~^ ERROR type parameter to bare `FnMut` trait must be a tuple
|
||||
extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
self.x + self.y + z
|
||||
}
|
||||
//~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument
|
||||
}
|
||||
|
||||
impl FnOnce<isize> for S {
|
||||
//~^ ERROR type parameter to bare `FnOnce` trait must be a tuple
|
||||
type Output = isize;
|
||||
extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
|
||||
extern "rust-call" fn call_once(mut self, z: isize) -> isize {
|
||||
//~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
self.call_mut(z)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut s = S {
|
||||
x: 1,
|
||||
y: 2,
|
||||
};
|
||||
drop(s(3)) //~ ERROR cannot use call notation
|
||||
let mut s = S { x: 1, y: 2 };
|
||||
drop(s(3))
|
||||
}
|
||||
|
@ -1,21 +1,40 @@
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
--> $DIR/overloaded-calls-nontuple.rs:11:5
|
||||
error[E0059]: type parameter to bare `FnMut` trait must be a tuple
|
||||
--> $DIR/overloaded-calls-nontuple.rs:10:6
|
||||
|
|
||||
LL | impl FnMut<isize> for S {
|
||||
| ^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
|
||||
|
|
||||
note: required by a bound in `FnMut`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait FnMut<Args: Tuple>: FnOnce<Args> {
|
||||
| ^^^^^ required by this bound in `FnMut`
|
||||
|
||||
error[E0059]: type parameter to bare `FnOnce` trait must be a tuple
|
||||
--> $DIR/overloaded-calls-nontuple.rs:18:6
|
||||
|
|
||||
LL | impl FnOnce<isize> for S {
|
||||
| ^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
|
||||
|
|
||||
note: required by a bound in `FnOnce`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait FnOnce<Args: Tuple> {
|
||||
| ^^^^^ required by this bound in `FnOnce`
|
||||
|
||||
error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/overloaded-calls-nontuple.rs:12:5
|
||||
|
|
||||
LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
|
||||
|
||||
error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
|
||||
--> $DIR/overloaded-calls-nontuple.rs:19:5
|
||||
error[E0277]: functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
--> $DIR/overloaded-calls-nontuple.rs:21:5
|
||||
|
|
||||
LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Tuple` is not implemented for `isize`
|
||||
|
||||
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
|
||||
--> $DIR/overloaded-calls-nontuple.rs:28:10
|
||||
|
|
||||
LL | drop(s(3))
|
||||
| ^^^^
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0059`.
|
||||
Some errors have detailed explanations: E0059, E0277.
|
||||
For more information about an error, try `rustc --explain E0059`.
|
||||
|
@ -94,8 +94,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error[E0405]: cannot find trait `r#fn` in this scope
|
||||
--> $DIR/kw-in-trait-bounds.rs:17:4
|
||||
@ -105,8 +105,8 @@ LL | G: fn(),
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error[E0405]: cannot find trait `r#fn` in this scope
|
||||
--> $DIR/kw-in-trait-bounds.rs:3:27
|
||||
@ -116,8 +116,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error[E0405]: cannot find trait `r#fn` in this scope
|
||||
--> $DIR/kw-in-trait-bounds.rs:3:41
|
||||
@ -127,8 +127,8 @@ LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error[E0405]: cannot find trait `r#struct` in this scope
|
||||
--> $DIR/kw-in-trait-bounds.rs:24:10
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
|
||||
|
||||
fn main() {
|
||||
let r = {
|
||||
|
@ -6,8 +6,8 @@ LL | impl F {
|
||||
|
|
||||
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args>: FnMut<Args> {
|
||||
| ------------------------------- similarly named trait `Fn` defined here
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| -------------------------------------- similarly named trait `Fn` defined here
|
||||
|
||||
error[E0412]: cannot find type `TestResult` in this scope
|
||||
--> $DIR/issue-83693.rs:9:22
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
fn a<F: Fn<usize>>(f: F) {}
|
||||
//~^ ERROR type parameter to bare `Fn` trait must be a tuple
|
||||
|
||||
fn main() {
|
||||
a(|_: usize| {});
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
@ -1,17 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/non-tupled-arg-mismatch.rs:6:5
|
||||
|
|
||||
LL | a(|_: usize| {});
|
||||
| ^ types differ
|
||||
|
|
||||
= note: expected trait `Fn<usize>`
|
||||
found trait `Fn<(usize,)>`
|
||||
note: required by a bound in `a`
|
||||
error[E0059]: type parameter to bare `Fn` trait must be a tuple
|
||||
--> $DIR/non-tupled-arg-mismatch.rs:3:9
|
||||
|
|
||||
LL | fn a<F: Fn<usize>>(f: F) {}
|
||||
| ^^^^^^^^^ required by this bound in `a`
|
||||
| ^^^^^^^^^ the trait `Tuple` is not implemented for `usize`
|
||||
|
|
||||
note: required by a bound in `Fn`
|
||||
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
|
||||
| ^^^^^ required by this bound in `Fn`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0059`.
|
||||
|
@ -1,12 +1,12 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
// Tests that we can't move out of an unboxed closure environment
|
||||
// if the upvar is captured by ref or the closure takes self by
|
||||
// reference.
|
||||
|
||||
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
|
||||
fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_once<A:std::marker::Tuple,F:FnOnce<A>>(f: F) -> F { f }
|
||||
|
||||
fn main() {
|
||||
// By-ref cases
|
||||
|
@ -2,12 +2,12 @@
|
||||
// as `mut` through a closure. Also test that we CAN mutate a moved copy,
|
||||
// unless this is a `Fn` closure. Issue #16749.
|
||||
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
use std::mem;
|
||||
|
||||
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
|
||||
fn a() {
|
||||
let n = 0;
|
||||
|
@ -28,8 +28,8 @@ LL | n += 1;
|
||||
error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/unboxed-closures-mutate-upvar.rs:53:9
|
||||
|
|
||||
LL | fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f }
|
||||
| - change this to accept `FnMut` instead of `Fn`
|
||||
...
|
||||
LL | let mut f = to_fn(move || {
|
||||
| ----- ------- in this closure
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unboxed_closures, tuple_trait)]
|
||||
|
||||
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
|
||||
fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f }
|
||||
|
||||
fn main() {
|
||||
let mut_ = to_fn_mut(|x| x);
|
||||
|
Loading…
Reference in New Issue
Block a user