1use rustc_hir::def_id::DefId;
21use rustc_middle::traits::solve::Goal;
22use rustc_middle::ty::relate::combine::{combine_ty_args, super_combine_consts, super_combine_tys};
23use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
24use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
25use rustc_span::Span;
26use tracing::{debug, instrument};
27
28use super::combine::PredicateEmittingRelation;
29use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
30use crate::traits::{Obligation, PredicateObligations};
31
32#[derive(#[automatically_derived]
impl ::core::clone::Clone for LatticeOpKind {
#[inline]
fn clone(&self) -> LatticeOpKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LatticeOpKind { }Copy)]
33pub(crate) enum LatticeOpKind {
34 Glb,
35 Lub,
36}
37
38impl LatticeOpKind {
39 fn invert(self) -> Self {
40 match self {
41 LatticeOpKind::Glb => LatticeOpKind::Lub,
42 LatticeOpKind::Lub => LatticeOpKind::Glb,
43 }
44 }
45}
46
47pub(crate) struct LatticeOp<'infcx, 'tcx> {
49 infcx: &'infcx InferCtxt<'tcx>,
50 trace: TypeTrace<'tcx>,
52 param_env: ty::ParamEnv<'tcx>,
53 kind: LatticeOpKind,
55 obligations: PredicateObligations<'tcx>,
56}
57
58impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
59 pub(crate) fn new(
60 infcx: &'infcx InferCtxt<'tcx>,
61 trace: TypeTrace<'tcx>,
62 param_env: ty::ParamEnv<'tcx>,
63 kind: LatticeOpKind,
64 ) -> LatticeOp<'infcx, 'tcx> {
65 LatticeOp { infcx, trace, param_env, kind, obligations: PredicateObligations::new() }
66 }
67
68 pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> {
69 self.obligations
70 }
71}
72
73impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
74 fn cx(&self) -> TyCtxt<'tcx> {
75 self.infcx.tcx
76 }
77
78 fn relate_ty_args(
79 &mut self,
80 a_ty: Ty<'tcx>,
81 b_ty: Ty<'tcx>,
82 def_id: DefId,
83 a_args: ty::GenericArgsRef<'tcx>,
84 b_args: ty::GenericArgsRef<'tcx>,
85 mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
86 ) -> RelateResult<'tcx, Ty<'tcx>> {
87 let variances = self.cx().variances_of(def_id);
88 combine_ty_args(self.infcx, self, a_ty, b_ty, variances, a_args, b_args, |args| mk(args))
89 }
90
91 fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
92 &mut self,
93 variance: ty::Variance,
94 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
95 a: T,
96 b: T,
97 ) -> RelateResult<'tcx, T> {
98 match variance {
99 ty::Invariant => {
100 self.obligations.extend(
101 self.infcx
102 .at(&self.trace.cause, self.param_env)
103 .eq_trace(DefineOpaqueTypes::Yes, self.trace.clone(), a, b)?
104 .into_obligations(),
105 );
106 Ok(a)
107 }
108 ty::Covariant => self.relate(a, b),
109 ty::Bivariant => Ok(a),
111 ty::Contravariant => {
112 self.kind = self.kind.invert();
113 let res = self.relate(a, b);
114 self.kind = self.kind.invert();
115 res
116 }
117 }
118 }
119
120 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("tys",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(121u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: RelateResult<'tcx, Ty<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
if a == b { return Ok(a); }
let infcx = self.infcx;
let a = infcx.shallow_resolve(a);
let b = infcx.shallow_resolve(b);
match (a.kind(), b.kind()) {
(&ty::Infer(TyVar(..)), _) => {
let v = infcx.next_ty_var(self.trace.cause.span);
self.relate_bound(v, b, a)?;
Ok(v)
}
(_, &ty::Infer(TyVar(..))) => {
let v = infcx.next_ty_var(self.trace.cause.span);
self.relate_bound(v, a, b)?;
Ok(v)
}
(&ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id: a_def_id }, .. }),
&ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id: b_def_id }, .. })) if
a_def_id == b_def_id =>
super_combine_tys(infcx, self, a, b),
(&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
}), _) |
(_,
&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
})) if def_id.is_local() && !infcx.next_trait_solver() => {
self.register_goals(infcx.handle_opaque_type(a, b,
self.span(), self.param_env())?);
Ok(a)
}
_ => super_combine_tys(infcx, self, a, b),
}
}
}
}#[instrument(skip(self), level = "trace")]
122 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
123 if a == b {
124 return Ok(a);
125 }
126
127 let infcx = self.infcx;
128
129 let a = infcx.shallow_resolve(a);
130 let b = infcx.shallow_resolve(b);
131
132 match (a.kind(), b.kind()) {
133 (&ty::Infer(TyVar(..)), _) => {
152 let v = infcx.next_ty_var(self.trace.cause.span);
153 self.relate_bound(v, b, a)?;
154 Ok(v)
155 }
156 (_, &ty::Infer(TyVar(..))) => {
157 let v = infcx.next_ty_var(self.trace.cause.span);
158 self.relate_bound(v, a, b)?;
159 Ok(v)
160 }
161
162 (
163 &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }),
164 &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }),
165 ) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b),
166
167 (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _)
168 | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }))
169 if def_id.is_local() && !infcx.next_trait_solver() =>
170 {
171 self.register_goals(infcx.handle_opaque_type(
172 a,
173 b,
174 self.span(),
175 self.param_env(),
176 )?);
177 Ok(a)
178 }
179
180 _ => super_combine_tys(infcx, self, a, b),
181 }
182 }
183
184 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("regions",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(184u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
RelateResult<'tcx, ty::Region<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let origin =
SubregionOrigin::Subtype(Box::new(self.trace.clone()));
let mut inner = self.infcx.inner.borrow_mut();
let mut constraints = inner.unwrap_region_constraints();
Ok(match self.kind {
LatticeOpKind::Glb =>
constraints.lub_regions(self.cx(), origin, a, b),
LatticeOpKind::Lub =>
constraints.glb_regions(self.cx(), origin, a, b),
})
}
}
}#[instrument(skip(self), level = "trace")]
185 fn regions(
186 &mut self,
187 a: ty::Region<'tcx>,
188 b: ty::Region<'tcx>,
189 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
190 let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
191 let mut inner = self.infcx.inner.borrow_mut();
192 let mut constraints = inner.unwrap_region_constraints();
193 Ok(match self.kind {
194 LatticeOpKind::Glb => constraints.lub_regions(self.cx(), origin, a, b),
196
197 LatticeOpKind::Lub => constraints.glb_regions(self.cx(), origin, a, b),
199 })
200 }
201
202 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("consts",
"rustc_infer::infer::relate::lattice",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(202u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
RelateResult<'tcx, ty::Const<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{ super_combine_consts(self.infcx, self, a, b) }
}
}#[instrument(skip(self), level = "trace")]
203 fn consts(
204 &mut self,
205 a: ty::Const<'tcx>,
206 b: ty::Const<'tcx>,
207 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
208 super_combine_consts(self.infcx, self, a, b)
209 }
210
211 fn binders<T>(
212 &mut self,
213 a: ty::Binder<'tcx, T>,
214 b: ty::Binder<'tcx, T>,
215 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
216 where
217 T: Relate<TyCtxt<'tcx>>,
218 {
219 if a == b {
221 return Ok(a);
222 }
223
224 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/lattice.rs:224",
"rustc_infer::infer::relate::lattice",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/lattice.rs"),
::tracing_core::__macro_support::Option::Some(224u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::lattice"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("binders(a={0:?}, b={1:?})",
a, b) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("binders(a={:?}, b={:?})", a, b);
225 if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
226 self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
230 Ok(a)
231 } else {
232 Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
233 }
234 }
235}
236
237impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> {
238 fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
245 let at = self.infcx.at(&self.trace.cause, self.param_env);
246 match self.kind {
247 LatticeOpKind::Glb => {
248 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, a)?.into_obligations());
249 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, b)?.into_obligations());
250 }
251 LatticeOpKind::Lub => {
252 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, a, v)?.into_obligations());
253 self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, b, v)?.into_obligations());
254 }
255 }
256 Ok(())
257 }
258}
259
260impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
261 fn span(&self) -> Span {
262 self.trace.span()
263 }
264
265 fn param_env(&self) -> ty::ParamEnv<'tcx> {
266 self.param_env
267 }
268
269 fn register_predicates(
270 &mut self,
271 preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
272 ) {
273 self.obligations.extend(preds.into_iter().map(|pred| {
274 Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
275 }))
276 }
277
278 fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
279 self.obligations.extend(goals.into_iter().map(|goal| {
280 Obligation::new(
281 self.infcx.tcx,
282 self.trace.cause.clone(),
283 goal.param_env,
284 goal.predicate,
285 )
286 }))
287 }
288
289 fn ambient_variance(&self) -> ty::Variance {
290 ty::Variance::Invariant
292 }
293}