Only assemble_candidates_from_impls for polarity Negative
This commit is contained in:
parent
511076a102
commit
da8873e343
@ -254,68 +254,72 @@ pub(super) fn assemble_candidates<'o>(
|
||||
|
||||
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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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>() {}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -1,3 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(negative_impls)]
|
||||
|
||||
// aux-build: foreign_trait.rs
|
||||
@ -16,6 +18,6 @@
|
||||
|
||||
trait LocalTrait { }
|
||||
impl<T: ForeignTrait> LocalTrait for T { }
|
||||
impl LocalTrait for String { } //~ ERROR conflicting implementations
|
||||
impl LocalTrait for String { }
|
||||
|
||||
fn main() { }
|
||||
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user