about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2021-10-14 16:15:44 -0300
committerSantiago Pastorino <spastorino@gmail.com>2021-10-20 12:10:46 -0300
commitda8873e3439c4e8335e59a389a0c0f5d0d43c534 (patch)
treed8c9cb638478f1f723863d53b1e97aa0d7e660bf
parent511076a102ec6e9a6d19233eeb661d60f40dd821 (diff)
downloadrust-da8873e3439c4e8335e59a389a0c0f5d0d43c534.tar.gz
rust-da8873e3439c4e8335e59a389a0c0f5d0d43c534.zip
Only assemble_candidates_from_impls for polarity Negative
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs120
-rw-r--r--src/test/ui/traits/cache-reached-depth-ice.rs2
-rw-r--r--src/test/ui/traits/cache-reached-depth-ice.stderr2
-rw-r--r--src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs8
-rw-r--r--src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr8
-rw-r--r--src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs4
-rw-r--r--src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr11
7 files changed, 75 insertions, 80 deletions
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 d532c951212..b46d35f061e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -254,68 +254,72 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
 
-        self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
-
-        // Other bounds. Consider both in-scope bounds from fn decl
-        // and applicable impls. There is a certain set of precedence rules here.
-        let def_id = obligation.predicate.def_id();
-        let lang_items = self.tcx().lang_items();
-
-        if lang_items.copy_trait() == Some(def_id) {
-            debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
-
-            // User-defined copy impls are permitted, but only for
-            // structs and enums.
+        if obligation.predicate.skip_binder().polarity == ty::ImplPolarity::Negative {
             self.assemble_candidates_from_impls(obligation, &mut candidates);
-
-            // For other types, we'll use the builtin rules.
-            let copy_conditions = self.copy_clone_conditions(obligation);
-            self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
-        } else if lang_items.discriminant_kind_trait() == Some(def_id) {
-            // `DiscriminantKind` is automatically implemented for every type.
-            candidates.vec.push(DiscriminantKindCandidate);
-        } else if lang_items.pointee_trait() == Some(def_id) {
-            // `Pointee` is automatically implemented for every type.
-            candidates.vec.push(PointeeCandidate);
-        } else if lang_items.sized_trait() == Some(def_id) {
-            // Sized is never implementable by end-users, it is
-            // always automatically computed.
-            let sized_conditions = self.sized_conditions(obligation);
-            self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
-        } else if lang_items.unsize_trait() == Some(def_id) {
-            self.assemble_candidates_for_unsizing(obligation, &mut candidates);
-        } else if lang_items.drop_trait() == Some(def_id)
-            && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
-        {
-            if self.is_in_const_context {
-                self.assemble_const_drop_candidates(obligation, &mut candidates)?;
-            } else {
-                debug!("passing ~const Drop bound; in non-const context");
-                // `~const Drop` when we are not in a const context has no effect.
-                candidates.vec.push(ConstDropCandidate)
-            }
         } else {
-            if lang_items.clone_trait() == Some(def_id) {
-                // Same builtin conditions as `Copy`, i.e., every type which has builtin support
-                // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
-                // types have builtin support for `Clone`.
-                let clone_conditions = self.copy_clone_conditions(obligation);
-                self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
-            }
+            self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
+
+            // Other bounds. Consider both in-scope bounds from fn decl
+            // and applicable impls. There is a certain set of precedence rules here.
+            let def_id = obligation.predicate.def_id();
+            let lang_items = self.tcx().lang_items();
+
+            if lang_items.copy_trait() == Some(def_id) {
+                debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
+
+                // User-defined copy impls are permitted, but only for
+                // structs and enums.
+                self.assemble_candidates_from_impls(obligation, &mut candidates);
+
+                // For other types, we'll use the builtin rules.
+                let copy_conditions = self.copy_clone_conditions(obligation);
+                self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
+            } else if lang_items.discriminant_kind_trait() == Some(def_id) {
+                // `DiscriminantKind` is automatically implemented for every type.
+                candidates.vec.push(DiscriminantKindCandidate);
+            } else if lang_items.pointee_trait() == Some(def_id) {
+                // `Pointee` is automatically implemented for every type.
+                candidates.vec.push(PointeeCandidate);
+            } else if lang_items.sized_trait() == Some(def_id) {
+                // Sized is never implementable by end-users, it is
+                // always automatically computed.
+                let sized_conditions = self.sized_conditions(obligation);
+                self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
+            } else if lang_items.unsize_trait() == Some(def_id) {
+                self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+            } else if lang_items.drop_trait() == Some(def_id)
+                && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
+            {
+                if self.is_in_const_context {
+                    self.assemble_const_drop_candidates(obligation, &mut candidates)?;
+                } else {
+                    debug!("passing ~const Drop bound; in non-const context");
+                    // `~const Drop` when we are not in a const context has no effect.
+                    candidates.vec.push(ConstDropCandidate)
+                }
+            } else {
+                if lang_items.clone_trait() == Some(def_id) {
+                    // Same builtin conditions as `Copy`, i.e., every type which has builtin support
+                    // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
+                    // types have builtin support for `Clone`.
+                    let clone_conditions = self.copy_clone_conditions(obligation);
+                    self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
+                }
 
-            self.assemble_generator_candidates(obligation, &mut candidates);
-            self.assemble_closure_candidates(obligation, &mut candidates);
-            self.assemble_fn_pointer_candidates(obligation, &mut candidates);
-            self.assemble_candidates_from_impls(obligation, &mut candidates);
-            self.assemble_candidates_from_object_ty(obligation, &mut candidates);
-        }
+                self.assemble_generator_candidates(obligation, &mut candidates);
+                self.assemble_closure_candidates(obligation, &mut candidates);
+                self.assemble_fn_pointer_candidates(obligation, &mut candidates);
+                self.assemble_candidates_from_impls(obligation, &mut candidates);
+                self.assemble_candidates_from_object_ty(obligation, &mut candidates);
+            }
 
-        self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
-        self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-        // Auto implementations have lower priority, so we only
-        // consider triggering a default if there is no other impl that can apply.
-        if candidates.vec.is_empty() {
-            self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
+            self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
+            self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
+            // Auto implementations have lower priority, so we only
+            // consider triggering a default if there is no other impl that can apply.
+            if candidates.vec.is_empty() {
+                self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
+            }
         }
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
diff --git a/src/test/ui/traits/cache-reached-depth-ice.rs b/src/test/ui/traits/cache-reached-depth-ice.rs
index 4318e07d07a..c36ac08579b 100644
--- a/src/test/ui/traits/cache-reached-depth-ice.rs
+++ b/src/test/ui/traits/cache-reached-depth-ice.rs
@@ -41,5 +41,5 @@ fn test<X: ?Sized + Send>() {}
 
 fn main() {
     test::<A>();
-    //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk)
+    //~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
 }
diff --git a/src/test/ui/traits/cache-reached-depth-ice.stderr b/src/test/ui/traits/cache-reached-depth-ice.stderr
index 5e662970bb9..082aa0f5cd9 100644
--- a/src/test/ui/traits/cache-reached-depth-ice.stderr
+++ b/src/test/ui/traits/cache-reached-depth-ice.stderr
@@ -1,4 +1,4 @@
-error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk)
+error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
   --> $DIR/cache-reached-depth-ice.rs:43:5
    |
 LL | fn test<X: ?Sized + Send>() {}
diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs
index 1be0b05fa2b..3cd68ff6f06 100644
--- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs
+++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs
@@ -57,10 +57,10 @@ fn main() {
     // Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions":
 
     forward();
-    //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
-    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+    //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
 
     reverse();
-    //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
-    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+    //~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
+    //~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
 }
diff --git a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
index 43acc66fd73..7c4041144a4 100644
--- a/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
+++ b/src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr
@@ -1,4 +1,4 @@
-error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
+error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
    |
 LL |     Vec<First>: Unpin,
@@ -7,7 +7,7 @@ LL |     Vec<First>: Unpin,
 LL |     forward();
    |     ^^^^^^^
 
-error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
    |
 LL |     Third<'a, Ty>: Unpin,
@@ -16,7 +16,7 @@ LL |     Third<'a, Ty>: Unpin,
 LL |     forward();
    |     ^^^^^^^
 
-error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
+error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
    |
 LL |     Third<'a, Ty>: Unpin,
@@ -25,7 +25,7 @@ LL |     Third<'a, Ty>: Unpin,
 LL |     reverse();
    |     ^^^^^^^
 
-error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
+error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
   --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
    |
 LL |     Vec<First>: Unpin,
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
index db72aaf1803..119ac05c33e 100644
--- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
+++ b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 #![feature(negative_impls)]
 
 // aux-build: foreign_trait.rs
@@ -16,6 +18,6 @@ use foreign_trait::ForeignTrait;
 
 trait LocalTrait { }
 impl<T: ForeignTrait> LocalTrait for T { }
-impl LocalTrait for String { } //~ ERROR conflicting implementations
+impl LocalTrait for String { }
 
 fn main() { }
diff --git a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr b/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr
deleted file mode 100644
index b970ad76208..00000000000
--- a/src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0119]: conflicting implementations of trait `LocalTrait` for type `std::string::String`
-  --> $DIR/rely-on-negative-impl-in-coherence.rs:19:1
-   |
-LL | impl<T: ForeignTrait> LocalTrait for T { }
-   | -------------------------------------- first implementation here
-LL | impl LocalTrait for String { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::string::String`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0119`.