]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/sub.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / sub.rs
CommitLineData
e1599b0c 1use super::combine::{CombineFields, RelationDir};
dfeec247 2use super::SubregionOrigin;
1a4d82fc 3
f9f354fc 4use crate::infer::combine::ConstEquateRelation;
ee023bcb 5use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
9fa01778 6use crate::traits::Obligation;
ba9703b0
XL
7use rustc_middle::ty::fold::TypeFoldable;
8use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
9use rustc_middle::ty::TyVar;
f9f354fc 10use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
62682a34 11use std::mem;
1a4d82fc 12
b039eaaf 13/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
dc9dc135
XL
14pub struct Sub<'combine, 'infcx, 'tcx> {
15 fields: &'combine mut CombineFields<'infcx, 'tcx>,
5bcae85e 16 a_is_expected: bool,
1a4d82fc
JJ
17}
18
dc9dc135
XL
19impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> {
20 pub fn new(
21 f: &'combine mut CombineFields<'infcx, 'tcx>,
22 a_is_expected: bool,
23 ) -> Sub<'combine, 'infcx, 'tcx> {
74b04a01 24 Sub { fields: f, a_is_expected }
c34b1796 25 }
54a0048b 26
5bcae85e
SL
27 fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
28 self.a_is_expected = !self.a_is_expected;
29 let result = f(self);
30 self.a_is_expected = !self.a_is_expected;
31 result
54a0048b 32 }
1a4d82fc
JJ
33}
34
a2a8927a 35impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
dfeec247
XL
36 fn tag(&self) -> &'static str {
37 "Sub"
38 }
39 fn tcx(&self) -> TyCtxt<'tcx> {
40 self.fields.infcx.tcx
41 }
416331ca 42
dfeec247
XL
43 fn param_env(&self) -> ty::ParamEnv<'tcx> {
44 self.fields.param_env
45 }
416331ca 46
dfeec247
XL
47 fn a_is_expected(&self) -> bool {
48 self.a_is_expected
49 }
85aaf69f 50
dfeec247
XL
51 fn with_cause<F, R>(&mut self, cause: Cause, f: F) -> R
52 where
53 F: FnOnce(&mut Self) -> R,
62682a34
SL
54 {
55 debug!("sub with_cause={:?}", cause);
56 let old_cause = mem::replace(&mut self.fields.cause, Some(cause));
57 let r = f(self);
58 debug!("sub old_cause={:?}", old_cause);
59 self.fields.cause = old_cause;
60 r
61 }
62
dfeec247
XL
63 fn relate_with_variance<T: Relate<'tcx>>(
64 &mut self,
65 variance: ty::Variance,
17df50a5 66 _info: ty::VarianceDiagInfo<'tcx>,
f035d41b
XL
67 a: T,
68 b: T,
dfeec247 69 ) -> RelateResult<'tcx, T> {
c34b1796 70 match variance {
5bcae85e 71 ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
c34b1796 72 ty::Covariant => self.relate(a, b),
3dfed10e 73 ty::Bivariant => Ok(a),
dfeec247 74 ty::Contravariant => self.with_expected_switched(|this| this.relate(b, a)),
85aaf69f 75 }
1a4d82fc
JJ
76 }
77
ee023bcb 78 #[instrument(skip(self), level = "debug")]
c34b1796 79 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
dfeec247
XL
80 if a == b {
81 return Ok(a);
82 }
1a4d82fc
JJ
83
84 let infcx = self.fields.infcx;
f9f354fc
XL
85 let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a);
86 let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b);
ee023bcb 87
1b1a35ee 88 match (a.kind(), b.kind()) {
94222f64 89 (&ty::Infer(TyVar(_)), &ty::Infer(TyVar(_))) => {
cc61c64b
XL
90 // Shouldn't have any LBR here, so we can safely put
91 // this under a binder below without fear of accidental
92 // capture.
a1dfa0c6
XL
93 assert!(!a.has_escaping_bound_vars());
94 assert!(!b.has_escaping_bound_vars());
cc61c64b
XL
95
96 // can't make progress on `A <: B` if both A and B are
94222f64 97 // type variables, so record an obligation.
dfeec247
XL
98 self.fields.obligations.push(Obligation::new(
99 self.fields.trace.cause.clone(),
100 self.fields.param_env,
c295e0f8 101 ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
dfeec247
XL
102 a_is_expected: self.a_is_expected,
103 a,
104 b,
c295e0f8 105 }))
f9f354fc 106 .to_predicate(self.tcx()),
dfeec247 107 ));
cc61c64b 108
1a4d82fc
JJ
109 Ok(a)
110 }
b7449926 111 (&ty::Infer(TyVar(a_id)), _) => {
dfeec247 112 self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
1a4d82fc
JJ
113 Ok(a)
114 }
b7449926 115 (_, &ty::Infer(TyVar(b_id))) => {
cc61c64b 116 self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
1a4d82fc
JJ
117 Ok(a)
118 }
119
f035d41b 120 (&ty::Error(_), _) | (_, &ty::Error(_)) => {
a7813a04 121 infcx.set_tainted_by_errors();
f035d41b 122 Ok(self.tcx().ty_error())
1a4d82fc
JJ
123 }
124
ee023bcb
FG
125 (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
126 self.fields.infcx.super_combine_tys(self, a, b)?;
127 Ok(a)
128 }
129 (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
130 if self.fields.define_opaque_types && did.is_local() =>
131 {
132 let mut generalize = |ty, ty_is_expected| {
133 let var = infcx.next_ty_var_id_in_universe(
134 TypeVariableOrigin {
135 kind: TypeVariableOriginKind::MiscVariable,
136 span: self.fields.trace.cause.span,
137 },
138 ty::UniverseIndex::ROOT,
139 );
140 self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
141 Ok(infcx.tcx.mk_ty_var(var))
142 };
143 let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
144 let (a, b) = match (a.kind(), b.kind()) {
145 (&ty::Opaque(..), _) => (a, generalize(b, true)?),
146 (_, &ty::Opaque(..)) => (generalize(a, false)?, b),
147 _ => unreachable!(),
148 };
149 self.fields.obligations.extend(
150 infcx
151 .handle_opaque_type(a, b, true, &self.fields.trace.cause, self.param_env())?
152 .obligations,
153 );
154 Ok(a)
155 }
156
1a4d82fc 157 _ => {
a7813a04 158 self.fields.infcx.super_combine_tys(self, a, b)?;
b039eaaf 159 Ok(a)
1a4d82fc
JJ
160 }
161 }
162 }
163
dfeec247
XL
164 fn regions(
165 &mut self,
166 a: ty::Region<'tcx>,
167 b: ty::Region<'tcx>,
168 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
169 debug!("{}.regions({:?}, {:?}) self.cause={:?}", self.tag(), a, b, self.fields.cause);
476ff2be 170
c1a9b12d
SL
171 // FIXME -- we have more fine-grained information available
172 // from the "cause" field, we could perhaps give more tailored
173 // error messages.
94222f64 174 let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
74b04a01
XL
175 self.fields
176 .infcx
177 .inner
178 .borrow_mut()
179 .unwrap_region_constraints()
180 .make_subregion(origin, a, b);
476ff2be 181
c34b1796
AL
182 Ok(a)
183 }
184
48663c56
XL
185 fn consts(
186 &mut self,
5099ac24
FG
187 a: ty::Const<'tcx>,
188 b: ty::Const<'tcx>,
189 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
e1599b0c 190 self.fields.infcx.super_combine_consts(self, a, b)
48663c56
XL
191 }
192
dfeec247
XL
193 fn binders<T>(
194 &mut self,
cdc7bbd5
XL
195 a: ty::Binder<'tcx, T>,
196 b: ty::Binder<'tcx, T>,
197 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
dfeec247
XL
198 where
199 T: Relate<'tcx>,
1a4d82fc 200 {
5bcae85e 201 self.fields.higher_ranked_sub(a, b, self.a_is_expected)
1a4d82fc
JJ
202 }
203}
f9f354fc
XL
204
205impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> {
5099ac24 206 fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
f9f354fc
XL
207 self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
208 }
209}