summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/variance
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/variance')
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs65
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs46
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/terms.rs11
4 files changed, 74 insertions, 50 deletions
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 6f0afae1b..8a40509d7 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -6,8 +6,8 @@
use hir::def_id::{DefId, LocalDefId};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
use super::terms::VarianceTerm::*;
use super::terms::*;
@@ -78,6 +78,11 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
}
}
DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+ {
+ constraint_cx.build_constraints_for_item(def_id)
+ }
_ => {}
}
}
@@ -101,7 +106,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let inferred_start = self.terms_cx.inferred_starts[&def_id];
let current_item = &CurrentItem { inferred_start };
- match tcx.type_of(def_id).subst_identity().kind() {
+ let ty = tcx.type_of(def_id).instantiate_identity();
+
+ // The type as returned by `type_of` is the underlying type and generally not a weak projection.
+ // Therefore we need to check the `DefKind` first.
+ if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id)
+ && (lazy || ty.has_opaque_types())
+ {
+ self.add_constraints_from_ty(current_item, ty, self.covariant);
+ return;
+ }
+
+ match ty.kind() {
ty::Adt(def, _) => {
// Not entirely obvious: constraints on structs/enums do not
// affect the variance of their type parameters. See discussion
@@ -112,7 +128,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
for field in def.all_fields() {
self.add_constraints_from_ty(
current_item,
- tcx.type_of(field.did).subst_identity(),
+ tcx.type_of(field.did).instantiate_identity(),
self.covariant,
);
}
@@ -121,12 +137,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
ty::FnDef(..) => {
self.add_constraints_from_sig(
current_item,
- tcx.fn_sig(def_id).subst_identity(),
+ tcx.fn_sig(def_id).instantiate_identity(),
self.covariant,
);
}
ty::Error(_) => {}
+
_ => {
span_bug!(
tcx.def_span(def_id),
@@ -175,16 +192,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self, current))]
- fn add_constraints_from_invariant_substs(
+ fn add_constraints_from_invariant_args(
&mut self,
current: &CurrentItem,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
variance: VarianceTermPtr<'a>,
) {
// Trait are always invariant so we can take advantage of that.
let variance_i = self.invariant(variance);
- for k in substs {
+ for k in args {
match k.unpack() {
GenericArgKind::Lifetime(lt) => {
self.add_constraints_from_region(current, lt, variance_i)
@@ -248,12 +265,16 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
}
- ty::Adt(def, substs) => {
- self.add_constraints_from_substs(current, def.did(), substs, variance);
+ ty::Adt(def, args) => {
+ self.add_constraints_from_args(current, def.did(), args, variance);
+ }
+
+ ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
+ self.add_constraints_from_invariant_args(current, data.args, variance);
}
- ty::Alias(_, ref data) => {
- self.add_constraints_from_invariant_substs(current, data.substs, variance);
+ ty::Alias(ty::Weak, ref data) => {
+ self.add_constraints_from_args(current, data.def_id, data.args, variance);
}
ty::Dynamic(data, r, _) => {
@@ -261,9 +282,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_region(current, r, variance);
if let Some(poly_trait_ref) = data.principal() {
- self.add_constraints_from_invariant_substs(
+ self.add_constraints_from_invariant_args(
current,
- poly_trait_ref.skip_binder().substs,
+ poly_trait_ref.skip_binder().args,
variance,
);
}
@@ -305,20 +326,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
/// Adds constraints appropriate for a nominal type (enum, struct,
/// object, etc) appearing in a context with ambient variance `variance`
- fn add_constraints_from_substs(
+ fn add_constraints_from_args(
&mut self,
current: &CurrentItem,
def_id: DefId,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
variance: VarianceTermPtr<'a>,
) {
debug!(
- "add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
- def_id, substs, variance
+ "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})",
+ def_id, args, variance
);
// We don't record `inferred_starts` entries for empty generics.
- if substs.is_empty() {
+ if args.is_empty() {
return;
}
@@ -328,7 +349,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
(None, Some(self.tcx().variances_of(def_id)))
};
- for (i, k) in substs.iter().enumerate() {
+ for (i, k) in args.iter().enumerate() {
let variance_decl = if let Some(InferredIndex(start)) = local {
// Parameter on an item defined within current crate:
// variance not yet inferred, so return a symbolic
@@ -341,7 +362,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
};
let variance_i = self.xform(variance, variance_decl);
debug!(
- "add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
+ "add_constraints_from_args: variance_decl={:?} variance_i={:?}",
variance_decl, variance_i
);
match k.unpack() {
@@ -368,7 +389,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
match &c.kind() {
ty::ConstKind::Unevaluated(uv) => {
- self.add_constraints_from_invariant_substs(current, uv.substs, variance);
+ self.add_constraints_from_invariant_args(current, uv.args, variance);
}
_ => {}
}
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 066e74491..d91d9fcbc 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -7,8 +7,8 @@ use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can
@@ -56,7 +56,14 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
let crate_map = tcx.crate_variances(());
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
}
- DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() =>
+ {
+ // These are inferred.
+ let crate_map = tcx.crate_variances(());
+ return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
+ }
+ DefKind::OpaqueTy => {
return variance_of_opaque(tcx, item_def_id);
}
_ => {}
@@ -83,17 +90,17 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)]
- fn visit_opaque(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> ControlFlow<!> {
+ fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow<!> {
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 substs.iter().zip(child_variances) {
+ for (a, v) in args.iter().zip(child_variances) {
if *v != ty::Bivariant {
a.visit_with(self)?;
}
}
ControlFlow::Continue(())
} else {
- substs.visit_with(self)
+ args.visit_with(self)
}
}
}
@@ -110,18 +117,10 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
#[instrument(level = "trace", skip(self), ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
- ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+ ty::Alias(_, ty::AliasTy { def_id, args, .. })
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
{
- self.visit_opaque(*def_id, substs)
- }
- // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
- // at all for RPITITs.
- ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if self.tcx.is_impl_trait_in_trait(*def_id)
- && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() =>
- {
- self.visit_opaque(*def_id, substs)
+ self.visit_opaque(*def_id, args)
}
_ => t.super_visit_with(self),
}
@@ -152,30 +151,29 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
let mut collector =
OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances };
- let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id);
- for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) {
+ let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
+ for (pred, _) in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) {
debug!(?pred);
- // We only ignore opaque type substs if the opaque type is the outermost type.
+ // We only ignore opaque type args if the opaque type is the outermost type.
// The opaque type may be nested within itself via recursion in e.g.
// type Foo<'a> = impl PartialEq<Foo<'a>>;
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate {
- trait_ref: ty::TraitRef { def_id: _, substs, .. },
- constness: _,
+ trait_ref: ty::TraitRef { def_id: _, args, .. },
polarity: _,
}) => {
- for subst in &substs[1..] {
+ for subst in &args[1..] {
subst.visit_with(&mut collector);
}
}
ty::ClauseKind::Projection(ty::ProjectionPredicate {
- projection_ty: ty::AliasTy { substs, .. },
+ projection_ty: ty::AliasTy { args, .. },
term,
}) => {
- for subst in &substs[1..] {
+ for subst in &args[1..] {
subst.visit_with(&mut collector);
}
term.visit_with(&mut collector);
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index c27c176e3..54da32770 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -103,7 +103,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
self.enforce_const_invariance(generics, variances);
// Functions are permitted to have unused generic parameters: make those invariant.
- if let ty::FnDef(..) = tcx.type_of(def_id).subst_identity().kind() {
+ if let ty::FnDef(..) = tcx.type_of(def_id).instantiate_identity().kind() {
for variance in variances.iter_mut() {
if *variance == ty::Bivariant {
*variance = ty::Invariant;
diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index 3b286bb9c..1a8ec5f08 100644
--- a/compiler/rustc_hir_analysis/src/variance/terms.rs
+++ b/compiler/rustc_hir_analysis/src/variance/terms.rs
@@ -12,7 +12,7 @@
use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use std::fmt;
use self::VarianceTerm::*;
@@ -32,8 +32,8 @@ pub enum VarianceTerm<'a> {
impl<'a> fmt::Debug for VarianceTerm<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ConstantTerm(c1) => write!(f, "{:?}", c1),
- TransformTerm(v1, v2) => write!(f, "({:?} \u{00D7} {:?})", v1, v2),
+ ConstantTerm(c1) => write!(f, "{c1:?}"),
+ TransformTerm(v1, v2) => write!(f, "({v1:?} \u{00D7} {v2:?})"),
InferredTerm(id) => write!(f, "[{}]", {
let InferredIndex(i) = id;
i
@@ -97,6 +97,11 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
}
}
DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
+ DefKind::TyAlias { lazy }
+ if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+ {
+ terms_cx.add_inferreds_for_item(def_id)
+ }
_ => {}
}
}