diff options
| author | bors <bors@rust-lang.org> | 2022-12-30 01:09:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-12-30 01:09:31 +0000 |
| commit | 973a4db8d590d1ddfa4d07bd216aeffd28ba354e (patch) | |
| tree | 4ad2aa5b9738da23077665fb818fa462630e8003 /compiler/rustc_trait_selection/src | |
| parent | 2c7536eaae59b44ff5259183ca98384129d69dd0 (diff) | |
| parent | 983606d3676c967e79a94b74b890bfb02367b608 (diff) | |
| download | rust-973a4db8d590d1ddfa4d07bd216aeffd28ba354e.tar.gz rust-973a4db8d590d1ddfa4d07bd216aeffd28ba354e.zip | |
Auto merge of #106210 - fee1-dead-contrib:const-closure-trait-method, r=compiler-errors
Allow trait method paths to satisfy const Fn bounds r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/confirmation.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 8 |
2 files changed, 27 insertions, 7 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f6fe71fbd4f..466641ea6df 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -12,8 +12,8 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::{ - self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, - ToPolyTraitRef, ToPredicate, Ty, TyCtxt, + self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, + ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, }; use rustc_span::def_id::DefId; @@ -98,8 +98,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Future(vtable_future) } - FnPointerCandidate { .. } => { - let data = self.confirm_fn_pointer_candidate(obligation)?; + FnPointerCandidate { is_const } => { + let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; ImplSource::FnPointer(data) } @@ -597,17 +597,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_fn_pointer_candidate( &mut self, obligation: &TraitObligation<'tcx>, + is_const: bool, ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); + let tcx = self.tcx(); let self_ty = self .infcx .shallow_resolve(obligation.self_ty().no_bound_vars()) .expect("fn pointer should not capture bound vars from predicate"); - let sig = self_ty.fn_sig(self.tcx()); + let sig = self_ty.fn_sig(tcx); let trait_ref = closure_trait_ref_and_return_type( - self.tcx(), + tcx, obligation.predicate.def_id(), self_ty, sig, @@ -616,9 +618,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_bound(|(trait_ref, _)| trait_ref); let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let cause = obligation.derived_cause(BuiltinDerivedObligation); + + if obligation.is_const() && !is_const { + // function is a trait method + if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) { + let trait_ref = TraitRef::from_method(tcx, trait_id, *substs); + let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst); + let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred); + nested.push(obligation); + } + } // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let cause = obligation.derived_cause(BuiltinDerivedObligation); let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output()); let output_ty = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 81e8f9e914c..760b4585f4e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1374,6 +1374,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { FutureCandidate => {} // FnDef where the function is const FnPointerCandidate { 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. + // We do not filter that out in here, but nested obligations will be needed to confirm this. + } else { + continue + } + } ConstDestructCandidate(_) => {} _ => { // reject all other types of candidates |
