From b988efc100efc2de615ef83ae271dda947cccaf0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 30 Nov 2022 11:09:22 +0000 Subject: [PATCH 1/5] Remove an unnecessary `unwrap` --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 5dc0ada153fb9..2a9748fb92538 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -93,11 +93,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let has_error = match method { - Ok(method) => method.substs.references_error() || method.sig.references_error(), - Err(_) => true, - }; - if has_error { + let method = method.ok().filter(|method| !method.references_error()); + let Some(method) = method else { let err_inputs = self.err_args(args_no_rcvr.len()); let err_inputs = match tuple_arguments { @@ -113,12 +110,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args_no_rcvr, false, tuple_arguments, - method.ok().map(|method| method.def_id), + method.map(|method| method.def_id), ); return self.tcx.ty_error_misc(); - } + }; - let method = method.unwrap(); // HACK(eddyb) ignore self in the definition (see above). let expected_input_tys = self.expected_inputs_for_expected_output( sp, From 27891c5e21f861efd932b4be5e2fe54fc9008d68 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 17 Mar 2023 09:19:33 +0000 Subject: [PATCH 2/5] Add Callable trait --- .../src/error_codes/E0183.md | 2 + compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_hir_typeck/src/callee.rs | 64 ++++++++++++++++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 + .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 29 ++++++--- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 17 +++-- compiler/rustc_hir_typeck/src/method/mod.rs | 3 +- compiler/rustc_middle/src/ty/consts/int.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/solve/assembly/mod.rs | 9 +++ .../src/solve/assembly/structural_traits.rs | 36 ++++++----- .../src/solve/fulfill.rs | 2 + .../src/solve/project_goals.rs | 10 ++- .../src/solve/trait_goals.rs | 30 ++++++++- .../src/traits/select/candidate_assembly.rs | 35 +++++++++- .../src/traits/select/confirmation.rs | 44 +++++++++++-- library/alloc/src/boxed.rs | 4 ++ library/core/src/internal_macros.rs | 3 + library/core/src/ops/function.rs | 37 +++++++++++ library/core/src/ops/mod.rs | 4 ++ library/core/src/panic/unwind_safe.rs | 4 ++ .../src/library-features/fn-traits.md | 1 + src/tools/clippy/tests/ui/no_effect.rs | 5 ++ src/tools/clippy/tests/ui/no_effect.stderr | 58 ++++++++--------- .../tests/pass/overloaded-calls-simple.rs | 2 + tests/assembly/asm/aarch64-modifiers.rs | 2 + tests/assembly/asm/aarch64-types.rs | 2 + tests/assembly/asm/arm-modifiers.rs | 2 + tests/assembly/asm/arm-types.rs | 2 + tests/assembly/asm/hexagon-types.rs | 2 + tests/assembly/asm/loongarch-type.rs | 4 +- tests/assembly/asm/mips-types.rs | 2 + tests/assembly/asm/powerpc-types.rs | 2 + tests/assembly/asm/riscv-types.rs | 2 + tests/assembly/asm/s390x-types.rs | 2 + tests/assembly/asm/x86-modifiers.rs | 2 + tests/assembly/asm/x86-types.rs | 2 + tests/assembly/pic-relocation-model.rs | 17 +++-- tests/assembly/pie-relocation-model.rs | 17 +++-- tests/assembly/sparc-struct-abi.rs | 2 + tests/assembly/target-feature-multiple.rs | 2 + tests/assembly/x86-stack-probes.rs | 2 + tests/codegen/avr/avr-func-addrspace.rs | 25 +++++--- .../riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs | 2 + ...it-kcfi-operand-bundle-attr-no-sanitize.rs | 12 ++-- ...rand-bundle-itanium-cxx-abi-generalized.rs | 12 ++-- ...-itanium-cxx-abi-normalized-generalized.rs | 12 ++-- ...erand-bundle-itanium-cxx-abi-normalized.rs | 12 ++-- ...mit-kcfi-operand-bundle-itanium-cxx-abi.rs | 12 ++-- ...sanitizer-kcfi-emit-kcfi-operand-bundle.rs | 12 ++-- ...r-kcfi-emit-type-metadata-trait-objects.rs | 41 ++++++------ tests/codegen/target-feature-overrides.rs | 2 + .../mir-opt/inline/inline_instruction_set.rs | 3 + .../atomic-lock-free/atomic_lock_free.rs | 4 +- tests/run-make/simd-ffi/simd.rs | 3 + tests/run-make/target-specs/foo.rs | 3 + tests/ui/borrowck/borrowck-overloaded-call.rs | 40 ++++++------ .../borrowck/borrowck-overloaded-call.stderr | 11 ++-- tests/ui/borrowck/issue-92157.rs | 8 ++- tests/ui/borrowck/issue-92157.stderr | 2 +- tests/ui/c-variadic/variadic-ffi-1.rs | 7 +- tests/ui/c-variadic/variadic-ffi-1.stderr | 26 ++++---- tests/ui/chalkify/assert.rs | 6 -- tests/ui/chalkify/builtin-copy-clone.rs | 45 ------------- tests/ui/chalkify/chalk_initial_program.rs | 16 ----- .../ui/chalkify/chalk_initial_program.stderr | 18 ------ tests/ui/chalkify/closure.rs | 38 ----------- tests/ui/chalkify/closure.stderr | 22 ------- tests/ui/chalkify/generic_impls.rs | 18 ------ tests/ui/chalkify/generic_impls.stderr | 29 --------- tests/ui/chalkify/inherent_impl.rs | 42 ------------ tests/ui/chalkify/inherent_impl_min.rs | 27 -------- tests/ui/chalkify/println.rs | 6 -- tests/ui/chalkify/projection.rs | 25 -------- .../recursive_where_clause_on_type.rs | 30 --------- .../recursive_where_clause_on_type.stderr | 14 ---- tests/ui/chalkify/super_trait.rs | 19 ------ tests/ui/chalkify/trait-objects.rs | 12 ---- tests/ui/chalkify/trait_implied_bound.rs | 18 ------ tests/ui/chalkify/type_implied_bound.rs | 29 --------- tests/ui/chalkify/type_inference.rs | 28 -------- tests/ui/chalkify/type_inference.stderr | 20 ------ tests/ui/chalkify/type_wf.rs | 25 -------- tests/ui/chalkify/type_wf.stderr | 16 ----- .../params-on-registers.rs | 15 +++-- .../cmse-nonsecure-call/params-on-stack.rs | 16 ++--- tests/ui/consts/fn_trait_refs.stderr | 8 +-- tests/ui/extern/issue-13655.rs | 12 ++-- .../normalize-under-binder/issue-62529-3.rs | 1 + .../issue-62529-3.stderr | 20 +++++- tests/ui/issues/issue-14959.rs | 16 +++-- tests/ui/issues/issue-15094.rs | 12 ++-- tests/ui/issues/issue-16739.rs | 38 ++++++++--- tests/ui/issues/issue-18952.rs | 3 + tests/ui/issues/issue-19982.rs | 2 + tests/ui/issues/issue-20225.rs | 16 +++-- tests/ui/issues/issue-20225.stderr | 36 +++++------ tests/ui/issues/issue-20544.rs | 7 +- tests/ui/issues/issue-22603.rs | 5 +- tests/ui/issues/issue-33687.rs | 2 + tests/ui/issues/issue-45510.rs | 4 ++ ...-fn_mut-call-ill-formed.fn_bad_item.stderr | 4 +- ...n-fn_mut-call-ill-formed.fn_bad_sig.stderr | 4 +- ...mut-call-ill-formed.fn_mut_bad_item.stderr | 4 +- ..._mut-call-ill-formed.fn_mut_bad_sig.stderr | 4 +- ...ut-call-ill-formed.fn_once_bad_item.stderr | 4 +- ...mut-call-ill-formed.fn_once_bad_sig.stderr | 4 +- .../lang-items/fn-fn_mut-call-ill-formed.rs | 16 +++-- tests/ui/lang-items/issue-86238.rs | 3 +- tests/ui/lang-items/issue-86238.stderr | 2 +- .../missing-clone-for-suggestion.rs | 3 + .../missing-clone-for-suggestion.stderr | 4 +- .../mismatched_types/overloaded-calls-bad.rs | 4 ++ .../overloaded-calls-bad.stderr | 10 +-- tests/ui/overloaded/issue-14958.rs | 20 ++++-- .../overloaded/overloaded-calls-nontuple.rs | 2 + .../overloaded-calls-param-vtables.rs | 18 ++++-- .../ui/overloaded/overloaded-calls-simple.rs | 33 +++++----- .../overloaded/overloaded-calls-zero-args.rs | 11 ++-- tests/ui/privacy/privacy1.rs | 3 + tests/ui/privacy/privacy1.stderr | 62 +++++++++--------- tests/ui/repr/16-bit-repr-c-enum.rs | 6 +- tests/ui/span/issue-23827.rs | 4 +- tests/ui/target-feature/feature-hierarchy.rs | 4 +- tests/ui/target-feature/no-llvm-leaks.rs | 4 +- tests/ui/target-feature/tied-features.rs | 6 +- tests/ui/target-feature/tied-features.stderr | 4 +- .../builtin-fn-must-return-sized.rs | 2 +- .../ui/traits/new-solver/callable.new.stderr | 15 +++++ .../ui/traits/new-solver/callable.old.stderr | 15 +++++ tests/ui/traits/new-solver/callable.rs | 13 ++++ tests/ui/traits/new-solver/object-unsafety.rs | 3 +- .../traits/new-solver/object-unsafety.stderr | 12 +++- tests/ui/unboxed-closures/issue-30906.rs | 7 ++ tests/ui/unboxed-closures/issue-30906.stderr | 2 +- ...unboxed-closures-fn-as-fnmut-and-fnonce.rs | 18 ++++-- .../unboxed-closures-fnmut-as-fn.rs | 10 ++- .../unboxed-closures-fnmut-as-fn.stderr | 8 +-- .../unboxed-closures-fnmut-as-fnonce.rs | 10 ++- .../unboxed-closures-infer-recursive-fn.rs | 28 ++++---- .../unboxed-closures-manual-impl.rs | 8 ++- ...oxed-closures-recursive-fn-using-fn-mut.rs | 23 ++++--- tests/ui/weird-exprs.rs | 7 +- 144 files changed, 937 insertions(+), 924 deletions(-) delete mode 100644 tests/ui/chalkify/assert.rs delete mode 100644 tests/ui/chalkify/builtin-copy-clone.rs delete mode 100644 tests/ui/chalkify/chalk_initial_program.rs delete mode 100644 tests/ui/chalkify/chalk_initial_program.stderr delete mode 100644 tests/ui/chalkify/closure.rs delete mode 100644 tests/ui/chalkify/closure.stderr delete mode 100644 tests/ui/chalkify/generic_impls.rs delete mode 100644 tests/ui/chalkify/generic_impls.stderr delete mode 100644 tests/ui/chalkify/inherent_impl.rs delete mode 100644 tests/ui/chalkify/inherent_impl_min.rs delete mode 100644 tests/ui/chalkify/println.rs delete mode 100644 tests/ui/chalkify/projection.rs delete mode 100644 tests/ui/chalkify/recursive_where_clause_on_type.rs delete mode 100644 tests/ui/chalkify/recursive_where_clause_on_type.stderr delete mode 100644 tests/ui/chalkify/super_trait.rs delete mode 100644 tests/ui/chalkify/trait-objects.rs delete mode 100644 tests/ui/chalkify/trait_implied_bound.rs delete mode 100644 tests/ui/chalkify/type_implied_bound.rs delete mode 100644 tests/ui/chalkify/type_inference.rs delete mode 100644 tests/ui/chalkify/type_inference.stderr delete mode 100644 tests/ui/chalkify/type_wf.rs delete mode 100644 tests/ui/chalkify/type_wf.stderr create mode 100644 tests/ui/traits/new-solver/callable.new.stderr create mode 100644 tests/ui/traits/new-solver/callable.old.stderr create mode 100644 tests/ui/traits/new-solver/callable.rs diff --git a/compiler/rustc_error_codes/src/error_codes/E0183.md b/compiler/rustc_error_codes/src/error_codes/E0183.md index 92fa4c7c21e72..73278e6102da8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0183.md +++ b/compiler/rustc_error_codes/src/error_codes/E0183.md @@ -31,6 +31,8 @@ impl FnOnce<()> for MyClosure { // ok! println!("{}", self.foo); } } + +impl std::ops::Callable<()> for MyClosure {} ``` The arguments must be a tuple representing the argument list. diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 302a949841316..7eeb963279a88 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -207,6 +207,7 @@ language_item_table! { Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + Callable, sym::callable, callable_trait, Target::Trait, GenericRequirement::Exact(1); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9da72aae77660..40a0a76b49a8e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -3,12 +3,14 @@ use super::method::MethodCallee; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; use crate::type_error_struct; +use hir::LangItem; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir_analysis::autoderef::Autoderef; +use rustc_infer::traits::ObligationCauseCode; use rustc_infer::{ infer, traits::{self, Obligation}, @@ -22,7 +24,6 @@ use rustc_middle::ty::adjustment::{ }; use rustc_middle::ty::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; @@ -66,7 +67,7 @@ pub fn check_legal_trait_for_method_call( #[derive(Debug)] enum CallStep<'tcx> { Builtin(Ty<'tcx>), - DeferredClosure(LocalDefId, ty::FnSig<'tcx>), + DeferredClosure(Ty<'tcx>, ty::FnSig<'tcx>), /// E.g., enum variant constructors. Overloaded(MethodCallee<'tcx>), } @@ -173,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_substs: substs, }, ); - return Some(CallStep::DeferredClosure(def_id, closure_sig)); + return Some(CallStep::DeferredClosure(adjusted_ty, closure_sig)); } } @@ -375,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let (fn_sig, def_id) = match *callee_ty.kind() { + let fn_sig = match *callee_ty.kind() { ty::FnDef(def_id, subst) => { let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst); @@ -403,9 +404,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); } } - (fn_sig, Some(def_id)) + fn_sig } - ty::FnPtr(sig) => (sig, None), + ty::FnPtr(sig) => sig, _ => { for arg in arg_exprs { self.check_expr(arg); @@ -459,7 +460,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::DontTupleArguments, - def_id, + callee_ty, + ); + + self.check_callable( + call_expr.hir_id, + call_expr.span, + callee_ty, + fn_sig.inputs().iter().copied(), ); if fn_sig.abi == abi::Abi::RustCall { @@ -705,12 +713,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit() } + /// Enforces that things being called actually are callable + #[instrument(skip(self, arguments))] + pub(super) fn check_callable( + &self, + hir_id: hir::HirId, + span: Span, + callable_ty: Ty<'tcx>, + arguments: impl IntoIterator>, + ) { + if callable_ty.references_error() { + return; + } + + let cause = self.cause(span, ObligationCauseCode::MiscObligation); + + let arguments_tuple = self.tcx.mk_tup_from_iter(arguments.into_iter()); + let pred = ty::Binder::dummy(ty::TraitRef::from_lang_item( + self.tcx, + LangItem::Callable, + span, + [callable_ty, arguments_tuple], + )); + self.register_predicate(Obligation::new(self.tcx, cause, self.param_env, pred)); + } + fn confirm_deferred_closure_call( &self, call_expr: &'tcx hir::Expr<'tcx>, arg_exprs: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, - closure_def_id: LocalDefId, + closure_ty: Ty<'tcx>, fn_sig: ty::FnSig<'tcx>, ) -> Ty<'tcx> { // `fn_sig` is the *signature* of the closure being called. We @@ -733,7 +766,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::TupleArguments, - Some(closure_def_id.to_def_id()), + closure_ty, + ); + + self.check_callable( + call_expr.hir_id, + call_expr.span, + closure_ty, + fn_sig.inputs()[0].tuple_fields(), ); fn_sig.output() @@ -804,6 +844,12 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { let mut adjustments = self.adjustments; adjustments.extend(autoref); fcx.apply_adjustments(self.callee_expr, adjustments); + fcx.check_callable( + self.callee_expr.hir_id, + self.callee_expr.span, + fcx.tcx.mk_fn_def(method_callee.def_id, method_callee.substs), + method_sig.inputs().iter().copied(), + ); fcx.write_method_call(self.call_expr.hir_id, method_callee); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cf6d9eda321ab..c54e3395316ce 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -313,6 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result } + #[instrument(level = "trace", skip(self, span), ret)] pub(in super::super) fn normalize(&self, span: Span, value: T) -> T where T: TypeFoldable>, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 2a9748fb92538..c2f45912df948 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { let method = method.ok().filter(|method| !method.references_error()); - let Some(method) = method else { + let Some(method) = method else { let err_inputs = self.err_args(args_no_rcvr.len()); let err_inputs = match tuple_arguments { @@ -102,6 +102,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { TupleArguments => vec![self.tcx.mk_tup(&err_inputs)], }; + let err = self.tcx.ty_error_misc(); + let callee_ty = method.map_or(err, |method| self.tcx.mk_fn_def(method.def_id, method.substs)); self.check_argument_types( sp, expr, @@ -110,9 +112,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args_no_rcvr, false, tuple_arguments, - method.map(|method| method.def_id), + callee_ty, ); - return self.tcx.ty_error_misc(); + self.check_callable(expr.hir_id, sp, callee_ty, std::iter::once(err).chain(err_inputs)); + return err; }; // HACK(eddyb) ignore self in the definition (see above). @@ -122,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method.sig.output(), &method.sig.inputs()[1..], ); + let callee_ty = self.tcx.mk_fn_def(method.def_id, method.substs); self.check_argument_types( sp, expr, @@ -130,14 +134,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args_no_rcvr, method.sig.c_variadic, tuple_arguments, - Some(method.def_id), + callee_ty, ); + self.check_callable(expr.hir_id, sp, callee_ty, method.sig.inputs().iter().copied()); + method.sig.output() } /// Generic function that factors out common logic from function calls, /// method calls and overloaded operators. + #[instrument(level = "trace", skip(self, call_expr, provided_args))] pub(in super::super) fn check_argument_types( &self, // Span enclosing the call site @@ -154,8 +161,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { c_variadic: bool, // Whether the arguments have been bundled in a tuple (ex: closures) tuple_arguments: TupleArgumentsFlag, - // The DefId for the function being called, for better error messages - fn_def_id: Option, + // The callee type (e.g. function item ZST, function pointer or closure). + // Note that this may have surprising function definitions, like often just + // referring to `FnOnce::call_once`, but with an appropriate `Self` type. + callee_ty: Ty<'tcx>, ) { let tcx = self.tcx; @@ -230,7 +239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let minimum_input_count = expected_input_tys.len(); let provided_arg_count = provided_args.len(); - let is_const_eval_select = matches!(fn_def_id, Some(def_id) if + let is_const_eval_select = matches!(*callee_ty.kind(), ty::FnDef(def_id, _) if self.tcx.def_kind(def_id) == hir::def::DefKind::Fn && self.tcx.is_intrinsic(def_id) && self.tcx.item_name(def_id) == sym::const_eval_select); @@ -456,7 +465,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_args, c_variadic, err_code, - fn_def_id, + match *callee_ty.kind() { + ty::Generator(did, ..) | ty::Closure(did, _) | ty::FnDef(did, _) => Some(did), + ty::FnPtr(..) | ty::Error(_) => None, + ref kind => span_bug!(call_span, "invalid call argument type: {kind:?}"), + }, call_span, call_expr, ); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 7a897778ff7af..1ae3914708190 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -430,7 +430,7 @@ fn report_unexpected_variant_res( /// # fn f(x: (isize, isize)) {} /// f((1, 2)); /// ``` -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq, Debug)] enum TupleArgumentsFlag { DontTupleArguments, TupleArguments, diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 31894d25b60dc..e3c91226f4b59 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -86,6 +86,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ConfirmContext { fcx, span, self_expr, call_expr, skip_record_for_diagnostics: false } } + #[instrument(level = "trace", skip(self), ret)] fn confirm( &mut self, unadjusted_self_ty: Ty<'tcx>, @@ -99,7 +100,8 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick); let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs); - debug!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}"); + debug!(?rcvr_substs); + debug!(?all_substs); // Create the final signature for the method, replacing late-bound regions. let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs); @@ -125,11 +127,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // could alter our Self-type, except for normalizing the receiver from the // signature (which is also done during probing). let method_sig_rcvr = self.normalize(self.span, method_sig.inputs()[0]); - debug!( - "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}", - self_ty, method_sig_rcvr, method_sig, method_predicates - ); + debug!(?self_ty, ?method_sig_rcvr, ?pick); self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs); + let inputs = method_sig.inputs(); let (method_sig, method_predicates) = self.normalize(self.span, (method_sig, method_predicates)); @@ -150,6 +150,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ); } + self.check_callable( + self.call_expr.hir_id, + self.span, + self.tcx.mk_fn_def(pick.item.def_id, all_substs), + inputs.iter().copied(), + ); + // Create the final `MethodCallee`. let callee = MethodCallee { def_id: pick.item.def_id, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index ebd7b3123ebfd..bd6f92dce90cb 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -18,6 +18,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; +use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; @@ -33,7 +34,7 @@ pub fn provide(providers: &mut Providers) { probe::provide(providers); } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, TypeVisitable)] pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 1e43fab457e56..624195cfb282b 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -418,7 +418,7 @@ impl TryFrom for char { #[inline] fn try_from(int: ScalarInt) -> Result { - let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::())) else { + let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::())) else { return Err(CharTryFromScalarInt); }; match char::from_u32(bits.try_into().unwrap()) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c71ed2097b8f5..205063baa3fe0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -450,6 +450,7 @@ symbols! { call, call_mut, call_once, + callable, caller_location, capture_disjoint_fields, cause, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 9e8dbd0cde217..c84f930d69a16 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -236,6 +236,12 @@ pub(super) trait GoalKind<'tcx>: goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + // `Callable` is implemented for all function items, function definitions and closures. + fn consider_builtin_callable_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; + // A generator (that comes from an `async` desugaring) is known to implement // `Future`, where `O` is given by the generator's return type // that was computed during type-checking. @@ -284,6 +290,7 @@ pub(super) trait GoalKind<'tcx>: } impl<'tcx> EvalCtxt<'_, 'tcx> { + #[instrument(level = "trace", skip(self), ret)] pub(super) fn assemble_and_evaluate_candidates>( &mut self, goal: Goal<'tcx, G>, @@ -430,6 +437,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_tuple_candidate(self, goal) } else if lang_items.pointee_trait() == Some(trait_def_id) { G::consider_builtin_pointee_candidate(self, goal) + } else if lang_items.callable_trait() == Some(trait_def_id) { + G::consider_builtin_callable_candidate(self, goal) } else if lang_items.future_trait() == Some(trait_def_id) { G::consider_builtin_future_candidate(self, goal) } else if lang_items.gen_trait() == Some(trait_def_id) { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 9eac53c39839b..43f05d7051969 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -218,18 +218,29 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } } +#[derive(Debug)] +pub(crate) enum CallableMode { + /// Check that the given type can implement a `Fn*` trait. + Fn(ty::ClosureKind), + /// Do not perform any signature checks, just extract the the tupled arguments and the output. + Callable, +} + // Returns a binder of the tupled inputs types and output type from a builtin callable type. +#[instrument(level = "trace", skip(tcx), ret)] pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>, - goal_kind: ty::ClosureKind, + mode: CallableMode, ) -> Result, Ty<'tcx>)>>, NoSolution> { + use CallableMode::*; match *self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, substs) => { let sig = tcx.fn_sig(def_id); - if sig.skip_binder().is_fn_trait_compatible() - && tcx.codegen_fn_attrs(def_id).target_features.is_empty() + if matches!(mode, Callable) + || sig.skip_binder().is_fn_trait_compatible() + && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { Ok(Some( sig.subst(tcx, substs) @@ -241,7 +252,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnPtr(sig) => { - if sig.is_fn_trait_compatible() { + if matches!(mode, Callable) || sig.is_fn_trait_compatible() { Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs()), sig.output())))) } else { Err(NoSolution) @@ -249,21 +260,16 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } ty::Closure(_, substs) => { let closure_substs = substs.as_closure(); - match closure_substs.kind_ty().to_opt_closure_kind() { + match (mode, closure_substs.kind_ty().to_opt_closure_kind()) { + (Callable, _) => {} // If the closure's kind doesn't extend the goal kind, // then the closure doesn't implement the trait. - Some(closure_kind) => { - if !closure_kind.extends(goal_kind) { - return Err(NoSolution); - } - } + (Fn(goal_kind), Some(closure_kind)) if closure_kind.extends(goal_kind) => {} + (Fn(_), Some(_)) => return Err(NoSolution), // Closure kind is not yet determined, so we return ambiguity unless // the expected kind is `FnOnce` as that is always implemented. - None => { - if goal_kind != ty::ClosureKind::FnOnce { - return Ok(None); - } - } + (Fn(ty::ClosureKind::FnOnce), None) => {} + (Fn(_), None) => return Ok(None), } Ok(Some(closure_substs.sig().map_bound(|sig| (sig.inputs()[0], sig.output())))) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 5c62ea64f993c..40740859569c8 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -43,6 +43,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { self.obligations.push(obligation); } + #[instrument(level = "trace", skip(self, infcx), ret)] fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { self.obligations .drain(..) @@ -76,6 +77,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .collect() } + #[instrument(level = "trace", skip(self, infcx), ret)] fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { let mut errors = Vec::new(); for i in 0.. { diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index cbea8009f0248..aeb2909a6541a 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -283,6 +283,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { bug!("`FnPtr` does not have an associated type: {:?}", goal); } + fn consider_builtin_callable_candidate( + _ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + bug!("`Callable` does not have an associated type: {:?}", goal); + } + + #[instrument(level = "trace", skip(ecx), ret)] fn consider_builtin_fn_trait_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -293,7 +301,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, goal.predicate.self_ty(), - goal_kind, + structural_traits::CallableMode::Fn(goal_kind), )? { Some(tupled_inputs_and_output) => tupled_inputs_and_output, None => { diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 18fec6d9c890a..4552a5a41b2be 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1,5 +1,6 @@ //! Dealing with trait goals, i.e. `T: Trait<'a, U>`. +use super::assembly::structural_traits::CallableMode; use super::assembly::{self, structural_traits}; use super::{EvalCtxt, SolverMode}; use rustc_hir::def_id::DefId; @@ -219,6 +220,31 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } } + #[instrument(level = "trace", skip(ecx), ret)] + fn consider_builtin_callable_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let tcx = ecx.tcx(); + let Some(tupled_inputs_and_output) = + structural_traits::extract_tupled_inputs_and_output_from_callable( + tcx, + goal.predicate.self_ty(), + CallableMode::Callable, + )? else { + return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); + }; + + let pred = tupled_inputs_and_output + .map_bound(|(inputs, _)| { + ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) + }) + .to_predicate(tcx); + // `Callable` is only implemented if its tupled inputs (`T`) match the ones from the function-like's signature. + Self::consider_implied_clause(ecx, goal, pred, []) + } + + #[instrument(level = "trace", skip(ecx), ret)] fn consider_builtin_fn_trait_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -233,7 +259,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { match structural_traits::extract_tupled_inputs_and_output_from_callable( tcx, goal.predicate.self_ty(), - goal_kind, + CallableMode::Fn(goal_kind), )? { Some(a) => a, None => { @@ -731,7 +757,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }) } - #[instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self), ret)] pub(super) fn compute_trait_goal( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 412b601c966ff..a8387e38ea187 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -108,9 +108,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // types have builtin support for `Clone`. let clone_conditions = self.copy_clone_conditions(obligation); self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates); - } - - if lang_items.gen_trait() == Some(def_id) { + } else if lang_items.callable_trait() == Some(def_id) { + // `Callable` is automatically implemented for all fn items and closures + self.assemble_builtin_callable_candidates(obligation, &mut candidates); + } else if lang_items.gen_trait() == Some(def_id) { self.assemble_generator_candidates(obligation, &mut candidates); } else if lang_items.future_trait() == Some(def_id) { self.assemble_future_candidates(obligation, &mut candidates); @@ -330,6 +331,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + /// Implements one of the `Fn()` family for a fn pointer. + #[instrument(skip(self, candidates), level = "debug")] + fn assemble_builtin_callable_candidates( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + trace!(substs = ?obligation.predicate.skip_binder().trait_ref.substs); + // Okay to skip binder because what we are inspecting doesn't involve bound regions. + let self_ty = obligation.self_ty().skip_binder(); + trace!(?self_ty); + trace!(ty = ?self_ty.kind()); + match *self_ty.kind() { + ty::Infer(ty::TyVar(_)) => { + debug!("assemble_builtin_callable_candidates: ambiguous self-type"); + candidates.ambiguous = true; // Could wind up being a fn() type. + } + // Unsafe or extern functions do not necessarily implement FnOnce, + // but they do implement `Callable` + ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) => { + candidates.vec.push(BuiltinCandidate { has_nested: true }) + } + // Everything else will have to implement `FnOnce` and thus + // implement `Callable` via the libcore blanket impl. + _ => {} + } + } + /// Searches for impls that might apply to `obligation`. #[instrument(level = "debug", skip(self, candidates))] fn assemble_candidates_from_impls( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c94fddc124ff7..9f6b7a52e38c5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -20,7 +20,7 @@ use rustc_session::config::TraitSolver; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; -use crate::traits::util::{self, closure_trait_ref_and_return_type}; +use crate::traits::util::{self, closure_trait_ref_and_return_type, TupleArgumentsFlag}; use crate::traits::vtable::{ count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset, VtblSegment, @@ -49,7 +49,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result, SelectionError<'tcx>> { let mut impl_src = match candidate { BuiltinCandidate { has_nested } => { - let data = self.confirm_builtin_candidate(obligation, has_nested); + let data = self.confirm_builtin_candidate(obligation, has_nested)?; ImplSource::Builtin(data) } @@ -242,7 +242,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, has_nested: bool, - ) -> Vec> { + ) -> Result>, SelectionError<'tcx>> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let lang_items = self.tcx().lang_items(); @@ -254,6 +254,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.copy_clone_conditions(obligation) } else if Some(trait_def) == lang_items.clone_trait() { self.copy_clone_conditions(obligation) + } else if Some(trait_def) == lang_items.callable_trait() { + return self.confirm_callable_candidate(obligation); } else { bug!("unexpected builtin trait {:?}", trait_def) }; @@ -275,7 +277,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligations); - obligations + Ok(obligations) } #[instrument(level = "debug", skip(self))] @@ -847,6 +849,40 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(nested) } + #[instrument(level = "trace", skip(self), ret)] + fn confirm_callable_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { + let tcx = self.tcx(); + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let (sig, tuple_arguments) = match *self_ty.kind() { + ty::FnPtr(sig) => (sig, TupleArgumentsFlag::Yes), + ty::FnDef(def_id, substs) => { + (tcx.fn_sig(def_id).subst(tcx, substs), TupleArgumentsFlag::Yes) + } + ty::Closure(_, substs) => (substs.as_closure().sig(), TupleArgumentsFlag::No), + _ => span_bug!(obligation.cause.span, "invalid callable candidate: {self_ty:?}"), + }; + if sig.has_escaping_bound_vars() { + // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Callable(&'a ())`, + // but we do not currently. Luckily, such a bound is not + // particularly useful, so we don't expect users to write + // them often. + return Err(SelectionError::Unimplemented); + } + let trait_ref = closure_trait_ref_and_return_type( + tcx, + obligation.predicate.def_id(), + self_ty, + sig, + tuple_arguments, + ) + .map_bound(|(trait_ref, _)| trait_ref); + + self.confirm_poly_trait_refs(obligation, trait_ref) + } + /// In the case of closure types and fn pointers, /// we currently treat the input type parameters on the trait as /// outputs. This means that when we have a match we have only diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 8ef2bac9282cd..b549ba1deb00b 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2008,6 +2008,10 @@ impl + ?Sized, A: Allocator> Fn for Box { } } +#[stable(feature = "boxed_closure_impls", since = "1.35.0")] +#[cfg(not(bootstrap))] +impl + ?Sized, A: Allocator> core::ops::Callable for Box {} + #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs index 5774107f5207f..f5bc1b255f672 100644 --- a/library/core/src/internal_macros.rs +++ b/library/core/src/internal_macros.rs @@ -113,6 +113,9 @@ macro_rules! impl_fn_for_zst { Fn::call(&self, ($( $arg, )*)) } } + + #[cfg(not(bootstrap))] + impl $( <$( $lifetime ),+> )? crate::ops::Callable<($( $ArgTy, )*)> for $Name {} )+ } } diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 67c8245f0bfe0..1ab78b7fb54a1 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -239,6 +239,25 @@ pub trait FnMut: FnOnce { #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] #[const_trait] +#[cfg(not(bootstrap))] +pub trait FnOnce: ~const Callable { + /// 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)] +#[const_trait] +#[lang = "fn_once"] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +/// remove with next bootstrap bump pub trait FnOnce { /// The returned type after the call operator is used. #[lang = "fn_once_output"] @@ -250,6 +269,14 @@ pub trait FnOnce { extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } +#[cfg(not(bootstrap))] +#[const_trait] +#[lang = "callable"] +#[unstable(feature = "fn_traits", issue = "29625")] +/// This is an internal trait that, in contrast to `FnOnce` is also implemented +/// for unsafe functions and intrinsics. +pub trait Callable {} + mod impls { use crate::marker::Tuple; @@ -285,6 +312,11 @@ mod impls { } } + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + #[cfg(not(bootstrap))] + impl const crate::ops::Callable for &F where F: ~const Fn {} + #[stable(feature = "rust1", since = "1.0.0")] impl FnMut for &mut F where @@ -295,6 +327,11 @@ mod impls { } } + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] + #[cfg(not(bootstrap))] + impl const crate::ops::Callable for &mut F where F: ~const FnMut {} + #[stable(feature = "rust1", since = "1.0.0")] impl FnOnce for &mut F where diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 97d9b750d92f9..7e2be8ebbefec 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -209,3 +209,7 @@ pub use self::unsize::DispatchFromDyn; #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] pub use self::control_flow::ControlFlow; + +#[unstable(feature = "fn_traits", issue = "29625")] +#[cfg(not(bootstrap))] +pub use self::function::Callable; diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 7e7b6b4dbe9b1..05649e1bf6c28 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -272,6 +272,10 @@ impl R> FnOnce<()> for AssertUnwindSafe { } } +#[stable(feature = "catch_unwind", since = "1.9.0")] +#[cfg(not(bootstrap))] +impl R> crate::ops::Callable<()> for AssertUnwindSafe {} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for AssertUnwindSafe { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md index 180184146d1a0..000aa48d4f078 100644 --- a/src/doc/unstable-book/src/library-features/fn-traits.md +++ b/src/doc/unstable-book/src/library-features/fn-traits.md @@ -27,6 +27,7 @@ impl FnOnce<(u32, )> for Adder { self.a + b.0 } } +impl std::ops::Callable<(u32,)> for Adder {} fn main() { let adder = Adder { a: 3 }; diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs index 1e42e1fbabfeb..40cb2ea017aba 100644 --- a/src/tools/clippy/tests/ui/no_effect.rs +++ b/src/tools/clippy/tests/ui/no_effect.rs @@ -69,6 +69,7 @@ impl FnOnce<(&str,)> for GreetStruct1 { println!("hello {}", who); } } +impl std::ops::Callable<(&str,)> for GreetStruct1 {} struct GreetStruct2(); @@ -80,6 +81,8 @@ impl FnOnce<(&str,)> for GreetStruct2 { } } +impl std::ops::Callable<(&str,)> for GreetStruct2 {} + struct GreetStruct3; impl FnOnce<(&str,)> for GreetStruct3 { @@ -90,6 +93,8 @@ impl FnOnce<(&str,)> for GreetStruct3 { } } +impl std::ops::Callable<(&str,)> for GreetStruct3 {} + fn main() { let s = get_struct(); let s2 = get_struct(); diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr index f10f2bcf2a8a0..b7e867e1c5fe2 100644 --- a/src/tools/clippy/tests/ui/no_effect.stderr +++ b/src/tools/clippy/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:102:5 | LL | 0; | ^^ @@ -7,151 +7,151 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:103:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:104:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:105:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:106:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:107:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:108:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:109:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:110:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:111:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:107:5 + --> $DIR/no_effect.rs:112:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:113:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:114:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:115:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:116:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:117:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:113:5 + --> $DIR/no_effect.rs:118:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:119:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:115:5 + --> $DIR/no_effect.rs:120:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:121:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:117:5 + --> $DIR/no_effect.rs:122:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:118:5 + --> $DIR/no_effect.rs:123:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:119:5 + --> $DIR/no_effect.rs:124:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:121:5 + --> $DIR/no_effect.rs:126:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:123:5 + --> $DIR/no_effect.rs:128:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:124:5 + --> $DIR/no_effect.rs:129:5 | LL | let _unused = 1; | ^^^^^^^^^^^^^^^^ @@ -159,19 +159,19 @@ LL | let _unused = 1; = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:125:5 + --> $DIR/no_effect.rs:130:5 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:126:5 + --> $DIR/no_effect.rs:131:5 | LL | let _duck = Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> $DIR/no_effect.rs:127:5 + --> $DIR/no_effect.rs:132:5 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/miri/tests/pass/overloaded-calls-simple.rs b/src/tools/miri/tests/pass/overloaded-calls-simple.rs index 9fcf7d4a819a5..b2fc3c6a7537b 100644 --- a/src/tools/miri/tests/pass/overloaded-calls-simple.rs +++ b/src/tools/miri/tests/pass/overloaded-calls-simple.rs @@ -12,6 +12,8 @@ impl FnOnce<(i32, i32)> for S3 { } } +impl std::ops::Callable<(i32, i32)> for S3 {} + fn main() { let s = S3 { x: 3, y: 3 }; let ans = s(3, 1); diff --git a/tests/assembly/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs index 5196aa9fa1759..7e619a1053967 100644 --- a/tests/assembly/asm/aarch64-modifiers.rs +++ b/tests/assembly/asm/aarch64-modifiers.rs @@ -21,6 +21,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 66c39a48c6e1d..b865059a490d2 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -22,6 +22,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs index 88ffeaecfecb6..66502d4dbc6d1 100644 --- a/tests/assembly/asm/arm-modifiers.rs +++ b/tests/assembly/asm/arm-modifiers.rs @@ -26,6 +26,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} #[repr(simd)] pub struct f32x4(f32, f32, f32, f32); diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index b22a26ce36f14..17c701f77c900 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -25,6 +25,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} type ptr = *mut u8; diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs index af16faedbc4a2..ab102821ffad0 100644 --- a/tests/assembly/asm/hexagon-types.rs +++ b/tests/assembly/asm/hexagon-types.rs @@ -24,6 +24,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} type ptr = *const i32; diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index 4e296f3ade58b..56df4965b8522 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -25,6 +25,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} type ptr = *const i32; @@ -42,7 +44,7 @@ extern "C" { // Hack to avoid function merging extern "Rust" { - fn dont_merge(s: &str); + fn dont_merge(s: &str); } // CHECK-LABEL: sym_fn: diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs index 27469b22980ab..d5b598dd3f642 100644 --- a/tests/assembly/asm/mips-types.rs +++ b/tests/assembly/asm/mips-types.rs @@ -25,6 +25,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs index e27b005206835..f639280883ba8 100644 --- a/tests/assembly/asm/powerpc-types.rs +++ b/tests/assembly/asm/powerpc-types.rs @@ -25,6 +25,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs index f18ba294d0cff..e96333caff5a2 100644 --- a/tests/assembly/asm/riscv-types.rs +++ b/tests/assembly/asm/riscv-types.rs @@ -26,6 +26,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index 2fb404dd9b280..b97a8612b8765 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -23,6 +23,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs index 574fdf12cd040..517db2effce0f 100644 --- a/tests/assembly/asm/x86-modifiers.rs +++ b/tests/assembly/asm/x86-modifiers.rs @@ -28,6 +28,8 @@ macro_rules! stringify { #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index 81be79cbaac18..e2ef497e94816 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -29,6 +29,8 @@ macro_rules! stringify { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} type ptr = *mut u8; diff --git a/tests/assembly/pic-relocation-model.rs b/tests/assembly/pic-relocation-model.rs index 72471ffcdb0cb..8c16e81bf0770 100644 --- a/tests/assembly/pic-relocation-model.rs +++ b/tests/assembly/pic-relocation-model.rs @@ -3,23 +3,22 @@ // [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic // [x64] needs-llvm-components: x86 - #![feature(no_core, lang_items)] #![no_core] -#![crate_type="rlib"] +#![crate_type = "rlib"] #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} // CHECK-LABEL: call_other_fn: // CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip) #[no_mangle] pub fn call_other_fn() -> u8 { - unsafe { - other_fn() - } + unsafe { other_fn() } } // CHECK-LABEL: other_fn: @@ -27,9 +26,9 @@ pub fn call_other_fn() -> u8 { #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} diff --git a/tests/assembly/pie-relocation-model.rs b/tests/assembly/pie-relocation-model.rs index e40797e038d4b..11f24505ceaf4 100644 --- a/tests/assembly/pie-relocation-model.rs +++ b/tests/assembly/pie-relocation-model.rs @@ -3,24 +3,23 @@ // [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie // [x64] needs-llvm-components: x86 - #![feature(no_core, lang_items)] #![no_core] -#![crate_type="rlib"] +#![crate_type = "rlib"] #[lang = "sized"] trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} // CHECK-LABEL: call_other_fn: // With PIE local functions are called "directly". // CHECK: {{(jmp|callq)}} other_fn #[no_mangle] pub fn call_other_fn() -> u8 { - unsafe { - other_fn() - } + unsafe { other_fn() } } // CHECK-LABEL: other_fn: @@ -30,9 +29,9 @@ pub fn call_other_fn() -> u8 { #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} diff --git a/tests/assembly/sparc-struct-abi.rs b/tests/assembly/sparc-struct-abi.rs index 6309dd420ffa4..8d65ea93ab863 100644 --- a/tests/assembly/sparc-struct-abi.rs +++ b/tests/assembly/sparc-struct-abi.rs @@ -11,6 +11,8 @@ #[lang = "sized"] pub trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] pub trait Copy {} impl Copy for f32 {} diff --git a/tests/assembly/target-feature-multiple.rs b/tests/assembly/target-feature-multiple.rs index 5c5d93863d71e..940d8d2625907 100644 --- a/tests/assembly/target-feature-multiple.rs +++ b/tests/assembly/target-feature-multiple.rs @@ -21,6 +21,8 @@ #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[lang = "copy"] trait Copy {} impl Copy for u32 {} diff --git a/tests/assembly/x86-stack-probes.rs b/tests/assembly/x86-stack-probes.rs index c7141fb208a0d..f8a543dbe511c 100644 --- a/tests/assembly/x86-stack-probes.rs +++ b/tests/assembly/x86-stack-probes.rs @@ -15,6 +15,8 @@ trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for u8 {} diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index bc11e1081244a..cf0fe028741b7 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -14,15 +14,18 @@ #![no_core] #[lang = "sized"] -pub trait Sized { } +pub trait Sized {} #[lang = "copy"] -pub trait Copy { } +pub trait Copy {} #[lang = "receiver"] -pub trait Receiver { } +pub trait Receiver {} #[lang = "tuple_trait"] -pub trait Tuple { } +pub trait Tuple {} -pub struct Result { _a: T, _b: E } +pub struct Result { + _a: T, + _b: E, +} impl Copy for usize {} impl Copy for &usize {} @@ -39,7 +42,7 @@ pub trait FnOnce { } #[lang = "fn_mut"] -pub trait FnMut : FnOnce { +pub trait FnMut: FnOnce { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } @@ -49,6 +52,9 @@ pub trait Fn: FnOnce { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } +#[lang = "callable"] +trait Callable {} + extern "rust-intrinsic" { pub fn transmute(src: Src) -> Dst; } @@ -64,7 +70,7 @@ fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> { #[inline(never)] #[no_mangle] -fn call_through_fn_trait(a: &mut impl Fn<(), Output=()>) { +fn call_through_fn_trait(a: &mut impl Fn<(), Output = ()>) { (*a)() } @@ -110,7 +116,10 @@ pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () { transmute(x) } -pub enum Either { A(T), B(U) } +pub enum Either { + A(T), + B(U), +} // Previously, we would codegen this as passing/returning a scalar pair of `{ i8, ptr }`, // with the `ptr` field representing both `&i32` and `fn()` depending on the variant. diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs index 045f01985a57f..4f63f543ea46b 100644 --- a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs +++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -18,6 +18,8 @@ impl Copy for i64 {} impl Copy for u64 {} impl Copy for f32 {} impl Copy for f64 {} +#[lang = "callable"] +trait Callable {} // CHECK: define void @f_void() #[no_mangle] diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs index bb317e4a2fad3..3208f506669a3 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-attr-no-sanitize.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, no_sanitize, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs index 29e4df3511fbb..264264fa51771 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs index 84d678a33ba90..6df9b22825b75 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs index 761c37a9e06a0..934b168bec5fe 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs index 83cda0ef136f8..01f19dd5e0dc1 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs index e1d617b5ee18e..fb00a6f7dcdf3 100644 --- a/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs +++ b/tests/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle.rs @@ -7,14 +7,16 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "callable"] +trait Callable {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs index 004a67e7df2ee..e9e37102d3ed2 100644 --- a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs @@ -7,28 +7,30 @@ // [x86_64] needs-llvm-components: // compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(arbitrary_self_types, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } -#[lang="receiver"] -trait Receiver { } -#[lang="dispatch_from_dyn"] -trait DispatchFromDyn { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "receiver"] +trait Receiver {} +#[lang = "dispatch_from_dyn"] +trait DispatchFromDyn {} impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} #[lang = "unsize"] -trait Unsize { } +trait Unsize {} #[lang = "coerce_unsized"] -pub trait CoerceUnsized { } +pub trait CoerceUnsized {} impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -#[lang="freeze"] -trait Freeze { } -#[lang="drop_in_place"] -fn drop_in_place_fn() { } +#[lang = "freeze"] +trait Freeze {} +#[lang = "drop_in_place"] +fn drop_in_place_fn() {} +#[lang = "callable"] +trait Callable {} pub trait Trait1 { fn foo(&self); @@ -37,8 +39,7 @@ pub trait Trait1 { pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { - } + fn foo(&self) {} } pub trait Trait2 { @@ -48,8 +49,7 @@ pub trait Trait2 { pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { - } + fn bar(&self) {} } pub trait Trait3 { @@ -59,8 +59,7 @@ pub trait Trait3 { pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { - } + fn baz(&self, _: &U) {} } pub trait Trait4<'a, T> { diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index 1bebf66f0df43..d646fe2a881da 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -14,6 +14,8 @@ trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} extern "C" { fn peach() -> u32; diff --git a/tests/mir-opt/inline/inline_instruction_set.rs b/tests/mir-opt/inline/inline_instruction_set.rs index 5dfb04943e39f..94fb6f60ebd13 100644 --- a/tests/mir-opt/inline/inline_instruction_set.rs +++ b/tests/mir-opt/inline/inline_instruction_set.rs @@ -59,3 +59,6 @@ pub fn default() { instruction_set_default(); inline_always_and_using_inline_asm(); } + +#[lang = "callable"] +trait Callable {} diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs index 47d90b1856be5..b7f94e7cbd56e 100644 --- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs @@ -1,5 +1,5 @@ #![feature(no_core, intrinsics, lang_items)] -#![crate_type="rlib"] +#![crate_type = "rlib"] #![no_core] extern "rust-intrinsic" { @@ -12,6 +12,8 @@ trait Sized {} trait Copy {} #[lang = "freeze"] trait Freeze {} +#[lang = "callable"] +trait Callable {} impl Copy for *mut T {} diff --git a/tests/run-make/simd-ffi/simd.rs b/tests/run-make/simd-ffi/simd.rs index d11cfd77c5bf9..d37d273810bfa 100644 --- a/tests/run-make/simd-ffi/simd.rs +++ b/tests/run-make/simd-ffi/simd.rs @@ -57,6 +57,9 @@ pub fn bar(a: i32x4, b: i32x4) -> i32x4 { #[lang = "sized"] pub trait Sized {} +#[lang = "callable"] +trait Callable {} + #[lang = "copy"] pub trait Copy {} diff --git a/tests/run-make/target-specs/foo.rs b/tests/run-make/target-specs/foo.rs index 22939e87912c1..b4b039f3d21da 100644 --- a/tests/run-make/target-specs/foo.rs +++ b/tests/run-make/target-specs/foo.rs @@ -10,6 +10,9 @@ trait Sized {} #[lang = "freeze"] auto trait Freeze {} +#[lang = "callable"] +trait Callable {} + #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { 0 diff --git a/tests/ui/borrowck/borrowck-overloaded-call.rs b/tests/ui/borrowck/borrowck-overloaded-call.rs index 7b16bf666d062..60dc8ed841761 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.rs +++ b/tests/ui/borrowck/borrowck-overloaded-call.rs @@ -14,14 +14,20 @@ impl Fn<(isize,)> for SFn { } impl FnMut<(isize,)> for SFn { - extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) } + extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { + self.call(args) + } } impl FnOnce<(isize,)> for SFn { type Output = isize; - extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) } + extern "rust-call" fn call_once(self, args: (isize,)) -> isize { + self.call(args) + } } +impl std::ops::Callable<(isize,)> for SFn {} + struct SFnMut { x: isize, y: isize, @@ -35,9 +41,13 @@ impl FnMut<(isize,)> for SFnMut { impl FnOnce<(isize,)> for SFnMut { type Output = isize; - extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { + self.call_mut(args) + } } +impl std::ops::Callable<(isize,)> for SFnMut {} + struct SFnOnce { x: String, } @@ -50,31 +60,25 @@ impl FnOnce<(String,)> for SFnOnce { } } +impl std::ops::Callable<(String,)> for SFnOnce {} + fn f() { - let mut s = SFn { - x: 1, - y: 2, - }; + let mut s = SFn { x: 1, y: 2 }; let sp = &mut s; - s(3); //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable + s(3); //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable use_mut(sp); } fn g() { - let s = SFnMut { - x: 1, - y: 2, - }; - s(3); //~ ERROR cannot borrow `s` as mutable, as it is not declared as mutable + let s = SFnMut { x: 1, y: 2 }; + s(3); //~ ERROR cannot borrow `s` as mutable, as it is not declared as mutable } fn h() { - let s = SFnOnce { - x: "hello".to_string(), - }; + let s = SFnOnce { x: "hello".to_string() }; s(" world".to_string()); - s(" world".to_string()); //~ ERROR use of moved value: `s` + s(" world".to_string()); //~ ERROR use of moved value: `s` } fn main() {} -fn use_mut(_: &mut T) { } +fn use_mut(_: &mut T) {} diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index 723b19f4124ac..c68f9662529b6 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-overloaded-call.rs:59:5 + --> $DIR/borrowck-overloaded-call.rs:68:5 | LL | let sp = &mut s; | ------ mutable borrow occurs here @@ -9,22 +9,21 @@ LL | use_mut(sp); | -- mutable borrow later used here error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable - --> $DIR/borrowck-overloaded-call.rs:67:5 + --> $DIR/borrowck-overloaded-call.rs:73:5 | LL | s(3); | ^ cannot borrow as mutable | help: consider changing this to be mutable | -LL | let mut s = SFnMut { +LL | let mut s = SFnMut { x: 1, y: 2 }; | +++ error[E0382]: use of moved value: `s` - --> $DIR/borrowck-overloaded-call.rs:75:5 + --> $DIR/borrowck-overloaded-call.rs:79:5 | -LL | let s = SFnOnce { +LL | let s = SFnOnce { x: "hello".to_string() }; | - move occurs because `s` has type `SFnOnce`, which does not implement the `Copy` trait -... LL | s(" world".to_string()); | - value moved here LL | s(" world".to_string()); diff --git a/tests/ui/borrowck/issue-92157.rs b/tests/ui/borrowck/issue-92157.rs index 6ee2320a603ad..85f72e76e9665 100644 --- a/tests/ui/borrowck/issue-92157.rs +++ b/tests/ui/borrowck/issue-92157.rs @@ -1,16 +1,15 @@ #![feature(no_core)] #![feature(lang_items)] - #![no_core] #[cfg(target_os = "linux")] #[link(name = "c")] -extern {} +extern "C" {} #[lang = "start"] fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { //~^ ERROR: incorrect number of parameters for the `start` lang item - 40+2 + 40 + 2 } #[lang = "sized"] @@ -18,6 +17,9 @@ pub trait Sized {} #[lang = "copy"] pub trait Copy {} +#[lang = "callable"] +trait Callable {} + #[lang = "drop_in_place"] #[allow(unconditional_recursion)] pub unsafe fn drop_in_place(to_drop: *mut T) { diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr index a4010d73d057a..2d4eeab0687e3 100644 --- a/tests/ui/borrowck/issue-92157.stderr +++ b/tests/ui/borrowck/issue-92157.stderr @@ -1,5 +1,5 @@ error: incorrect number of parameters for the `start` lang item - --> $DIR/issue-92157.rs:11:1 + --> $DIR/issue-92157.rs:10:1 | LL | fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/c-variadic/variadic-ffi-1.rs b/tests/ui/c-variadic/variadic-ffi-1.rs index acd8a25dc533b..6cfa4efb9f65a 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.rs +++ b/tests/ui/c-variadic/variadic-ffi-1.rs @@ -2,8 +2,11 @@ // compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib #![no_core] #![feature(no_core, lang_items)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} + +#[lang = "callable"] +trait Callable {} extern "stdcall" { fn printf(_: *const u8, ...); diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index c7899338197d8..2d2b3820ba6ef 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -1,17 +1,17 @@ error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` - --> $DIR/variadic-ffi-1.rs:9:5 + --> $DIR/variadic-ffi-1.rs:12:5 | LL | fn printf(_: *const u8, ...); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied - --> $DIR/variadic-ffi-1.rs:22:9 + --> $DIR/variadic-ffi-1.rs:25:9 | LL | foo(); | ^^^-- two arguments of type `isize` and `u8` are missing | note: function defined here - --> $DIR/variadic-ffi-1.rs:15:8 + --> $DIR/variadic-ffi-1.rs:18:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ @@ -21,13 +21,13 @@ LL | foo(/* isize */, /* u8 */); | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0060]: this function takes at least 2 arguments but 1 argument was supplied - --> $DIR/variadic-ffi-1.rs:23:9 + --> $DIR/variadic-ffi-1.rs:26:9 | LL | foo(1); | ^^^--- an argument of type `u8` is missing | note: function defined here - --> $DIR/variadic-ffi-1.rs:15:8 + --> $DIR/variadic-ffi-1.rs:18:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ @@ -37,7 +37,7 @@ LL | foo(1, /* u8 */); | ~~~~~~~~~~~~~ error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:25:56 + --> $DIR/variadic-ffi-1.rs:28:56 | LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ------------------------------------- ^^^ expected non-variadic fn, found variadic function @@ -49,7 +49,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; = note: when the arguments and return types match, functions can be coerced to function pointers error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:26:54 + --> $DIR/variadic-ffi-1.rs:29:54 | LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ----------------------------------- ^^^ expected variadic fn, found non-variadic function @@ -61,37 +61,37 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; = note: when the arguments and return types match, functions can be coerced to function pointers error[E0617]: can't pass `f32` to variadic function - --> $DIR/variadic-ffi-1.rs:28:19 + --> $DIR/variadic-ffi-1.rs:31:19 | LL | foo(1, 2, 3f32); | ^^^^ help: cast the value to `c_double`: `3f32 as c_double` error[E0617]: can't pass `bool` to variadic function - --> $DIR/variadic-ffi-1.rs:29:19 + --> $DIR/variadic-ffi-1.rs:32:19 | LL | foo(1, 2, true); | ^^^^ help: cast the value to `c_int`: `true as c_int` error[E0617]: can't pass `i8` to variadic function - --> $DIR/variadic-ffi-1.rs:30:19 + --> $DIR/variadic-ffi-1.rs:33:19 | LL | foo(1, 2, 1i8); | ^^^ help: cast the value to `c_int`: `1i8 as c_int` error[E0617]: can't pass `u8` to variadic function - --> $DIR/variadic-ffi-1.rs:31:19 + --> $DIR/variadic-ffi-1.rs:34:19 | LL | foo(1, 2, 1u8); | ^^^ help: cast the value to `c_uint`: `1u8 as c_uint` error[E0617]: can't pass `i16` to variadic function - --> $DIR/variadic-ffi-1.rs:32:19 + --> $DIR/variadic-ffi-1.rs:35:19 | LL | foo(1, 2, 1i16); | ^^^^ help: cast the value to `c_int`: `1i16 as c_int` error[E0617]: can't pass `u16` to variadic function - --> $DIR/variadic-ffi-1.rs:33:19 + --> $DIR/variadic-ffi-1.rs:36:19 | LL | foo(1, 2, 1u16); | ^^^^ help: cast the value to `c_uint`: `1u16 as c_uint` diff --git a/tests/ui/chalkify/assert.rs b/tests/ui/chalkify/assert.rs deleted file mode 100644 index 834c8935e7620..0000000000000 --- a/tests/ui/chalkify/assert.rs +++ /dev/null @@ -1,6 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -fn main() { - assert_eq!(1, 1); -} diff --git a/tests/ui/chalkify/builtin-copy-clone.rs b/tests/ui/chalkify/builtin-copy-clone.rs deleted file mode 100644 index a478c006ef1ca..0000000000000 --- a/tests/ui/chalkify/builtin-copy-clone.rs +++ /dev/null @@ -1,45 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -// Test that `Clone` is correctly implemented for builtin types. - -#[derive(Copy, Clone)] -struct S(#[allow(unused_tuple_struct_fields)] i32); - -fn test_clone(arg: T) { - let _ = arg.clone(); -} - -fn test_copy(arg: T) { - let _ = arg; - let _ = arg; -} - -fn test_copy_clone(arg: T) { - test_copy(arg); - test_clone(arg); -} - -fn foo() { } - -fn main() { - // FIXME: add closures when they're considered WF - test_copy_clone(foo); - let f: fn() = foo; - test_copy_clone(f); - // FIXME(#86252): reinstate array test after chalk upgrade - //test_copy_clone([1; 56]); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1)); - test_copy_clone(()); - test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ())); - - let a = ( - (S(1), S(0)), - ( - (S(0), S(0), S(1)), - S(0) - ) - ); - test_copy_clone(a); -} diff --git a/tests/ui/chalkify/chalk_initial_program.rs b/tests/ui/chalkify/chalk_initial_program.rs deleted file mode 100644 index 21de72b6fcccb..0000000000000 --- a/tests/ui/chalkify/chalk_initial_program.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -impl Foo for i32 { } - -impl Foo for u32 { } - -fn gimme() { } - -// Note: this also tests that `std::process::Termination` is implemented for `()`. -fn main() { - gimme::(); - gimme::(); - gimme::(); //~ERROR the trait bound `f32: Foo` is not satisfied -} diff --git a/tests/ui/chalkify/chalk_initial_program.stderr b/tests/ui/chalkify/chalk_initial_program.stderr deleted file mode 100644 index 343c0a31862b9..0000000000000 --- a/tests/ui/chalkify/chalk_initial_program.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `f32: Foo` is not satisfied - --> $DIR/chalk_initial_program.rs:15:13 - | -LL | gimme::(); - | ^^^ the trait `Foo` is not implemented for `f32` - | - = help: the following other types implement trait `Foo`: - i32 - u32 -note: required by a bound in `gimme` - --> $DIR/chalk_initial_program.rs:9:13 - | -LL | fn gimme() { } - | ^^^ required by this bound in `gimme` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/closure.rs b/tests/ui/chalkify/closure.rs deleted file mode 100644 index a908a1e97ecd9..0000000000000 --- a/tests/ui/chalkify/closure.rs +++ /dev/null @@ -1,38 +0,0 @@ -// compile-flags: -Z trait-solver=chalk - -fn main() -> () { - let t = || {}; - t(); - - let mut a = 0; - let mut b = move || { - a = 1; - }; - b(); - - let mut c = b; - - c(); - b(); - - let mut a = 0; - let mut b = || { - a = 1; - }; - b(); - - let mut c = b; - - c(); - b(); //~ ERROR - - // FIXME(chalk): this doesn't quite work - /* - let b = |c| { - c - }; - - let a = &32; - b(a); - */ -} diff --git a/tests/ui/chalkify/closure.stderr b/tests/ui/chalkify/closure.stderr deleted file mode 100644 index a33c0ba0d37c9..0000000000000 --- a/tests/ui/chalkify/closure.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0382]: borrow of moved value: `b` - --> $DIR/closure.rs:27:5 - | -LL | let mut c = b; - | - value moved here -... -LL | b(); - | ^ value borrowed here after move - | -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:20:9 - | -LL | a = 1; - | ^ -help: consider mutably borrowing `b` - | -LL | let mut c = &mut b; - | ++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/chalkify/generic_impls.rs b/tests/ui/chalkify/generic_impls.rs deleted file mode 100644 index 7d33e12d8be17..0000000000000 --- a/tests/ui/chalkify/generic_impls.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -impl Foo for (T, u32) { } - -fn gimme() { } - -fn foo() { - gimme::<(T, u32)>(); - gimme::<(Option, u32)>(); - gimme::<(Option, f32)>(); //~ ERROR -} - -fn main() { - gimme::<(i32, u32)>(); - gimme::<(i32, f32)>(); //~ ERROR -} diff --git a/tests/ui/chalkify/generic_impls.stderr b/tests/ui/chalkify/generic_impls.stderr deleted file mode 100644 index d4a8354d3fc80..0000000000000 --- a/tests/ui/chalkify/generic_impls.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `(Option, f32): Foo` is not satisfied - --> $DIR/generic_impls.rs:12:13 - | -LL | gimme::<(Option, f32)>(); - | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(Option, f32)` - | - = help: the trait `Foo` is implemented for `(T, u32)` -note: required by a bound in `gimme` - --> $DIR/generic_impls.rs:7:13 - | -LL | fn gimme() { } - | ^^^ required by this bound in `gimme` - -error[E0277]: the trait bound `(i32, f32): Foo` is not satisfied - --> $DIR/generic_impls.rs:17:13 - | -LL | gimme::<(i32, f32)>(); - | ^^^^^^^^^^ the trait `Foo` is not implemented for `(i32, f32)` - | - = help: the trait `Foo` is implemented for `(T, u32)` -note: required by a bound in `gimme` - --> $DIR/generic_impls.rs:7:13 - | -LL | fn gimme() { } - | ^^^ required by this bound in `gimme` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/inherent_impl.rs b/tests/ui/chalkify/inherent_impl.rs deleted file mode 100644 index f0f24d485cd87..0000000000000 --- a/tests/ui/chalkify/inherent_impl.rs +++ /dev/null @@ -1,42 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -impl Foo for i32 { } - -struct S { - x: T, -} - -fn only_foo(_x: &T) { } - -impl S { - // Test that we have the correct environment inside an inherent method. - fn dummy_foo(&self) { - only_foo(&self.x) - } -} - -trait Bar { } -impl Bar for u32 { } - -fn only_bar() { } - -impl S { - // Test that the environment of `dummy_bar` adds up with the environment - // of the inherent impl. - fn dummy_bar(&self) { - only_foo(&self.x); - only_bar::(); - } -} - -fn main() { - let s = S { - x: 5, - }; - - s.dummy_bar::(); - s.dummy_foo(); -} diff --git a/tests/ui/chalkify/inherent_impl_min.rs b/tests/ui/chalkify/inherent_impl_min.rs deleted file mode 100644 index 3eda7102decd1..0000000000000 --- a/tests/ui/chalkify/inherent_impl_min.rs +++ /dev/null @@ -1,27 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -impl Foo for i32 { } - -struct S { - x: T, -} - -fn only_foo(_x: &T) { } - -impl S { - // Test that we have the correct environment inside an inherent method. - fn dummy_foo(&self) { - only_foo(&self.x) - } -} - -fn main() { - let s = S { - x: 5, - }; - - s.dummy_foo(); -} diff --git a/tests/ui/chalkify/println.rs b/tests/ui/chalkify/println.rs deleted file mode 100644 index edddc38215234..0000000000000 --- a/tests/ui/chalkify/println.rs +++ /dev/null @@ -1,6 +0,0 @@ -// check-pass -// compile-flags: -Z trait-solver=chalk - -fn main() { - println!("hello"); -} diff --git a/tests/ui/chalkify/projection.rs b/tests/ui/chalkify/projection.rs deleted file mode 100644 index 19bb2ae149723..0000000000000 --- a/tests/ui/chalkify/projection.rs +++ /dev/null @@ -1,25 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -trait Bar { - type Item: Foo; -} - -impl Foo for i32 { } -impl Bar for i32 { - type Item = i32; -} - -fn only_foo() { } - -fn only_bar() { - // `T` implements `Bar` hence `::Item` must also implement `Bar` - only_foo::() -} - -fn main() { - only_bar::(); - only_foo::<::Item>(); -} diff --git a/tests/ui/chalkify/recursive_where_clause_on_type.rs b/tests/ui/chalkify/recursive_where_clause_on_type.rs deleted file mode 100644 index c2c8aa6aabec2..0000000000000 --- a/tests/ui/chalkify/recursive_where_clause_on_type.rs +++ /dev/null @@ -1,30 +0,0 @@ -// FIXME(chalk): should fail, see comments -// check-fail -// compile-flags: -Z trait-solver=chalk - -#![feature(trivial_bounds)] - -trait Bar { - fn foo(); -} -trait Foo: Bar { } - -struct S where S: Foo; - -impl Foo for S { -} - -fn bar() { - T::foo(); -} - -fn foo() { - bar::() -} - -fn main() { - // For some reason, the error is duplicated... - - foo::() //~ ERROR the type `S` is not well-formed - //~^ ERROR the type `S` is not well-formed -} diff --git a/tests/ui/chalkify/recursive_where_clause_on_type.stderr b/tests/ui/chalkify/recursive_where_clause_on_type.stderr deleted file mode 100644 index cead5adeaaadb..0000000000000 --- a/tests/ui/chalkify/recursive_where_clause_on_type.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: the type `S` is not well-formed - --> $DIR/recursive_where_clause_on_type.rs:28:11 - | -LL | foo::() - | ^ - -error: the type `S` is not well-formed - --> $DIR/recursive_where_clause_on_type.rs:28:5 - | -LL | foo::() - | ^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/chalkify/super_trait.rs b/tests/ui/chalkify/super_trait.rs deleted file mode 100644 index 540ae51e57f6d..0000000000000 --- a/tests/ui/chalkify/super_trait.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Foo { } -trait Bar: Foo { } - -impl Foo for i32 { } -impl Bar for i32 { } - -fn only_foo() { } - -fn only_bar() { - // `T` implements `Bar` hence `T` must also implement `Foo` - only_foo::() -} - -fn main() { - only_bar::() -} diff --git a/tests/ui/chalkify/trait-objects.rs b/tests/ui/chalkify/trait-objects.rs deleted file mode 100644 index 144d9788b82e6..0000000000000 --- a/tests/ui/chalkify/trait-objects.rs +++ /dev/null @@ -1,12 +0,0 @@ -// check-pass -// compile-flags: -Z trait-solver=chalk - -use std::fmt::Display; - -fn main() { - let d: &dyn Display = &mut 3; - d.to_string(); - (&d).to_string(); - let f: &dyn Fn(i32) -> _ = &|x| x + x; - f(2); -} diff --git a/tests/ui/chalkify/trait_implied_bound.rs b/tests/ui/chalkify/trait_implied_bound.rs deleted file mode 100644 index f97dbf6b7e774..0000000000000 --- a/tests/ui/chalkify/trait_implied_bound.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Foo { } -trait Bar where U: Foo { } - -impl Foo for i32 { } -impl Bar for i32 { } - -fn only_foo() { } - -fn only_bar>() { - only_foo::() -} - -fn main() { - only_bar::() -} diff --git a/tests/ui/chalkify/type_implied_bound.rs b/tests/ui/chalkify/type_implied_bound.rs deleted file mode 100644 index 70f1b4265e499..0000000000000 --- a/tests/ui/chalkify/type_implied_bound.rs +++ /dev/null @@ -1,29 +0,0 @@ -// run-pass -// compile-flags: -Z trait-solver=chalk - -trait Eq { } -trait Hash: Eq { } - -impl Eq for i32 { } -impl Hash for i32 { } - -struct Set { - _x: T, -} - -fn only_eq() { } - -fn take_a_set(_: &Set) { - // `Set` is an input type of `take_a_set`, hence we know that - // `T` must implement `Hash`, and we know in turn that `T` must - // implement `Eq`. - only_eq::() -} - -fn main() { - let set = Set { - _x: 5, - }; - - take_a_set(&set); -} diff --git a/tests/ui/chalkify/type_inference.rs b/tests/ui/chalkify/type_inference.rs deleted file mode 100644 index d7167d0dc57fa..0000000000000 --- a/tests/ui/chalkify/type_inference.rs +++ /dev/null @@ -1,28 +0,0 @@ -// compile-flags: -Z trait-solver=chalk - -trait Foo { } -impl Foo for i32 { } - -trait Bar { } -impl Bar for i32 { } -impl Bar for u32 { } - -fn only_foo(_x: T) { } - -fn only_bar(_x: T) { } - -fn main() { - let x = 5.0; - - // The only type which implements `Foo` is `i32`, so the chalk trait solver - // is expecting a variable of type `i32`. This behavior differs from the - // old-style trait solver. I guess this will change, that's why I'm - // adding that test. - // FIXME(chalk): order of these two errors is non-deterministic, - // so let's just hide one for now - //only_foo(x); // ERROR the trait bound `f64: Foo` is not satisfied - - // Here we have two solutions so we get back the behavior of the old-style - // trait solver. - only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied -} diff --git a/tests/ui/chalkify/type_inference.stderr b/tests/ui/chalkify/type_inference.stderr deleted file mode 100644 index 508a6dd1388cb..0000000000000 --- a/tests/ui/chalkify/type_inference.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0277]: the trait bound `{float}: Bar` is not satisfied - --> $DIR/type_inference.rs:27:14 - | -LL | only_bar(x); - | -------- ^ the trait `Bar` is not implemented for `{float}` - | | - | required by a bound introduced by this call - | - = help: the following other types implement trait `Bar`: - i32 - u32 -note: required by a bound in `only_bar` - --> $DIR/type_inference.rs:12:16 - | -LL | fn only_bar(_x: T) { } - | ^^^ required by this bound in `only_bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/chalkify/type_wf.rs b/tests/ui/chalkify/type_wf.rs deleted file mode 100644 index 37d2f5ca832ce..0000000000000 --- a/tests/ui/chalkify/type_wf.rs +++ /dev/null @@ -1,25 +0,0 @@ -// check-fail -// compile-flags: -Z trait-solver=chalk - -trait Foo { } - -struct S { - x: T, -} - -impl Foo for i32 { } -impl Foo for Option { } - -fn main() { - let s = S { - x: 5, - }; - - let s = S { - x: 5.0, //~ ERROR the trait bound `{float}: Foo` is not satisfied - }; - - let s = S { - x: Some(5.0), - }; -} diff --git a/tests/ui/chalkify/type_wf.stderr b/tests/ui/chalkify/type_wf.stderr deleted file mode 100644 index 6e8daf635175f..0000000000000 --- a/tests/ui/chalkify/type_wf.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `{float}: Foo` is not satisfied - --> $DIR/type_wf.rs:19:12 - | -LL | x: 5.0, - | ^^^ the trait `Foo` is not implemented for `{float}` - | - = help: the trait `Foo` is implemented for `i32` -note: required by a bound in `S` - --> $DIR/type_wf.rs:6:13 - | -LL | struct S { - | ^^^ required by this bound in `S` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs index bbc039bdf5c7b..f3220e27e1a6d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs @@ -3,12 +3,15 @@ // needs-llvm-components: arm #![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] #![no_core] -#[lang="sized"] -pub trait Sized { } -#[lang="copy"] -pub trait Copy { } +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} impl Copy for u32 {} +#[lang = "callable"] +trait Callable {} + extern "rust-intrinsic" { pub fn transmute(e: T) -> U; } @@ -16,9 +19,7 @@ extern "rust-intrinsic" { #[no_mangle] pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 { let non_secure_function = unsafe { - transmute:: u32>( - 0x10000004, - ) + transmute:: u32>(0x10000004) }; non_secure_function(a, b, c, d) } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs index b8112b20a54c6..7a6b0b879c1c3 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs @@ -3,12 +3,15 @@ // needs-llvm-components: arm #![feature(abi_c_cmse_nonsecure_call, no_core, lang_items, intrinsics)] #![no_core] -#[lang="sized"] -pub trait Sized { } -#[lang="copy"] -pub trait Copy { } +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} impl Copy for u32 {} +#[lang = "callable"] +trait Callable {} + extern "rust-intrinsic" { pub fn transmute(e: T) -> U; } @@ -16,10 +19,7 @@ extern "rust-intrinsic" { #[no_mangle] pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { let non_secure_function = unsafe { - transmute::< - usize, - extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32> - ( + transmute:: u32>( 0x10000004, ) }; diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index bfebf66701bd9..a4195a5042d1f 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -1,15 +1,9 @@ -error[E0635]: unknown feature `const_fn_trait_ref_impls` - --> $DIR/fn_trait_refs.rs:3:12 - | -LL | #![feature(const_fn_trait_ref_impls)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0635]: unknown feature `const_cmp` --> $DIR/fn_trait_refs.rs:8:12 | LL | #![feature(const_cmp)] | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0635`. diff --git a/tests/ui/extern/issue-13655.rs b/tests/ui/extern/issue-13655.rs index 6dd1847995f00..fa920138473c7 100644 --- a/tests/ui/extern/issue-13655.rs +++ b/tests/ui/extern/issue-13655.rs @@ -6,9 +6,9 @@ struct Foo(T); impl Fn<()> for Foo { extern "rust-call" fn call(&self, _: ()) -> T { - match *self { - Foo(t) => t - } + match *self { + Foo(t) => t, + } } } @@ -26,7 +26,9 @@ impl FnOnce<()> for Foo { } } +impl std::ops::Callable<()> for Foo {} + fn main() { - let t: u8 = 1; - println!("{}", Foo(t)()); + let t: u8 = 1; + println!("{}", Foo(t)()); } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs index d84e30f4984ea..f241fe809273f 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -24,6 +24,7 @@ impl WithDefault for () { // Going through another generic function works fine. call(f, ()); //~^ expected a + //~| ERROR: type mismatch in function arguments } } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index b30dd36d2ad6a..aac4b85e439ae 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -14,6 +14,22 @@ note: required by a bound in `call` LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` -error: aborting due to previous error +error[E0631]: type mismatch in function arguments + --> $DIR/issue-62529-3.rs:25:9 + | +LL | / fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( +LL | | f: F, +LL | | x: >::Type, +LL | | ) { + | |_- found signature defined here +... +LL | call(f, ()); + | ^^^^^^^^^^^ expected due to this + | + = note: expected function signature `fn((_, ())) -> _` + found function signature `for<'b> fn((_, <_ as ATC<'b>>::Type)) -> _` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0631. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-14959.rs b/tests/ui/issues/issue-14959.rs index e31a9431558f6..c05dbb68b0b1d 100644 --- a/tests/ui/issues/issue-14959.rs +++ b/tests/ui/issues/issue-14959.rs @@ -5,8 +5,12 @@ use std::ops::Fn; -trait Response { fn dummy(&self) { } } -trait Request { fn dummy(&self) { } } +trait Response { + fn dummy(&self) {} +} +trait Request { + fn dummy(&self) {} +} trait Ingot { fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status; } @@ -17,7 +21,7 @@ struct HelloWorld; struct SendFile; struct Alloy; enum Status { - Continue + Continue, } impl Alloy { @@ -31,7 +35,7 @@ impl<'b> Fn<(&'b mut (dyn Response + 'b),)> for SendFile { } impl<'b> FnMut<(&'b mut (dyn Response + 'b),)> for SendFile { - extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (dyn Response+'b),)) { + extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (dyn Response + 'b),)) { self.call((_res,)) } } @@ -39,11 +43,13 @@ impl<'b> FnMut<(&'b mut (dyn Response + 'b),)> for SendFile { impl<'b> FnOnce<(&'b mut (dyn Response + 'b),)> for SendFile { type Output = (); - extern "rust-call" fn call_once(self, (_res,): (&'b mut (dyn Response+'b),)) { + extern "rust-call" fn call_once(self, (_res,): (&'b mut (dyn Response + 'b),)) { self.call((_res,)) } } +impl<'b> std::ops::Callable<(&'b mut (dyn Response + 'b),)> for SendFile {} + impl Ingot for HelloWorld { fn enter(&mut self, _req: &mut Rq, res: &mut Rs, alloy: &mut Alloy) -> Status { let send_file = alloy.find::().unwrap(); diff --git a/tests/ui/issues/issue-15094.rs b/tests/ui/issues/issue-15094.rs index cb27e2bcfb6c0..f4c5f1a6896bf 100644 --- a/tests/ui/issues/issue-15094.rs +++ b/tests/ui/issues/issue-15094.rs @@ -3,19 +3,21 @@ use std::{fmt, ops}; struct Debuger { - x: T + x: T, } -impl ops::FnOnce<(),> for Debuger { +impl ops::FnOnce<()> for Debuger { type Output = (); fn call_once(self, _args: ()) { - //~^ ERROR `call_once` has an incompatible type for trait - //~| expected signature `extern "rust-call" fn - //~| found signature `fn + //~^ ERROR `call_once` has an incompatible type for trait + //~| expected signature `extern "rust-call" fn + //~| found signature `fn println!("{:?}", self.x); } } +impl ops::Callable<()> for Debuger {} + fn make_shower(x: T) -> Debuger { Debuger { x: x } } diff --git a/tests/ui/issues/issue-16739.rs b/tests/ui/issues/issue-16739.rs index b21ea4bcd7869..99f16efee6c24 100644 --- a/tests/ui/issues/issue-16739.rs +++ b/tests/ui/issues/issue-16739.rs @@ -4,35 +4,55 @@ // Test that unboxing shim for calling rust-call ABI methods through a // trait box works and does not cause an ICE. -struct Foo { foo: u32 } +struct Foo { + foo: u32, +} impl FnMut<()> for Foo { - extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo } + extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { + self.foo + } } impl FnOnce<()> for Foo { type Output = u32; - extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } + extern "rust-call" fn call_once(mut self, _: ()) -> u32 { + self.call_mut(()) + } } +impl std::ops::Callable<()> for Foo {} + impl FnMut<(u32,)> for Foo { - extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } + extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { + self.foo + x + } } impl FnOnce<(u32,)> for Foo { type Output = u32; - extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { + self.call_mut(args) + } } -impl FnMut<(u32,u32)> for Foo { - extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } +impl std::ops::Callable<(u32,)> for Foo {} + +impl FnMut<(u32, u32)> for Foo { + extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { + self.foo + x + y + } } -impl FnOnce<(u32,u32)> for Foo { +impl FnOnce<(u32, u32)> for Foo { type Output = u32; - extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (u32, u32)) -> u32 { + self.call_mut(args) + } } +impl std::ops::Callable<(u32, u32)> for Foo {} + fn main() { let mut f = Box::new(Foo { foo: 42 }) as Box u32>; assert_eq!(f.call_mut(()), 42); diff --git a/tests/ui/issues/issue-18952.rs b/tests/ui/issues/issue-18952.rs index 56378b59e3642..b6e0d37eeca4a 100644 --- a/tests/ui/issues/issue-18952.rs +++ b/tests/ui/issues/issue-18952.rs @@ -28,6 +28,8 @@ impl FnOnce<(isize, isize)> for Foo { } } +impl std::ops::Callable<(isize, isize)> for Foo {} + impl Fn<(isize, isize, isize)> for Foo { extern "rust-call" fn call(&self, args: (isize, isize, isize)) -> Self::Output { println!("{:?}", args); @@ -48,6 +50,7 @@ impl FnOnce<(isize, isize, isize)> for Foo { (args.0 + 3, args.1 + 3, args.2 + 3) } } +impl std::ops::Callable<(isize, isize, isize)> for Foo {} fn main() { let foo = Foo; diff --git a/tests/ui/issues/issue-19982.rs b/tests/ui/issues/issue-19982.rs index 12419c109c5d4..3cce1395d3bb2 100644 --- a/tests/ui/issues/issue-19982.rs +++ b/tests/ui/issues/issue-19982.rs @@ -19,4 +19,6 @@ impl FnOnce<(&(),)> for Foo { extern "rust-call" fn call_once(self, (_,): (&(),)) {} } +impl std::ops::Callable<(&(),)> for Foo {} + fn main() {} diff --git a/tests/ui/issues/issue-20225.rs b/tests/ui/issues/issue-20225.rs index 0c8e6e402e2ce..637b0b44c751b 100644 --- a/tests/ui/issues/issue-20225.rs +++ b/tests/ui/issues/issue-20225.rs @@ -3,20 +3,22 @@ struct Foo; impl<'a, T> Fn<(&'a T,)> for Foo { - extern "rust-call" fn call(&self, (_,): (T,)) {} - //~^ ERROR: has an incompatible type for trait + extern "rust-call" fn call(&self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait } impl<'a, T> FnMut<(&'a T,)> for Foo { - extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} - //~^ ERROR: has an incompatible type for trait + extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait } impl<'a, T> FnOnce<(&'a T,)> for Foo { - type Output = (); + type Output = (); - extern "rust-call" fn call_once(self, (_,): (T,)) {} - //~^ ERROR: has an incompatible type for trait + extern "rust-call" fn call_once(self, (_,): (T,)) {} + //~^ ERROR: has an incompatible type for trait } +impl<'a, T> std::ops::Callable<(&'a T,)> for Foo {} + fn main() {} diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr index b1c15672051d2..8c7e240c98a2b 100644 --- a/tests/ui/issues/issue-20225.stderr +++ b/tests/ui/issues/issue-20225.stderr @@ -1,42 +1,42 @@ error[E0053]: method `call` has an incompatible type for trait - --> $DIR/issue-20225.rs:6:43 + --> $DIR/issue-20225.rs:6:45 | LL | impl<'a, T> Fn<(&'a T,)> for Foo { | - this type parameter -LL | extern "rust-call" fn call(&self, (_,): (T,)) {} - | ^^^^ - | | - | expected `&'a T`, found type parameter `T` - | help: change the parameter type to match the trait: `(&'a T,)` +LL | extern "rust-call" fn call(&self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&'a T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))` found signature `extern "rust-call" fn(&Foo, (T,))` error[E0053]: method `call_mut` has an incompatible type for trait - --> $DIR/issue-20225.rs:11:51 + --> $DIR/issue-20225.rs:11:53 | LL | impl<'a, T> FnMut<(&'a T,)> for Foo { | - this type parameter -LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} - | ^^^^ - | | - | expected `&'a T`, found type parameter `T` - | help: change the parameter type to match the trait: `(&'a T,)` +LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&'a T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))` found signature `extern "rust-call" fn(&mut Foo, (T,))` error[E0053]: method `call_once` has an incompatible type for trait - --> $DIR/issue-20225.rs:18:47 + --> $DIR/issue-20225.rs:18:49 | LL | impl<'a, T> FnOnce<(&'a T,)> for Foo { | - this type parameter ... -LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} - | ^^^^ - | | - | expected `&'a T`, found type parameter `T` - | help: change the parameter type to match the trait: `(&'a T,)` +LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} + | ^^^^ + | | + | expected `&'a T`, found type parameter `T` + | help: change the parameter type to match the trait: `(&'a T,)` | = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))` found signature `extern "rust-call" fn(Foo, (T,))` diff --git a/tests/ui/issues/issue-20544.rs b/tests/ui/issues/issue-20544.rs index 0f4d314f166c7..d617354ffe7eb 100644 --- a/tests/ui/issues/issue-20544.rs +++ b/tests/ui/issues/issue-20544.rs @@ -4,7 +4,10 @@ struct Fun(F); -impl FnOnce<(T,)> for Fun where F: Fn(T) -> T { +impl FnOnce<(T,)> for Fun +where + F: Fn(T) -> T, +{ type Output = T; extern "rust-call" fn call_once(self, (t,): (T,)) -> T { @@ -12,6 +15,8 @@ impl FnOnce<(T,)> for Fun where F: Fn(T) -> T { } } +impl std::ops::Callable<(T,)> for Fun where F: Fn(T) -> T {} + fn main() { let fun = Fun(|i: isize| i * 2); println!("{}", fun(3)); diff --git a/tests/ui/issues/issue-22603.rs b/tests/ui/issues/issue-22603.rs index a83e291f999ab..2a5e9c14f7bc4 100644 --- a/tests/ui/issues/issue-22603.rs +++ b/tests/ui/issues/issue-22603.rs @@ -6,10 +6,11 @@ struct Foo; impl FnOnce<(A,)> for Foo { type Output = (); - extern "rust-call" fn call_once(self, (_,): (A,)) { - } + extern "rust-call" fn call_once(self, (_,): (A,)) {} } +impl std::ops::Callable<(A,)> for Foo {} + fn main() { println!("{:?}", Foo("bar")); } diff --git a/tests/ui/issues/issue-33687.rs b/tests/ui/issues/issue-33687.rs index ac802ed86dc63..c30206c631e7b 100644 --- a/tests/ui/issues/issue-33687.rs +++ b/tests/ui/issues/issue-33687.rs @@ -12,6 +12,8 @@ impl FnOnce<(u32, u32)> for Test { } } +impl std::ops::Callable<(u32, u32)> for Test {} + fn main() { assert_eq!(Test(1u32, 2u32), 3u32); } diff --git a/tests/ui/issues/issue-45510.rs b/tests/ui/issues/issue-45510.rs index 9e104ce6c4f30..ee815dd4b7eeb 100644 --- a/tests/ui/issues/issue-45510.rs +++ b/tests/ui/issues/issue-45510.rs @@ -18,6 +18,8 @@ impl FnOnce<(Ishmael,)> for CallMe { } } +impl std::ops::Callable<(Ishmael,)> for CallMe {} + impl FnOnce<(Maybe,)> for CallMe { type Output = Maybe; extern "rust-call" fn call_once(self, _args: (Maybe,)) -> Maybe { @@ -26,6 +28,8 @@ impl FnOnce<(Maybe,)> for CallMe { } } +impl std::ops::Callable<(Maybe,)> for CallMe {} + fn main() { assert_eq!(CallMe(Ishmael), Ishmael); assert_eq!(CallMe(Maybe), Maybe); diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr index 02e33c597fe87..56ac51e3e5315 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:50:5 | LL | a(); | ^^^ @@ -7,7 +7,7 @@ LL | a(); = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 + --> $DIR/fn-fn_mut-call-ill-formed.rs:55:5 | LL | b(); | ^^^ diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs index 757c6538d05b0..08aada54b1866 100644 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs +++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs @@ -6,12 +6,16 @@ #[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} #[cfg(any(fn_bad_item, fn_bad_sig))] #[lang = "fn"] trait MyFn { #[cfg(fn_bad_sig)] - fn call(i: i32) -> i32 { 0 } + fn call(i: i32) -> i32 { + 0 + } #[cfg(fn_bad_item)] const call: i32 = 42; @@ -21,7 +25,9 @@ trait MyFn { #[lang = "fn_mut"] trait MyFnMut { #[cfg(fn_mut_bad_sig)] - fn call_mut(i: i32) -> i32 { 0 } + fn call_mut(i: i32) -> i32 { + 0 + } #[cfg(fn_mut_bad_item)] const call_mut: i32 = 42; @@ -31,7 +37,9 @@ trait MyFnMut { #[lang = "fn_once"] trait MyFnOnce { #[cfg(fn_once_bad_sig)] - fn call_once(i: i32) -> i32 { 0 } + fn call_once(i: i32) -> i32 { + 0 + } #[cfg(fn_once_bad_item)] const call_once: i32 = 42; @@ -43,7 +51,7 @@ fn main() { //~^ ERROR failed to find an overloaded call trait for closure call let mut i = 0; - let mut b = || { }; + let mut b = || {}; b(); //~^ ERROR failed to find an overloaded call trait for closure call } diff --git a/tests/ui/lang-items/issue-86238.rs b/tests/ui/lang-items/issue-86238.rs index 509f94f3834a5..0f1596afcb963 100644 --- a/tests/ui/lang-items/issue-86238.rs +++ b/tests/ui/lang-items/issue-86238.rs @@ -2,7 +2,6 @@ #![feature(lang_items)] #![feature(no_core)] - #![no_core] fn main() { let one = || {}; @@ -14,3 +13,5 @@ fn main() { trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} diff --git a/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr index c6e811a94fe20..29f0a96e11abd 100644 --- a/tests/ui/lang-items/issue-86238.stderr +++ b/tests/ui/lang-items/issue-86238.stderr @@ -1,5 +1,5 @@ error: failed to find an overloaded call trait for closure call - --> $DIR/issue-86238.rs:9:5 + --> $DIR/issue-86238.rs:8:5 | LL | one() | ^^^^^ diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.rs b/tests/ui/lang-items/missing-clone-for-suggestion.rs index e8290c0098afd..7bfed866c04bf 100644 --- a/tests/ui/lang-items/missing-clone-for-suggestion.rs +++ b/tests/ui/lang-items/missing-clone-for-suggestion.rs @@ -10,6 +10,9 @@ trait Sized {} #[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} + fn g(x: T) {} fn f(x: *mut u8) { diff --git a/tests/ui/lang-items/missing-clone-for-suggestion.stderr b/tests/ui/lang-items/missing-clone-for-suggestion.stderr index 35783a1be78ad..6906ac84719c5 100644 --- a/tests/ui/lang-items/missing-clone-for-suggestion.stderr +++ b/tests/ui/lang-items/missing-clone-for-suggestion.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/missing-clone-for-suggestion.rs:17:7 + --> $DIR/missing-clone-for-suggestion.rs:20:7 | LL | fn f(x: *mut u8) { | - move occurs because `x` has type `*mut u8`, which does not implement the `Copy` trait @@ -9,7 +9,7 @@ LL | g(x); | ^ value used here after move | note: consider changing this parameter type in function `g` to borrow instead if owning the value isn't necessary - --> $DIR/missing-clone-for-suggestion.rs:13:12 + --> $DIR/missing-clone-for-suggestion.rs:16:12 | LL | fn g(x: T) {} | - ^ this parameter takes ownership of the value diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.rs b/tests/ui/mismatched_types/overloaded-calls-bad.rs index 5b1804d825d82..0a595c5406e2a 100644 --- a/tests/ui/mismatched_types/overloaded-calls-bad.rs +++ b/tests/ui/mismatched_types/overloaded-calls-bad.rs @@ -20,6 +20,8 @@ impl FnOnce<(isize,)> for S { } } +impl std::ops::Callable<(isize,)> for S {} + struct F; impl FnOnce<(i32,)> for F { @@ -28,6 +30,8 @@ impl FnOnce<(i32,)> for F { extern "rust-call" fn call_once(self, args: (i32,)) -> Self::Output {} } +impl std::ops::Callable<(i32,)> for F {} + fn main() { let mut s = S { x: 3, y: 3 }; let ans = s("what"); diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr index cd483e7ad2c64..05f9f297c4ed4 100644 --- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/overloaded-calls-bad.rs:33:17 + --> $DIR/overloaded-calls-bad.rs:37:17 | LL | let ans = s("what"); | - ^^^^^^ expected `isize`, found `&str` @@ -13,7 +13,7 @@ LL | impl FnMut<(isize,)> for S { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0057]: this function takes 1 argument but 0 arguments were supplied - --> $DIR/overloaded-calls-bad.rs:35:15 + --> $DIR/overloaded-calls-bad.rs:39:15 | LL | let ans = s(); | ^-- an argument of type `isize` is missing @@ -29,7 +29,7 @@ LL | let ans = s(/* isize */); | ~~~~~~~~~~~~~ error[E0057]: this function takes 1 argument but 2 arguments were supplied - --> $DIR/overloaded-calls-bad.rs:37:15 + --> $DIR/overloaded-calls-bad.rs:41:15 | LL | let ans = s("burma", "shave"); | ^ ------- ------- unexpected argument of type `&'static str` @@ -48,7 +48,7 @@ LL + let ans = s(/* isize */); | error[E0308]: mismatched types - --> $DIR/overloaded-calls-bad.rs:40:7 + --> $DIR/overloaded-calls-bad.rs:44:7 | LL | F(""); | - ^^ expected `i32`, found `&str` @@ -56,7 +56,7 @@ LL | F(""); | arguments to this struct are incorrect | note: implementation defined here - --> $DIR/overloaded-calls-bad.rs:25:1 + --> $DIR/overloaded-calls-bad.rs:27:1 | LL | impl FnOnce<(i32,)> for F { | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/overloaded/issue-14958.rs b/tests/ui/overloaded/issue-14958.rs index a12564ca9c0ee..4b0cf672d2eb6 100644 --- a/tests/ui/overloaded/issue-14958.rs +++ b/tests/ui/overloaded/issue-14958.rs @@ -3,23 +3,31 @@ #![feature(fn_traits, unboxed_closures)] -trait Foo { fn dummy(&self) { }} +trait Foo { + fn dummy(&self) {} +} struct Bar; -impl<'a> std::ops::Fn<(&'a (dyn Foo+'a),)> for Bar { +impl<'a> std::ops::Fn<(&'a (dyn Foo + 'a),)> for Bar { extern "rust-call" fn call(&self, _: (&'a dyn Foo,)) {} } -impl<'a> std::ops::FnMut<(&'a (dyn Foo+'a),)> for Bar { - extern "rust-call" fn call_mut(&mut self, a: (&'a dyn Foo,)) { self.call(a) } +impl<'a> std::ops::FnMut<(&'a (dyn Foo + 'a),)> for Bar { + extern "rust-call" fn call_mut(&mut self, a: (&'a dyn Foo,)) { + self.call(a) + } } -impl<'a> std::ops::FnOnce<(&'a (dyn Foo+'a),)> for Bar { +impl<'a> std::ops::FnOnce<(&'a (dyn Foo + 'a),)> for Bar { type Output = (); - extern "rust-call" fn call_once(self, a: (&'a dyn Foo,)) { self.call(a) } + extern "rust-call" fn call_once(self, a: (&'a dyn Foo,)) { + self.call(a) + } } +impl<'a> std::ops::Callable<(&'a (dyn Foo + 'a),)> for Bar {} + struct Baz; impl Foo for Baz {} diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.rs b/tests/ui/overloaded/overloaded-calls-nontuple.rs index 32a3b93e0a1e5..19b177d20c021 100644 --- a/tests/ui/overloaded/overloaded-calls-nontuple.rs +++ b/tests/ui/overloaded/overloaded-calls-nontuple.rs @@ -24,6 +24,8 @@ impl FnOnce for S { } } +impl std::ops::Callable for S {} + fn main() { let mut s = S { x: 1, y: 2 }; drop(s(3)) diff --git a/tests/ui/overloaded/overloaded-calls-param-vtables.rs b/tests/ui/overloaded/overloaded-calls-param-vtables.rs index fde1ad20f7d9c..d412cac195227 100644 --- a/tests/ui/overloaded/overloaded-calls-param-vtables.rs +++ b/tests/ui/overloaded/overloaded-calls-param-vtables.rs @@ -6,26 +6,32 @@ #![feature(unboxed_closures, fn_traits)] use std::marker::PhantomData; -use std::ops::Fn; use std::ops::Add; +use std::ops::Fn; struct G(PhantomData); -impl<'a, A: Add> Fn<(A,)> for G { +impl<'a, A: Add> Fn<(A,)> for G { extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { arg.add(1) } } -impl<'a, A: Add> FnMut<(A,)> for G { - extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) } +impl<'a, A: Add> FnMut<(A,)> for G { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { + self.call(args) + } } -impl<'a, A: Add> FnOnce<(A,)> for G { +impl<'a, A: Add> FnOnce<(A,)> for G { type Output = i32; - extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) } + extern "rust-call" fn call_once(self, args: (A,)) -> i32 { + self.call(args) + } } +impl<'a, A: Add> std::ops::Callable<(A,)> for G {} + fn main() { // ICE trigger (G(PhantomData))(1); diff --git a/tests/ui/overloaded/overloaded-calls-simple.rs b/tests/ui/overloaded/overloaded-calls-simple.rs index 4131836079907..b8495e2f90e51 100644 --- a/tests/ui/overloaded/overloaded-calls-simple.rs +++ b/tests/ui/overloaded/overloaded-calls-simple.rs @@ -22,6 +22,8 @@ impl FnOnce<(i32,)> for S1 { } } +impl std::ops::Callable<(i32,)> for S1 {} + struct S2 { x: i32, y: i32, @@ -34,45 +36,44 @@ impl Fn<(i32,)> for S2 { } impl FnMut<(i32,)> for S2 { - extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { + self.call(args) + } } impl FnOnce<(i32,)> for S2 { type Output = i32; - extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { + self.call(args) + } } +impl std::ops::Callable<(i32,)> for S2 {} + struct S3 { x: i32, y: i32, } -impl FnOnce<(i32,i32)> for S3 { +impl FnOnce<(i32, i32)> for S3 { type Output = i32; - extern "rust-call" fn call_once(self, (z,zz): (i32,i32)) -> i32 { + extern "rust-call" fn call_once(self, (z, zz): (i32, i32)) -> i32 { self.x * self.y * z * zz } } +impl std::ops::Callable<(i32, i32)> for S3 {} + fn main() { - let mut s = S1 { - x: 3, - y: 3, - }; + let mut s = S1 { x: 3, y: 3 }; let ans = s(3); assert_eq!(ans, 27); - let s = S2 { - x: 3, - y: 3, - }; + let s = S2 { x: 3, y: 3 }; let ans = s.call((3,)); assert_eq!(ans, 27); - let s = S3 { - x: 3, - y: 3, - }; + let s = S3 { x: 3, y: 3 }; let ans = s(3, 1); assert_eq!(ans, 27); } diff --git a/tests/ui/overloaded/overloaded-calls-zero-args.rs b/tests/ui/overloaded/overloaded-calls-zero-args.rs index 69ca88619b8c0..fca0ab94afa1c 100644 --- a/tests/ui/overloaded/overloaded-calls-zero-args.rs +++ b/tests/ui/overloaded/overloaded-calls-zero-args.rs @@ -17,14 +17,15 @@ impl FnMut<()> for S { impl FnOnce<()> for S { type Output = i32; - extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: ()) -> i32 { + self.call_mut(args) + } } +impl std::ops::Callable<()> for S {} + fn main() { - let mut s = S { - x: 3, - y: 3, - }; + let mut s = S { x: 3, y: 3 }; let ans = s(); assert_eq!(ans, 9); } diff --git a/tests/ui/privacy/privacy1.rs b/tests/ui/privacy/privacy1.rs index fcb2108ab5fec..7f3d50fef8cdf 100644 --- a/tests/ui/privacy/privacy1.rs +++ b/tests/ui/privacy/privacy1.rs @@ -12,6 +12,9 @@ pub trait Deref { type Target; } +#[lang = "callable"] +trait Callable {} + #[lang="receiver"] pub trait Receiver: Deref {} diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index ca8f242e0bed2..e9ce51242010c 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -1,53 +1,53 @@ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:132:18 + --> $DIR/privacy1.rs:135:18 | LL | use bar::baz::{foo, bar}; | ^^^ private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:132:18 + --> $DIR/privacy1.rs:135:18 | LL | use bar::baz::{foo, bar}; | ^^^ private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:141:18 + --> $DIR/privacy1.rs:144:18 | LL | use bar::baz; | ^^^ private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `i` is private - --> $DIR/privacy1.rs:165:20 + --> $DIR/privacy1.rs:168:20 | LL | use self::foo::i::A; | ^ private module | note: the module `i` is defined here - --> $DIR/privacy1.rs:170:9 + --> $DIR/privacy1.rs:173:9 | LL | mod i { | ^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:104:16 + --> $DIR/privacy1.rs:107:16 | LL | ::bar::baz::A::foo(); | ^^^ - struct `A` is not publicly re-exported @@ -55,13 +55,13 @@ LL | ::bar::baz::A::foo(); | private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:105:16 + --> $DIR/privacy1.rs:108:16 | LL | ::bar::baz::A::bar(); | ^^^ - struct `A` is not publicly re-exported @@ -69,13 +69,13 @@ LL | ::bar::baz::A::bar(); | private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:107:16 + --> $DIR/privacy1.rs:110:16 | LL | ::bar::baz::A.foo2(); | ^^^ - unit struct `A` is not publicly re-exported @@ -83,13 +83,13 @@ LL | ::bar::baz::A.foo2(); | private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:108:16 + --> $DIR/privacy1.rs:111:16 | LL | ::bar::baz::A.bar2(); | ^^^ - unit struct `A` is not publicly re-exported @@ -97,13 +97,13 @@ LL | ::bar::baz::A.bar2(); | private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ error[E0603]: trait `B` is private - --> $DIR/privacy1.rs:112:16 + --> $DIR/privacy1.rs:115:16 | LL | ::bar::B::foo(); | ^ --- associated function `foo` is not publicly re-exported @@ -111,31 +111,31 @@ LL | ::bar::B::foo(); | private trait | note: the trait `B` is defined here - --> $DIR/privacy1.rs:40:5 + --> $DIR/privacy1.rs:43:5 | LL | trait B { | ^^^^^^^ error[E0603]: function `epriv` is private - --> $DIR/privacy1.rs:118:20 + --> $DIR/privacy1.rs:121:20 | LL | ::bar::epriv(); | ^^^^^ private function | note: the function `epriv` is defined here - --> $DIR/privacy1.rs:65:9 + --> $DIR/privacy1.rs:68:9 | LL | fn epriv(); | ^^^^^^^^^^^ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:127:16 + --> $DIR/privacy1.rs:130:16 | LL | ::bar::baz::foo(); | ^^^ private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ @@ -145,13 +145,13 @@ LL | bar::foo(); | ~~~~~~~~ error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:128:16 + --> $DIR/privacy1.rs:131:16 | LL | ::bar::baz::bar(); | ^^^ private module | note: the module `baz` is defined here - --> $DIR/privacy1.rs:50:5 + --> $DIR/privacy1.rs:53:5 | LL | mod baz { | ^^^^^^^ @@ -161,19 +161,19 @@ LL | bar::bar(); | ~~~~~~~~ error[E0603]: trait `B` is private - --> $DIR/privacy1.rs:157:17 + --> $DIR/privacy1.rs:160:17 | LL | impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } } | ^ private trait | note: the trait `B` is defined here - --> $DIR/privacy1.rs:40:5 + --> $DIR/privacy1.rs:43:5 | LL | trait B { | ^^^^^^^ error[E0624]: associated function `bar` is private - --> $DIR/privacy1.rs:77:23 + --> $DIR/privacy1.rs:80:23 | LL | fn bar() {} | -------- private associated function defined here @@ -182,7 +182,7 @@ LL | self::baz::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private - --> $DIR/privacy1.rs:95:13 + --> $DIR/privacy1.rs:98:13 | LL | fn bar() {} | -------- private associated function defined here @@ -191,7 +191,7 @@ LL | bar::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private - --> $DIR/privacy1.rs:102:19 + --> $DIR/privacy1.rs:105:19 | LL | fn bar() {} | -------- private associated function defined here @@ -200,7 +200,7 @@ LL | ::bar::A::bar(); | ^^^ private associated function error[E0624]: associated function `bar` is private - --> $DIR/privacy1.rs:105:24 + --> $DIR/privacy1.rs:108:24 | LL | fn bar() {} | -------- private associated function defined here @@ -209,7 +209,7 @@ LL | ::bar::baz::A::bar(); | ^^^ private associated function error[E0624]: method `bar2` is private - --> $DIR/privacy1.rs:108:23 + --> $DIR/privacy1.rs:111:23 | LL | fn bar2(&self) {} | -------------- private method defined here diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2acfde4be46d9..ac3efd577aa79 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -28,10 +28,12 @@ extern "rust-intrinsic" { fn size_of() -> usize; } -#[lang="sized"] +#[lang = "sized"] trait Sized {} -#[lang="copy"] +#[lang = "copy"] trait Copy {} +#[lang = "callable"] +trait Callable {} const EXPECTED: usize = 2; const ACTUAL: usize = size_of::(); diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs index 6b065bf6cbff2..8907122dd6b4b 100644 --- a/tests/ui/span/issue-23827.rs +++ b/tests/ui/span/issue-23827.rs @@ -3,7 +3,7 @@ #![feature(fn_traits, unboxed_closures)] pub struct Prototype { - pub target: u32 + pub target: u32, } trait Component { @@ -30,4 +30,6 @@ impl FnOnce<(C,)> for Prototype { } } +impl std::ops::Callable<(C,)> for Prototype {} + fn main() {} diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs index 5fbd5e8a28d94..af0a2a3f5a73d 100644 --- a/tests/ui/target-feature/feature-hierarchy.rs +++ b/tests/ui/target-feature/feature-hierarchy.rs @@ -18,6 +18,9 @@ trait Sized {} trait Copy {} impl Copy for bool {} +#[lang = "callable"] +trait Callable {} + extern "rust-intrinsic" { #[rustc_const_stable(feature = "test", since = "1.0.0")] fn unreachable() -> !; @@ -42,7 +45,6 @@ macro_rules! assert { }; } - #[cfg(aarch64_neon)] fn check_neon_not_sve2() { // This checks that a normal aarch64 target doesn't suddenly jump up the feature hierarchy. diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs index 5a71b2166c3ae..ade2686112971 100644 --- a/tests/ui/target-feature/no-llvm-leaks.rs +++ b/tests/ui/target-feature/no-llvm-leaks.rs @@ -16,6 +16,9 @@ trait Sized {} trait Copy {} impl Copy for bool {} +#[lang = "callable"] +trait Callable {} + extern "rust-intrinsic" { #[rustc_const_stable(feature = "test", since = "1.0.0")] fn unreachable() -> !; @@ -40,7 +43,6 @@ macro_rules! assert { }; } - #[cfg(target_arch = "aarch64")] fn check_aarch64() { // This checks that the rustc feature name is used, not the LLVM feature. diff --git a/tests/ui/target-feature/tied-features.rs b/tests/ui/target-feature/tied-features.rs index 15f01505eba8f..834e7d3d524ae 100644 --- a/tests/ui/target-feature/tied-features.rs +++ b/tests/ui/target-feature/tied-features.rs @@ -4,9 +4,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] +#[lang = "sized"] trait Sized {} +#[lang = "callable"] +trait Callable {} + // FIXME: this should not need to be public. pub fn main() { #[target_feature(enable = "pacg")] @@ -25,7 +28,6 @@ pub fn main() { //~^ ERROR must all be either enabled or disabled together unsafe fn foo() {} - #[target_feature(enable = "paca,pacg")] unsafe fn bar() {} diff --git a/tests/ui/target-feature/tied-features.stderr b/tests/ui/target-feature/tied-features.stderr index 525c9084330d4..8ce03bf36904b 100644 --- a/tests/ui/target-feature/tied-features.stderr +++ b/tests/ui/target-feature/tied-features.stderr @@ -1,5 +1,5 @@ error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:12:5 + --> $DIR/tied-features.rs:15:5 | LL | #[target_feature(enable = "pacg")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[target_feature(enable = "pacg")] = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:24:1 + --> $DIR/tied-features.rs:27:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs index ba473653ecfe3..17fbd2461f36d 100644 --- a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs +++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs @@ -4,8 +4,8 @@ #![feature(unboxed_closures)] #![feature(tuple_trait)] -use std::ops::Fn; use std::marker::Tuple; +use std::ops::Fn; fn foo, T: Tuple>(f: Option, t: T) { let y = (f.unwrap()).call(t); diff --git a/tests/ui/traits/new-solver/callable.new.stderr b/tests/ui/traits/new-solver/callable.new.stderr new file mode 100644 index 0000000000000..e8c10099aaf4c --- /dev/null +++ b/tests/ui/traits/new-solver/callable.new.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `fn(i32) -> i32: Callable<()>` is not satisfied + --> $DIR/callable.rs:10:12 + | +LL | test:: i32>(); + | ^^^^^^^^^^^^^^ the trait `Callable<()>` is not implemented for `fn(i32) -> i32` + | +note: required by a bound in `test` + --> $DIR/callable.rs:7:12 + | +LL | fn test>() {} + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/callable.old.stderr b/tests/ui/traits/new-solver/callable.old.stderr new file mode 100644 index 0000000000000..9add72108ccde --- /dev/null +++ b/tests/ui/traits/new-solver/callable.old.stderr @@ -0,0 +1,15 @@ +error[E0593]: function is expected to take 0 arguments, but it takes 1 argument + --> $DIR/callable.rs:10:12 + | +LL | test:: i32>(); + | ^^^^^^^^^^^^^^ expected function that takes 0 arguments + | +note: required by a bound in `test` + --> $DIR/callable.rs:7:12 + | +LL | fn test>() {} + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0593`. diff --git a/tests/ui/traits/new-solver/callable.rs b/tests/ui/traits/new-solver/callable.rs new file mode 100644 index 0000000000000..dcf40116a8057 --- /dev/null +++ b/tests/ui/traits/new-solver/callable.rs @@ -0,0 +1,13 @@ +//[new] compile-flags: -Ztrait-solver=next +// edition: 2021 +// revisions: old new + +#![feature(fn_traits)] + +fn test>() {} + +fn main() { + test:: i32>(); + //[old]~^ ERROR: function is expected to take 0 arguments, but it takes 1 argument + //[new]~^^ ERROR: the trait bound `fn(i32) -> i32: Callable<()>` is not satisfied +} diff --git a/tests/ui/traits/new-solver/object-unsafety.rs b/tests/ui/traits/new-solver/object-unsafety.rs index 7bdd863a762c4..f9ff38bbc97be 100644 --- a/tests/ui/traits/new-solver/object-unsafety.rs +++ b/tests/ui/traits/new-solver/object-unsafety.rs @@ -9,8 +9,9 @@ fn copy(from: &U::From) -> U::From { } pub fn copy_any(t: &T) -> T { - copy::>(t) + copy::>(t) //~^ ERROR the trait bound `dyn Setup: Setup` is not satisfied + //~| ERROR: Callable<(&T,)>` is not satisfied } fn main() { diff --git a/tests/ui/traits/new-solver/object-unsafety.stderr b/tests/ui/traits/new-solver/object-unsafety.stderr index 198ac623df8a6..82264aa6cb30a 100644 --- a/tests/ui/traits/new-solver/object-unsafety.stderr +++ b/tests/ui/traits/new-solver/object-unsafety.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `dyn Setup: Setup` is not satisfied --> $DIR/object-unsafety.rs:12:12 | -LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup` +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup` | note: required by a bound in `copy` --> $DIR/object-unsafety.rs:7:12 @@ -14,6 +14,12 @@ help: consider introducing a `where` clause, but there might be an alternative b LL | pub fn copy_any(t: &T) -> T where dyn Setup: Setup { | ++++++++++++++++++++++++++++++++ -error: aborting due to previous error +error[E0277]: the trait bound `for<'a> fn(&'a as Setup>::From) -> as Setup>::From {copy::>}: Callable<(&T,)>` is not satisfied + --> $DIR/object-unsafety.rs:12:5 + | +LL | copy::>(t) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callable<(&T,)>` is not implemented for fn item `for<'a> fn(&'a as Setup>::From) -> as Setup>::From {copy::>}` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/issue-30906.rs b/tests/ui/unboxed-closures/issue-30906.rs index e2d219e470384..69ae7052fe55a 100644 --- a/tests/ui/unboxed-closures/issue-30906.rs +++ b/tests/ui/unboxed-closures/issue-30906.rs @@ -14,6 +14,13 @@ where } } +impl std::ops::Callable<(T,)> for Compose +where + F: FnOnce<(T,)>, + G: FnOnce<(F::Output,)>, +{ +} + fn bad(f: fn(&'static str) -> T) { test(Compose(f, |_| {})); //~^ ERROR: implementation of `FnOnce` is not general enough diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 147a20974732d..275b17b917af9 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/issue-30906.rs:18:5 + --> $DIR/issue-30906.rs:25:5 | LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough diff --git a/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs index 851f3d2fe9ba0..d07a3e4a3c3f1 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs @@ -4,7 +4,7 @@ #![feature(unboxed_closures, fn_traits)] -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; struct S; @@ -15,23 +15,29 @@ impl Fn<(i32,)> for S { } impl FnMut<(i32,)> for S { - extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) } + extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { + self.call(args) + } } impl FnOnce<(i32,)> for S { type Output = i32; - extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) } + extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { + self.call(args) + } } -fn call_iti32>(f: &F, x: i32) -> i32 { +impl std::ops::Callable<(i32,)> for S {} + +fn call_it i32>(f: &F, x: i32) -> i32 { f(x) } -fn call_it_muti32>(f: &mut F, x: i32) -> i32 { +fn call_it_mut i32>(f: &mut F, x: i32) -> i32 { f(x) } -fn call_it_oncei32>(f: F, x: i32) -> i32 { +fn call_it_once i32>(f: F, x: i32) -> i32 { f(x) } diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs index 867e5fb1de759..6e4593d895ab0 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.rs @@ -3,7 +3,7 @@ #![feature(fn_traits, unboxed_closures)] -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; struct S; @@ -16,10 +16,14 @@ impl FnMut<(isize,)> for S { impl FnOnce<(isize,)> for S { type Output = isize; - extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { + self.call_mut(args) + } } -fn call_itisize>(f: &F, x: isize) -> isize { +impl std::ops::Callable<(isize,)> for S {} + +fn call_it isize>(f: &F, x: isize) -> isize { f.call((x,)) } diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index 0ea1c1dcd5bde..086c9c4a0514e 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -1,5 +1,5 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `S` - --> $DIR/unboxed-closures-fnmut-as-fn.rs:27:21 + --> $DIR/unboxed-closures-fnmut-as-fn.rs:31:21 | LL | let x = call_it(&S, 22); | ------- ^^ expected an `Fn<(isize,)>` closure, found `S` @@ -9,10 +9,10 @@ LL | let x = call_it(&S, 22); = help: the trait `Fn<(isize,)>` is not implemented for `S` = note: `S` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `call_it` - --> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14 + --> $DIR/unboxed-closures-fnmut-as-fn.rs:26:15 | -LL | fn call_itisize>(f: &F, x: isize) -> isize { - | ^^^^^^^^^^^^^^^^ required by this bound in `call_it` +LL | fn call_it isize>(f: &F, x: isize) -> isize { + | ^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` error: aborting due to previous error diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs index bd577f7c479e5..49f4f0b4200b6 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fnonce.rs @@ -15,14 +15,18 @@ impl FnMut<(i32,)> for S { impl FnOnce<(i32,)> for S { type Output = i32; - extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { + self.call_mut(args) + } } -fn call_it_muti32>(f: &mut F, x: i32) -> i32 { +impl std::ops::Callable<(i32,)> for S {} + +fn call_it_mut i32>(f: &mut F, x: i32) -> i32 { f(x) } -fn call_it_oncei32>(f: F, x: i32) -> i32 { +fn call_it_once i32>(f: F, x: i32) -> i32 { f(x) } diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs index a0fbbafe25ffb..e93a4d2e4533a 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-recursive-fn.rs @@ -9,37 +9,43 @@ use std::marker::PhantomData; // // [Y Combinator]: https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator -struct YCombinator { +struct YCombinator { func: F, - marker: PhantomData<(A,R)>, + marker: PhantomData<(A, R)>, } -impl YCombinator { - fn new(f: F) -> YCombinator { +impl YCombinator { + fn new(f: F) -> YCombinator { YCombinator { func: f, marker: PhantomData } } } -impl R, A) -> R> Fn<(A,)> for YCombinator { +impl R, A) -> R> Fn<(A,)> for YCombinator { extern "rust-call" fn call(&self, (arg,): (A,)) -> R { (self.func)(self, arg) } } -impl R, A) -> R> FnMut<(A,)> for YCombinator { - extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) } +impl R, A) -> R> FnMut<(A,)> for YCombinator { + extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { + self.call(args) + } } -impl R, A) -> R> FnOnce<(A,)> for YCombinator { +impl R, A) -> R> FnOnce<(A,)> for YCombinator { type Output = R; - extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) } + extern "rust-call" fn call_once(self, args: (A,)) -> R { + self.call(args) + } } +impl R, A) -> R> std::ops::Callable<(A,)> for YCombinator {} + fn main() { let factorial = |recur: &dyn Fn(u32) -> u32, arg: u32| -> u32 { - if arg == 0 {1} else {arg * recur(arg-1)} + if arg == 0 { 1 } else { arg * recur(arg - 1) } }; - let factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial); + let factorial: YCombinator<_, u32, u32> = YCombinator::new(factorial); let r = factorial(10); assert_eq!(3628800, r); } diff --git a/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs b/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs index df60b42ab126a..c1cfd70da11de 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-manual-impl.rs @@ -12,10 +12,14 @@ impl FnMut<(i32,)> for S { impl FnOnce<(i32,)> for S { type Output = i32; - extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) } + extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { + self.call_mut(args) + } } -fn call_iti32>(mut f: F, x: i32) -> i32 { +impl std::ops::Callable<(i32,)> for S {} + +fn call_it i32>(mut f: F, x: i32) -> i32 { f(x) + 3 } diff --git a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs index 5e354cb6fce25..4586192553f56 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -6,38 +6,43 @@ use std::marker::PhantomData; // where we attempt to perform mutation in the recursive function. This fails to compile // because it winds up requiring `FnMut` which enforces linearity. -struct YCombinator { +struct YCombinator { func: F, - marker: PhantomData<(A,R)>, + marker: PhantomData<(A, R)>, } -impl YCombinator { - fn new(f: F) -> YCombinator { +impl YCombinator { + fn new(f: F) -> YCombinator { YCombinator { func: f, marker: PhantomData } } } -impl R, A) -> R> FnMut<(A,)> for YCombinator { +impl R, A) -> R> FnMut<(A,)> for YCombinator { extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R { (self.func)(self, arg) - //~^ ERROR cannot borrow `*self` as mutable more than once at a time + //~^ ERROR cannot borrow `*self` as mutable more than once at a time } } -impl R, A) -> R> FnOnce<(A,)> for YCombinator { +impl R, A) -> R> FnOnce<(A,)> for YCombinator { type Output = R; extern "rust-call" fn call_once(mut self, args: (A,)) -> R { self.call_mut(args) } } +impl R, A) -> R> std::ops::Callable<(A,)> + for YCombinator +{ +} + fn main() { let mut counter = 0; let factorial = |recur: &mut dyn FnMut(u32) -> u32, arg: u32| -> u32 { counter += 1; - if arg == 0 {1} else {arg * recur(arg-1)} + if arg == 0 { 1 } else { arg * recur(arg - 1) } }; - let mut factorial: YCombinator<_,u32,u32> = YCombinator::new(factorial); + let mut factorial: YCombinator<_, u32, u32> = YCombinator::new(factorial); let mut r = factorial(10); assert_eq!(3628800, r); } diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs index 892b281357f2e..0f225a3cccb81 100644 --- a/tests/ui/weird-exprs.rs +++ b/tests/ui/weird-exprs.rs @@ -1,7 +1,8 @@ // run-pass #![feature(generators)] - +#![feature(custom_inner_attributes)] +#![feature(fn_traits)] #![allow(non_camel_case_types)] #![allow(dead_code)] #![allow(redundant_semicolons)] @@ -10,9 +11,10 @@ #![allow(uncommon_codepoints, confusable_idents)] #![allow(unused_imports)] #![allow(unreachable_patterns)] - #![recursion_limit = "256"] +#![rustfmt::skip] + extern crate core; use std::cell::Cell; use std::mem::swap; @@ -189,6 +191,7 @@ fn function() { &((|| foo) as _) } } + impl std::ops::Callable<()> for foo {} let foo = foo () ()() ()()() ()()()() ()()()()(); } From e39927e5cb76a2b6330bf0b2c64a9facbffaadac Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 27 Jun 2023 13:20:48 +0000 Subject: [PATCH 3/5] Fix indentation --- compiler/rustc_hir_typeck/src/callee.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 40a0a76b49a8e..a005c24c4f600 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -481,9 +481,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(ty, sp, traits::RustCall); } else { self.tcx.sess.span_err( - sp, - "functions with the \"rust-call\" ABI must take a single non-self tuple argument", - ); + sp, + "functions with the \"rust-call\" ABI must take a single non-self tuple argument", + ); } } From f3face62345de84865dd2e7140f41e9503378c3a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 27 Jun 2023 15:03:53 +0000 Subject: [PATCH 4/5] Leave some notes for where we could remove some work duplication --- compiler/rustc_hir_typeck/src/callee.rs | 3 +++ compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a005c24c4f600..6a9c01e5bace4 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -452,6 +452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_sig.output(), fn_sig.inputs(), ); + // FIXME(callable_trait): make this work automatically with `check_callable` self.check_argument_types( call_expr.span, call_expr, @@ -758,6 +759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_sig.inputs(), ); + // FIXME(callable_trait): make this work just with `check_callable` self.check_argument_types( call_expr.span, call_expr, @@ -833,6 +835,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { debug!("attempt_resolution: method_callee={:?}", method_callee); + // FIXME(callable_trait): this argument check is now unnecessary for (method_arg_ty, self_arg_ty) in iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c2f45912df948..cd18403f9bc0a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -104,6 +104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = self.tcx.ty_error_misc(); let callee_ty = method.map_or(err, |method| self.tcx.mk_fn_def(method.def_id, method.substs)); + + // FIXME(callable_trait): make this work automatically with `check_callable` self.check_argument_types( sp, expr, @@ -126,6 +128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &method.sig.inputs()[1..], ); let callee_ty = self.tcx.mk_fn_def(method.def_id, method.substs); + + // FIXME(callable_trait): make this work automatically with `check_callable` self.check_argument_types( sp, expr, From 3080b86ff4e14381b6a5e27771976a417b6a3b9d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 28 Jun 2023 08:49:36 +0000 Subject: [PATCH 5/5] rustfmt --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index cd18403f9bc0a..e095f65f8753c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -104,7 +104,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = self.tcx.ty_error_misc(); let callee_ty = method.map_or(err, |method| self.tcx.mk_fn_def(method.def_id, method.substs)); - + // FIXME(callable_trait): make this work automatically with `check_callable` self.check_argument_types( sp,