1 //! Experimental types for the trait query interface. The methods 2 //! defined in this module are all based on **canonicalization**, 3 //! which makes a canonical query by replacing unbound inference 4 //! variables and regions, so that results can be reused more broadly. 5 //! The providers for the queries defined here can be found in 6 //! `rustc_traits`. 7 8 use crate::error::DropCheckOverflow; 9 use crate::infer::canonical::{Canonical, QueryResponse}; 10 use crate::ty::error::TypeError; 11 use crate::ty::subst::GenericArg; 12 use crate::ty::{self, Ty, TyCtxt}; 13 use rustc_span::source_map::Span; 14 15 pub mod type_op { 16 use crate::ty::fold::TypeFoldable; 17 use crate::ty::{Predicate, Ty, TyCtxt, UserType}; 18 use std::fmt; 19 20 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] 21 #[derive(TypeFoldable, TypeVisitable)] 22 pub struct AscribeUserType<'tcx> { 23 pub mir_ty: Ty<'tcx>, 24 pub user_ty: UserType<'tcx>, 25 } 26 27 impl<'tcx> AscribeUserType<'tcx> { new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self28 pub fn new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self { 29 Self { mir_ty, user_ty } 30 } 31 } 32 33 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] 34 #[derive(TypeFoldable, TypeVisitable)] 35 pub struct Eq<'tcx> { 36 pub a: Ty<'tcx>, 37 pub b: Ty<'tcx>, 38 } 39 40 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] 41 #[derive(TypeFoldable, TypeVisitable)] 42 pub struct Subtype<'tcx> { 43 pub sub: Ty<'tcx>, 44 pub sup: Ty<'tcx>, 45 } 46 47 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] 48 #[derive(TypeFoldable, TypeVisitable)] 49 pub struct ProvePredicate<'tcx> { 50 pub predicate: Predicate<'tcx>, 51 } 52 53 impl<'tcx> ProvePredicate<'tcx> { new(predicate: Predicate<'tcx>) -> Self54 pub fn new(predicate: Predicate<'tcx>) -> Self { 55 ProvePredicate { predicate } 56 } 57 } 58 59 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)] 60 #[derive(TypeFoldable, TypeVisitable)] 61 pub struct Normalize<T> { 62 pub value: T, 63 } 64 65 impl<'tcx, T> Normalize<T> 66 where 67 T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>, 68 { new(value: T) -> Self69 pub fn new(value: T) -> Self { 70 Self { value } 71 } 72 } 73 } 74 75 pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>; 76 77 pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>; 78 79 pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>; 80 81 pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> = 82 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>; 83 84 pub type CanonicalTypeOpEqGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Eq<'tcx>>>; 85 86 pub type CanonicalTypeOpSubtypeGoal<'tcx> = 87 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Subtype<'tcx>>>; 88 89 pub type CanonicalTypeOpProvePredicateGoal<'tcx> = 90 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ProvePredicate<'tcx>>>; 91 92 pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = 93 Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>; 94 95 #[derive(Copy, Clone, Debug, Hash, HashStable, PartialEq, Eq)] 96 pub struct NoSolution; 97 98 impl<'tcx> From<TypeError<'tcx>> for NoSolution { from(_: TypeError<'tcx>) -> NoSolution99 fn from(_: TypeError<'tcx>) -> NoSolution { 100 NoSolution 101 } 102 } 103 104 #[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)] 105 pub struct DropckOutlivesResult<'tcx> { 106 pub kinds: Vec<GenericArg<'tcx>>, 107 pub overflows: Vec<Ty<'tcx>>, 108 } 109 110 impl<'tcx> DropckOutlivesResult<'tcx> { report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>)111 pub fn report_overflows(&self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { 112 if let Some(overflow_ty) = self.overflows.get(0) { 113 tcx.sess.emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty }); 114 } 115 } 116 into_kinds_reporting_overflows( self, tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>, ) -> Vec<GenericArg<'tcx>>117 pub fn into_kinds_reporting_overflows( 118 self, 119 tcx: TyCtxt<'tcx>, 120 span: Span, 121 ty: Ty<'tcx>, 122 ) -> Vec<GenericArg<'tcx>> { 123 self.report_overflows(tcx, span, ty); 124 let DropckOutlivesResult { kinds, overflows: _ } = self; 125 kinds 126 } 127 } 128 129 /// A set of constraints that need to be satisfied in order for 130 /// a type to be valid for destruction. 131 #[derive(Clone, Debug, HashStable)] 132 pub struct DropckConstraint<'tcx> { 133 /// Types that are required to be alive in order for this 134 /// type to be valid for destruction. 135 pub outlives: Vec<ty::subst::GenericArg<'tcx>>, 136 137 /// Types that could not be resolved: projections and params. 138 pub dtorck_types: Vec<Ty<'tcx>>, 139 140 /// If, during the computation of the dtorck constraint, we 141 /// overflow, that gets recorded here. The caller is expected to 142 /// report an error. 143 pub overflows: Vec<Ty<'tcx>>, 144 } 145 146 impl<'tcx> DropckConstraint<'tcx> { empty() -> DropckConstraint<'tcx>147 pub fn empty() -> DropckConstraint<'tcx> { 148 DropckConstraint { outlives: vec![], dtorck_types: vec![], overflows: vec![] } 149 } 150 } 151 152 impl<'tcx> FromIterator<DropckConstraint<'tcx>> for DropckConstraint<'tcx> { from_iter<I: IntoIterator<Item = DropckConstraint<'tcx>>>(iter: I) -> Self153 fn from_iter<I: IntoIterator<Item = DropckConstraint<'tcx>>>(iter: I) -> Self { 154 let mut result = Self::empty(); 155 156 for DropckConstraint { outlives, dtorck_types, overflows } in iter { 157 result.outlives.extend(outlives); 158 result.dtorck_types.extend(dtorck_types); 159 result.overflows.extend(overflows); 160 } 161 162 result 163 } 164 } 165 166 #[derive(Debug, HashStable)] 167 pub struct CandidateStep<'tcx> { 168 pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, 169 pub autoderefs: usize, 170 /// `true` if the type results from a dereference of a raw pointer. 171 /// when assembling candidates, we include these steps, but not when 172 /// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods 173 /// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then 174 /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. 175 pub from_unsafe_deref: bool, 176 pub unsize: bool, 177 } 178 179 #[derive(Copy, Clone, Debug, HashStable)] 180 pub struct MethodAutoderefStepsResult<'tcx> { 181 /// The valid autoderef steps that could be find. 182 pub steps: &'tcx [CandidateStep<'tcx>], 183 /// If Some(T), a type autoderef reported an error on. 184 pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>, 185 /// If `true`, `steps` has been truncated due to reaching the 186 /// recursion limit. 187 pub reached_recursion_limit: bool, 188 } 189 190 #[derive(Debug, HashStable)] 191 pub struct MethodAutoderefBadTy<'tcx> { 192 pub reached_raw_pointer: bool, 193 pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, 194 } 195 196 /// Result from the `normalize_projection_ty` query. 197 #[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] 198 pub struct NormalizationResult<'tcx> { 199 /// Result of normalization. 200 pub normalized_ty: Ty<'tcx>, 201 } 202 203 /// Outlives bounds are relationships between generic parameters, 204 /// whether they both be regions (`'a: 'b`) or whether types are 205 /// involved (`T: 'a`). These relationships can be extracted from the 206 /// full set of predicates we understand or also from types (in which 207 /// case they are called implied bounds). They are fed to the 208 /// `OutlivesEnv` which in turn is supplied to the region checker and 209 /// other parts of the inference system. 210 #[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift, HashStable)] 211 pub enum OutlivesBound<'tcx> { 212 RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>), 213 RegionSubParam(ty::Region<'tcx>, ty::ParamTy), 214 RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>), 215 } 216