about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-08-04 09:18:58 +0200
committerGitHub <noreply@github.com>2023-08-04 09:18:58 +0200
commit5ea536b35f3b6a208090960374e03a8f4a35a935 (patch)
tree3304c9ee2ffb25cc66795a1a433ca004bd4b7db7
parent576bf82702d5312209355975fc79cb8f13b3161a (diff)
parent6f5d8556ca79473df091466306f69633877bdcd1 (diff)
downloadrust-5ea536b35f3b6a208090960374e03a8f4a35a935.tar.gz
rust-5ea536b35f3b6a208090960374e03a8f4a35a935.zip
Rollup merge of #114253 - fmease:compute-variances-for-lazy-ty-aliases, r=oli-obk
Compute variances for lazy type aliases

Fixes #114221.

CC ``@oli-obk``
r? types
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs28
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/variance/terms.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs10
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_bound.rs17
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_projections.rs12
-rw-r--r--tests/rustdoc/inherent-projections.rs10
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-0.rs4
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-0.stderr6
-rw-r--r--tests/ui/associated-inherent-types/late-bound-regions.rs4
-rw-r--r--tests/ui/associated-inherent-types/late-bound-regions.stderr2
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr16
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr16
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.rs9
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.stderr29
-rw-r--r--tests/ui/associated-inherent-types/substitute-params-bad.rs2
-rw-r--r--tests/ui/associated-inherent-types/substitute-params.rs3
-rw-r--r--tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs4
-rw-r--r--tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr55
-rw-r--r--tests/ui/lazy-type-alias/variance.rs38
22 files changed, 226 insertions, 85 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index e64848da86b..16d4d099c7e 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -245,13 +245,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
         }
         // `ForeignItem`s are handled separately.
         hir::ItemKind::ForeignMod { .. } => {}
-        hir::ItemKind::TyAlias(hir_ty, ..) => {
+        hir::ItemKind::TyAlias(hir_ty, ast_generics) => {
             if tcx.features().lazy_type_alias
                 || tcx.type_of(item.owner_id).skip_binder().has_opaque_types()
             {
                 // Bounds of lazy type aliases and of eager ones that contain opaque types are respected.
                 // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`.
                 check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+                check_variances_for_type_defn(tcx, item, ast_generics);
             }
         }
         _ => {}
@@ -1700,10 +1701,27 @@ fn check_variances_for_type_defn<'tcx>(
     hir_generics: &hir::Generics<'_>,
 ) {
     let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
-    for field in tcx.adt_def(item.owner_id).all_fields() {
-        if field.ty(tcx, identity_args).references_error() {
-            return;
+
+    match item.kind {
+        ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
+            for field in tcx.adt_def(item.owner_id).all_fields() {
+                if field.ty(tcx, identity_args).references_error() {
+                    return;
+                }
+            }
+        }
+        ItemKind::TyAlias(..) => {
+            let ty = tcx.type_of(item.owner_id).instantiate_identity();
+
+            if tcx.features().lazy_type_alias || ty.has_opaque_types() {
+                if ty.references_error() {
+                    return;
+                }
+            } else {
+                bug!();
+            }
         }
+        _ => bug!(),
     }
 
     let ty_predicates = tcx.predicates_of(item.owner_id);
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index ec8889781f4..4a3d522e488 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -6,7 +6,7 @@
 use hir::def_id::{DefId, LocalDefId};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-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::*;
@@ -78,6 +78,12 @@ pub fn add_constraints_from_crate<'a, 'tcx>(
                 }
             }
             DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id),
+            DefKind::TyAlias
+                if tcx.features().lazy_type_alias
+                    || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+            {
+                constraint_cx.build_constraints_for_item(def_id)
+            }
             _ => {}
         }
     }
@@ -101,7 +107,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).instantiate_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 = tcx.def_kind(def_id)
+            && (tcx.features().lazy_type_alias || 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
@@ -127,6 +144,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::Error(_) => {}
+
             _ => {
                 span_bug!(
                     tcx.def_span(def_id),
@@ -252,10 +270,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_args(current, def.did(), args, variance);
             }
 
-            ty::Alias(_, ref data) => {
+            ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, ref data) => {
                 self.add_constraints_from_invariant_args(current, data.args, variance);
             }
 
+            ty::Alias(ty::Weak, ref data) => {
+                self.add_constraints_from_args(current, data.def_id, data.args, variance);
+            }
+
             ty::Dynamic(data, r, _) => {
                 // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
                 self.add_constraints_from_region(current, r, variance);
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 6952a3fa66f..2ef294c6793 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
 use std::ops::ControlFlow;
 
 /// Defines the `TermsContext` basically houses an arena where we can
@@ -56,6 +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::TyAlias
+            if tcx.features().lazy_type_alias
+                || 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);
         }
diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index ed03c5da26f..1ef3d383bd8 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::*;
@@ -97,6 +97,12 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
                 }
             }
             DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id),
+            DefKind::TyAlias
+                if tcx.features().lazy_type_alias
+                    || tcx.type_of(def_id).instantiate_identity().has_opaque_types() =>
+            {
+                terms_cx.add_inferreds_for_item(def_id)
+            }
             _ => {}
         }
     }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index d72053ca985..f12094a271f 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -30,6 +30,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
 use rustc_middle::util::common::to_readable_str;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@@ -1034,7 +1035,7 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
     }
 }
 
-fn should_encode_variances(def_kind: DefKind) -> bool {
+fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool {
     match def_kind {
         DefKind::Struct
         | DefKind::Union
@@ -1053,7 +1054,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Static(..)
         | DefKind::Const
         | DefKind::ForeignMod
-        | DefKind::TyAlias
         | DefKind::Impl { .. }
         | DefKind::Trait
         | DefKind::TraitAlias
@@ -1067,6 +1067,10 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Closure
         | DefKind::Generator
         | DefKind::ExternCrate => false,
+        DefKind::TyAlias => {
+            tcx.features().lazy_type_alias
+                || tcx.type_of(def_id).instantiate_identity().has_opaque_types()
+        }
     }
 }
 
@@ -1349,7 +1353,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 self.encode_default_body_stability(def_id);
                 self.encode_deprecation(def_id);
             }
-            if should_encode_variances(def_kind) {
+            if should_encode_variances(tcx, def_id, def_kind) {
                 let v = self.tcx.variances_of(def_id);
                 record_array!(self.tables.variances_of[def_id] <- v);
             }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1189dcdfcbb..a02f9a9f796 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -749,7 +749,7 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Gets a map with the variance of every item; use `item_variance` instead.
+    /// Gets a map with the variance of every item; use `variances_of` instead.
     query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
         arena_cache
         desc { "computing the variances for items in this crate" }
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index 2e9b13d0cac..8e39f471824 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -5,14 +5,15 @@
 // @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
 pub struct Carrier<'a>(&'a ());
 
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.generic_params[*].name' \""'b"\"
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.trait' null
-// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
-
-pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
+// @count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
+// @is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
 
 impl<'a> Carrier<'a> {
     pub type Focus<T> = &'a mut T;
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index 942e323efca..d12e5f4a784 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -5,11 +5,13 @@
 // @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
 pub struct Parametrized<T>(T);
 
-// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.id' $Parametrized
-// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
-// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.name' '"Proj"'
-// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.trait' null
-pub type Test = Parametrized<i32>::Proj;
+// @count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
+// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
+// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
+// @is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
+pub fn test(_: Parametrized<i32>::Proj) {}
 
 /// param_bool
 impl Parametrized<bool> {
diff --git a/tests/rustdoc/inherent-projections.rs b/tests/rustdoc/inherent-projections.rs
index 9bda0acaf83..25f51282617 100644
--- a/tests/rustdoc/inherent-projections.rs
+++ b/tests/rustdoc/inherent-projections.rs
@@ -13,8 +13,8 @@ impl Owner {
 }
 
 // Make sure we handle bound vars correctly.
-// @has 'inherent_projections/type.User.html' '//pre[@class="rust item-decl"]' "for<'a> fn(_: Carrier<'a>::Focus)"
-pub type User = for<'a> fn(Carrier<'a>::Focus);
+// @has 'inherent_projections/fn.user.html' '//pre[@class="rust item-decl"]' "user(_: for<'a> fn(_: Carrier<'a>::Focus))"
+pub fn user(_: for<'a> fn(Carrier<'a>::Focus)) {}
 
 pub struct Carrier<'a>(&'a ());
 
@@ -27,11 +27,11 @@ impl<'a> Carrier<'a> {
 // FIXME(inherent_associated_types): Below we link to `Proj` but we should link to `Proj-1`.
 // The current test checks for the buggy behavior for demonstration purposes.
 
-// @has 'inherent_projections/type.Test.html'
-// @has - '//pre[@class="rust item-decl"]' "Parametrized<i32>"
+// @has 'inherent_projections/fn.test.html'
+// @has - '//pre[@class="rust item-decl"]' "test(_: Parametrized<i32>::Proj)"
 // @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj'
 // @!has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj-1'
-pub type Test = Parametrized<i32>::Proj;
+pub fn test(_: Parametrized<i32>::Proj) {}
 
 pub struct Parametrized<T>(T);
 
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.rs b/tests/ui/associated-inherent-types/issue-111879-0.rs
index e37f7d34ab5..d01354465df 100644
--- a/tests/ui/associated-inherent-types/issue-111879-0.rs
+++ b/tests/ui/associated-inherent-types/issue-111879-0.rs
@@ -5,10 +5,8 @@
 
 pub struct Carrier<'a>(&'a ());
 
-pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
-
 impl<'a> Carrier<'a> {
-    pub type Focus<T> = &'a mut User; //~ ERROR overflow evaluating associated type
+    pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>); //~ ERROR overflow evaluating associated type
 }
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.stderr b/tests/ui/associated-inherent-types/issue-111879-0.stderr
index 7bdbad44017..f6367c88aea 100644
--- a/tests/ui/associated-inherent-types/issue-111879-0.stderr
+++ b/tests/ui/associated-inherent-types/issue-111879-0.stderr
@@ -1,8 +1,8 @@
 error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
-  --> $DIR/issue-111879-0.rs:11:25
+  --> $DIR/issue-111879-0.rs:9:25
    |
-LL |     pub type Focus<T> = &'a mut User;
-   |                         ^^^^^^^^^^^^
+LL |     pub type Focus<T> = &'a mut for<'b> fn(Carrier<'b>::Focus<i32>);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/associated-inherent-types/late-bound-regions.rs b/tests/ui/associated-inherent-types/late-bound-regions.rs
index 488a2cda649..1dbeb00d495 100644
--- a/tests/ui/associated-inherent-types/late-bound-regions.rs
+++ b/tests/ui/associated-inherent-types/late-bound-regions.rs
@@ -3,8 +3,6 @@
 
 // Test if we correctly normalize `S<'a>::P` with respect to late-bound regions.
 
-type Function = for<'a> fn(&'a i32) -> S<'a>::P;
-
 struct S<'a>(&'a ());
 
 trait Inter {
@@ -16,7 +14,7 @@ impl<'a> S<'a> {
 }
 
 fn ret_ref_local<'e>() -> &'e i32 {
-    let f: Function = |x| x;
+    let f: for<'a> fn(&'a i32) -> S<'a>::P = |x| x;
 
     let local = 0;
     f(&local) //~ ERROR cannot return value referencing local variable `local`
diff --git a/tests/ui/associated-inherent-types/late-bound-regions.stderr b/tests/ui/associated-inherent-types/late-bound-regions.stderr
index 4706fcca91d..0dd17b05cd0 100644
--- a/tests/ui/associated-inherent-types/late-bound-regions.stderr
+++ b/tests/ui/associated-inherent-types/late-bound-regions.stderr
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `local`
-  --> $DIR/late-bound-regions.rs:22:5
+  --> $DIR/late-bound-regions.rs:20:5
    |
 LL |     f(&local)
    |     ^^------^
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr
deleted file mode 100644
index 4396435a6dd..00000000000
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
-  --> $DIR/not-found-self-type-differs.rs:17:34
-   |
-LL | struct Family<T>(T);
-   | ---------------- associated item `Proj` not found for this struct
-...
-LL | type Alias = Family<Option<()>>::Proj;
-   |                                  ^^^^ associated item not found in `Family<Option<()>>`
-   |
-   = note: the associated type was found for
-           - `Family<()>`
-           - `Family<Result<T, ()>>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr
deleted file mode 100644
index d527db02217..00000000000
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
-  --> $DIR/not-found-self-type-differs.rs:21:40
-   |
-LL | struct Family<T>(T);
-   | ---------------- associated item `Proj` not found for this struct
-...
-LL |     let _: Family<std::path::PathBuf>::Proj = ();
-   |                                        ^^^^ associated item not found in `Family<PathBuf>`
-   |
-   = note: the associated type was found for
-           - `Family<()>`
-           - `Family<Result<T, ()>>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.rs b/tests/ui/associated-inherent-types/not-found-self-type-differs.rs
index 93f58dcb6e6..76c5d4e7f69 100644
--- a/tests/ui/associated-inherent-types/not-found-self-type-differs.rs
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.rs
@@ -1,5 +1,3 @@
-// revisions: local alias
-
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
@@ -13,10 +11,7 @@ impl<T> Family<Result<T, ()>> {
     type Proj = Self;
 }
 
-#[cfg(alias)]
-type Alias = Family<Option<()>>::Proj; //[alias]~ ERROR associated type `Proj` not found for `Family<Option<()>>`
-
 fn main() {
-    #[cfg(local)]
-    let _: Family<std::path::PathBuf>::Proj = (); //[local]~ ERROR associated type `Proj` not found for `Family<PathBuf>`
+    let _: Family<Option<()>>::Proj; //~ ERROR associated type `Proj` not found for `Family<Option<()>>`
+    let _: Family<std::path::PathBuf>::Proj = (); //~ ERROR associated type `Proj` not found for `Family<PathBuf>`
 }
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr
new file mode 100644
index 00000000000..1871407c64f
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.stderr
@@ -0,0 +1,29 @@
+error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
+  --> $DIR/not-found-self-type-differs.rs:15:32
+   |
+LL | struct Family<T>(T);
+   | ---------------- associated item `Proj` not found for this struct
+...
+LL |     let _: Family<Option<()>>::Proj;
+   |                                ^^^^ associated item not found in `Family<Option<()>>`
+   |
+   = note: the associated type was found for
+           - `Family<()>`
+           - `Family<Result<T, ()>>`
+
+error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
+  --> $DIR/not-found-self-type-differs.rs:16:40
+   |
+LL | struct Family<T>(T);
+   | ---------------- associated item `Proj` not found for this struct
+...
+LL |     let _: Family<std::path::PathBuf>::Proj = ();
+   |                                        ^^^^ associated item not found in `Family<PathBuf>`
+   |
+   = note: the associated type was found for
+           - `Family<()>`
+           - `Family<Result<T, ()>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/substitute-params-bad.rs b/tests/ui/associated-inherent-types/substitute-params-bad.rs
index 00eb1a14da4..a5d73c7b49f 100644
--- a/tests/ui/associated-inherent-types/substitute-params-bad.rs
+++ b/tests/ui/associated-inherent-types/substitute-params-bad.rs
@@ -17,7 +17,7 @@ impl<T, S> Subj<(T, S)> {
 }
 
 fn main() {
-    type A = S<()>::P;
+    let _: S<()>::P;
 
     let _: Subj<(i32, i32)>::Un = 0i32; //~ ERROR mismatched types
 }
diff --git a/tests/ui/associated-inherent-types/substitute-params.rs b/tests/ui/associated-inherent-types/substitute-params.rs
index e94d6833159..631340b2b4d 100644
--- a/tests/ui/associated-inherent-types/substitute-params.rs
+++ b/tests/ui/associated-inherent-types/substitute-params.rs
@@ -15,8 +15,7 @@ impl<T> S<(T,)> {
 
 fn main() {
     // Regression test for issue #104240.
-    type A = S<()>::P;
-    let _: A = ();
+    let _: S<()>::P = ();
 
     // Regression test for issue #107468.
     let _: S<(i32,)>::Un = 0i32;
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
index b32b4288ac9..5c59f217be6 100644
--- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
+++ b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs
@@ -1,4 +1,5 @@
-// check-pass
+// FIXME(inherent_associated_types): This should be `check-pass`
+// known-bug: #108491
 // compile-flags: --crate-type=lib
 
 #![feature(inherent_associated_types)]
@@ -17,7 +18,6 @@
 
 pub type Alias<T: Bound> = (Source<T>::Assoc,);
 
-
 pub struct Source<T>(T);
 pub trait Bound {}
 
diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr
new file mode 100644
index 00000000000..5e18543fc90
--- /dev/null
+++ b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr
@@ -0,0 +1,55 @@
+error[E0391]: cycle detected when expanding type alias `Alias`
+  --> $DIR/type-alias-bounds-are-enforced.rs:19:1
+   |
+LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing the variances of `Source`...
+  --> $DIR/type-alias-bounds-are-enforced.rs:21:1
+   |
+LL | pub struct Source<T>(T);
+   | ^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires expanding type alias `Alias`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/type-alias-bounds-are-enforced.rs:5:1
+   |
+LL | / #![feature(inherent_associated_types)]
+LL | | #![allow(incomplete_features)]
+LL | |
+LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
+...  |
+LL | |     pub type Assoc = ();
+LL | | }
+   | |_^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error[E0391]: cycle detected when expanding type alias `Alias`
+  --> $DIR/type-alias-bounds-are-enforced.rs:19:1
+   |
+LL | pub type Alias<T: Bound> = (Source<T>::Assoc,);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing the variances of `Source`...
+  --> $DIR/type-alias-bounds-are-enforced.rs:21:1
+   |
+LL | pub struct Source<T>(T);
+   | ^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires expanding type alias `Alias`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/type-alias-bounds-are-enforced.rs:5:1
+   |
+LL | / #![feature(inherent_associated_types)]
+LL | | #![allow(incomplete_features)]
+LL | |
+LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*).
+...  |
+LL | |     pub type Assoc = ();
+LL | | }
+   | |_^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/lazy-type-alias/variance.rs b/tests/ui/lazy-type-alias/variance.rs
new file mode 100644
index 00000000000..f83215856b8
--- /dev/null
+++ b/tests/ui/lazy-type-alias/variance.rs
@@ -0,0 +1,38 @@
+// This is a regression test for issue #114221.
+// Check that we compute variances for lazy type aliases.
+
+// check-pass
+
+#![feature(lazy_type_alias)]
+#![allow(incomplete_features)]
+
+// [+] `A` is covariant over `'a`.
+struct A<'a>(Co<'a>);
+
+// [+] `Co` is covariant over `'a`.
+type Co<'a> = &'a ();
+
+fn co<'a>(x: A<'static>) {
+    let _: A<'a> = x;
+}
+
+// [-] `B` is contravariant over `'a`.
+struct B<'a>(Contra<'a>);
+
+// [-] `Contra` is contravariant over `'a`.
+type Contra<'a> = fn(&'a ());
+
+fn contra<'a>(x: B<'a>) {
+    let _: B<'static> = x;
+}
+
+struct C<T, U>(CoContra<T, U>);
+
+// [+, -] `CoContra` is covariant over `T` and contravariant over `U`.
+type CoContra<T, U> = Option<(T, fn(U))>;
+
+fn co_contra<'a>(x: C<&'static (), &'a ()>) -> C<&'a (), &'static ()> {
+    x
+}
+
+fn main() {}