mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Allow calling const closures in const items
This commit is contained in:
@@ -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:?}"),
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -2118,11 +2118,7 @@ pub fn is_conditionally_const(self, def_id: impl Into<DefId>) -> 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
|
||||
|
||||
@@ -661,10 +661,11 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
|
||||
///
|
||||
/// 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<I: Interner>(
|
||||
cx: I,
|
||||
self_ty: I::Ty,
|
||||
) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, I::FunctionId, I::GenericArgs), NoSolution> {
|
||||
) -> Result<(ty::Binder<I, (I::Ty, I::Ty)>, 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<I: Interner>(
|
||||
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<I: Interner>(
|
||||
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(..) => {
|
||||
|
||||
@@ -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<I, Self>,
|
||||
@@ -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| {
|
||||
(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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`.
|
||||
Reference in New Issue
Block a user