about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-08-22 10:44:38 +0000
committerbors <bors@rust-lang.org>2021-08-22 10:44:38 +0000
commit1eb187c16ec4f26fdeaff527e3ba2b1e609cabd2 (patch)
tree18f682ff9ed72b38d477b84cbbe7145a5a145ce5
parent80dad6477520553899049c994a6f534dce5a4951 (diff)
parent3329f67f173028bc41165894611ef54cab2c1438 (diff)
downloadrust-1eb187c16ec4f26fdeaff527e3ba2b1e609cabd2.tar.gz
rust-1eb187c16ec4f26fdeaff527e3ba2b1e609cabd2.zip
Auto merge of #88139 - lcnr:marker-trait-attr, r=nikomatsakis
marker_traits: require `EvaluatedToOk` during winnowing

closes #84955, while it doesn't really fix it in a way that makes me happy it should prevent the issue for now and this
test can't be reproduced anyways, so it doesn't make much sense to keep it open.

fixes #84917 as only one of the impls depends on regions, so we now drop the ambiguous one instead of the correct one.

cc https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/winnowing.20soundly/near/247899832

r? `@nikomatsakis`
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs13
-rw-r--r--src/test/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs9
-rw-r--r--src/test/ui/marker_trait_attr/region-overlap.rs8
-rw-r--r--src/test/ui/marker_trait_attr/region-overlap.stderr29
-rw-r--r--src/test/ui/marker_trait_attr/unsound-overlap.rs25
-rw-r--r--src/test/ui/marker_trait_attr/unsound-overlap.stderr12
6 files changed, 93 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 14d8aa494be..f95e7b8b6c3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1586,12 +1586,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // See if we can toss out `victim` based on specialization.
                 // This requires us to know *for sure* that the `other` impl applies
                 // i.e., `EvaluatedToOk`.
+                //
+                // FIXME(@lcnr): Using `modulo_regions` here seems kind of scary
+                // to me but is required for `std` to compile, so I didn't change it
+                // for now.
+                let tcx = self.tcx();
                 if other.evaluation.must_apply_modulo_regions() {
-                    let tcx = self.tcx();
                     if tcx.specializes((other_def, victim_def)) {
                         return true;
                     }
-                    return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+                }
+
+                if other.evaluation.must_apply_considering_regions() {
+                    match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
                         Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
                             // Subtle: If the predicate we are evaluating has inference
                             // variables, do *not* allow discarding candidates due to
@@ -1636,7 +1643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         }
                         Some(_) => true,
                         None => false,
-                    };
+                    }
                 } else {
                     false
                 }
diff --git a/src/test/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs b/src/test/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs
new file mode 100644
index 00000000000..a8f3db5f5b2
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlapping-impl-1-modulo-regions.rs
@@ -0,0 +1,9 @@
+// check-pass
+#![feature(marker_trait_attr)]
+
+#[marker]
+pub trait F {}
+impl<T> F for T where T: Copy {}
+impl<T> F for T where T: 'static {}
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/region-overlap.rs b/src/test/ui/marker_trait_attr/region-overlap.rs
new file mode 100644
index 00000000000..b3c66710355
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/region-overlap.rs
@@ -0,0 +1,8 @@
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait A {}
+impl<'a> A for (&'static (), &'a ()) {} //~ ERROR type annotations needed
+impl<'a> A for (&'a (), &'static ()) {} //~ ERROR type annotations needed
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/region-overlap.stderr b/src/test/ui/marker_trait_attr/region-overlap.stderr
new file mode 100644
index 00000000000..e4a94d56f12
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/region-overlap.stderr
@@ -0,0 +1,29 @@
+error[E0283]: type annotations needed
+  --> $DIR/region-overlap.rs:5:10
+   |
+LL | impl<'a> A for (&'static (), &'a ()) {}
+   |          ^ cannot infer type for tuple `(&'static (), &'a ())`
+   |
+   = note: cannot satisfy `(&'static (), &'a ()): A`
+note: required by a bound in `A`
+  --> $DIR/region-overlap.rs:4:1
+   |
+LL | trait A {}
+   | ^^^^^^^ required by this bound in `A`
+
+error[E0283]: type annotations needed
+  --> $DIR/region-overlap.rs:6:10
+   |
+LL | impl<'a> A for (&'a (), &'static ()) {}
+   |          ^ cannot infer type for tuple `(&'a (), &'static ())`
+   |
+   = note: cannot satisfy `(&'a (), &'static ()): A`
+note: required by a bound in `A`
+  --> $DIR/region-overlap.rs:4:1
+   |
+LL | trait A {}
+   | ^^^^^^^ required by this bound in `A`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/marker_trait_attr/unsound-overlap.rs b/src/test/ui/marker_trait_attr/unsound-overlap.rs
new file mode 100644
index 00000000000..2e5101b822c
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/unsound-overlap.rs
@@ -0,0 +1,25 @@
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait A {}
+
+trait B {}
+
+impl<T: A> B for T {}
+impl<T: B> A for T {}
+impl A for &str {}
+impl<T: A + B> A for (T,) {}
+trait TraitWithAssoc {
+    type Assoc;
+}
+
+impl<T: A> TraitWithAssoc for T {
+    type Assoc = T;
+}
+
+impl TraitWithAssoc for ((&str,),) {
+    //~^ ERROR conflicting implementations
+    type Assoc = ((&'static str,),);
+}
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/unsound-overlap.stderr b/src/test/ui/marker_trait_attr/unsound-overlap.stderr
new file mode 100644
index 00000000000..5ebac8270dd
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/unsound-overlap.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `TraitWithAssoc` for type `((&str,),)`
+  --> $DIR/unsound-overlap.rs:20:1
+   |
+LL | impl<T: A> TraitWithAssoc for T {
+   | ------------------------------- first implementation here
+...
+LL | impl TraitWithAssoc for ((&str,),) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `((&str,),)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.