about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-11-26 09:46:05 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2022-11-26 09:50:01 +0000
commit89afda781149e5779c38d1ee1d5bf4d633a27d61 (patch)
tree5c21a66cb2800960cbcd5fb8494e0e741314fd1b
parentf8a2e491ebec34113563cf8683f6fec2646cebb1 (diff)
downloadrust-89afda781149e5779c38d1ee1d5bf4d633a27d61.tar.gz
rust-89afda781149e5779c38d1ee1d5bf4d633a27d61.zip
Ignore bivariant parameters in test_type_match.
-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<_>>();
+}