diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index e16fa5492979..98999232a743 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1069,6 +1069,9 @@ pub(super) fn const_conditions<'tcx>( }, // N.B. Tuple ctors are unconditionally constant. Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(), + Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_), .. }) => { + (hir::Generics::empty(), None, tcx.is_conditionally_const(tcx.local_parent(def_id))) + } _ => bug!("const_conditions called on wrong item: {def_id:?}"), }; diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index e59573976af5..5179a77d6cb6 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -402,6 +402,11 @@ fn fn_is_const(self, def_id: DefId) -> bool { self.is_conditionally_const(def_id) } + fn closure_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::Closure); + self.constness(def_id) == hir::Constness::Const + } + fn alias_has_const_conditions(self, def_id: DefId) -> bool { debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); self.is_conditionally_const(def_id) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6abe7d146699..01c351de9319 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2118,11 +2118,7 @@ pub fn is_conditionally_const(self, def_id: impl Into) -> bool { // FIXME(const_trait_impl): ATPITs could be conditionally const? hir::OpaqueTyOrigin::TyAlias { .. } => false, }, - DefKind::Closure => { - // Closures and RPITs will eventually have const conditions - // for `[const]` bounds. - false - } + DefKind::Closure => self.constness(def_id) == hir::Constness::Const, DefKind::Ctor(_, CtorKind::Const) | DefKind::Mod | DefKind::Struct diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 05ea217c1de0..cd74e87b670f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -661,10 +661,11 @@ fn coroutine_closure_to_ambiguous_coroutine( /// /// Doing so on all calls to `extract_tupled_inputs_and_output_from_callable` /// would be wasteful. +#[instrument(level = "trace", skip(cx), ret)] pub(in crate::solve) fn extract_fn_def_from_const_callable( cx: I, self_ty: I::Ty, -) -> Result<(ty::Binder, I::FunctionId, I::GenericArgs), NoSolution> { +) -> Result<(ty::Binder, I::DefId, I::GenericArgs), NoSolution> { match self_ty.kind() { ty::FnDef(def_id, args) => { let sig = cx.fn_sig(def_id); @@ -675,7 +676,7 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( Ok(( sig.instantiate(cx, args) .map_bound(|sig| (Ty::new_tup(cx, sig.inputs().as_slice()), sig.output())), - def_id, + def_id.into(), args, )) } else { @@ -686,9 +687,19 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( ty::FnPtr(..) => { return Err(NoSolution); } - // `Closure`s are not const for now. - ty::Closure(..) => { - return Err(NoSolution); + ty::Closure(def, args) => { + if cx.closure_is_const(def) { + let closure_args = args.as_closure(); + Ok(( + closure_args + .sig() + .map_bound(|sig| (sig.inputs().get(0).unwrap(), sig.output())), + def.into(), + args, + )) + } else { + return Err(NoSolution); + } } // `CoroutineClosure`s are not const for now. ty::CoroutineClosure(..) => { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 4da76b88b5de..4b1e4b2de571 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -272,6 +272,7 @@ fn consider_builtin_fn_ptr_trait_candidate( todo!("Fn* are not yet const") } + #[instrument(level = "trace", skip_all, ret)] fn consider_builtin_fn_trait_candidates( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -289,7 +290,7 @@ fn consider_builtin_fn_trait_candidates( let output_is_sized_pred = ty::TraitRef::new(cx, cx.require_trait_lang_item(SolverTraitLangItem::Sized), [output]); let requirements = cx - .const_conditions(def_id.into()) + .const_conditions(def_id) .iter_instantiated(cx, args) .map(|trait_ref| { ( diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index e77e7af071b9..25f7c36e9985 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -308,6 +308,7 @@ fn impl_super_outlives( fn impl_is_const(self, def_id: Self::ImplId) -> bool; fn fn_is_const(self, def_id: Self::FunctionId) -> bool; + fn closure_is_const(self, def_id: Self::ClosureId) -> bool; fn alias_has_const_conditions(self, def_id: Self::DefId) -> bool; fn const_conditions( self, diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index e93ea4ccbd70..41883f648513 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -1,11 +1,10 @@ -// FIXME(const_trait_impl) check-pass +//@ check-pass //@ compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl)] #![allow(incomplete_features)] const _: () = { assert!((const || true)()); - //~^ ERROR }: const Fn()` is not satisfied }; fn main() {} diff --git a/tests/ui/traits/const-traits/call.stderr b/tests/ui/traits/const-traits/call.stderr deleted file mode 100644 index 3503938327a9..000000000000 --- a/tests/ui/traits/const-traits/call.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0277]: the trait bound `{closure@$DIR/call.rs:7:14: 7:22}: const Fn()` is not satisfied - --> $DIR/call.rs:7:13 - | -LL | assert!((const || true)()); - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`.