about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-10-13 09:42:51 +0000
committerlcnr <rust@lcnr.de>2023-10-13 09:42:51 +0000
commit1bc6ae44014f953844a61123b7984f39b683ad78 (patch)
tree6ffea7f52e90f274f64d0671617652b9f63bdacc
parent2763ca50da1192aa28295ef4dbe5d06443e1b90a (diff)
downloadrust-1bc6ae44014f953844a61123b7984f39b683ad78.tar.gz
rust-1bc6ae44014f953844a61123b7984f39b683ad78.zip
explicitly handle auto trait leakage in coherence
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs33
-rw-r--r--tests/ui/impl-trait/auto-trait-coherence.next.stderr (renamed from tests/ui/impl-trait/auto-trait.stderr)2
-rw-r--r--tests/ui/impl-trait/auto-trait-coherence.old.stderr12
-rw-r--r--tests/ui/impl-trait/auto-trait-coherence.rs (renamed from tests/ui/impl-trait/auto-trait.rs)3
5 files changed, 38 insertions, 17 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 8055c63b9f3..d87e05ad02f 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -136,12 +136,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         // `assemble_candidates_after_normalizing_self_ty`, and we'd
         // just be registering an identical candidate here.
         //
-        // Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence`
-        // since we'll always be registering an ambiguous candidate in
+        // We always return `Err(NoSolution)` here in `SolverMode::Coherence`
+        // since we'll always register an ambiguous candidate in
         // `assemble_candidates_after_normalizing_self_ty` due to normalizing
         // the TAIT.
         if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
             if matches!(goal.param_env.reveal(), Reveal::All)
+                || matches!(ecx.solver_mode(), SolverMode::Coherence)
                 || opaque_ty
                     .def_id
                     .as_local()
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index bead8758ad6..f08cf6cef5b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -492,7 +492,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // this trait and type.
                 }
                 ty::Param(..)
-                | ty::Alias(ty::Projection | ty::Inherent, ..)
+                | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
                 | ty::Placeholder(..)
                 | ty::Bound(..) => {
                     // In these cases, we don't know what the actual
@@ -536,20 +536,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     );
                 }
 
-                ty::Alias(_, _)
-                    if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) =>
-                {
-                    // We do not generate an auto impl candidate for `impl Trait`s which already
-                    // reference our auto trait.
-                    //
-                    // For example during candidate assembly for `impl Send: Send`, we don't have
-                    // to look at the constituent types for this opaque types to figure out that this
-                    // trivially holds.
-                    //
-                    // Note that this is only sound as projection candidates of opaque types
-                    // are always applicable for auto traits.
+                ty::Alias(ty::Opaque, _) => {
+                    if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) {
+                        // We do not generate an auto impl candidate for `impl Trait`s which already
+                        // reference our auto trait.
+                        //
+                        // For example during candidate assembly for `impl Send: Send`, we don't have
+                        // to look at the constituent types for this opaque types to figure out that this
+                        // trivially holds.
+                        //
+                        // Note that this is only sound as projection candidates of opaque types
+                        // are always applicable for auto traits.
+                    } else if self.infcx.intercrate {
+                        // We do not emit auto trait candidates for opaque types in coherence.
+                        // Doing so can result in weird dependency cycles.
+                        candidates.ambiguous = true;
+                    } else {
+                        candidates.vec.push(AutoImplCandidate)
+                    }
                 }
-                ty::Alias(_, _) => candidates.vec.push(AutoImplCandidate),
 
                 ty::Bool
                 | ty::Char
diff --git a/tests/ui/impl-trait/auto-trait.stderr b/tests/ui/impl-trait/auto-trait-coherence.next.stderr
index 81009413c9a..7833ac688ba 100644
--- a/tests/ui/impl-trait/auto-trait.stderr
+++ b/tests/ui/impl-trait/auto-trait-coherence.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-  --> $DIR/auto-trait.rs:21:1
+  --> $DIR/auto-trait-coherence.rs:24:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
new file mode 100644
index 00000000000..7833ac688ba
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+  --> $DIR/auto-trait-coherence.rs:24:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/auto-trait.rs b/tests/ui/impl-trait/auto-trait-coherence.rs
index 35994e4a5ba..a5cd01a87ff 100644
--- a/tests/ui/impl-trait/auto-trait.rs
+++ b/tests/ui/impl-trait/auto-trait-coherence.rs
@@ -1,3 +1,6 @@
+// revisions: old next
+//[next] compile-flags: -Ztrait-solver=next
+
 // Tests that type alias impls traits do not leak auto-traits for
 // the purposes of coherence checking
 #![feature(type_alias_impl_trait)]