diff options
Diffstat (limited to 'compiler')
10 files changed, 50 insertions, 20 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index f1674d04f8d..351c701305a 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -41,6 +41,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { }; if is_const { hir::Constness::Const } else { hir::Constness::NotConst } } + hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness, _ => { if let Some(fn_kind) = node.fn_kind() { if fn_kind.constness() == hir::Constness::Const { diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 443c01fdb90..46e7b09a55e 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -20,6 +20,7 @@ Rust MIR: a lowered representation of Rust. #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![feature(if_let_guard)] #![feature(is_some_and)] #![recursion_limit = "256"] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index fd166e3c938..38212496ec8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -783,6 +783,20 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); return; } + Ok(Some(ImplSource::Closure(data))) => { + if !tcx.is_const_fn_raw(data.closure_def_id) { + self.check_op(ops::FnCallNonConst { + caller, + callee, + substs, + span: *fn_span, + from_hir_call: *from_hir_call, + feature: None, + }); + + return; + } + } Ok(Some(ImplSource::UserDefined(data))) => { let callee_name = tcx.item_name(callee); if let Some(&did) = tcx diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index bdc4ae391f0..030328d1e26 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1686,6 +1686,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } ty::Closure(_, substs) => { + let constness = self.tcx.constness(def_id.to_def_id()); + self.tables.constness.set(def_id.to_def_id().index, constness); record!(self.tables.fn_sig[def_id.to_def_id()] <- substs.as_closure().sig()); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 883554f959c..4b09a9b6939 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -485,7 +485,7 @@ impl<'hir> Map<'hir> { BodyOwnerKind::Static(mt) => ConstContext::Static(mt), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None, - BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(def_id.to_def_id()) => { + BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id.to_def_id()) => { ConstContext::ConstFn } BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => { diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ec69864c951..1cc9fd526b4 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -131,7 +131,9 @@ pub enum SelectionCandidate<'tcx> { /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for an `||` expression. - ClosureCandidate, + ClosureCandidate { + is_const: bool, + }, /// Implementation of a `Generator` trait by one of the anonymous types /// generated for a generator. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fa571d480b6..993e95b3514 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2465,8 +2465,10 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn is_const_fn_raw(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) - && self.constness(def_id) == hir::Constness::Const + matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure + ) && self.constness(def_id) == hir::Constness::Const } #[inline] 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 c54d901e9b1..a5635ccfec4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -254,18 +254,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters match *obligation.self_ty().skip_binder().kind() { - ty::Closure(_, closure_substs) => { + ty::Closure(def_id, closure_substs) => { + let is_const = self.tcx().is_const_fn_raw(def_id); debug!(?kind, ?obligation, "assemble_unboxed_candidates"); match self.infcx.closure_kind(closure_substs) { Some(closure_kind) => { debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { - candidates.vec.push(ClosureCandidate); + candidates.vec.push(ClosureCandidate { + is_const, + }); } } None => { debug!("assemble_unboxed_candidates: closure_kind not yet known"); - candidates.vec.push(ClosureCandidate); + candidates.vec.push(ClosureCandidate { + is_const, + }); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 15526b34ed2..a41d10f1043 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -84,7 +84,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Object(data) } - ClosureCandidate => { + ClosureCandidate { .. } => { let vtable_closure = self.confirm_closure_candidate(obligation)?; ImplSource::Closure(vtable_closure) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3f14491f803..25a294b5401 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1365,15 +1365,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // const param ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {} // const projection - ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {} + ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) // auto trait impl - AutoImplCandidate => {} + | AutoImplCandidate // generator / future, this will raise error in other places // or ignore error with const_async_blocks feature - GeneratorCandidate => {} - FutureCandidate => {} + | GeneratorCandidate + | FutureCandidate // FnDef where the function is const - FnPointerCandidate { is_const: true } => {} + | FnPointerCandidate { is_const: true } + | ConstDestructCandidate(_) + | ClosureCandidate { is_const: true } => {} + FnPointerCandidate { is_const: false } => { if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() { // Trait methods are not seen as const unless the trait is implemented as const. @@ -1382,7 +1385,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { continue } } - ConstDestructCandidate(_) => {} + _ => { // reject all other types of candidates continue; @@ -1844,7 +1847,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ParamCandidate(ref cand), ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1863,7 +1866,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ( ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1894,7 +1897,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ObjectCandidate(_) | ProjectionCandidate(..), ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1907,7 +1910,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ( ImplCandidate(..) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1989,7 +1992,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Everything else is ambiguous ( ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } @@ -1999,7 +2002,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | BuiltinCandidate { has_nested: true } | TraitAliasCandidate, ImplCandidate(_) - | ClosureCandidate + | ClosureCandidate { .. } | GeneratorCandidate | FutureCandidate | FnPointerCandidate { .. } |
