1 use super::combine
::{CombineFields, RelationDir}
;
2 use super::{ObligationEmittingRelation, SubregionOrigin}
;
4 use crate::traits
::{Obligation, PredicateObligations}
;
5 use rustc_middle
::ty
::relate
::{Cause, Relate, RelateResult, TypeRelation}
;
6 use rustc_middle
::ty
::visit
::TypeVisitableExt
;
7 use rustc_middle
::ty
::TyVar
;
8 use rustc_middle
::ty
::{self, Ty, TyCtxt}
;
11 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
12 pub struct Sub
<'combine
, 'a
, 'tcx
> {
13 fields
: &'combine
mut CombineFields
<'a
, 'tcx
>,
17 impl<'combine
, 'infcx
, 'tcx
> Sub
<'combine
, 'infcx
, 'tcx
> {
19 f
: &'combine
mut CombineFields
<'infcx
, 'tcx
>,
21 ) -> Sub
<'combine
, 'infcx
, 'tcx
> {
22 Sub { fields: f, a_is_expected }
25 fn with_expected_switched
<R
, F
: FnOnce(&mut Self) -> R
>(&mut self, f
: F
) -> R
{
26 self.a_is_expected
= !self.a_is_expected
;
28 self.a_is_expected
= !self.a_is_expected
;
33 impl<'tcx
> TypeRelation
<'tcx
> for Sub
<'_
, '_
, 'tcx
> {
34 fn tag(&self) -> &'
static str {
38 fn intercrate(&self) -> bool
{
39 self.fields
.infcx
.intercrate
42 fn tcx(&self) -> TyCtxt
<'tcx
> {
46 fn param_env(&self) -> ty
::ParamEnv
<'tcx
> {
50 fn a_is_expected(&self) -> bool
{
54 fn mark_ambiguous(&mut self) {
55 self.fields
.mark_ambiguous()
58 fn with_cause
<F
, R
>(&mut self, cause
: Cause
, f
: F
) -> R
60 F
: FnOnce(&mut Self) -> R
,
62 debug
!("sub with_cause={:?}", cause
);
63 let old_cause
= mem
::replace(&mut self.fields
.cause
, Some(cause
));
65 debug
!("sub old_cause={:?}", old_cause
);
66 self.fields
.cause
= old_cause
;
70 fn relate_with_variance
<T
: Relate
<'tcx
>>(
72 variance
: ty
::Variance
,
73 _info
: ty
::VarianceDiagInfo
<'tcx
>,
76 ) -> RelateResult
<'tcx
, T
> {
78 ty
::Invariant
=> self.fields
.equate(self.a_is_expected
).relate(a
, b
),
79 ty
::Covariant
=> self.relate(a
, b
),
80 ty
::Bivariant
=> Ok(a
),
81 ty
::Contravariant
=> self.with_expected_switched(|this
| this
.relate(b
, a
)),
85 #[instrument(skip(self), level = "debug")]
86 fn tys(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
91 let infcx
= self.fields
.infcx
;
92 let a
= infcx
.inner
.borrow_mut().type_variables().replace_if_possible(a
);
93 let b
= infcx
.inner
.borrow_mut().type_variables().replace_if_possible(b
);
95 match (a
.kind(), b
.kind()) {
96 (&ty
::Infer(TyVar(_
)), &ty
::Infer(TyVar(_
))) => {
97 // Shouldn't have any LBR here, so we can safely put
98 // this under a binder below without fear of accidental
100 assert
!(!a
.has_escaping_bound_vars());
101 assert
!(!b
.has_escaping_bound_vars());
103 // can't make progress on `A <: B` if both A and B are
104 // type variables, so record an obligation.
105 self.fields
.obligations
.push(Obligation
::new(
107 self.fields
.trace
.cause
.clone(),
108 self.fields
.param_env
,
109 ty
::Binder
::dummy(ty
::PredicateKind
::Subtype(ty
::SubtypePredicate
{
110 a_is_expected
: self.a_is_expected
,
118 (&ty
::Infer(TyVar(a_id
)), _
) => {
119 self.fields
.instantiate(b
, RelationDir
::SupertypeOf
, a_id
, !self.a_is_expected
)?
;
122 (_
, &ty
::Infer(TyVar(b_id
))) => {
123 self.fields
.instantiate(a
, RelationDir
::SubtypeOf
, b_id
, self.a_is_expected
)?
;
127 (&ty
::Error(e
), _
) | (_
, &ty
::Error(e
)) => {
128 infcx
.set_tainted_by_errors(e
);
129 Ok(self.tcx().ty_error(e
))
133 &ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id: a_def_id, .. }
),
134 &ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id: b_def_id, .. }
),
135 ) if a_def_id
== b_def_id
=> {
136 self.fields
.infcx
.super_combine_tys(self, a
, b
)?
;
139 (&ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id, .. }
), _
)
140 | (_
, &ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id, .. }
))
141 if self.fields
.define_opaque_types
&& def_id
.is_local() =>
143 self.fields
.obligations
.extend(
149 &self.fields
.trace
.cause
,
156 // Optimization of GeneratorWitness relation since we know that all
157 // free regions are replaced with bound regions during construction.
158 // This greatly speeds up subtyping of GeneratorWitness.
159 (&ty
::GeneratorWitness(a_types
), &ty
::GeneratorWitness(b_types
)) => {
160 let a_types
= infcx
.tcx
.anonymize_bound_vars(a_types
);
161 let b_types
= infcx
.tcx
.anonymize_bound_vars(b_types
);
162 if a_types
.bound_vars() == b_types
.bound_vars() {
163 let (a_types
, b_types
) = infcx
.instantiate_binder_with_placeholders(
164 a_types
.map_bound(|a_types
| (a_types
, b_types
.skip_binder())),
166 for (a
, b
) in std
::iter
::zip(a_types
, b_types
) {
171 Err(ty
::error
::TypeError
::Sorts(ty
::relate
::expected_found(self, a
, b
)))
176 self.fields
.infcx
.super_combine_tys(self, a
, b
)?
;
186 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>> {
187 debug
!("{}.regions({:?}, {:?}) self.cause={:?}", self.tag(), a
, b
, self.fields
.cause
);
189 // FIXME -- we have more fine-grained information available
190 // from the "cause" field, we could perhaps give more tailored
192 let origin
= SubregionOrigin
::Subtype(Box
::new(self.fields
.trace
.clone()));
193 // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
198 .unwrap_region_constraints()
199 .make_subregion(origin
, b
, a
);
208 ) -> RelateResult
<'tcx
, ty
::Const
<'tcx
>> {
209 self.fields
.infcx
.super_combine_consts(self, a
, b
)
214 a
: ty
::Binder
<'tcx
, T
>,
215 b
: ty
::Binder
<'tcx
, T
>,
216 ) -> RelateResult
<'tcx
, ty
::Binder
<'tcx
, T
>>
220 // A binder is always a subtype of itself if it's structually equal to itself
225 self.fields
.higher_ranked_sub(a
, b
, self.a_is_expected
)?
;
230 impl<'tcx
> ObligationEmittingRelation
<'tcx
> for Sub
<'_
, '_
, 'tcx
> {
231 fn register_predicates(&mut self, obligations
: impl IntoIterator
<Item
: ty
::ToPredicate
<'tcx
>>) {
232 self.fields
.register_predicates(obligations
);
235 fn register_obligations(&mut self, obligations
: PredicateObligations
<'tcx
>) {
236 self.fields
.register_obligations(obligations
);