Skip to content

Commit da8873e

Browse files
committed
Only assemble_candidates_from_impls for polarity Negative
1 parent 511076a commit da8873e

7 files changed

+75
-80
lines changed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+62-58
Original file line numberDiff line numberDiff line change
@@ -254,68 +254,72 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
254254

255255
let mut candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
256256

257-
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
258-
259-
// Other bounds. Consider both in-scope bounds from fn decl
260-
// and applicable impls. There is a certain set of precedence rules here.
261-
let def_id = obligation.predicate.def_id();
262-
let lang_items = self.tcx().lang_items();
263-
264-
if lang_items.copy_trait() == Some(def_id) {
265-
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
266-
267-
// User-defined copy impls are permitted, but only for
268-
// structs and enums.
257+
if obligation.predicate.skip_binder().polarity == ty::ImplPolarity::Negative {
269258
self.assemble_candidates_from_impls(obligation, &mut candidates);
270-
271-
// For other types, we'll use the builtin rules.
272-
let copy_conditions = self.copy_clone_conditions(obligation);
273-
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
274-
} else if lang_items.discriminant_kind_trait() == Some(def_id) {
275-
// `DiscriminantKind` is automatically implemented for every type.
276-
candidates.vec.push(DiscriminantKindCandidate);
277-
} else if lang_items.pointee_trait() == Some(def_id) {
278-
// `Pointee` is automatically implemented for every type.
279-
candidates.vec.push(PointeeCandidate);
280-
} else if lang_items.sized_trait() == Some(def_id) {
281-
// Sized is never implementable by end-users, it is
282-
// always automatically computed.
283-
let sized_conditions = self.sized_conditions(obligation);
284-
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
285-
} else if lang_items.unsize_trait() == Some(def_id) {
286-
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
287-
} else if lang_items.drop_trait() == Some(def_id)
288-
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
289-
{
290-
if self.is_in_const_context {
291-
self.assemble_const_drop_candidates(obligation, &mut candidates)?;
292-
} else {
293-
debug!("passing ~const Drop bound; in non-const context");
294-
// `~const Drop` when we are not in a const context has no effect.
295-
candidates.vec.push(ConstDropCandidate)
296-
}
297259
} else {
298-
if lang_items.clone_trait() == Some(def_id) {
299-
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
300-
// for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
301-
// types have builtin support for `Clone`.
302-
let clone_conditions = self.copy_clone_conditions(obligation);
303-
self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
304-
}
260+
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
261+
262+
// Other bounds. Consider both in-scope bounds from fn decl
263+
// and applicable impls. There is a certain set of precedence rules here.
264+
let def_id = obligation.predicate.def_id();
265+
let lang_items = self.tcx().lang_items();
266+
267+
if lang_items.copy_trait() == Some(def_id) {
268+
debug!(obligation_self_ty = ?obligation.predicate.skip_binder().self_ty());
269+
270+
// User-defined copy impls are permitted, but only for
271+
// structs and enums.
272+
self.assemble_candidates_from_impls(obligation, &mut candidates);
273+
274+
// For other types, we'll use the builtin rules.
275+
let copy_conditions = self.copy_clone_conditions(obligation);
276+
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
277+
} else if lang_items.discriminant_kind_trait() == Some(def_id) {
278+
// `DiscriminantKind` is automatically implemented for every type.
279+
candidates.vec.push(DiscriminantKindCandidate);
280+
} else if lang_items.pointee_trait() == Some(def_id) {
281+
// `Pointee` is automatically implemented for every type.
282+
candidates.vec.push(PointeeCandidate);
283+
} else if lang_items.sized_trait() == Some(def_id) {
284+
// Sized is never implementable by end-users, it is
285+
// always automatically computed.
286+
let sized_conditions = self.sized_conditions(obligation);
287+
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
288+
} else if lang_items.unsize_trait() == Some(def_id) {
289+
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
290+
} else if lang_items.drop_trait() == Some(def_id)
291+
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
292+
{
293+
if self.is_in_const_context {
294+
self.assemble_const_drop_candidates(obligation, &mut candidates)?;
295+
} else {
296+
debug!("passing ~const Drop bound; in non-const context");
297+
// `~const Drop` when we are not in a const context has no effect.
298+
candidates.vec.push(ConstDropCandidate)
299+
}
300+
} else {
301+
if lang_items.clone_trait() == Some(def_id) {
302+
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
303+
// for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
304+
// types have builtin support for `Clone`.
305+
let clone_conditions = self.copy_clone_conditions(obligation);
306+
self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates);
307+
}
305308

306-
self.assemble_generator_candidates(obligation, &mut candidates);
307-
self.assemble_closure_candidates(obligation, &mut candidates);
308-
self.assemble_fn_pointer_candidates(obligation, &mut candidates);
309-
self.assemble_candidates_from_impls(obligation, &mut candidates);
310-
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
311-
}
309+
self.assemble_generator_candidates(obligation, &mut candidates);
310+
self.assemble_closure_candidates(obligation, &mut candidates);
311+
self.assemble_fn_pointer_candidates(obligation, &mut candidates);
312+
self.assemble_candidates_from_impls(obligation, &mut candidates);
313+
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
314+
}
312315

313-
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
314-
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
315-
// Auto implementations have lower priority, so we only
316-
// consider triggering a default if there is no other impl that can apply.
317-
if candidates.vec.is_empty() {
318-
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
316+
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
317+
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
318+
// Auto implementations have lower priority, so we only
319+
// consider triggering a default if there is no other impl that can apply.
320+
if candidates.vec.is_empty() {
321+
self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
322+
}
319323
}
320324
debug!("candidate list size: {}", candidates.vec.len());
321325
Ok(candidates)

src/test/ui/traits/cache-reached-depth-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@ fn test<X: ?Sized + Send>() {}
4141

4242
fn main() {
4343
test::<A>();
44-
//~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk)
44+
//~^ ERROR evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
4545
}

src/test/ui/traits/cache-reached-depth-ice.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>), [])) = Ok(EvaluatedToOk)
1+
error: evaluate(Binder(TraitPredicate(<A as std::marker::Send>, polarity:Positive), [])) = Ok(EvaluatedToOk)
22
--> $DIR/cache-reached-depth-ice.rs:43:5
33
|
44
LL | fn test<X: ?Sized + Send>() {}

src/test/ui/traits/issue-83538-tainted-cache-after-cycle.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ fn main() {
5757
// Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions":
5858

5959
forward();
60-
//~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
61-
//~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
60+
//~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
61+
//~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
6262

6363
reverse();
64-
//~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
65-
//~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
64+
//~^ ERROR evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
65+
//~| ERROR evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
6666
}

src/test/ui/traits/issue-83538-tainted-cache-after-cycle.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
1+
error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
22
--> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
33
|
44
LL | Vec<First>: Unpin,
@@ -7,7 +7,7 @@ LL | Vec<First>: Unpin,
77
LL | forward();
88
| ^^^^^^^
99

10-
error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
10+
error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
1111
--> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5
1212
|
1313
LL | Third<'a, Ty>: Unpin,
@@ -16,7 +16,7 @@ LL | Third<'a, Ty>: Unpin,
1616
LL | forward();
1717
| ^^^^^^^
1818

19-
error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>), [])) = Ok(EvaluatedToOkModuloRegions)
19+
error: evaluate(Binder(TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOkModuloRegions)
2020
--> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
2121
|
2222
LL | Third<'a, Ty>: Unpin,
@@ -25,7 +25,7 @@ LL | Third<'a, Ty>: Unpin,
2525
LL | reverse();
2626
| ^^^^^^^
2727

28-
error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>), [])) = Ok(EvaluatedToOk)
28+
error: evaluate(Binder(TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), [])) = Ok(EvaluatedToOk)
2929
--> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5
3030
|
3131
LL | Vec<First>: Unpin,

src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
#![feature(negative_impls)]
24

35
// aux-build: foreign_trait.rs
@@ -16,6 +18,6 @@ use foreign_trait::ForeignTrait;
1618

1719
trait LocalTrait { }
1820
impl<T: ForeignTrait> LocalTrait for T { }
19-
impl LocalTrait for String { } //~ ERROR conflicting implementations
21+
impl LocalTrait for String { }
2022

2123
fn main() { }

src/test/ui/traits/negative-impls/rely-on-negative-impl-in-coherence.stderr

-11
This file was deleted.

0 commit comments

Comments
 (0)