1
Fork 0

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`
This commit is contained in:
Matthias Krüger 2023-01-28 05:20:18 +01:00 committed by GitHub
commit a5caa989c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 43 additions and 52 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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)
}