diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index efaebfd0610..6f0b794129b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -71,7 +71,8 @@ use std::fmt; use std::hash::Hash; use syntax_pos::symbol::InternedString; use traits::query::{ - CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalPredicateGoal, + CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, + CanonicalPredicateGoal, }; use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; use ty::subst::Substs; @@ -649,6 +650,7 @@ define_dep_nodes!( <'tcx> [] DropckOutlives(CanonicalTyGoal<'tcx>), [] EvaluateObligation(CanonicalPredicateGoal<'tcx>), [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>), + [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>), [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index 3ee0c0cdd0b..47f55b7e5e4 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -35,6 +35,9 @@ pub type CanonicalPredicateGoal<'tcx> = pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, type_op::eq::Eq<'tcx>>; +pub type CanonicalTypeOpSubtypeGoal<'tcx> = + Canonical<'tcx, type_op::subtype::Subtype<'tcx>>; + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct NoSolution; diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs index e9adabc8b08..01f9386bec4 100644 --- a/src/librustc/traits/query/type_op/subtype.rs +++ b/src/librustc/traits/query/type_op/subtype.rs @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use infer::{InferCtxt, InferResult}; -use traits::ObligationCause; +use infer::canonical::{Canonical, CanonicalizedQueryResult}; use ty::{ParamEnv, Ty, TyCtxt}; -#[derive(Debug)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct Subtype<'tcx> { - param_env: ParamEnv<'tcx>, - sub: Ty<'tcx>, - sup: Ty<'tcx>, + pub param_env: ParamEnv<'tcx>, + pub sub: Ty<'tcx>, + pub sup: Ty<'tcx>, } impl<'tcx> Subtype<'tcx> { @@ -29,10 +28,10 @@ impl<'tcx> Subtype<'tcx> { } } -impl<'gcx, 'tcx> super::TypeOp<'gcx, 'tcx> for Subtype<'tcx> { - type Output = (); +impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> { + type QueryResult = (); - fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result { + fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<(), Self> { if self.sub == self.sup { Ok(()) } else { @@ -40,9 +39,35 @@ impl<'gcx, 'tcx> super::TypeOp<'gcx, 'tcx> for Subtype<'tcx> { } } - fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> { - infcx - .at(&ObligationCause::dummy(), self.param_env) - .sup(self.sup, self.sub) + fn param_env(&self) -> ParamEnv<'tcx> { + self.param_env + } + + fn perform_query( + tcx: TyCtxt<'_, 'gcx, 'tcx>, + canonicalized: Canonical<'gcx, Subtype<'gcx>>, + ) -> CanonicalizedQueryResult<'gcx, ()> { + tcx.type_op_subtype(canonicalized).unwrap() } } + +BraceStructTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for Subtype<'tcx> { + param_env, + sub, + sup, + } +} + +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for Subtype<'a> { + type Lifted = Subtype<'tcx>; + param_env, + sub, + sup, + } +} + +impl_stable_hash_for! { + struct Subtype<'tcx> { param_env, sub, sup } +} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index d02eac6f212..bccdec27099 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -14,6 +14,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex}; use mir::interpret::{GlobalId, ConstValue}; use traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, + CanonicalTypeOpSubtypeGoal, }; use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::subst::Substs; @@ -110,6 +111,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> { } } +impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> { + fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpSubtypeGoal<'tcx>) -> String { + format!("evaluating `type_op_eq` `{:?}`", 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 d5cd37fd98a..e848fa2c347 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -34,7 +34,7 @@ use session::{CompileResult, CrateDisambiguator}; use session::config::OutputFilenames; use traits::{self, Vtable}; use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, - CanonicalTyGoal, CanonicalTypeOpEqGoal, NoSolution}; + CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, NoSolution}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::specialization_graph; @@ -454,6 +454,14 @@ define_queries! { <'tcx> NoSolution, >, + /// Do not call this query directly: invoke `infcx.at().subtype()` instead. + [] fn type_op_subtype: TypeOpSubtype( + CanonicalTypeOpSubtypeGoal<'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 51695b113d5..2380764252b 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1029,6 +1029,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::DropckOutlives | DepKind::EvaluateObligation | DepKind::TypeOpEq | + DepKind::TypeOpSubtype | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | DepKind::ProgramClausesForEnv | diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index dae960c9aa3..671e352c0e4 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_subtype; use rustc::ty::query::Providers; @@ -49,6 +50,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_subtype: type_op_subtype::type_op_subtype, ..*p }; } diff --git a/src/librustc_traits/type_op_subtype.rs b/src/librustc_traits/type_op_subtype.rs new file mode 100644 index 00000000000..1fa5ec915f2 --- /dev/null +++ b/src/librustc_traits/type_op_subtype.rs @@ -0,0 +1,35 @@ +// 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::subtype::Subtype; +use rustc::traits::query::NoSolution; +use rustc::traits::{FulfillmentContext, ObligationCause}; +use rustc::ty::TyCtxt; +use rustc_data_structures::sync::Lrc; +use syntax::codemap::DUMMY_SP; + +crate fn type_op_subtype<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + canonicalized: Canonical<'tcx, Subtype<'tcx>>, +) -> Result>>, NoSolution> { + let tcx = tcx.global_tcx(); + tcx.infer_ctxt().enter(|ref infcx| { + let (Subtype { param_env, sub, sup }, canonical_inference_vars) = + infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized); + let fulfill_cx = &mut FulfillmentContext::new(); + let obligations = match infcx.at(&ObligationCause::dummy(), param_env).sup(sup, sub) { + Ok(v) => v.into_obligations(), + Err(_) => return Err(NoSolution), + }; + fulfill_cx.register_predicate_obligations(infcx, obligations); + infcx.make_canonicalized_query_result(canonical_inference_vars, (), fulfill_cx) + }) +}