diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_typeck/messages.ftl | 7 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/callee.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/errors.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/upvar.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/effects.rs | 51 |
5 files changed, 55 insertions, 50 deletions
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index c21b16c9f9f..bac4d70103c 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -82,13 +82,6 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to -> hir_typeck_const_continue_bad_label = `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` -hir_typeck_const_select_must_be_const = this argument must be a `const fn` - .help = consult the documentation on `const_eval_select` for more information - -hir_typeck_const_select_must_be_fn = this argument must be a function item - .note = expected a function item, found {$ty} - .help = consult the documentation on `const_eval_select` for more information - hir_typeck_continue_labeled_block = `continue` pointing to a labeled block .label = labeled blocks cannot be `continue`'d diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 7611f8ac3e1..48bb45de53e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -578,29 +578,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let Some(def_id) = def_id - && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn - && self.tcx.is_intrinsic(def_id, sym::const_eval_select) - { - let fn_sig = self.resolve_vars_if_possible(fn_sig); - for idx in 0..=1 { - let arg_ty = fn_sig.inputs()[idx + 1]; - let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span); - // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that - // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed - // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here. - // - // This check is here because there is currently no way to express a trait bound for `FnDef` types only. - if let ty::FnDef(def_id, _args) = *arg_ty.kind() { - if idx == 0 && !self.tcx.is_const_fn(def_id) { - self.dcx().emit_err(errors::ConstSelectMustBeConst { span }); - } - } else { - self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty }); - } - } - } - fn_sig.output() } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3606c778fc4..a8bb6956f10 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -606,24 +606,6 @@ impl Subdiagnostic for RemoveSemiForCoerce { } #[derive(Diagnostic)] -#[diag(hir_typeck_const_select_must_be_const)] -#[help] -pub(crate) struct ConstSelectMustBeConst { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_typeck_const_select_must_be_fn)] -#[note] -#[help] -pub(crate) struct ConstSelectMustBeFn<'a> { - #[primary_span] - pub span: Span, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] #[diag(hir_typeck_union_pat_multiple_fields)] pub(crate) struct UnionPatMultipleFields { #[primary_span] diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 982cfa2e42b..be774106abf 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // process any deferred resolutions. let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id); for deferred_call_resolution in deferred_call_resolutions { - deferred_call_resolution.resolve(self); + deferred_call_resolution.resolve(&mut FnCtxt::new( + self, + self.param_env, + closure_def_id, + )); } } diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index 176d308de91..d694a092853 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -1,7 +1,8 @@ use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::traits::{ - ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation, + ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode, + PredicateObligation, }; use rustc_middle::span_bug; use rustc_middle::traits::query::NoSolution; @@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>( ) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { match selcx.tcx().as_lang_item(obligation.predicate.def_id()) { Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation), + Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => { + evaluate_host_effect_for_fn_goal(selcx, obligation) + } _ => Err(EvaluationFailure::NoSolution), } } @@ -398,6 +402,51 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>( .collect()) } +// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver. +fn evaluate_host_effect_for_fn_goal<'tcx>( + selcx: &mut SelectionContext<'_, 'tcx>, + obligation: &HostEffectObligation<'tcx>, +) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { + let tcx = selcx.tcx(); + let self_ty = obligation.predicate.self_ty(); + + let (def, args) = match *self_ty.kind() { + ty::FnDef(def, args) => (def, args), + + // We may support function pointers at some point in the future + ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution), + + // Closures could implement `[const] Fn`, + // but they don't really need to right now. + ty::Closure(..) | ty::CoroutineClosure(_, _) => { + return Err(EvaluationFailure::NoSolution); + } + + // Everything else needs explicit impls or cannot have an impl + _ => return Err(EvaluationFailure::NoSolution), + }; + + match tcx.constness(def) { + hir::Constness::Const => Ok(tcx + .const_conditions(def) + .instantiate(tcx, args) + .into_iter() + .map(|(c, span)| { + let code = ObligationCauseCode::WhereClause(def, span); + let cause = + ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code); + Obligation::new( + tcx, + cause, + obligation.param_env, + c.to_host_effect_clause(tcx, obligation.predicate.constness), + ) + }) + .collect()), + hir::Constness::NotConst => Err(EvaluationFailure::NoSolution), + } +} + fn evaluate_host_effect_from_selection_candidate<'tcx>( selcx: &mut SelectionContext<'_, 'tcx>, obligation: &HostEffectObligation<'tcx>, |
