From 93298ee0dd938c0fece0ee5dbafe851e54dd6386 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Nov 2023 04:02:46 +0000 Subject: [PATCH 1/2] Remove ClosureKind predicate kind --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 - compiler/rustc_infer/src/traits/util.rs | 3 -- compiler/rustc_middle/src/ty/flags.rs | 3 -- compiler/rustc_middle/src/ty/mod.rs | 4 -- compiler/rustc_middle/src/ty/print/pretty.rs | 5 -- compiler/rustc_smir/src/rustc_smir/mod.rs | 7 --- .../src/solve/eval_ctxt/mod.rs | 2 - .../src/solve/fulfill.rs | 1 - .../src/traits/auto_trait.rs | 1 - .../error_reporting/type_err_ctxt_ext.rs | 5 -- .../src/traits/fulfill.rs | 14 ----- .../query/type_op/implied_outlives_bounds.rs | 1 - .../src/traits/select/candidate_assembly.rs | 7 ++- .../src/traits/select/confirmation.rs | 12 +---- .../src/traits/select/mod.rs | 13 ----- .../src/normalize_erasing_regions.rs | 1 - compiler/rustc_type_ir/src/predicate_kind.rs | 24 --------- compiler/stable_mir/src/ty.rs | 1 - .../closure_context/issue-26046-fn-mut.stderr | 16 +++--- .../issue-26046-fn-once.stderr | 16 +++--- .../closure-origin-array-diagnostics.stderr | 16 +++--- .../closure-origin-tuple-diagnostics.stderr | 16 +++--- tests/ui/closures/closure-wrong-kind.stderr | 14 +++-- tests/ui/issues/issue-34349.stderr | 16 +++--- .../move-ref-patterns-closure-captures.stderr | 53 ++++++++----------- ...-infer-fn-once-move-from-projection.stderr | 15 +++--- 26 files changed, 76 insertions(+), 191 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 750ed2c34913f..91540e0c284a1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -662,7 +662,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this closure yet; this is exactly why the other // code is looking for a self type of an unresolved // inference variable. - | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Ambiguous => None, }, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ed3409149d094..1bcae736fd952 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -308,9 +308,6 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { // Nothing to elaborate in a projection predicate. } - ty::PredicateKind::ClosureKind(..) => { - // Nothing to elaborate when waiting for a closure's kind to be inferred. - } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { // Currently, we do not elaborate const-evaluatable // predicates. diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 4d7b12662c663..cd9b429ec56c7 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -263,9 +263,6 @@ impl FlagComputation { self.add_args(slice::from_ref(&arg)); } ty::PredicateKind::ObjectSafe(_def_id) => {} - ty::PredicateKind::ClosureKind(_def_id, args, _kind) => { - self.add_args(args); - } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { self.add_const(uv); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2436daf62cf2b..bab79bfcae9f9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -548,7 +548,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) - | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) @@ -1276,7 +1275,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1296,7 +1294,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1317,7 +1314,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous => None, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d478677c36793..bbbd3347361e7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2781,11 +2781,6 @@ define_print! { ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } - ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!( - "the closure `", - print_value_path(closure_def_id, &[]), - write("` implements the trait `{}`", kind) - ), ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 167a01ab7990c..9ad4f9800b4e6 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1699,13 +1699,6 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { PredicateKind::ObjectSafe(did) => { stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did)) } - PredicateKind::ClosureKind(did, generic_args, closure_kind) => { - stable_mir::ty::PredicateKind::ClosureKind( - tables.closure_def(*did), - generic_args.stable(tables), - closure_kind.stable(tables), - ) - } PredicateKind::Subtype(subtype_predicate) => { stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables)) } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 23ce0a301ce70..ded7874b62a5a 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -406,8 +406,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::Coerce(predicate) => { self.compute_coerce_goal(Goal { param_env, predicate }) } - ty::PredicateKind::ClosureKind(def_id, args, kind) => self - .compute_closure_kind_goal(Goal { param_env, predicate: (def_id, args, kind) }), ty::PredicateKind::ObjectSafe(trait_def_id) => { self.compute_object_safe_goal(trait_def_id) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f1d3091225c0f..b73ec93b82487 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -135,7 +135,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { } ty::PredicateKind::Clause(_) | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Ambiguous => { FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index dbf6749b52378..867b1c913ef35 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -822,7 +822,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) // FIXME(generic_const_exprs): you can absolutely add this as a where clauses | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 5239725f5096a..5f642ca9a792f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -786,11 +786,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { report_object_safety_error(self.tcx, span, trait_def_id, violations) } - ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { - let found_kind = self.closure_kind(closure_args).unwrap(); - self.report_closure_error(&obligation, closure_def_id, found_kind, kind) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty)) => { let ty = self.resolve_vars_if_possible(ty); match self.tcx.sess.opts.unstable_opts.trait_solver { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index fb9cf51b513bb..08544b4a93a9f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -350,7 +350,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) @@ -411,19 +410,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } - ty::PredicateKind::ClosureKind(_, closure_args, kind) => { - match self.selcx.infcx.closure_kind(closure_args) { - Some(closure_kind) => { - if closure_kind.extends(kind) { - ProcessResult::Changed(vec![]) - } else { - ProcessResult::Error(CodeSelectionError(Unimplemented)) - } - } - None => ProcessResult::Unchanged, - } - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { match wf::obligations( self.selcx.infcx, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 57df277f4b3a2..94d6b15fe437e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -130,7 +130,6 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) - | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) 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 1529f736109a3..a0ed773b62ca3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -291,8 +291,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } None => { - debug!("assemble_unboxed_candidates: closure_kind not yet known"); - candidates.vec.push(ClosureCandidate { is_const }); + if kind == ty::ClosureKind::FnOnce { + candidates.vec.push(ClosureCandidate { is_const }); + } else { + candidates.ambiguous = true; + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2ab3ecbd5a3ee..6cb76addd7d4d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -821,11 +821,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, SelectionError<'tcx>> { - let kind = self - .tcx() - .fn_trait_kind_from_def_id(obligation.predicate.def_id()) - .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); - // Okay to skip binder because the args on closure types never // touch bound regions, they just capture the in-scope // type/region parameters. @@ -835,15 +830,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let trait_ref = self.closure_trait_ref_unnormalized(obligation, args); - let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); - nested.push(obligation.with( - self.tcx(), - ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)), - )); - Ok(nested) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1ed0da59b64f0..4bef362665502 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -885,19 +885,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::PredicateKind::ClosureKind(_, closure_args, kind) => { - match self.infcx.closure_kind(closure_args) { - Some(closure_kind) => { - if closure_kind.extends(kind) { - Ok(EvaluatedToOk) - } else { - Ok(EvaluatedToErr) - } - } - None => Ok(EvaluatedToAmbig), - } - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { match const_evaluatable::is_const_evaluatable( self.infcx, diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index cb2a36cb998bd..06486a100a9a0 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -58,7 +58,6 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index da041ab1f355f..f6a2dca4eee33 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -129,11 +129,6 @@ pub enum PredicateKind { /// Trait must be object-safe. ObjectSafe(I::DefId), - /// No direct syntax. May be thought of as `where T: FnFoo<...>` - /// for some generic args `...` and `T` being a closure type. - /// Satisfied (or refuted) once we know the closure's kind. - ClosureKind(I::DefId, I::GenericArgs, I::ClosureKind), - /// `T1 <: T2` /// /// This obligation is created most often when we have two @@ -173,7 +168,6 @@ where I::Term: Copy, I::CoercePredicate: Copy, I::SubtypePredicate: Copy, - I::ClosureKind: Copy, ClauseKind: Copy, { } @@ -183,9 +177,6 @@ impl PartialEq for PredicateKind { match (self, other) { (Self::Clause(l0), Self::Clause(r0)) => l0 == r0, (Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0, - (Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => { - l0 == r0 && l1 == r1 && l2 == r2 - } (Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0, (Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0, (Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1, @@ -207,18 +198,12 @@ where I::Term: TypeFoldable, I::CoercePredicate: TypeFoldable, I::SubtypePredicate: TypeFoldable, - I::ClosureKind: TypeFoldable, ClauseKind: TypeFoldable, { fn try_fold_with>(self, folder: &mut F) -> Result { Ok(match self { PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?), PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?), - PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind( - d.try_fold_with(folder)?, - g.try_fold_with(folder)?, - k.try_fold_with(folder)?, - ), PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?), PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?), PredicateKind::ConstEquate(a, b) => { @@ -242,18 +227,12 @@ where I::Term: TypeVisitable, I::CoercePredicate: TypeVisitable, I::SubtypePredicate: TypeVisitable, - I::ClosureKind: TypeVisitable, ClauseKind: TypeVisitable, { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { match self { PredicateKind::Clause(p) => p.visit_with(visitor), PredicateKind::ObjectSafe(d) => d.visit_with(visitor), - PredicateKind::ClosureKind(d, g, k) => { - d.visit_with(visitor)?; - g.visit_with(visitor)?; - k.visit_with(visitor) - } PredicateKind::Subtype(s) => s.visit_with(visitor), PredicateKind::Coerce(s) => s.visit_with(visitor), PredicateKind::ConstEquate(a, b) => { @@ -313,9 +292,6 @@ impl fmt::Debug for PredicateKind { PredicateKind::ObjectSafe(trait_def_id) => { write!(f, "ObjectSafe({trait_def_id:?})") } - PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => { - write!(f, "ClosureKind({closure_def_id:?}, {closure_args:?}, {kind:?})") - } PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"), PredicateKind::Ambiguous => write!(f, "Ambiguous"), PredicateKind::AliasRelate(t1, t2, dir) => { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index f0b11dce9aac6..ae48fff78996d 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -766,7 +766,6 @@ pub struct GenericPredicates { pub enum PredicateKind { Clause(ClauseKind), ObjectSafe(TraitDef), - ClosureKind(ClosureDef, GenericArgs, ClosureKind), SubType(SubtypePredicate), Coerce(CoercePredicate), ConstEquate(Const, Const), diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr index eeb4094524243..5f0b6fd451c41 100644 --- a/tests/ui/closure_context/issue-26046-fn-mut.stderr +++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr @@ -1,16 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` - --> $DIR/issue-26046-fn-mut.rs:4:19 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` + --> $DIR/issue-26046-fn-mut.rs:8:5 | -LL | let closure = || { - | ^^ this closure implements `FnMut`, not `Fn` -LL | num += 1; - | --- closure is `FnMut` because it mutates the variable `num` here -... LL | Box::new(closure) - | ----------------- the requirement to implement `Fn` derives from here + | ^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` + = note: wrap the `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` implements `FnMut`, but it must implement `Fn`, which is more general = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}>` to `Box<(dyn Fn() + 'static)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr index 24773a1d7e351..da3dcf3e3af83 100644 --- a/tests/ui/closure_context/issue-26046-fn-once.stderr +++ b/tests/ui/closure_context/issue-26046-fn-once.stderr @@ -1,16 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/issue-26046-fn-once.rs:4:19 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` + --> $DIR/issue-26046-fn-once.rs:8:5 | -LL | let closure = move || { - | ^^^^^^^ this closure implements `FnOnce`, not `Fn` -LL | vec - | --- closure is `FnOnce` because it moves the variable `vec` out of its environment -... LL | Box::new(closure) - | ----------------- the requirement to implement `Fn` derives from here + | ^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` + = note: wrap the `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` implements `FnOnce`, but it must implement `Fn`, which is more general = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}>` to `Box<(dyn Fn() -> Vec + 'static)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr index 309c63e52932b..189f08c12e9cf 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -1,16 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-array-diagnostics.rs:9:13 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` + --> $DIR/closure-origin-array-diagnostics.rs:12:15 | -LL | let c = || { - | ^^ this closure implements `FnOnce`, not `Fn` -LL | let [_, _s] = s; - | - closure is `FnOnce` because it moves the variable `s` out of its environment -LL | }; LL | expect_fn(c); - | --------- - the requirement to implement `Fn` derives from here + | --------- ^ expected an `Fn()` closure, found `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` + = note: wrap the `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `expect_fn` --> $DIR/closure-origin-array-diagnostics.rs:5:17 | @@ -19,4 +17,4 @@ LL | fn expect_fn(_f: F) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr index 3e77635f9e0c8..75c49d312a581 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -1,16 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` + --> $DIR/closure-origin-tuple-diagnostics.rs:12:15 | -LL | let c = || { - | ^^ this closure implements `FnOnce`, not `Fn` -LL | let s = s.1; - | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment -LL | }; LL | expect_fn(c); - | --------- - the requirement to implement `Fn` derives from here + | --------- ^ expected an `Fn()` closure, found `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` + = note: wrap the `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `expect_fn` --> $DIR/closure-origin-tuple-diagnostics.rs:5:17 | @@ -19,4 +17,4 @@ LL | fn expect_fn(_f: F) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/closure-wrong-kind.stderr b/tests/ui/closures/closure-wrong-kind.stderr index 9ea55d764f345..c1c8301443841 100644 --- a/tests/ui/closures/closure-wrong-kind.stderr +++ b/tests/ui/closures/closure-wrong-kind.stderr @@ -1,15 +1,13 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/closure-wrong-kind.rs:10:19 +error[E0277]: expected a `Fn(u32)` closure, found `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` + --> $DIR/closure-wrong-kind.rs:11:9 | -LL | let closure = |_| foo(x); - | ^^^ - closure is `FnOnce` because it moves the variable `x` out of its environment - | | - | this closure implements `FnOnce`, not `Fn` LL | bar(closure); - | --- ------- the requirement to implement `Fn` derives from here + | --- ^^^^^^^ expected an `Fn(u32)` closure, found `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` | | | required by a bound introduced by this call | + = help: the trait `Fn<(u32,)>` is not implemented for closure `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` + = note: `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `bar` --> $DIR/closure-wrong-kind.rs:6:11 | @@ -18,4 +16,4 @@ LL | fn bar(_: T) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-34349.stderr b/tests/ui/issues/issue-34349.stderr index 8e9a16619f3b1..1235f44f4aa61 100644 --- a/tests/ui/issues/issue-34349.stderr +++ b/tests/ui/issues/issue-34349.stderr @@ -1,16 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` - --> $DIR/issue-34349.rs:16:17 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-34349.rs:16:17: 16:19}` + --> $DIR/issue-34349.rs:21:11 | -LL | let diary = || { - | ^^ this closure implements `FnMut`, not `Fn` -LL | farewell.push_str("!!!"); - | -------- closure is `FnMut` because it mutates the variable `farewell` here -... LL | apply(diary); - | ----- ----- the requirement to implement `Fn` derives from here + | ----- ^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-34349.rs:16:17: 16:19}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-34349.rs:16:17: 16:19}` + = note: wrap the `{closure@$DIR/issue-34349.rs:16:17: 16:19}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/issue-34349.rs:16:17: 16:19}` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `apply` --> $DIR/issue-34349.rs:11:32 | @@ -19,4 +17,4 @@ LL | fn apply(f: F) where F: Fn() { error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr index eba65a61803d0..9a8c8123fbaf8 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr @@ -1,57 +1,48 @@ -error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` - --> $DIR/move-ref-patterns-closure-captures.rs:9:14 - | -LL | let c1 = || { - | ^^ this closure implements `FnOnce`, not `FnMut` -... -LL | drop::(_x1); - | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment -... +error[E0277]: expected a `FnMut()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + --> $DIR/move-ref-patterns-closure-captures.rs:17:19 + | LL | accept_fn_mut(&c1); - | ------------- --- the requirement to implement `FnMut` derives from here + | ------------- ^^^ expected an `FnMut()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` | | | required by a bound introduced by this call | + = help: the trait `FnMut<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` implements `FnOnce`, but it must implement `FnMut`, which is more general note: required by a bound in `accept_fn_mut` --> $DIR/move-ref-patterns-closure-captures.rs:4:31 | LL | fn accept_fn_mut(_: &impl FnMut()) {} | ^^^^^^^ required by this bound in `accept_fn_mut` -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/move-ref-patterns-closure-captures.rs:9:14 - | -LL | let c1 = || { - | ^^ this closure implements `FnOnce`, not `Fn` -... -LL | drop::(_x1); - | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment -... +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + --> $DIR/move-ref-patterns-closure-captures.rs:18:15 + | LL | accept_fn(&c1); - | --------- --- the requirement to implement `Fn` derives from here + | --------- ^^^ expected an `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `accept_fn` --> $DIR/move-ref-patterns-closure-captures.rs:5:27 | LL | fn accept_fn(_: &impl Fn()) {} | ^^^^ required by this bound in `accept_fn` -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` - --> $DIR/move-ref-patterns-closure-captures.rs:20:14 - | -LL | let c2 = || { - | ^^ this closure implements `FnMut`, not `Fn` -... -LL | drop::<&mut U>(_x2); - | --- closure is `FnMut` because it mutates the variable `_x2` here -... +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` + --> $DIR/move-ref-patterns-closure-captures.rs:26:15 + | LL | accept_fn(&c2); - | --------- --- the requirement to implement `Fn` derives from here + | --------- ^^^ expected an `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` + = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `accept_fn` --> $DIR/move-ref-patterns-closure-captures.rs:5:27 | @@ -60,4 +51,4 @@ LL | fn accept_fn(_: &impl Fn()) {} error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index 846a44ce4d7a9..8a06d2f66bf18 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -1,15 +1,14 @@ -error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` - --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13 +error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` + --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:15:9 | -LL | let c = || drop(y.0); - | ^^ --- closure is `FnOnce` because it moves the variable `y` out of its environment - | | - | this closure implements `FnOnce`, not `Fn` LL | foo(c); - | --- - the requirement to implement `Fn` derives from here + | --- ^ expected an `Fn()` closure, found `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` | | | required by a bound introduced by this call | + = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` + = note: wrap the `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` in a closure with no arguments: `|| { /* code */ }` + = note: `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `foo` --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14 | @@ -20,4 +19,4 @@ LL | where F: Fn() error: aborting due to previous error -For more information about this error, try `rustc --explain E0525`. +For more information about this error, try `rustc --explain E0277`. From 128feaa2b40d063a834030d3ff9410c9327c5286 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Nov 2023 04:20:18 +0000 Subject: [PATCH 2/2] Restore closure-kind error messages --- compiler/rustc_infer/src/infer/mod.rs | 6 ++- .../error_reporting/type_err_ctxt_ext.rs | 44 ++++++++++++++- .../closure_context/issue-26046-fn-mut.stderr | 16 +++--- .../issue-26046-fn-once.stderr | 16 +++--- .../closure-origin-array-diagnostics.stderr | 16 +++--- .../closure-origin-tuple-diagnostics.stderr | 16 +++--- tests/ui/closures/closure-wrong-kind.stderr | 14 ++--- tests/ui/issues/issue-34349.stderr | 16 +++--- .../move-ref-patterns-closure-captures.stderr | 53 +++++++++++-------- ...-infer-fn-once-move-from-projection.stderr | 15 +++--- 10 files changed, 139 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 956d097a5b2e2..d6c7a24476f9e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -906,12 +906,14 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) } - pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool + pub fn can_sub(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool where T: at::ToTrace<'tcx>, { let origin = &ObligationCause::dummy(); - self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok()) + self.probe(|_| { + self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok() + }) } pub fn can_eq(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 5f642ca9a792f..fa24b2a40555c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -98,6 +98,12 @@ pub trait TypeErrCtxtExt<'tcx> { error: &SelectionError<'tcx>, ); + fn emit_specialized_closure_kind_error( + &self, + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Option; + fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool; fn report_const_param_not_wf( @@ -411,6 +417,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let trait_ref = trait_predicate.to_poly_trait_ref(); + + if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { + return; + } // FIXME(effects) let predicate_is_const = false; @@ -425,7 +436,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // reported on the binding definition (#56607). return; } - let trait_ref = trait_predicate.to_poly_trait_ref(); let (post_message, pre_message, type_def, file_note) = self .get_parent_trait_ref(obligation.cause.code()) .map(|(t, s)| { @@ -922,6 +932,38 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.emit(); } + fn emit_specialized_closure_kind_error( + &self, + obligation: &PredicateObligation<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Option { + if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind() + && let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) + && let Some(found_kind) = self.closure_kind(closure_args) + && !found_kind.extends(expected_kind) + && let sig = closure_args.as_closure().sig() + && self.can_sub( + obligation.param_env, + trait_ref, + sig.map_bound(|sig| { + ty::TraitRef::new( + self.tcx, + trait_ref.def_id(), + [trait_ref.self_ty().skip_binder(), sig.inputs()[0]], + ) + }), + ) + { + let mut err = + self.report_closure_error(&obligation, closure_def_id, found_kind, expected_kind); + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + Some(err.emit()) + } else { + None + } + } + fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool { if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() diff --git a/tests/ui/closure_context/issue-26046-fn-mut.stderr b/tests/ui/closure_context/issue-26046-fn-mut.stderr index 5f0b6fd451c41..eeb4094524243 100644 --- a/tests/ui/closure_context/issue-26046-fn-mut.stderr +++ b/tests/ui/closure_context/issue-26046-fn-mut.stderr @@ -1,14 +1,16 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` - --> $DIR/issue-26046-fn-mut.rs:8:5 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-26046-fn-mut.rs:4:19 | +LL | let closure = || { + | ^^ this closure implements `FnMut`, not `Fn` +LL | num += 1; + | --- closure is `FnMut` because it mutates the variable `num` here +... LL | Box::new(closure) - | ^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` + | ----------------- the requirement to implement `Fn` derives from here | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` - = note: wrap the `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}` implements `FnMut`, but it must implement `Fn`, which is more general = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21}>` to `Box<(dyn Fn() + 'static)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closure_context/issue-26046-fn-once.stderr b/tests/ui/closure_context/issue-26046-fn-once.stderr index da3dcf3e3af83..24773a1d7e351 100644 --- a/tests/ui/closure_context/issue-26046-fn-once.stderr +++ b/tests/ui/closure_context/issue-26046-fn-once.stderr @@ -1,14 +1,16 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` - --> $DIR/issue-26046-fn-once.rs:8:5 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/issue-26046-fn-once.rs:4:19 | +LL | let closure = move || { + | ^^^^^^^ this closure implements `FnOnce`, not `Fn` +LL | vec + | --- closure is `FnOnce` because it moves the variable `vec` out of its environment +... LL | Box::new(closure) - | ^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` + | ----------------- the requirement to implement `Fn` derives from here | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` - = note: wrap the `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}` implements `FnOnce`, but it must implement `Fn`, which is more general = note: required for the cast from `Box<{closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26}>` to `Box<(dyn Fn() -> Vec + 'static)>` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr index 189f08c12e9cf..309c63e52932b 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr @@ -1,14 +1,16 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` - --> $DIR/closure-origin-array-diagnostics.rs:12:15 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-array-diagnostics.rs:9:13 | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let [_, _s] = s; + | - closure is `FnOnce` because it moves the variable `s` out of its environment +LL | }; LL | expect_fn(c); - | --------- ^ expected an `Fn()` closure, found `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` + | --------- - the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` - = note: wrap the `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/closure-origin-array-diagnostics.rs:9:13: 9:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `expect_fn` --> $DIR/closure-origin-array-diagnostics.rs:5:17 | @@ -17,4 +19,4 @@ LL | fn expect_fn(_f: F) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr index 75c49d312a581..3e77635f9e0c8 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr @@ -1,14 +1,16 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` - --> $DIR/closure-origin-tuple-diagnostics.rs:12:15 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-origin-tuple-diagnostics.rs:9:13 | +LL | let c = || { + | ^^ this closure implements `FnOnce`, not `Fn` +LL | let s = s.1; + | --- closure is `FnOnce` because it moves the variable `s.1` out of its environment +LL | }; LL | expect_fn(c); - | --------- ^ expected an `Fn()` closure, found `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` + | --------- - the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` - = note: wrap the `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/closure-origin-tuple-diagnostics.rs:9:13: 9:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `expect_fn` --> $DIR/closure-origin-tuple-diagnostics.rs:5:17 | @@ -17,4 +19,4 @@ LL | fn expect_fn(_f: F) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/closure-wrong-kind.stderr b/tests/ui/closures/closure-wrong-kind.stderr index c1c8301443841..9ea55d764f345 100644 --- a/tests/ui/closures/closure-wrong-kind.stderr +++ b/tests/ui/closures/closure-wrong-kind.stderr @@ -1,13 +1,15 @@ -error[E0277]: expected a `Fn(u32)` closure, found `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` - --> $DIR/closure-wrong-kind.rs:11:9 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/closure-wrong-kind.rs:10:19 | +LL | let closure = |_| foo(x); + | ^^^ - closure is `FnOnce` because it moves the variable `x` out of its environment + | | + | this closure implements `FnOnce`, not `Fn` LL | bar(closure); - | --- ^^^^^^^ expected an `Fn(u32)` closure, found `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` + | --- ------- the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<(u32,)>` is not implemented for closure `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` - = note: `{closure@$DIR/closure-wrong-kind.rs:10:19: 10:22}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `bar` --> $DIR/closure-wrong-kind.rs:6:11 | @@ -16,4 +18,4 @@ LL | fn bar(_: T) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/issues/issue-34349.stderr b/tests/ui/issues/issue-34349.stderr index 1235f44f4aa61..8e9a16619f3b1 100644 --- a/tests/ui/issues/issue-34349.stderr +++ b/tests/ui/issues/issue-34349.stderr @@ -1,14 +1,16 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/issue-34349.rs:16:17: 16:19}` - --> $DIR/issue-34349.rs:21:11 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/issue-34349.rs:16:17 | +LL | let diary = || { + | ^^ this closure implements `FnMut`, not `Fn` +LL | farewell.push_str("!!!"); + | -------- closure is `FnMut` because it mutates the variable `farewell` here +... LL | apply(diary); - | ----- ^^^^^ expected an `Fn()` closure, found `{closure@$DIR/issue-34349.rs:16:17: 16:19}` + | ----- ----- the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/issue-34349.rs:16:17: 16:19}` - = note: wrap the `{closure@$DIR/issue-34349.rs:16:17: 16:19}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/issue-34349.rs:16:17: 16:19}` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `apply` --> $DIR/issue-34349.rs:11:32 | @@ -17,4 +19,4 @@ LL | fn apply(f: F) where F: Fn() { error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr index 9a8c8123fbaf8..eba65a61803d0 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr @@ -1,48 +1,57 @@ -error[E0277]: expected a `FnMut()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` - --> $DIR/move-ref-patterns-closure-captures.rs:17:19 - | +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:9:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `FnMut` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... LL | accept_fn_mut(&c1); - | ------------- ^^^ expected an `FnMut()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + | ------------- --- the requirement to implement `FnMut` derives from here | | | required by a bound introduced by this call | - = help: the trait `FnMut<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` - = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` implements `FnOnce`, but it must implement `FnMut`, which is more general note: required by a bound in `accept_fn_mut` --> $DIR/move-ref-patterns-closure-captures.rs:4:31 | LL | fn accept_fn_mut(_: &impl FnMut()) {} | ^^^^^^^ required by this bound in `accept_fn_mut` -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` - --> $DIR/move-ref-patterns-closure-captures.rs:18:15 - | +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:9:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `Fn` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... LL | accept_fn(&c1); - | --------- ^^^ expected an `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` + | --------- --- the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` - = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:9:14: 9:16}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `accept_fn` --> $DIR/move-ref-patterns-closure-captures.rs:5:27 | LL | fn accept_fn(_: &impl Fn()) {} | ^^^^ required by this bound in `accept_fn` -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` - --> $DIR/move-ref-patterns-closure-captures.rs:26:15 - | +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/move-ref-patterns-closure-captures.rs:20:14 + | +LL | let c2 = || { + | ^^ this closure implements `FnMut`, not `Fn` +... +LL | drop::<&mut U>(_x2); + | --- closure is `FnMut` because it mutates the variable `_x2` here +... LL | accept_fn(&c2); - | --------- ^^^ expected an `Fn()` closure, found `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` + | --------- --- the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` - = note: wrap the `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/move-ref-patterns-closure-captures.rs:20:14: 20:16}` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `accept_fn` --> $DIR/move-ref-patterns-closure-captures.rs:5:27 | @@ -51,4 +60,4 @@ LL | fn accept_fn(_: &impl Fn()) {} error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index 8a06d2f66bf18..846a44ce4d7a9 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -1,14 +1,15 @@ -error[E0277]: expected a `Fn()` closure, found `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` - --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:15:9 +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13 | +LL | let c = || drop(y.0); + | ^^ --- closure is `FnOnce` because it moves the variable `y` out of its environment + | | + | this closure implements `FnOnce`, not `Fn` LL | foo(c); - | --- ^ expected an `Fn()` closure, found `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` + | --- - the requirement to implement `Fn` derives from here | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for closure `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` - = note: wrap the `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` in a closure with no arguments: `|| { /* code */ }` - = note: `{closure@$DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13: 14:15}` implements `FnOnce`, but it must implement `Fn`, which is more general note: required by a bound in `foo` --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14 | @@ -19,4 +20,4 @@ LL | where F: Fn() error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`.