about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2024-03-22 08:02:12 +0000
committerAli MJ Al-Nasrawy <alimjalnasrawy@gmail.com>2024-03-28 06:00:26 +0000
commit7c6876f9a9fe400e29430cb47cc11e71c13bb875 (patch)
tree0f5dd58bc769dc525628cbf0c09124efada93217
parent6b6ed2ea28e591ccae99048f226f98abfcd2e087 (diff)
downloadrust-7c6876f9a9fe400e29430cb47cc11e71c13bb875.tar.gz
rust-7c6876f9a9fe400e29430cb47cc11e71c13bb875.zip
simplify check_unique
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs95
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr2
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.rs3
-rw-r--r--tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr33
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs4
-rw-r--r--tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr34
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr69
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr53
10 files changed, 52 insertions, 250 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 8a03d59b710..63b80445817 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -9,7 +9,6 @@ use rustc_infer::traits::{Obligation, ObligationCause};
 use rustc_macros::extension;
 use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::RegionVid;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{GenericArgKind, GenericArgs};
 use rustc_span::Span;
@@ -23,73 +22,6 @@ use crate::universal_regions::RegionClassification;
 use super::RegionInferenceContext;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
-    fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
-        let scc = self.constraint_sccs.scc(vid);
-        self.scc_values
-            .universal_regions_outlived_by(scc)
-            .find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
-    }
-
-    fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
-        let region = arg.as_region()?;
-
-        if let ty::RePlaceholder(..) = region.kind() {
-            None
-        } else {
-            Some(self.to_region_vid(region))
-        }
-    }
-
-    /// Check that all opaque types have the same region parameters if they have the same
-    /// non-region parameters. This is necessary because within the new solver we perform various query operations
-    /// modulo regions, and thus could unsoundly select some impls that don't hold.
-    fn check_unique(
-        &self,
-        infcx: &InferCtxt<'tcx>,
-        opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
-    ) {
-        for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
-            for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
-                if a.def_id != b.def_id {
-                    continue;
-                }
-                // Non-lifetime params differ -> ok
-                if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
-                    continue;
-                }
-                trace!(?a, ?b);
-                for (a, b) in a.args.iter().zip(b.args) {
-                    trace!(?a, ?b);
-                    let Some(r1) = self.generic_arg_to_region(a) else {
-                        continue;
-                    };
-                    let Some(r2) = self.generic_arg_to_region(b) else {
-                        continue;
-                    };
-                    if self.eval_equal(r1, r2) {
-                        continue;
-                    }
-
-                    // Ignore non-universal regions because they result in an error eventually.
-                    // FIXME(aliemjay): This logic will be rewritten in a later commit.
-                    let Some(r1) = self.universal_name(r1) else {
-                        continue;
-                    };
-                    let Some(r2) = self.universal_name(r2) else {
-                        continue;
-                    };
-
-                    infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
-                        arg: r1.into(),
-                        prev: r2.into(),
-                        span: a_ty.span,
-                        prev_span: b_ty.span,
-                    });
-                }
-            }
-        }
-    }
-
     /// Resolve any opaque types that were encountered while borrow checking
     /// this item. This is then used to get the type in the `type_of` query.
     ///
@@ -139,9 +71,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
     ) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
-        self.check_unique(infcx, &opaque_ty_decls);
-
         let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
+        let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
+            FxIndexMap::default();
 
         for (opaque_type_key, concrete_type) in opaque_ty_decls {
             debug!(?opaque_type_key, ?concrete_type);
@@ -228,6 +160,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     OpaqueHiddenType { ty, span: concrete_type.span },
                 );
             }
+
+            // Check that all opaque types have the same region parameters if they have the same
+            // non-region parameters. This is necessary because within the new solver we perform
+            // various query operations modulo regions, and thus could unsoundly select some impls
+            // that don't hold.
+            if !ty.references_error()
+                && let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
+                    infcx.tcx.erase_regions(opaque_type_key),
+                    (opaque_type_key, concrete_type.span),
+                )
+                && let Some((arg1, arg2)) = std::iter::zip(
+                    prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+                    opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+                )
+                .find(|(arg1, arg2)| arg1 != arg2)
+            {
+                infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
+                    arg: arg1,
+                    prev: arg2,
+                    span: prev_span,
+                    prev_span: concrete_type.span,
+                });
+            }
         }
         result
     }
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
index ec062abb2fc..2cb82bf771c 100644
--- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/defining-use-captured-non-universal-region.rs:15:18
+  --> $DIR/defining-use-captured-non-universal-region.rs:14:18
    |
 LL | fn foo<'a>() -> impl Sized + 'a {
    |                              -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
index 4f72333e65e..2d54804f1fa 100644
--- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs
@@ -8,8 +8,7 @@
 fn foo<'a>() -> impl Sized + 'a {
     #[cfg(statik)]
     let i: i32 = foo::<'static>();
-    //[statik]~^ ERROR opaque type used twice with different lifetimes
-    //[statik]~| ERROR opaque type used twice with different lifetimes
+    //[statik]~^ ERROR expected generic lifetime parameter, found `'static`
 
     #[cfg(infer)]
     let i: i32 = foo::<'_>();
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
index b44f9ca6944..0d9b7df2257 100644
--- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
+++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr
@@ -1,33 +1,12 @@
-error: opaque type used twice with different lifetimes
-  --> $DIR/defining-use-captured-non-universal-region.rs:10:18
-   |
-LL |     let i: i32 = foo::<'static>();
-   |                  ^^^^^^^^^^^^^^^^ lifetime `'static` used here
-...
-LL |     i
-   |     - lifetime `'a` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/defining-use-captured-non-universal-region.rs:10:18
-   |
-LL |     let i: i32 = foo::<'static>();
-   |                  ^^^^^^^^^^^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/defining-use-captured-non-universal-region.rs:10:18
-   |
-LL |     let i: i32 = foo::<'static>();
-   |                  ^^^^^^^^^^^^^^^^ lifetime `'static` used here
-...
-LL |     i
-   |     - lifetime `'a` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
+error[E0792]: expected generic lifetime parameter, found `'static`
   --> $DIR/defining-use-captured-non-universal-region.rs:10:18
    |
+LL | fn foo<'a>() -> impl Sized + 'a {
+   |                              -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     #[cfg(statik)]
 LL |     let i: i32 = foo::<'static>();
    |                  ^^^^^^^^^^^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
index 923b194d483..cad41d2f2ed 100644
--- a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs
@@ -12,7 +12,7 @@ mod statik {
     // invalid defining use: Opaque<'static> := ()
     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
         let _: () = foo(Lt::<'static>::None);
-        //~^ ERROR opaque type used twice with different lifetimes
+        //~^ ERROR expected generic lifetime parameter, found `'static`
     }
 }
 
@@ -31,7 +31,7 @@ mod equal {
     // because of the use of equal lifetimes in args
     fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
         let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
-        //~^ ERROR opaque type used twice with different lifetimes
+        //~^ ERROR non-defining opaque type use in defining scope
     }
 }
 
diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
index e0122d32abe..7ef96a2e595 100644
--- a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
+++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr
@@ -1,17 +1,8 @@
-error: opaque type used twice with different lifetimes
-  --> $DIR/non-defining-use-lifetimes.rs:14:16
-   |
-LL |       fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
-   |  ______________________________________________-
-LL | |         let _: () = foo(Lt::<'static>::None);
-   | |                ^^ lifetime `'static` used here
-LL | |
-LL | |     }
-   | |_____- lifetime `'a` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
+error[E0792]: expected generic lifetime parameter, found `'static`
   --> $DIR/non-defining-use-lifetimes.rs:14:16
    |
+LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
+   |                                           -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
 LL |         let _: () = foo(Lt::<'static>::None);
    |                ^^
 
@@ -23,22 +14,17 @@ LL |     fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a {
 LL |         let _: () = foo(Lt::<'_>::None);
    |                ^^
 
-error: opaque type used twice with different lifetimes
-  --> $DIR/non-defining-use-lifetimes.rs:33:16
-   |
-LL |       fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
-   |  __________________________________________________________________-
-LL | |         let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
-   | |                ^^ lifetime `'a` used here
-LL | |
-LL | |     }
-   | |_____- lifetime `'b` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
+error: non-defining opaque type use in defining scope
   --> $DIR/non-defining-use-lifetimes.rs:33:16
    |
 LL |         let _: () = foo(Lt::<'a>::None, Lt::<'a>::None);
    |                ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/non-defining-use-lifetimes.rs:32:58
+   |
+LL |     fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b {
+   |                                                          ^^   ^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
index 9ec585d93f5..45a55050c44 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
@@ -5,7 +5,6 @@ type Foo<'a> = impl Sized;
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
     (x, y)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 type Bar<'a, 'b> = impl std::fmt::Debug;
@@ -13,9 +12,6 @@ type Bar<'a, 'b> = impl std::fmt::Debug;
 fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
     (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
index 7f54f47d27d..4f7b0f17407 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
@@ -14,53 +14,7 @@ LL |     (x, y)
    |     ^^^^^^
 
 error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'a` used here
-   |     lifetime `'b` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:6:5
-   |
-LL |     (x, y)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
@@ -69,27 +23,10 @@ LL |     (i, j)
    |     lifetime `'y` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:14:5
-   |
-LL |     (i, j)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:14:5
+  --> $DIR/lifetime_mismatch.rs:13:5
    |
 LL |     (i, j)
    |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
index 5bec38c5e5b..580fb58ef83 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -3,11 +3,8 @@
 type Foo<'a, 'b> = impl std::fmt::Debug;
 
 fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
-    (i, i)
+    (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
-    //~| ERROR opaque type used twice with different lifetimes
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
index 0ccb3e2221d..b2b9e604a6b 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -1,7 +1,7 @@
 error: opaque type used twice with different lifetimes
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
    |     |
    |     lifetime `'x` used here
@@ -10,55 +10,8 @@ LL |     (i, i)
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
   --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
    |
-LL |     (i, i)
+LL |     (i, j)
    |     ^^^^^^
 
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'x` used here
-   |     lifetime `'y` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   |     |
-   |     lifetime `'y` used here
-   |     lifetime `'x` previously used here
-   |
-note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
-   |
-LL |     (i, i)
-   |     ^^^^^^
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error