From de7e941e4eafdc73f4d68c6cdbb8c49224e5a90b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 11 Jun 2018 11:29:46 -0400 Subject: [PATCH] convert `prove_predicate` into a query --- src/librustc/dep_graph/dep_node.rs | 3 +- src/librustc/traits/query/mod.rs | 3 ++ .../traits/query/type_op/prove_predicate.rs | 49 +++++++++++++------ src/librustc/ty/query/config.rs | 8 ++- src/librustc/ty/query/mod.rs | 11 ++++- src/librustc/ty/query/plumbing.rs | 1 + src/librustc_traits/lib.rs | 2 + .../type_op_prove_predicate.rs | 32 ++++++++++++ 8 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 src/librustc_traits/type_op_prove_predicate.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 6f0b794129b..94c79c17f05 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -72,7 +72,7 @@ use std::hash::Hash; use syntax_pos::symbol::InternedString; use traits::query::{ CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, - CanonicalPredicateGoal, + CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, }; use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; use ty::subst::Substs; @@ -651,6 +651,7 @@ define_dep_nodes!( <'tcx> [] EvaluateObligation(CanonicalPredicateGoal<'tcx>), [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>), [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>), + [] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>), [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 47f55b7e5e4..aa0b524af06 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -38,6 +38,9 @@ pub type CanonicalTypeOpEqGoal<'tcx> = pub type CanonicalTypeOpSubtypeGoal<'tcx> = Canonical<'tcx, type_op::subtype::Subtype<'tcx>>; +pub type CanonicalTypeOpProvePredicateGoal<'tcx> = + Canonical<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>; + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct NoSolution; diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 7dacf6a7dea..193dd1c7c84 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use infer::{InferCtxt, InferOk, InferResult}; -use traits::{Obligation, ObligationCause}; +use infer::canonical::{Canonical, CanonicalizedQueryResult}; use ty::{ParamEnv, Predicate, TyCtxt}; -#[derive(Debug)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ProvePredicate<'tcx> { - param_env: ParamEnv<'tcx>, - predicate: Predicate<'tcx>, + pub param_env: ParamEnv<'tcx>, + pub predicate: Predicate<'tcx>, } impl<'tcx> ProvePredicate<'tcx> { @@ -27,18 +26,40 @@ impl<'tcx> ProvePredicate<'tcx> { } } -impl<'gcx, 'tcx> super::TypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> { - type Output = (); +impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> { + type QueryResult = (); - fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result { + fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result { Err(self) } - fn perform(self, _infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> { - let obligation = Obligation::new(ObligationCause::dummy(), self.param_env, self.predicate); - Ok(InferOk { - value: (), - obligations: vec![obligation], - }) + fn param_env(&self) -> ParamEnv<'tcx> { + self.param_env + } + + fn perform_query( + tcx: TyCtxt<'_, 'gcx, 'tcx>, + canonicalized: Canonical<'gcx, ProvePredicate<'gcx>>, + ) -> CanonicalizedQueryResult<'gcx, ()> { + tcx.type_op_prove_predicate(canonicalized).unwrap() } } + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for ProvePredicate<'tcx> { + param_env, + predicate, + } +} + +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for ProvePredicate<'a> { + type Lifted = ProvePredicate<'tcx>; + param_env, + predicate, + } +} + +impl_stable_hash_for! { + struct ProvePredicate<'tcx> { param_env, predicate } +} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index bccdec27099..930826dad62 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -14,7 +14,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex}; use mir::interpret::{GlobalId, ConstValue}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, - CanonicalTypeOpSubtypeGoal, + CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, }; use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::subst::Substs; @@ -117,6 +117,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::type_op_prove_predicate<'tcx> { + fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) -> String { + format!("evaluating `type_op_prove_predicate` `{:?}`", goal) + } +} + impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> { fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { format!("computing whether `{}` is `Copy`", env.value) diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index e848fa2c347..dfc54cb1425 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -34,7 +34,8 @@ use session::{CompileResult, CrateDisambiguator}; use session::config::OutputFilenames; use traits::{self, Vtable}; use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, - CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, NoSolution}; + CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, + CanonicalTypeOpProvePredicateGoal, NoSolution}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::specialization_graph; @@ -462,6 +463,14 @@ define_queries! { <'tcx> NoSolution, >, + /// Do not call this query directly: invoke `infcx.at().prove_predicates()` instead. + [] fn type_op_prove_predicate: TypeOpProvePredicate( + CanonicalTypeOpProvePredicateGoal<'tcx> + ) -> Result< + Lrc>>, + NoSolution, + >, + [] fn substitute_normalize_and_test_predicates: substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 2380764252b..57568f60b86 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1030,6 +1030,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::EvaluateObligation | DepKind::TypeOpEq | DepKind::TypeOpSubtype | + DepKind::TypeOpProvePredicate | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | DepKind::ProgramClausesForEnv | diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 671e352c0e4..261d6b2fbfa 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -35,6 +35,7 @@ mod normalize_projection_ty; mod normalize_erasing_regions; pub mod lowering; mod type_op_eq; +mod type_op_prove_predicate; mod type_op_subtype; use rustc::ty::query::Providers; @@ -50,6 +51,7 @@ pub fn provide(p: &mut Providers) { program_clauses_for_env: lowering::program_clauses_for_env, evaluate_obligation: evaluate_obligation::evaluate_obligation, type_op_eq: type_op_eq::type_op_eq, + type_op_prove_predicate: type_op_prove_predicate::type_op_prove_predicate, type_op_subtype: type_op_subtype::type_op_subtype, ..*p }; diff --git a/src/librustc_traits/type_op_prove_predicate.rs b/src/librustc_traits/type_op_prove_predicate.rs new file mode 100644 index 00000000000..ad16e6d31d7 --- /dev/null +++ b/src/librustc_traits/type_op_prove_predicate.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::infer::canonical::{Canonical, QueryResult}; +use rustc::traits::query::type_op::prove_predicate::ProvePredicate; +use rustc::traits::query::NoSolution; +use rustc::traits::{FulfillmentContext, Obligation, ObligationCause, TraitEngine}; +use rustc::ty::TyCtxt; +use rustc_data_structures::sync::Lrc; +use syntax::codemap::DUMMY_SP; + +crate fn type_op_prove_predicate<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + canonicalized: Canonical<'tcx, ProvePredicate<'tcx>>, +) -> Result>>, NoSolution> { + let tcx = tcx.global_tcx(); + tcx.infer_ctxt().enter(|ref infcx| { + let (ProvePredicate { param_env, predicate }, canonical_inference_vars) = + infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized); + let fulfill_cx = &mut FulfillmentContext::new(); + let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); + fulfill_cx.register_predicate_obligation(infcx, obligation); + infcx.make_canonicalized_query_result(canonical_inference_vars, (), fulfill_cx) + }) +}