|
1 | 1 | use rustc_hir::{self as hir, LangItem};
|
2 | 2 | use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
|
3 | 3 | use rustc_infer::traits::{
|
4 |
| - ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation, |
| 4 | + ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode, |
| 5 | + PredicateObligation, |
5 | 6 | };
|
6 | 7 | use rustc_middle::span_bug;
|
7 | 8 | use rustc_middle::traits::query::NoSolution;
|
@@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
|
303 | 304 | ) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
304 | 305 | match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
|
305 | 306 | Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
|
| 307 | + Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => { |
| 308 | + evaluate_host_effect_for_fn_goal(selcx, obligation) |
| 309 | + } |
306 | 310 | _ => Err(EvaluationFailure::NoSolution),
|
307 | 311 | }
|
308 | 312 | }
|
@@ -398,6 +402,51 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
|
398 | 402 | .collect())
|
399 | 403 | }
|
400 | 404 |
|
| 405 | +// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver. |
| 406 | +fn evaluate_host_effect_for_fn_goal<'tcx>( |
| 407 | + selcx: &mut SelectionContext<'_, 'tcx>, |
| 408 | + obligation: &HostEffectObligation<'tcx>, |
| 409 | +) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> { |
| 410 | + let tcx = selcx.tcx(); |
| 411 | + let self_ty = obligation.predicate.self_ty(); |
| 412 | + |
| 413 | + let (def, args) = match *self_ty.kind() { |
| 414 | + ty::FnDef(def, args) => (def, args), |
| 415 | + |
| 416 | + // We may support function pointers at some point in the future |
| 417 | + ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution), |
| 418 | + |
| 419 | + // Closures could implement `[const] Fn`, |
| 420 | + // but they don't really need to right now. |
| 421 | + ty::Closure(..) | ty::CoroutineClosure(_, _) => { |
| 422 | + return Err(EvaluationFailure::NoSolution); |
| 423 | + } |
| 424 | + |
| 425 | + // Everything else needs explicit impls or cannot have an impl |
| 426 | + _ => return Err(EvaluationFailure::NoSolution), |
| 427 | + }; |
| 428 | + |
| 429 | + match tcx.constness(def) { |
| 430 | + hir::Constness::Const => Ok(tcx |
| 431 | + .const_conditions(def) |
| 432 | + .instantiate(tcx, args) |
| 433 | + .into_iter() |
| 434 | + .map(|(c, span)| { |
| 435 | + let code = ObligationCauseCode::WhereClause(def, span); |
| 436 | + let cause = |
| 437 | + ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code); |
| 438 | + Obligation::new( |
| 439 | + tcx, |
| 440 | + cause, |
| 441 | + obligation.param_env, |
| 442 | + c.to_host_effect_clause(tcx, obligation.predicate.constness), |
| 443 | + ) |
| 444 | + }) |
| 445 | + .collect()), |
| 446 | + hir::Constness::NotConst => Err(EvaluationFailure::NoSolution), |
| 447 | + } |
| 448 | +} |
| 449 | + |
401 | 450 | fn evaluate_host_effect_from_selection_candidate<'tcx>(
|
402 | 451 | selcx: &mut SelectionContext<'_, 'tcx>,
|
403 | 452 | obligation: &HostEffectObligation<'tcx>,
|
|
0 commit comments