about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-20 09:25:51 +0000
committerbors <bors@rust-lang.org>2023-02-20 09:25:51 +0000
commite7eaed21d50d7bfb8d614d6ee7fcea940b39185d (patch)
treec0edc08f3287e10ebf5518a12bcced4fcb09aa92 /compiler
parent7e253a7fb2e2e050021fed32da6fa2ec7bcea0fb (diff)
parent758cc957638e4edcfd9985e9f32e46f1dbac1fc1 (diff)
downloadrust-e7eaed21d50d7bfb8d614d6ee7fcea940b39185d.tar.gz
rust-e7eaed21d50d7bfb8d614d6ee7fcea940b39185d.zip
Auto merge of #107969 - b-naber:proj-relate-variance, r=lcnr
Use covariance on type relations of field projection types if possible

It's fine to use covariance here unless we're in a mutating context.

Fixes https://github.com/rust-lang/rust/issues/96514

Supersedes https://github.com/rust-lang/rust/pull/105958

r? `@lcnr`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs29
1 files changed, 25 insertions, 4 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 004b945eada..5e1334559f5 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -534,7 +534,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                     return PlaceTy::from_ty(self.tcx().ty_error());
                 }
             }
-            place_ty = self.sanitize_projection(place_ty, elem, place, location);
+            place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
         }
 
         if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
@@ -630,12 +630,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn sanitize_projection(
         &mut self,
         base: PlaceTy<'tcx>,
         pi: PlaceElem<'tcx>,
         place: &Place<'tcx>,
         location: Location,
+        context: PlaceContext,
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
         let tcx = self.tcx();
@@ -713,8 +715,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 match self.field_ty(place, base, field, location) {
                     Ok(ty) => {
                         let ty = self.cx.normalize(ty, location);
-                        if let Err(terr) = self.cx.eq_types(
+                        debug!(?fty, ?ty);
+
+                        if let Err(terr) = self.cx.relate_types(
                             ty,
+                            self.get_ambient_variance(context),
                             fty,
                             location.to_locations(),
                             ConstraintCategory::Boring,
@@ -743,9 +748,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 let ty = self.sanitize_type(place, ty);
                 let ty = self.cx.normalize(ty, location);
                 self.cx
-                    .eq_types(
-                        base.ty,
+                    .relate_types(
                         ty,
+                        self.get_ambient_variance(context),
+                        base.ty,
                         location.to_locations(),
                         ConstraintCategory::TypeAnnotation,
                     )
@@ -760,6 +766,21 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         self.tcx().ty_error()
     }
 
+    fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
+        use rustc_middle::mir::visit::NonMutatingUseContext::*;
+        use rustc_middle::mir::visit::NonUseContext::*;
+
+        match context {
+            PlaceContext::MutatingUse(_) => ty::Invariant,
+            PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+            PlaceContext::NonMutatingUse(
+                Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
+                | Projection,
+            ) => ty::Covariant,
+            PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
+        }
+    }
+
     fn field_ty(
         &mut self,
         parent: &dyn fmt::Debug,