rustc_hir_analysis/variance/mod.rs
1//! Module for inferring the variance of type and lifetime parameters. See the [rustc dev guide]
2//! chapter for more info.
3//!
4//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
5
6use itertools::Itertools;
7use rustc_arena::DroplessArena;
8use rustc_hir as hir;
9use rustc_hir::def::DefKind;
10use rustc_hir::def_id::{DefId, LocalDefId};
11use rustc_middle::span_bug;
12use rustc_middle::ty::{
13 self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
14 Unnormalized,
15};
16use tracing::{debug, instrument};
17
18/// Defines the `TermsContext` basically houses an arena where we can
19/// allocate terms.
20mod terms;
21
22/// Code to gather up constraints.
23mod constraints;
24
25/// Code to solve constraints and write out the results.
26mod solve;
27
28pub(crate) mod dump;
29
30pub(super) fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
31 let arena = DroplessArena::default();
32 let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &arena);
33 let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
34 solve::solve_constraints(constraints_cx)
35}
36
37pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
38 // Skip items with no generics - there's nothing to infer in them.
39 if tcx.generics_of(item_def_id).is_empty() {
40 return &[];
41 }
42
43 let kind = tcx.def_kind(item_def_id);
44 match kind {
45 DefKind::Fn
46 | DefKind::AssocFn
47 | DefKind::Enum
48 | DefKind::Struct
49 | DefKind::Union
50 | DefKind::Ctor(..) => {
51 // These are inferred.
52 let crate_map = tcx.crate_variances(());
53 return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
54 }
55 DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
56 Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
57 return variance_of_opaque(
58 tcx,
59 opaque_def_id.expect_local(),
60 ForceCaptureTraitArgs::Yes,
61 );
62 }
63 None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
64 },
65 DefKind::OpaqueTy => {
66 let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn {
67 parent: _,
68 in_trait_or_impl: Some(hir::RpitContext::Trait),
69 } =
70 tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin
71 {
72 ForceCaptureTraitArgs::Yes
73 } else {
74 ForceCaptureTraitArgs::No
75 };
76
77 return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
78 }
79 _ => {}
80 }
81
82 // Variance not relevant.
83 ::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(item_def_id),
format_args!("asked to compute variance for {0}",
kind.descr(item_def_id.to_def_id())));span_bug!(
84 tcx.def_span(item_def_id),
85 "asked to compute variance for {}",
86 kind.descr(item_def_id.to_def_id())
87 );
88}
89
90#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ForceCaptureTraitArgs {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
ForceCaptureTraitArgs::Yes => "Yes",
ForceCaptureTraitArgs::No => "No",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ForceCaptureTraitArgs { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ForceCaptureTraitArgs { }
#[automatically_derived]
impl ::core::clone::Clone for ForceCaptureTraitArgs {
#[inline]
fn clone(&self) -> ForceCaptureTraitArgs { *self }
}Clone)]
91enum ForceCaptureTraitArgs {
92 Yes,
93 No,
94}
95
96{}
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("variance_of_opaque",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(96u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("item_def_id")
}> =
::tracing::__macro_support::FieldName::new("item_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("force_capture_trait_args")
}> =
::tracing::__macro_support::FieldName::new("force_capture_trait_args");
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(&item_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&force_capture_trait_args)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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: &[ty::Variance] = loop {};
return __tracing_attr_fake_return;
}
{
let generics = tcx.generics_of(item_def_id);
struct OpaqueTypeLifetimeCollector<'tcx> {
tcx: TyCtxt<'tcx>,
root_def_id: DefId,
variances: Vec<ty::Variance>,
}
impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
fn visit_opaque(&mut self, def_id: DefId,
args: GenericArgsRef<'tcx>) {
{}
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("visit_opaque",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("args")
}> =
::tracing::__macro_support::FieldName::new("args");
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(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&args)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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;
}
{
if def_id != self.root_def_id &&
self.tcx.is_descendant_of(def_id, self.root_def_id) {
let child_variances = self.tcx.variances_of(def_id);
for (a, v) in args.iter().zip_eq(child_variances) {
if *v != ty::Bivariant { a.visit_with(self); }
}
} else { args.visit_with(self) }
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs:116",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for
OpaqueTypeLifetimeCollector<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) {
{}
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("visit_region",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(132u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r")
}> =
::tracing::__macro_support::FieldName::new("r");
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(&r)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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;
}
{
if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() {
self.variances[ebr.index as usize] = ty::Invariant;
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs:132",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(132u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn visit_ty(&mut self, t: Ty<'tcx>) {
{}
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("visit_ty",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(139u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("t")
}> =
::tracing::__macro_support::FieldName::new("t");
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(&t)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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 t.kind() {
ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id }, args, .. }) => {
self.visit_opaque(*def_id, args);
}
_ => t.super_visit_with(self),
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs:139",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(139u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
let mut variances =
::alloc::vec::from_elem(ty::Invariant, generics.count());
{
let mut generics = generics;
while let Some(def_id) = generics.parent {
generics = tcx.generics_of(def_id);
if #[allow(non_exhaustive_omitted_patterns)] match force_capture_trait_args
{
ForceCaptureTraitArgs::Yes => true,
_ => false,
} && generics.parent.is_none() {
if true {
{
match (&tcx.def_kind(def_id), &DefKind::Trait) {
(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);
}
}
}
};
};
break;
}
for param in &generics.own_params {
match param.kind {
ty::GenericParamDefKind::Lifetime => {
variances[param.index as usize] = ty::Bivariant;
}
ty::GenericParamDefKind::Type { .. } |
ty::GenericParamDefKind::Const { .. } => {}
}
}
}
}
let mut collector =
OpaqueTypeLifetimeCollector {
tcx,
root_def_id: item_def_id.to_def_id(),
variances,
};
let id_args =
ty::GenericArgs::identity_for_item(tcx, item_def_id);
for (clause, _) in
tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx,
id_args).map(Unnormalized::skip_norm_wip) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs:189",
"rustc_hir_analysis::variance", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(189u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("clause")
}> =
::tracing::__macro_support::FieldName::new("clause");
NAME.as_str()
}], ::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(&::tracing::field::debug(&clause)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitClause {
trait_ref: ty::TraitRef { def_id: _, args, .. }, polarity: _
}) |
ty::ClauseKind::HostEffect(ty::HostEffectClause {
trait_ref: ty::TraitRef { def_id: _, args, .. },
constness: _ }) => {
for arg in &args[1..] { arg.visit_with(&mut collector); }
}
ty::ClauseKind::Projection(ty::ProjectionClause {
projection_term: ty::AliasTerm { args, .. }, term }) => {
for arg in &args[1..] { arg.visit_with(&mut collector); }
term.visit_with(&mut collector);
}
ty::ClauseKind::TypeOutlives(ty::OutlivesClause(_, region))
=> {
region.visit_with(&mut collector);
}
_ => { clause.visit_with(&mut collector); }
}
}
tcx.arena.alloc_from_iter(collector.variances)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs:96",
"rustc_hir_analysis::variance", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_hir_analysis/src/variance/mod.rs"),
::tracing_core::__macro_support::Option::Some(96u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::variance"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "trace", skip(tcx), ret)]
97fn variance_of_opaque(
98 tcx: TyCtxt<'_>,
99 item_def_id: LocalDefId,
100 force_capture_trait_args: ForceCaptureTraitArgs,
101) -> &[ty::Variance] {
102 let generics = tcx.generics_of(item_def_id);
103
104 // Opaque types may only use regions that are bound. So for
105 // ```rust
106 // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
107 // ```
108 // we may not use `'c` in the hidden type.
109 struct OpaqueTypeLifetimeCollector<'tcx> {
110 tcx: TyCtxt<'tcx>,
111 root_def_id: DefId,
112 variances: Vec<ty::Variance>,
113 }
114
115 impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
116 #[instrument(level = "trace", skip(self), ret)]
117 fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) {
118 if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) {
119 let child_variances = self.tcx.variances_of(def_id);
120 for (a, v) in args.iter().zip_eq(child_variances) {
121 if *v != ty::Bivariant {
122 a.visit_with(self);
123 }
124 }
125 } else {
126 args.visit_with(self)
127 }
128 }
129 }
130
131 impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> {
132 #[instrument(level = "trace", skip(self), ret)]
133 fn visit_region(&mut self, r: ty::Region<'tcx>) {
134 if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() {
135 self.variances[ebr.index as usize] = ty::Invariant;
136 }
137 }
138
139 #[instrument(level = "trace", skip(self), ret)]
140 fn visit_ty(&mut self, t: Ty<'tcx>) {
141 match t.kind() {
142 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => {
143 self.visit_opaque(*def_id, args);
144 }
145 _ => t.super_visit_with(self),
146 }
147 }
148 }
149
150 // By default, RPIT are invariant wrt type and const generics, but they are bivariant wrt
151 // lifetime generics.
152 let mut variances = vec![ty::Invariant; generics.count()];
153
154 // Mark all lifetimes from parent generics as unused (Bivariant).
155 // This will be overridden later if required.
156 {
157 let mut generics = generics;
158 while let Some(def_id) = generics.parent {
159 generics = tcx.generics_of(def_id);
160
161 // Don't mark trait params generic if we're in an RPITIT.
162 if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
163 && generics.parent.is_none()
164 {
165 debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
166 break;
167 }
168
169 for param in &generics.own_params {
170 match param.kind {
171 ty::GenericParamDefKind::Lifetime => {
172 variances[param.index as usize] = ty::Bivariant;
173 }
174 ty::GenericParamDefKind::Type { .. }
175 | ty::GenericParamDefKind::Const { .. } => {}
176 }
177 }
178 }
179 }
180
181 let mut collector =
182 OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
183 let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
184 for (clause, _) in tcx
185 .explicit_item_bounds(item_def_id)
186 .iter_instantiated_copied(tcx, id_args)
187 .map(Unnormalized::skip_norm_wip)
188 {
189 debug!(?clause);
190
191 // We only ignore opaque type args if the opaque type is the outermost type.
192 // The opaque type may be nested within itself via recursion in e.g.
193 // type Foo<'a> = impl PartialEq<Foo<'a>>;
194 // which thus mentions `'a` and should thus accept hidden types that borrow 'a
195 // instead of requiring an additional `+ 'a`.
196 match clause.kind().skip_binder() {
197 ty::ClauseKind::Trait(ty::TraitClause {
198 trait_ref: ty::TraitRef { def_id: _, args, .. },
199 polarity: _,
200 })
201 | ty::ClauseKind::HostEffect(ty::HostEffectClause {
202 trait_ref: ty::TraitRef { def_id: _, args, .. },
203 constness: _,
204 }) => {
205 for arg in &args[1..] {
206 arg.visit_with(&mut collector);
207 }
208 }
209 ty::ClauseKind::Projection(ty::ProjectionClause {
210 projection_term: ty::AliasTerm { args, .. },
211 term,
212 }) => {
213 for arg in &args[1..] {
214 arg.visit_with(&mut collector);
215 }
216 term.visit_with(&mut collector);
217 }
218 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(_, region)) => {
219 region.visit_with(&mut collector);
220 }
221 _ => {
222 clause.visit_with(&mut collector);
223 }
224 }
225 }
226 tcx.arena.alloc_from_iter(collector.variances)
227}