about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-11-28 17:25:47 +0100
committerGitHub <noreply@github.com>2022-11-28 17:25:47 +0100
commit60d136000eab7e171e4d2c5bab47e6fee1fd5ec6 (patch)
treeddf9a6ada8b74d9b8ea2abf411c2a2d0509c218a
parent9a96a6dd8289b612f5b50c9403ffdbb34fe95d48 (diff)
parent89afda781149e5779c38d1ee1d5bf4d633a27d61 (diff)
downloadrust-60d136000eab7e171e4d2c5bab47e6fee1fd5ec6.tar.gz
rust-60d136000eab7e171e4d2c5bab47e6fee1fd5ec6.zip
Rollup merge of #104936 - cjgillot:self-rpit-orig-too, r=oli-obk
Ignore bivariant parameters in test_type_match.

https://github.com/rust-lang/rust/pull/103491 made opaque types bivariant with respect of some of their lifetime parameters.  Because of this bivariance, some lifetime variables were not unified to anything during borrowck, and were considered as unequal by borrowck type test.

This PR makes type test ignore the bivariant parameters in test_type_match.

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

r? `@oli-obk`
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs7
-rw-r--r--src/test/ui/impl-trait/issues/issue-104815.rs66
2 files changed, 71 insertions, 2 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 5d204dd70ed..10b474efd5a 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -155,14 +155,17 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
         bug!()
     }
 
+    #[instrument(level = "trace", skip(self))]
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
-        _: ty::Variance,
+        variance: ty::Variance,
         _: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
-        self.relate(a, b)
+        // Opaque types substs have lifetime parameters.
+        // We must not check them to be equal, as we never insert anything to make them so.
+        if variance != ty::Bivariant { self.relate(a, b) } else { Ok(a) }
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/src/test/ui/impl-trait/issues/issue-104815.rs b/src/test/ui/impl-trait/issues/issue-104815.rs
new file mode 100644
index 00000000000..7a9826a8dff
--- /dev/null
+++ b/src/test/ui/impl-trait/issues/issue-104815.rs
@@ -0,0 +1,66 @@
+// check-pass
+
+struct It;
+
+struct Data {
+    items: Vec<It>,
+}
+
+impl Data {
+    fn new() -> Self {
+        Self {
+            items: vec![It, It],
+        }
+    }
+
+    fn content(&self) -> impl Iterator<Item = &It> {
+        self.items.iter()
+    }
+}
+
+struct Container<'a> {
+    name: String,
+    resolver: Box<dyn Resolver + 'a>,
+}
+
+impl<'a> Container<'a> {
+    fn new<R: Resolver + 'a>(name: &str, resolver: R) -> Self {
+        Self {
+            name: name.to_owned(),
+            resolver: Box::new(resolver),
+        }
+    }
+}
+
+trait Resolver {}
+
+impl<R: Resolver> Resolver for &R {}
+
+impl Resolver for It {}
+
+fn get<'a>(mut items: impl Iterator<Item = &'a It>) -> impl Resolver + 'a {
+    items.next().unwrap()
+}
+
+fn get2<'a, 'b: 'b>(mut items: impl Iterator<Item = &'a It>) -> impl Resolver + 'a {
+    items.next().unwrap()
+}
+
+fn main() {
+    let data = Data::new();
+    let resolver = get(data.content());
+
+    let _ = ["a", "b"]
+        .iter()
+        .map(|&n| Container::new(n, &resolver))
+        .map(|c| c.name)
+        .collect::<Vec<_>>();
+
+    let resolver = get2(data.content());
+
+    let _ = ["a", "b"]
+        .iter()
+        .map(|&n| Container::new(n, &resolver))
+        .map(|c| c.name)
+        .collect::<Vec<_>>();
+}