Skip to main content

rustc_hir_analysis/variance/
constraints.rs

1//! Constraint construction and representation
2//!
3//! The second pass over the HIR determines the set of constraints.
4//! We walk the set of items and, for each member, generate new constraints.
5
6use hir::def_id::{DefId, LocalDefId};
7use rustc_hir as hir;
8use rustc_hir::def::DefKind;
9use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Ty, TyCtxt};
10use rustc_middle::{bug, span_bug};
11use tracing::{debug, instrument};
12
13use super::terms::VarianceTerm::*;
14use super::terms::*;
15
16pub(crate) struct ConstraintContext<'a, 'tcx> {
17    pub terms_cx: TermsContext<'a, 'tcx>,
18
19    // These are pointers to common `ConstantTerm` instances
20    covariant: VarianceTermPtr<'a>,
21    contravariant: VarianceTermPtr<'a>,
22    invariant: VarianceTermPtr<'a>,
23    bivariant: VarianceTermPtr<'a>,
24
25    pub constraints: Vec<Constraint<'a>>,
26}
27
28/// Declares that the variable `decl_id` appears in a location with
29/// variance `variance`.
30#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for Constraint<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for Constraint<'a> {
    #[inline]
    fn clone(&self) -> Constraint<'a> {
        let _: ::core::clone::AssertParamIsClone<InferredIndex>;
        let _: ::core::clone::AssertParamIsClone<&'a VarianceTerm<'a>>;
        *self
    }
}Clone)]
31pub(crate) struct Constraint<'a> {
32    pub inferred: InferredIndex,
33    pub variance: &'a VarianceTerm<'a>,
34}
35
36/// To build constraints, we visit one item (type, trait) at a time
37/// and look at its contents. So e.g., if we have
38/// ```ignore (illustrative)
39/// struct Foo<T> {
40///     b: Bar<T>
41/// }
42/// ```
43/// then while we are visiting `Bar<T>`, the `CurrentItem` would have
44/// the `DefId` and the start of `Foo`'s inferreds.
45struct CurrentItem {
46    inferred_start: InferredIndex,
47}
48
49pub(crate) fn add_constraints_from_crate<'a, 'tcx>(
50    terms_cx: TermsContext<'a, 'tcx>,
51) -> ConstraintContext<'a, 'tcx> {
52    let tcx = terms_cx.tcx;
53    let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant));
54    let contravariant = terms_cx.arena.alloc(ConstantTerm(ty::Contravariant));
55    let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant));
56    let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant));
57    let mut constraint_cx = ConstraintContext {
58        terms_cx,
59        covariant,
60        contravariant,
61        invariant,
62        bivariant,
63        constraints: Vec::new(),
64    };
65
66    let crate_items = tcx.hir_crate_items(());
67
68    for def_id in crate_items.definitions() {
69        let def_kind = tcx.def_kind(def_id);
70        match def_kind {
71            DefKind::Struct | DefKind::Union | DefKind::Enum => {
72                constraint_cx.build_constraints_for_item(def_id);
73
74                let adt = tcx.adt_def(def_id);
75                for variant in adt.variants() {
76                    if let Some(ctor_def_id) = variant.ctor_def_id() {
77                        constraint_cx.build_constraints_for_item(ctor_def_id.expect_local());
78                    }
79                }
80            }
81            DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
82            _ => {}
83        }
84    }
85
86    constraint_cx
87}
88
89impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
90    fn tcx(&self) -> TyCtxt<'tcx> {
91        self.terms_cx.tcx
92    }
93
94    fn build_constraints_for_item(&mut self, def_id: LocalDefId) {
95        let tcx = self.tcx();
96        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/variance/constraints.rs:96",
                        "rustc_hir_analysis::variance::constraints",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                        ::tracing_core::__macro_support::Option::Some(96u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                        ::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!("build_constraints_for_item({0})",
                                                    tcx.def_path_str(def_id)) as &dyn Value))])
            });
    } else { ; }
};debug!("build_constraints_for_item({})", tcx.def_path_str(def_id));
97
98        // Skip items with no generics - there's nothing to infer in them.
99        if tcx.generics_of(def_id).is_empty() {
100            return;
101        }
102
103        let inferred_start = self.terms_cx.inferred_starts[&def_id];
104        let current_item = &CurrentItem { inferred_start };
105        let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
106
107        match ty.kind() {
108            ty::Adt(def, _) => {
109                // Not entirely obvious: constraints on structs/enums do not
110                // affect the variance of their type parameters. See discussion
111                // in comment at top of module.
112                //
113                // self.add_constraints_from_generics(generics);
114
115                for field in def.all_fields() {
116                    self.add_constraints_from_ty(
117                        current_item,
118                        tcx.type_of(field.did).instantiate_identity().skip_norm_wip(),
119                        self.covariant,
120                    );
121                }
122            }
123
124            ty::FnDef(..) => {
125                self.add_constraints_from_sig(
126                    current_item,
127                    tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(),
128                    self.covariant,
129                );
130            }
131
132            ty::Error(_) => {}
133
134            _ => {
135                ::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(def_id),
    format_args!("`build_constraints_for_item` unsupported for this item"));span_bug!(
136                    tcx.def_span(def_id),
137                    "`build_constraints_for_item` unsupported for this item"
138                );
139            }
140        }
141    }
142
143    fn add_constraint(&mut self, current: &CurrentItem, index: u32, variance: VarianceTermPtr<'a>) {
144        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/variance/constraints.rs:144",
                        "rustc_hir_analysis::variance::constraints",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                        ::tracing_core::__macro_support::Option::Some(144u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                        ::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!("add_constraint(index={0}, variance={1:?})",
                                                    index, variance) as &dyn Value))])
            });
    } else { ; }
};debug!("add_constraint(index={}, variance={:?})", index, variance);
145        self.constraints.push(Constraint {
146            inferred: InferredIndex(current.inferred_start.0 + index as usize),
147            variance,
148        });
149    }
150
151    fn contravariant(&mut self, variance: VarianceTermPtr<'a>) -> VarianceTermPtr<'a> {
152        self.xform(variance, self.contravariant)
153    }
154
155    fn invariant(&mut self, variance: VarianceTermPtr<'a>) -> VarianceTermPtr<'a> {
156        self.xform(variance, self.invariant)
157    }
158
159    fn constant_term(&self, v: ty::Variance) -> VarianceTermPtr<'a> {
160        match v {
161            ty::Covariant => self.covariant,
162            ty::Invariant => self.invariant,
163            ty::Contravariant => self.contravariant,
164            ty::Bivariant => self.bivariant,
165        }
166    }
167
168    fn xform(&mut self, v1: VarianceTermPtr<'a>, v2: VarianceTermPtr<'a>) -> VarianceTermPtr<'a> {
169        match (*v1, *v2) {
170            (_, ConstantTerm(ty::Covariant)) => {
171                // Applying a "covariant" transform is always a no-op
172                v1
173            }
174
175            (ConstantTerm(c1), ConstantTerm(c2)) => self.constant_term(c1.xform(c2)),
176
177            _ => &*self.terms_cx.arena.alloc(TransformTerm(v1, v2)),
178        }
179    }
180
181    #[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("add_constraints_from_invariant_args",
                                    "rustc_hir_analysis::variance::constraints",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                                    ::tracing_core::__macro_support::Option::Some(181u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                                    ::tracing_core::field::FieldSet::new(&["args", "variance"],
                                        ::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(&::tracing::field::debug(&args)
                                                            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(&variance)
                                                            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: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let variance_i = self.invariant(variance);
            for arg in args {
                match arg.kind() {
                    GenericArgKind::Lifetime(lt) => {
                        self.add_constraints_from_region(current, lt, variance_i)
                    }
                    GenericArgKind::Type(ty) =>
                        self.add_constraints_from_ty(current, ty, variance_i),
                    GenericArgKind::Const(val) => {
                        self.add_constraints_from_const(current, val, variance_i)
                    }
                }
            }
        }
    }
}#[instrument(level = "debug", skip(self, current))]
182    fn add_constraints_from_invariant_args(
183        &mut self,
184        current: &CurrentItem,
185        args: GenericArgsRef<'tcx>,
186        variance: VarianceTermPtr<'a>,
187    ) {
188        // Trait are always invariant so we can take advantage of that.
189        let variance_i = self.invariant(variance);
190
191        for arg in args {
192            match arg.kind() {
193                GenericArgKind::Lifetime(lt) => {
194                    self.add_constraints_from_region(current, lt, variance_i)
195                }
196                GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
197                GenericArgKind::Const(val) => {
198                    self.add_constraints_from_const(current, val, variance_i)
199                }
200            }
201        }
202    }
203
204    /// Adds constraints appropriate for an instance of `ty` appearing
205    /// in a context with the generics defined in `generics` and
206    /// ambient variance `variance`
207    #[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("add_constraints_from_ty",
                                    "rustc_hir_analysis::variance::constraints",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                                    ::tracing_core::__macro_support::Option::Some(207u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                                    ::tracing_core::field::FieldSet::new(&["ty", "variance"],
                                        ::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(&::tracing::field::debug(&ty)
                                                            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(&variance)
                                                            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: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            match *ty.kind() {
                ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_)
                    | ty::Str | ty::Never | ty::Foreign(..) => {}
                ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) |
                    ty::CoroutineClosure(..) => {
                    ::rustc_middle::util::bug::bug_fmt(format_args!("Unexpected unnameable type in variance computation: {0}",
                            ty));
                }
                ty::Ref(region, ty, mutbl) => {
                    self.add_constraints_from_region(current, region, variance);
                    self.add_constraints_from_mt(current,
                        &ty::TypeAndMut { ty, mutbl }, variance);
                }
                ty::Array(typ, len) => {
                    self.add_constraints_from_const(current, len, variance);
                    self.add_constraints_from_ty(current, typ, variance);
                }
                ty::Pat(typ, pat) => {
                    self.add_constraints_from_pat(current, variance, pat);
                    self.add_constraints_from_ty(current, typ, variance);
                }
                ty::Slice(typ) => {
                    self.add_constraints_from_ty(current, typ, variance);
                }
                ty::RawPtr(ty, mutbl) => {
                    self.add_constraints_from_mt(current,
                        &ty::TypeAndMut { ty, mutbl }, variance);
                }
                ty::Tuple(subtys) => {
                    for subty in subtys {
                        self.add_constraints_from_ty(current, subty, variance);
                    }
                }
                ty::Adt(def, args) => {
                    self.add_constraints_from_args(current, def.did(), args,
                        variance);
                }
                ty::Alias(ty::AliasTy {
                    kind: ty::Projection { .. } | ty::Inherent { .. } |
                        ty::Opaque { .. },
                    args, .. }) => {
                    self.add_constraints_from_invariant_args(current, args,
                        variance);
                }
                ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => {
                    let ty = self.tcx().expand_free_alias_tys(ty);
                    self.add_constraints_from_ty(current, ty, variance);
                }
                ty::Dynamic(data, r) => {
                    self.add_constraints_from_region(current, r, variance);
                    if let Some(poly_trait_ref) = data.principal() {
                        self.add_constraints_from_invariant_args(current,
                            poly_trait_ref.skip_binder().args, variance);
                    }
                    for projection in data.projection_bounds() {
                        match projection.skip_binder().term.kind() {
                            ty::TermKind::Ty(ty) => {
                                self.add_constraints_from_ty(current, ty, self.invariant);
                            }
                            ty::TermKind::Const(c) => {
                                self.add_constraints_from_const(current, c, self.invariant)
                            }
                        }
                    }
                }
                ty::Param(ref data) => {
                    self.add_constraint(current, data.index, variance);
                }
                ty::FnPtr(sig_tys, hdr) => {
                    self.add_constraints_from_sig(current, sig_tys.with(hdr),
                        variance);
                }
                ty::UnsafeBinder(ty) => {
                    self.add_constraints_from_ty(current, ty.skip_binder(),
                        variance);
                }
                ty::Error(_) => {}
                ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Bound(..)
                    | ty::Infer(..) => {
                    ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type encountered in variance inference: {0}",
                            ty));
                }
            }
        }
    }
}#[instrument(level = "debug", skip(self, current))]
208    fn add_constraints_from_ty(
209        &mut self,
210        current: &CurrentItem,
211        ty: Ty<'tcx>,
212        variance: VarianceTermPtr<'a>,
213    ) {
214        match *ty.kind() {
215            ty::Bool
216            | ty::Char
217            | ty::Int(_)
218            | ty::Uint(_)
219            | ty::Float(_)
220            | ty::Str
221            | ty::Never
222            | ty::Foreign(..) => {
223                // leaf type -- noop
224            }
225
226            ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => {
227                bug!("Unexpected unnameable type in variance computation: {ty}");
228            }
229
230            ty::Ref(region, ty, mutbl) => {
231                self.add_constraints_from_region(current, region, variance);
232                self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
233            }
234
235            ty::Array(typ, len) => {
236                self.add_constraints_from_const(current, len, variance);
237                self.add_constraints_from_ty(current, typ, variance);
238            }
239
240            ty::Pat(typ, pat) => {
241                self.add_constraints_from_pat(current, variance, pat);
242                self.add_constraints_from_ty(current, typ, variance);
243            }
244
245            ty::Slice(typ) => {
246                self.add_constraints_from_ty(current, typ, variance);
247            }
248
249            ty::RawPtr(ty, mutbl) => {
250                self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
251            }
252
253            ty::Tuple(subtys) => {
254                for subty in subtys {
255                    self.add_constraints_from_ty(current, subty, variance);
256                }
257            }
258
259            ty::Adt(def, args) => {
260                self.add_constraints_from_args(current, def.did(), args, variance);
261            }
262
263            ty::Alias(ty::AliasTy {
264                kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. },
265                args,
266                ..
267            }) => {
268                self.add_constraints_from_invariant_args(current, args, variance);
269            }
270
271            ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => {
272                let ty = self.tcx().expand_free_alias_tys(ty);
273                self.add_constraints_from_ty(current, ty, variance);
274            }
275
276            ty::Dynamic(data, r) => {
277                // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
278                self.add_constraints_from_region(current, r, variance);
279
280                if let Some(poly_trait_ref) = data.principal() {
281                    self.add_constraints_from_invariant_args(
282                        current,
283                        poly_trait_ref.skip_binder().args,
284                        variance,
285                    );
286                }
287
288                for projection in data.projection_bounds() {
289                    match projection.skip_binder().term.kind() {
290                        ty::TermKind::Ty(ty) => {
291                            self.add_constraints_from_ty(current, ty, self.invariant);
292                        }
293                        ty::TermKind::Const(c) => {
294                            self.add_constraints_from_const(current, c, self.invariant)
295                        }
296                    }
297                }
298            }
299
300            ty::Param(ref data) => {
301                self.add_constraint(current, data.index, variance);
302            }
303
304            ty::FnPtr(sig_tys, hdr) => {
305                self.add_constraints_from_sig(current, sig_tys.with(hdr), variance);
306            }
307
308            ty::UnsafeBinder(ty) => {
309                // FIXME(unsafe_binders): This is covariant, right?
310                self.add_constraints_from_ty(current, ty.skip_binder(), variance);
311            }
312
313            ty::Error(_) => {
314                // we encounter this when walking the trait references for object
315                // types, where we use Error as the Self type
316            }
317
318            ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Bound(..) | ty::Infer(..) => {
319                bug!("unexpected type encountered in variance inference: {}", ty);
320            }
321        }
322    }
323
324    fn add_constraints_from_pat(
325        &mut self,
326        current: &CurrentItem,
327        variance: VarianceTermPtr<'a>,
328        pat: ty::Pattern<'tcx>,
329    ) {
330        match *pat {
331            ty::PatternKind::Range { start, end } => {
332                self.add_constraints_from_const(current, start, variance);
333                self.add_constraints_from_const(current, end, variance);
334            }
335            ty::PatternKind::NotNull => {}
336            ty::PatternKind::Or(patterns) => {
337                for pat in patterns {
338                    self.add_constraints_from_pat(current, variance, pat)
339                }
340            }
341        }
342    }
343
344    /// Adds constraints appropriate for a nominal type (enum, struct,
345    /// object, etc) appearing in a context with ambient variance `variance`
346    fn add_constraints_from_args(
347        &mut self,
348        current: &CurrentItem,
349        def_id: DefId,
350        args: GenericArgsRef<'tcx>,
351        variance: VarianceTermPtr<'a>,
352    ) {
353        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/variance/constraints.rs:353",
                        "rustc_hir_analysis::variance::constraints",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                        ::tracing_core::__macro_support::Option::Some(353u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                        ::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!("add_constraints_from_args(def_id={0:?}, args={1:?}, variance={2:?})",
                                                    def_id, args, variance) as &dyn Value))])
            });
    } else { ; }
};debug!(
354            "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})",
355            def_id, args, variance
356        );
357
358        // We don't record `inferred_starts` entries for empty generics.
359        if args.is_empty() {
360            return;
361        }
362
363        let (local, remote) = if let Some(def_id) = def_id.as_local() {
364            (Some(self.terms_cx.inferred_starts[&def_id]), None)
365        } else {
366            (None, Some(self.tcx().variances_of(def_id)))
367        };
368
369        for (i, arg) in args.iter().enumerate() {
370            let variance_decl = if let Some(InferredIndex(start)) = local {
371                // Parameter on an item defined within current crate:
372                // variance not yet inferred, so return a symbolic
373                // variance.
374                self.terms_cx.inferred_terms[start + i]
375            } else {
376                // Parameter on an item defined within another crate:
377                // variance already inferred, just look it up.
378                self.constant_term(remote.as_ref().unwrap()[i])
379            };
380            let variance_i = self.xform(variance, variance_decl);
381            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/variance/constraints.rs:381",
                        "rustc_hir_analysis::variance::constraints",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                        ::tracing_core::__macro_support::Option::Some(381u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                        ::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!("add_constraints_from_args: variance_decl={0:?} variance_i={1:?}",
                                                    variance_decl, variance_i) as &dyn Value))])
            });
    } else { ; }
};debug!(
382                "add_constraints_from_args: variance_decl={:?} variance_i={:?}",
383                variance_decl, variance_i
384            );
385            match arg.kind() {
386                GenericArgKind::Lifetime(lt) => {
387                    self.add_constraints_from_region(current, lt, variance_i)
388                }
389                GenericArgKind::Type(ty) => self.add_constraints_from_ty(current, ty, variance_i),
390                GenericArgKind::Const(val) => {
391                    self.add_constraints_from_const(current, val, variance)
392                }
393            }
394        }
395    }
396
397    /// Adds constraints appropriate for a const expression `val`
398    /// in a context with ambient variance `variance`
399    fn add_constraints_from_const(
400        &mut self,
401        current: &CurrentItem,
402        c: ty::Const<'tcx>,
403        variance: VarianceTermPtr<'a>,
404    ) {
405        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/variance/constraints.rs:405",
                        "rustc_hir_analysis::variance::constraints",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/variance/constraints.rs"),
                        ::tracing_core::__macro_support::Option::Some(405u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance::constraints"),
                        ::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!("add_constraints_from_const(c={0:?}, variance={1:?})",
                                                    c, variance) as &dyn Value))])
            });
    } else { ; }
};debug!("add_constraints_from_const(c={:?}, variance={:?})", c, variance);
406
407        match &c.kind() {
408            ty::ConstKind::Unevaluated(uv) => {
409                self.add_constraints_from_invariant_args(current, uv.args, variance);
410            }
411            _ => {}
412        }
413    }
414
415    /// Adds constraints appropriate for a function with signature
416    /// `sig` appearing in a context with ambient variance `variance`
417    fn add_constraints_from_sig(
418        &mut self,
419        current: &CurrentItem,
420        sig: ty::PolyFnSig<'tcx>,
421        variance: VarianceTermPtr<'a>,
422    ) {
423        let contra = self.contravariant(variance);
424        for &input in sig.skip_binder().inputs() {
425            self.add_constraints_from_ty(current, input, contra);
426        }
427        self.add_constraints_from_ty(current, sig.skip_binder().output(), variance);
428    }
429
430    /// Adds constraints appropriate for a region appearing in a
431    /// context with ambient variance `variance`
432    fn add_constraints_from_region(
433        &mut self,
434        current: &CurrentItem,
435        region: ty::Region<'tcx>,
436        variance: VarianceTermPtr<'a>,
437    ) {
438        match region.kind() {
439            ty::ReEarlyParam(ref data) => {
440                self.add_constraint(current, data.index, variance);
441            }
442
443            ty::ReStatic => {}
444
445            ty::ReBound(..) => {
446                // Either a higher-ranked region inside of a type or a
447                // late-bound function parameter.
448                //
449                // We do not compute constraints for either of these.
450            }
451
452            ty::ReError(_) => {}
453
454            ty::ReLateParam(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => {
455                // We don't expect to see anything but 'static or bound
456                // regions when visiting member types or method types.
457                ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected region encountered in variance inference: {0:?}",
        region));bug!(
458                    "unexpected region encountered in variance \
459                      inference: {:?}",
460                    region
461                );
462            }
463        }
464    }
465
466    /// Adds constraints appropriate for a mutability-type pair
467    /// appearing in a context with ambient variance `variance`
468    fn add_constraints_from_mt(
469        &mut self,
470        current: &CurrentItem,
471        mt: &ty::TypeAndMut<'tcx>,
472        variance: VarianceTermPtr<'a>,
473    ) {
474        match mt.mutbl {
475            hir::Mutability::Mut => {
476                let invar = self.invariant(variance);
477                self.add_constraints_from_ty(current, mt.ty, invar);
478            }
479
480            hir::Mutability::Not => {
481                self.add_constraints_from_ty(current, mt.ty, variance);
482            }
483        }
484    }
485}