diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-01-28 05:20:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-28 05:20:18 +0100 |
| commit | a5caa989c94f0a0ca3f977b013a1a7c2c2c5c3a0 (patch) | |
| tree | 58f37390e1e5146c188a26da7a508834ddf8d52e /compiler | |
| parent | fa2cd945af6bfb14c16cfaa8b74c636dfb821b48 (diff) | |
| parent | 43cb610464393640a56fd7aa528c1c8f5b33ad0d (diff) | |
| download | rust-a5caa989c94f0a0ca3f977b013a1a7c2c2c5c3a0.tar.gz rust-a5caa989c94f0a0ca3f977b013a1a7c2c2c5c3a0.zip | |
Rollup merge of #107339 - aliemjay:covariant, r=lcnr
internally change regions to be covariant
Surprisingly, we consider the reference type `&'a T` to be contravaraint in its lifetime parameter. This is confusing and conflicts with the documentation we have in the reference, rustnomicon, and rustc-dev-guide. This also arguably not the correct use of terminology since we can use `&'static u8` in a place where `&' a u8` is expected, this implies that `&'static u8 <: &' a u8` and consequently `'static <: ' a`, hence covariance.
Because of this, when relating two types, we used to switch the argument positions in a confusing way:
`Subtype(&'a u8 <: &'b u8) => Subtype('b <: 'a) => Outlives('a: 'b) => RegionSubRegion('b <= 'a)`
The reason for the current behavior is probably that we wanted `Subtype('b <: 'a)` and `RegionSubRegion('b <= 'a)` to be equivalent, but I don' t think this is a good reason since these relations are sufficiently different in that the first is a relation in the subtyping lattice and is intrinsic to the type-systems, while the the second relation is an implementation detail of regionck.
This PR changes this behavior to use covariance, so..
`Subtype(&'a u8 <: &'b u8) => Subtype('a <: 'b) => Outlives('a: 'b) => RegionSubRegion('b <= 'a) `
Resolves #103676
r? `@lcnr`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/variance/constraints.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/glb.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/lub.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/nll_relate/mod.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/sub.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/relate.rs | 14 |
6 files changed, 15 insertions, 24 deletions
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index a1872822d36..165782f209a 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -225,8 +225,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::Ref(region, ty, mutbl) => { - let contra = self.contravariant(variance); - self.add_constraints_from_region(current, region, contra); + self.add_constraints_from_region(current, region, variance); self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance); } @@ -258,9 +257,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } ty::Dynamic(data, r, _) => { - // The type `Foo<T+'a>` is contravariant w/r/t `'a`: - let contra = self.contravariant(variance); - self.add_constraints_from_region(current, r, contra); + // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`: + self.add_constraints_from_region(current, r, variance); if let Some(poly_trait_ref) = data.principal() { self.add_constraints_from_invariant_substs( diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index 21b68ce9989..b92b162a978 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -79,7 +79,8 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { debug!("{}.regions({:?}, {:?})", self.tag(), a, b); let origin = Subtype(Box::new(self.fields.trace.clone())); - Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions( + // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8 + Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions( self.tcx(), origin, a, diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index c07ac1d3ace..f6e0554fd1f 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -79,7 +79,8 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { debug!("{}.regions({:?}, {:?})", self.tag(), a, b); let origin = Subtype(Box::new(self.fields.trace.clone())); - Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions( + // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8 + Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions( self.tcx(), origin, a, diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index f235cb5ab45..f83219b8ee2 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -663,13 +663,13 @@ where debug!(?v_b); if self.ambient_covariance() { - // Covariance: a <= b. Hence, `b: a`. - self.push_outlives(v_b, v_a, self.ambient_variance_info); + // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`. + self.push_outlives(v_a, v_b, self.ambient_variance_info); } if self.ambient_contravariance() { - // Contravariant: b <= a. Hence, `a: b`. - self.push_outlives(v_a, v_b, self.ambient_variance_info); + // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`. + self.push_outlives(v_b, v_a, self.ambient_variance_info); } Ok(a) diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index bd38b52ba34..51c34f0d55f 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -191,12 +191,13 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { // from the "cause" field, we could perhaps give more tailored // error messages. let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) self.fields .infcx .inner .borrow_mut() .unwrap_region_constraints() - .make_subregion(origin, a, b); + .make_subregion(origin, b, a); Ok(a) } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 7122e864cf2..fa87301df7e 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -443,12 +443,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( if a_repr == b_repr => { let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| { - relation.relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_region, - b_region, - ) + relation.relate(a_region, b_region) })?; Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr)) } @@ -497,12 +492,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( } (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => { - let r = relation.relate_with_variance( - ty::Contravariant, - ty::VarianceDiagInfo::default(), - a_r, - b_r, - )?; + let r = relation.relate(a_r, b_r)?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; |
