1use std::mem;
23use rustc_data_structures::sso::SsoHashMap;
4use rustc_data_structures::stack::ensure_sufficient_stack;
5use rustc_hir::def_id::DefId;
6use rustc_middle::bug;
7use rustc_middle::ty::error::TypeError;
8use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
9use rustc_span::Span;
10use tracing::{debug, instrument, warn};
1112use super::{
13PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
14};
15use crate::infer::type_variable::TypeVariableValue;
16use crate::infer::unify_key::ConstVariableValue;
17use crate::infer::{InferCtxt, RegionVariableOrigin, relate};
1819#[derive(#[automatically_derived]
impl ::core::marker::Copy for TermVid { }Copy, #[automatically_derived]
impl ::core::clone::Clone for TermVid {
#[inline]
fn clone(&self) -> TermVid {
let _: ::core::clone::AssertParamIsClone<ty::TyVid>;
let _: ::core::clone::AssertParamIsClone<ty::ConstVid>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for TermVid {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ty::TyVid>;
let _: ::core::cmp::AssertParamIsEq<ty::ConstVid>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for TermVid {
#[inline]
fn eq(&self, other: &TermVid) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TermVid::Ty(__self_0), TermVid::Ty(__arg1_0)) =>
__self_0 == __arg1_0,
(TermVid::Const(__self_0), TermVid::Const(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for TermVid {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
TermVid::Ty(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ty",
&__self_0),
TermVid::Const(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Const",
&__self_0),
}
}
}Debug)]
20enum TermVid {
21 Ty(ty::TyVid),
22 Const(ty::ConstVid),
23}
2425impl From<ty::TyVid> for TermVid {
26fn from(value: ty::TyVid) -> Self {
27 TermVid::Ty(value)
28 }
29}
3031impl From<ty::ConstVid> for TermVid {
32fn from(value: ty::ConstVid) -> Self {
33 TermVid::Const(value)
34 }
35}
3637impl<'tcx> InferCtxt<'tcx> {
38/// The idea is that we should ensure that the type variable `target_vid`
39 /// is equal to, a subtype of, or a supertype of `source_ty`.
40 ///
41 /// For this, we will instantiate `target_vid` with a *generalized* version
42 /// of `source_ty`. Generalization introduces other inference variables wherever
43 /// subtyping could occur. This also does the occurs checks, detecting whether
44 /// instantiating `target_vid` would result in a cyclic type. We eagerly error
45 /// in this case.
46 ///
47 /// This is *not* expected to be used anywhere except for an implementation of
48 /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
49 /// other usecases (i.e. setting the value of a type var).
50#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::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("instantiate_ty_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(50u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "instantiation_variance", "source_ty"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ty)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()
{
::core::panicking::panic("assertion failed: self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()")
};
};
self.instantiate_var(relation, target_is_expected,
target_vid.into(), instantiation_variance, source_ty.into())
}
}
}#[instrument(level = "debug", skip(self, relation))]51pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
52&self,
53 relation: &mut R,
54 target_is_expected: bool,
55 target_vid: ty::TyVid,
56 instantiation_variance: ty::Variance,
57 source_ty: Ty<'tcx>,
58 ) -> RelateResult<'tcx, ()> {
59debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
6061self.instantiate_var(
62 relation,
63 target_is_expected,
64 target_vid.into(),
65 instantiation_variance,
66 source_ty.into(),
67 )
68 }
6970/// Instantiates the const variable `target_vid` with the given constant.
71 ///
72 /// This also tests if the given const `ct` contains an inference variable which was previously
73 /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
74 /// would result in an infinite type as we continuously replace an inference variable
75 /// in `ct` with `ct` itself.
76 ///
77 /// This is especially important as alias consts use their parents generics.
78 /// They therefore often contain unused args, making these errors far more likely.
79 ///
80 /// A good example of this is the following:
81 ///
82 /// ```compile_fail,E0308
83 /// #![feature(generic_const_exprs)]
84 ///
85 /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
86 /// todo!()
87 /// }
88 ///
89 /// fn main() {
90 /// let mut arr = Default::default();
91 /// arr = bind(arr);
92 /// }
93 /// ```
94 ///
95 /// Here `3 + 4` ends up as `ConstKind::Alias` which uses the generics
96 /// of `fn bind` (meaning that its args contain `N`).
97 ///
98 /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
99 /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
100 ///
101 /// As `3 + 4` contains `N` in its args, this must not succeed.
102 ///
103 /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
104#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::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("instantiate_const_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(104u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "source_ct"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ct)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
{
::core::panicking::panic("assertion failed: self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()")
};
};
self.instantiate_var(relation, target_is_expected,
target_vid.into(), ty::Invariant, source_ct.into())
}
}
}#[instrument(level = "debug", skip(self, relation))]105pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
106&self,
107 relation: &mut R,
108 target_is_expected: bool,
109 target_vid: ty::ConstVid,
110 source_ct: ty::Const<'tcx>,
111 ) -> RelateResult<'tcx, ()> {
112// FIXME(generic_const_exprs): Occurs check failures for alias consts
113 // and generic expressions are not yet handled correctly.
114debug_assert!(
115self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
116 );
117118self.instantiate_var(
119 relation,
120 target_is_expected,
121 target_vid.into(),
122 ty::Invariant,
123 source_ct.into(),
124 )
125 }
126127#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::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("instantiate_var",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(127u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["target_is_expected",
"target_vid", "instantiation_variance", "source_term"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&target_is_expected
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_term)
as &dyn 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, ()> = loop {};
return __tracing_attr_fake_return;
}
{
let Generalization { value_may_be_infer: generalized_term } =
self.generalize(relation.span(),
relation.structurally_relate_aliases(), target_vid,
instantiation_variance, source_term)?;
self.union_var_term(target_vid, generalized_term);
if generalized_term.is_infer() {
let Some(source_alias) =
source_term.to_alias_term() else {
::rustc_middle::util::bug::bug_fmt(format_args!("generalized `{0:?} to infer, not an alias",
source_term));
};
if self.next_trait_solver() {
if let Some(generalized_ty) = generalized_term.as_type() {
match instantiation_variance {
ty::Invariant =>
relation.register_predicates([ty::ProjectionPredicate {
projection_term: source_alias.into(),
term: generalized_ty.into(),
}]),
ty::Covariant => {
let new_var = self.next_ty_var(relation.span());
relation.register_predicates([ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: !target_is_expected,
a: new_var,
b: generalized_ty,
}),
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term: source_alias.into(),
term: new_var.into(),
}))]);
}
ty::Contravariant => {
let new_var = self.next_ty_var(relation.span());
relation.register_predicates([ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: target_is_expected,
a: generalized_ty,
b: new_var,
}),
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_term: source_alias.into(),
term: new_var.into(),
}))]);
}
ty::Bivariant => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("bivariant generalization")));
}
}
} else {
if true {
{
match (&instantiation_variance, &ty::Variance::Invariant) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
relation.register_predicates([ty::ProjectionPredicate {
projection_term: source_alias,
term: generalized_term,
}]);
}
} else {
match source_alias.kind {
ty::AliasTermKind::ProjectionTy { .. } |
ty::AliasTermKind::ProjectionConst { .. } => {
relation.register_predicates([ty::ProjectionPredicate {
projection_term: source_alias,
term: generalized_term,
}]);
}
ty::AliasTermKind::InherentTy { .. } |
ty::AliasTermKind::FreeTy { .. } |
ty::AliasTermKind::OpaqueTy { .. } => {
return Err(TypeError::CyclicTy(source_term.expect_type()));
}
ty::AliasTermKind::InherentConst { .. } |
ty::AliasTermKind::FreeConst { .. } |
ty::AliasTermKind::AnonConst { .. } => {
return Err(TypeError::CyclicConst(source_term.expect_const()));
}
}
}
} else {
match generalized_term.kind() {
ty::TermKind::Ty(_) => {
if target_is_expected {
relation.relate(generalized_term, source_term)?;
} else {
{
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/generalize.rs:271",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(271u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("flip relation")
as &dyn Value))])
});
} else { ; }
};
relation.relate(source_term, generalized_term)?;
}
}
ty::TermKind::Const(_) => {
if target_is_expected {
relation.relate_with_variance(ty::Invariant,
ty::VarianceDiagInfo::default(), generalized_term,
source_term)?;
} else {
relation.relate_with_variance(ty::Invariant,
ty::VarianceDiagInfo::default(), source_term,
generalized_term)?;
}
}
}
}
Ok(())
}
}
}#[instrument(level = "debug", skip(self, relation))]128fn instantiate_var<R: PredicateEmittingRelation<Self>>(
129&self,
130 relation: &mut R,
131 target_is_expected: bool,
132 target_vid: TermVid,
133 instantiation_variance: ty::Variance,
134 source_term: Term<'tcx>,
135 ) -> RelateResult<'tcx, ()> {
136// Generalize `source_term` depending on the current variance. As an example, assume
137 // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
138 // variable.
139 //
140 // Then the `generalized_term` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
141 // region/type inference variables.
142 //
143 // We then relate `generalized_term <: source_term`, adding constraints like `'x: '?2` and
144 // `?1 <: ?3`.
145let Generalization { value_may_be_infer: generalized_term } = self.generalize(
146 relation.span(),
147 relation.structurally_relate_aliases(),
148 target_vid,
149 instantiation_variance,
150 source_term,
151 )?;
152153// Constrain `b_vid` to the generalized type `generalized_term`.
154self.union_var_term(target_vid, generalized_term);
155156// Finally, relate `generalized_term` to `source_term`, as described in previous comment.
157 //
158 // FIXME(#16847): This code is non-ideal because all these subtype
159 // relations wind up attributed to the same spans. We need
160 // to associate causes/spans with each of the relations in
161 // the stack to get this right.
162if generalized_term.is_infer() {
163// This happens for cases like `<?0 as Trait>::Assoc == ?0`.
164 // We can't instantiate `?0` here as that would result in a
165 // cyclic type. We instead delay the unification in case
166 // the alias can be normalized to something which does not
167 // mention `?0`.
168let Some(source_alias) = source_term.to_alias_term() else {
169bug!("generalized `{source_term:?} to infer, not an alias");
170 };
171if self.next_trait_solver() {
172if let Some(generalized_ty) = generalized_term.as_type() {
173match instantiation_variance {
174 ty::Invariant => relation.register_predicates([ty::ProjectionPredicate {
175 projection_term: source_alias.into(),
176 term: generalized_ty.into(),
177 }]),
178 ty::Covariant => {
179// Generate a new var, then do:
180 // `source_alias == ?A && ?A <: generalized_ty`
181let new_var = self.next_ty_var(relation.span());
182 relation.register_predicates([
183 ty::PredicateKind::Subtype(ty::SubtypePredicate {
184 a_is_expected: !target_is_expected,
185 a: new_var,
186 b: generalized_ty,
187 }),
188 ty::PredicateKind::Clause(ty::ClauseKind::Projection(
189 ty::ProjectionPredicate {
190 projection_term: source_alias.into(),
191 term: new_var.into(),
192 },
193 )),
194 ]);
195 }
196 ty::Contravariant => {
197// a :> b is b <: a
198let new_var = self.next_ty_var(relation.span());
199 relation.register_predicates([
200 ty::PredicateKind::Subtype(ty::SubtypePredicate {
201 a_is_expected: target_is_expected,
202 a: generalized_ty,
203 b: new_var,
204 }),
205 ty::PredicateKind::Clause(ty::ClauseKind::Projection(
206 ty::ProjectionPredicate {
207 projection_term: source_alias.into(),
208 term: new_var.into(),
209 },
210 )),
211 ]);
212 }
213 ty::Bivariant => unreachable!("bivariant generalization"),
214 }
215 } else {
216debug_assert_eq!(instantiation_variance, ty::Variance::Invariant);
217 relation.register_predicates([ty::ProjectionPredicate {
218 projection_term: source_alias,
219 term: generalized_term,
220 }]);
221 }
222 } else {
223match source_alias.kind {
224 ty::AliasTermKind::ProjectionTy { .. }
225 | ty::AliasTermKind::ProjectionConst { .. } => {
226// FIXME: This does not handle subtyping correctly, we could
227 // instead create a new inference variable `?normalized_source`, emitting
228 // `Projection(normalized_source, ?ty_normalized)` and
229 // `?normalized_source <: generalized_term`.
230relation.register_predicates([ty::ProjectionPredicate {
231 projection_term: source_alias,
232 term: generalized_term,
233 }]);
234 }
235// The old solver only accepts projection predicates for associated types.
236ty::AliasTermKind::InherentTy { .. }
237 | ty::AliasTermKind::FreeTy { .. }
238 | ty::AliasTermKind::OpaqueTy { .. } => {
239return Err(TypeError::CyclicTy(source_term.expect_type()));
240 }
241 ty::AliasTermKind::InherentConst { .. }
242 | ty::AliasTermKind::FreeConst { .. }
243 | ty::AliasTermKind::AnonConst { .. } => {
244return Err(TypeError::CyclicConst(source_term.expect_const()));
245 }
246 }
247 }
248 } else {
249// NOTE: The `instantiation_variance` is not the same variance as
250 // used by the relation. When instantiating `b`, `target_is_expected`
251 // is flipped and the `instantiation_variance` is also flipped. To
252 // constrain the `generalized_term` while using the original relation,
253 // we therefore only have to flip the arguments.
254 //
255 // ```ignore (not code)
256 // ?a rel B
257 // instantiate_ty_var(?a, B) # expected and variance not flipped
258 // B' rel B
259 // ```
260 // or
261 // ```ignore (not code)
262 // A rel ?b
263 // instantiate_ty_var(?b, A) # expected and variance flipped
264 // A rel A'
265 // ```
266match generalized_term.kind() {
267 ty::TermKind::Ty(_) => {
268if target_is_expected {
269 relation.relate(generalized_term, source_term)?;
270 } else {
271debug!("flip relation");
272 relation.relate(source_term, generalized_term)?;
273 }
274 }
275 ty::TermKind::Const(_) => {
276// Override consts to always be invariant
277if target_is_expected {
278 relation.relate_with_variance(
279 ty::Invariant,
280 ty::VarianceDiagInfo::default(),
281 generalized_term,
282 source_term,
283 )?;
284 } else {
285 relation.relate_with_variance(
286 ty::Invariant,
287 ty::VarianceDiagInfo::default(),
288 source_term,
289 generalized_term,
290 )?;
291 }
292 }
293 }
294 }
295296Ok(())
297 }
298299/// This is a thin wrapper around inserting into the var tables. You probably want
300 /// [`Self::instantiate_var`] instead, which calls this method.
301fn union_var_term(&self, l: TermVid, r: ty::Term<'tcx>) {
302match (l, r.kind()) {
303 (TermVid::Ty(l), ty::TermKind::Ty(r)) => {
304if let Some(r) = r.ty_vid() {
305self.inner.borrow_mut().type_variables().equate(l, r)
306 } else {
307self.inner.borrow_mut().type_variables().instantiate(l, r)
308 }
309 }
310 (TermVid::Const(l), ty::TermKind::Const(r)) => {
311if let Some(r) = r.ct_vid() {
312self.inner.borrow_mut().const_unification_table().union(l, r)
313 } else {
314self.inner
315 .borrow_mut()
316 .const_unification_table()
317 .union_value(l, ConstVariableValue::Known { value: r })
318 }
319 }
320_ => ::rustc_middle::util::bug::bug_fmt(format_args!("mismatched term kinds in generalize: {0:?}, {1:?}",
l, r))bug!("mismatched term kinds in generalize: {l:?}, {r:?}"),
321 }
322 }
323324/// Attempts to generalize `source_term` for the type variable `target_vid`.
325 /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
326fn generalize(
327&self,
328 span: Span,
329 structurally_relate_aliases: StructurallyRelateAliases,
330 target_vid: TermVid,
331 ambient_variance: ty::Variance,
332 source_term: Term<'tcx>,
333 ) -> RelateResult<'tcx, Generalization<Term<'tcx>>> {
334if !!source_term.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !source_term.has_escaping_bound_vars()")
};assert!(!source_term.has_escaping_bound_vars());
335let (for_universe, root_vid) = match target_vid {
336 TermVid::Ty(ty_vid) => {
337 (self.try_resolve_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid)))
338 }
339 TermVid::Const(ct_vid) => (
340self.try_resolve_const_var(ct_vid).unwrap_err(),
341 TermVid::Const(self.inner.borrow_mut().const_unification_table().find(ct_vid).vid),
342 ),
343 };
344345let mut generalizer = Generalizer {
346 infcx: self,
347span,
348structurally_relate_aliases,
349root_vid,
350for_universe,
351 root_term: source_term,
352ambient_variance,
353 in_alias: false,
354 cache: Default::default(),
355 };
356357let value_may_be_infer = generalizer.relate(source_term, source_term)?;
358Ok(Generalization { value_may_be_infer })
359 }
360}
361362/// The "generalizer" is used when handling inference variables.
363///
364/// The basic strategy for handling a constraint like `?A <: B` is to
365/// apply a "generalization strategy" to the term `B` -- this replaces
366/// all the lifetimes in the term `B` with fresh inference variables.
367/// (You can read more about the strategy in this [blog post].)
368///
369/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
370/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
371/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
372/// establishes `'0: 'x` as a constraint.
373///
374/// [blog post]: https://is.gd/0hKvIr
375struct Generalizer<'me, 'tcx> {
376 infcx: &'me InferCtxt<'tcx>,
377378 span: Span,
379380/// Whether aliases should be related structurally. If not, we have to
381 /// be careful when generalizing aliases.
382structurally_relate_aliases: StructurallyRelateAliases,
383384/// The vid of the type variable that is in the process of being
385 /// instantiated. If we find this within the value we are folding,
386 /// that means we would have created a cyclic value.
387root_vid: TermVid,
388389/// The universe of the type variable that is in the process of being
390 /// instantiated. If we find anything that this universe cannot name,
391 /// we reject the relation.
392for_universe: ty::UniverseIndex,
393394/// The root term (const or type) we're generalizing. Used for cycle errors.
395root_term: Term<'tcx>,
396397/// After we generalize this type, we are going to relate it to
398 /// some other type. What will be the variance at this point?
399ambient_variance: ty::Variance,
400401/// This is set once we're generalizing the arguments of an alias.
402 ///
403 /// This is necessary to correctly handle
404 /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
405 /// hold by either normalizing the outer or the inner associated type.
406in_alias: bool,
407408 cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
409}
410411impl<'tcx> Generalizer<'_, 'tcx> {
412/// Create an error that corresponds to the term kind in `root_term`
413fn cyclic_term_error(&self) -> TypeError<'tcx> {
414match self.root_term.kind() {
415 ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
416 ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
417 }
418 }
419420/// Create a new type variable in the universe of the target when
421 /// generalizing an alias.
422fn next_var_for_alias_of_kind(&self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
423if alias.kind.is_type() {
424self.infcx.next_ty_var_in_universe(self.span, self.for_universe).into()
425 } else {
426self.infcx.next_const_var_in_universe(self.span, self.for_universe).into()
427 }
428 }
429430/// We only handle potentially normalizable aliases via this method. For rigid alias,
431 /// we always generalize structurally.
432 ///
433 /// An occurs check failure inside of an alias does not mean
434 /// that the types definitely don't unify. We may be able
435 /// to normalize the alias after all.
436 ///
437 /// We handle this by lazily equating the normalizable alias
438 /// and generalizing it to an inference variable. In the new solver,
439 /// we always generalize to an infer var unless the alias contains escaping
440 /// bound variables.
441 ///
442 /// Correctly handling aliases with escaping bound variables is
443 /// difficult and currently incomplete in two opposite ways:
444 /// - if we get an occurs check failure in the alias, replace it with a new infer var.
445 /// This causes us to later emit an alias-relate goal and is incomplete in case the
446 /// alias normalizes to type containing one of the bound variables.
447 /// - if the alias contains an inference variable not nameable by `for_universe`, we
448 /// continue generalizing the alias. This ends up pulling down the universe of the
449 /// inference variable and is incomplete in case the alias would normalize to a type
450 /// which does not mention that inference variable.
451fn generalize_alias_term(
452&mut self,
453 alias: ty::AliasTerm<'tcx>,
454 ) -> Result<Term<'tcx>, TypeError<'tcx>> {
455// We do not eagerly replace aliases with inference variables if they have
456 // escaping bound vars, see the method comment for details. However, when we
457 // are inside of an alias with escaping bound vars replacing nested aliases
458 // with inference variables can cause incorrect ambiguity.
459 //
460 // cc trait-system-refactor-initiative#110
461if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
462return Ok(self.next_var_for_alias_of_kind(alias));
463 }
464465let is_nested_alias = mem::replace(&mut self.in_alias, true);
466let result = match self.relate(alias, alias) {
467Ok(alias) => Ok(alias.to_term(self.cx(), ty::IsRigid::No)),
468Err(e) => {
469if is_nested_alias {
470return Err(e);
471 } else {
472let alias_max_universe = ty::max_universe_of_placeholders(self.infcx, alias);
473let infer_replacement_is_complete =
474self.for_universe.can_name(alias_max_universe)
475 && !alias.has_escaping_bound_vars();
476if !infer_replacement_is_complete {
477{
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/generalize.rs:477",
"rustc_infer::infer::relate::generalize",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(477u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("may incompletely handle alias type: {0:?}",
alias) as &dyn Value))])
});
} else { ; }
};warn!("may incompletely handle alias type: {alias:?}");
478 }
479480{
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/generalize.rs:480",
"rustc_infer::infer::relate::generalize",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
::tracing_core::__macro_support::Option::Some(480u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("generalization failure in alias")
as &dyn Value))])
});
} else { ; }
};debug!("generalization failure in alias");
481Ok(self.next_var_for_alias_of_kind(alias))
482 }
483 }
484 };
485self.in_alias = is_nested_alias;
486result487 }
488}
489490impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
491fn cx(&self) -> TyCtxt<'tcx> {
492self.infcx.tcx
493 }
494495fn relate_ty_args(
496&mut self,
497 a_ty: Ty<'tcx>,
498_: Ty<'tcx>,
499 def_id: DefId,
500 a_args: ty::GenericArgsRef<'tcx>,
501 b_args: ty::GenericArgsRef<'tcx>,
502 mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
503 ) -> RelateResult<'tcx, Ty<'tcx>> {
504let args = if self.ambient_variance == ty::Invariant {
505// Avoid fetching the variance if we are in an invariant
506 // context; no need, and it can induce dependency cycles
507 // (e.g., #41849).
508relate::relate_args_invariantly(self, a_args, b_args)
509 } else {
510let tcx = self.cx();
511let variances = tcx.variances_of(def_id);
512 relate::relate_args_with_variances(self, variances, a_args, b_args)
513 }?;
514if args == a_args { Ok(a_ty) } else { Ok(mk(args)) }
515 }
516517x;#[instrument(level = "debug", skip(self, variance, b), ret)]518fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
519&mut self,
520 variance: ty::Variance,
521 _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
522 a: T,
523 b: T,
524 ) -> RelateResult<'tcx, T> {
525let old_ambient_variance = self.ambient_variance;
526self.ambient_variance = self.ambient_variance.xform(variance);
527debug!(?self.ambient_variance, "new ambient variance");
528// Recursive calls to `relate` can overflow the stack. For example a deeper version of
529 // `ui/associated-consts/issue-93775.rs`.
530let r = ensure_sufficient_stack(|| self.relate(a, b));
531self.ambient_variance = old_ambient_variance;
532 r
533 }
534535x;#[instrument(level = "debug", skip(self, t2), ret)]536fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
537assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
538539if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
540return Ok(result);
541 }
542543// Check to see whether the type we are generalizing references
544 // any other type variable related to `vid` via
545 // subtyping. This is basically our "occurs check", preventing
546 // us from creating infinitely sized types.
547let g = match *t.kind() {
548 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
549bug!("unexpected infer type: {t}")
550 }
551552 ty::Infer(ty::TyVar(vid)) => {
553let mut inner = self.infcx.inner.borrow_mut();
554let vid = inner.type_variables().root_var(vid);
555if TermVid::Ty(vid) == self.root_vid {
556// If sub-roots are equal, then `root_vid` and
557 // `vid` are related via subtyping.
558Err(self.cyclic_term_error())
559 } else {
560let probe = inner.type_variables().probe(vid);
561match probe {
562 TypeVariableValue::Known { value: u } => {
563 drop(inner);
564self.relate(u, u)
565 }
566 TypeVariableValue::Unknown { universe } => {
567match self.ambient_variance {
568// Invariant: no need to make a fresh type variable
569 // if we can name the universe.
570ty::Invariant => {
571if self.for_universe.can_name(universe) {
572return Ok(t);
573 }
574 }
575576// We do need a fresh type variable otherwise.
577ty::Bivariant | ty::Covariant | ty::Contravariant => (),
578 }
579580let origin = inner.type_variables().var_origin(vid);
581let new_var_id =
582 inner.type_variables().new_var(self.for_universe, origin);
583// Record that `vid` and `new_var_id` have to be subtypes
584 // of each other. This is currently only used for diagnostics.
585 // To see why, see the docs in the `type_variables` module.
586inner.type_variables().sub_unify(vid, new_var_id);
587// If we're in the new solver and create a new inference
588 // variable inside of an alias we eagerly constrain that
589 // inference variable to prevent unexpected ambiguity errors.
590 //
591 // This is incomplete as it pulls down the universe of the
592 // original inference variable, even though the alias could
593 // normalize to a type which does not refer to that type at
594 // all. I don't expect this to cause unexpected errors in
595 // practice.
596 //
597 // We only need to do so for type and const variables, as
598 // region variables do not impact normalization, and will get
599 // correctly constrained by `AliasRelate` later on.
600 //
601 // cc trait-system-refactor-initiative#108
602if self.infcx.next_trait_solver()
603 && !self.infcx.typing_mode_raw().is_coherence()
604 && self.in_alias
605 {
606 inner.type_variables().equate(vid, new_var_id);
607 }
608609debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
610Ok(Ty::new_var(self.cx(), new_var_id))
611 }
612 }
613 }
614 }
615616 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
617// No matter what mode we are in,
618 // integer/floating-point types must be equal to be
619 // relatable.
620Ok(t)
621 }
622623 ty::Placeholder(placeholder) => {
624if self.for_universe.can_name(placeholder.universe) {
625Ok(t)
626 } else {
627debug!(
628"root universe {:?} cannot name placeholder in universe {:?}",
629self.for_universe, placeholder.universe
630 );
631Err(TypeError::Mismatch)
632 }
633 }
634635// We only need to be careful with potentially normalizeable
636 // aliases here. See `generalize_alias_term` for more information.
637ty::Alias(ty::IsRigid::No, data) => match self.structurally_relate_aliases {
638 StructurallyRelateAliases::No => {
639self.generalize_alias_term(data.into()).map(|v| v.expect_type())
640 }
641 StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
642 },
643644_ => relate::structurally_relate_tys(self, t, t),
645 }?;
646647self.cache.insert((t, self.ambient_variance, self.in_alias), g);
648Ok(g)
649 }
650651x;#[instrument(level = "debug", skip(self, r2), ret)]652fn regions(
653&mut self,
654 r: ty::Region<'tcx>,
655 r2: ty::Region<'tcx>,
656 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
657assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
658659match r.kind() {
660// Never make variables for regions bound within the type itself,
661 // nor for erased regions.
662ty::ReBound(..) | ty::ReErased => {
663return Ok(r);
664 }
665666// It doesn't really matter for correctness if we generalize ReError,
667 // since we're already on a doomed compilation path.
668ty::ReError(_) => {
669return Ok(r);
670 }
671672 ty::RePlaceholder(..)
673 | ty::ReVar(..)
674 | ty::ReStatic
675 | ty::ReEarlyParam(..)
676 | ty::ReLateParam(..) => {
677// see common code below
678}
679 }
680681// If we are in an invariant context, we can re-use the region
682 // as is, unless it happens to be in some universe that we
683 // can't name.
684if let ty::Invariant = self.ambient_variance {
685let r_universe = self.infcx.universe_of_region(r);
686if self.for_universe.can_name(r_universe) {
687return Ok(r);
688 }
689 }
690691Ok(self
692.infcx
693 .next_region_var_in_universe(RegionVariableOrigin::Misc(self.span), self.for_universe))
694 }
695696x;#[instrument(level = "debug", skip(self, c2), ret)]697fn consts(
698&mut self,
699 c: ty::Const<'tcx>,
700 c2: ty::Const<'tcx>,
701 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
702let tcx = self.cx();
703assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
704705match c.kind() {
706 ty::ConstKind::Infer(InferConst::Var(vid)) => {
707// If root const vids are equal, then `root_vid` and
708 // `vid` are related and we'd be inferring an infinitely
709 // deep const.
710if TermVid::Const(
711self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid,
712 ) == self.root_vid
713 {
714return Err(self.cyclic_term_error());
715 }
716717let mut inner = self.infcx.inner.borrow_mut();
718let variable_table = &mut inner.const_unification_table();
719match variable_table.probe_value(vid) {
720 ConstVariableValue::Known { value: u } => {
721 drop(inner);
722self.relate(u, u)
723 }
724 ConstVariableValue::Unknown { origin, universe } => {
725if self.for_universe.can_name(universe) {
726Ok(c)
727 } else {
728let new_var_id = variable_table
729 .new_key(ConstVariableValue::Unknown {
730 origin,
731 universe: self.for_universe,
732 })
733 .vid;
734735// See the comment for type inference variables
736 // for more details.
737if self.infcx.next_trait_solver()
738 && !self.infcx.typing_mode_raw().is_coherence()
739 && self.in_alias
740 {
741 variable_table.union(vid, new_var_id);
742 }
743Ok(ty::Const::new_var(tcx, new_var_id))
744 }
745 }
746 }
747 }
748// FIXME: Alias consts are also not rigid, so the current
749 // approach of always relating them structurally is incomplete.
750 //
751 // FIXME: replace the StructurallyRelateAliases::Yes branch with
752 // `structurally_relate_consts` once it is fully structural.
753 //
754 // We only need to be careful with potentially normalizeable
755 // aliases here. See `generalize_alias_term` for more information.
756ty::ConstKind::Alias(ty::IsRigid::No, alias_const) => {
757match self.structurally_relate_aliases {
758// Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
759 // path), as doing this new No path breaks some GCE things. I expect GCE to be
760 // ripped out soon so this shouldn't matter soon.
761StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => {
762self.generalize_alias_term(alias_const.into()).map(|v| v.expect_const())
763 }
764_ => {
765let ty::AliasConst { kind, args, .. } = alias_const;
766let args = self.relate_with_variance(
767 ty::Invariant,
768 ty::VarianceDiagInfo::default(),
769 args,
770 args,
771 )?;
772Ok(ty::Const::new_alias(
773 tcx,
774 ty::IsRigid::No,
775 ty::AliasConst::new(tcx, kind, args),
776 ))
777 }
778 }
779 }
780 ty::ConstKind::Placeholder(placeholder) => {
781if self.for_universe.can_name(placeholder.universe) {
782Ok(c)
783 } else {
784debug!(
785"root universe {:?} cannot name placeholder in universe {:?}",
786self.for_universe, placeholder.universe
787 );
788Err(TypeError::Mismatch)
789 }
790 }
791_ => relate::structurally_relate_consts(self, c, c),
792 }
793 }
794795x;#[instrument(level = "debug", skip(self), ret)]796fn binders<T>(
797&mut self,
798 a: ty::Binder<'tcx, T>,
799_: ty::Binder<'tcx, T>,
800 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
801where
802T: Relate<TyCtxt<'tcx>>,
803 {
804let result = self.relate(a.skip_binder(), a.skip_binder())?;
805Ok(a.rebind(result))
806 }
807}
808809/// Result from a generalization operation. This includes
810/// not only the generalized type, but also a bool flag
811/// indicating whether further WF checks are needed.
812#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for Generalization<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Generalization", "value_may_be_infer", &&self.value_may_be_infer)
}
}Debug)]
813struct Generalization<T> {
814/// When generalizing `<?0 as Trait>::Assoc` or
815 /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
816 /// for `?0` generalization returns an inference
817 /// variable.
818 ///
819 /// This has to be handled with care as it can
820 /// otherwise very easily result in infinite
821 /// recursion.
822pub value_may_be_infer: T,
823}