explicitly handle auto trait leakage in coherence
This commit is contained in:
parent
2763ca50da
commit
1bc6ae4401
5 changed files with 38 additions and 17 deletions
|
@ -136,12 +136,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
// `assemble_candidates_after_normalizing_self_ty`, and we'd
|
// `assemble_candidates_after_normalizing_self_ty`, and we'd
|
||||||
// just be registering an identical candidate here.
|
// just be registering an identical candidate here.
|
||||||
//
|
//
|
||||||
// Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence`
|
// We always return `Err(NoSolution)` here in `SolverMode::Coherence`
|
||||||
// since we'll always be registering an ambiguous candidate in
|
// since we'll always register an ambiguous candidate in
|
||||||
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
|
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
|
||||||
// the TAIT.
|
// the TAIT.
|
||||||
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
|
||||||
if matches!(goal.param_env.reveal(), Reveal::All)
|
if matches!(goal.param_env.reveal(), Reveal::All)
|
||||||
|
|| matches!(ecx.solver_mode(), SolverMode::Coherence)
|
||||||
|| opaque_ty
|
|| opaque_ty
|
||||||
.def_id
|
.def_id
|
||||||
.as_local()
|
.as_local()
|
||||||
|
|
|
@ -492,7 +492,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// this trait and type.
|
// this trait and type.
|
||||||
}
|
}
|
||||||
ty::Param(..)
|
ty::Param(..)
|
||||||
| ty::Alias(ty::Projection | ty::Inherent, ..)
|
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
|
||||||
| ty::Placeholder(..)
|
| ty::Placeholder(..)
|
||||||
| ty::Bound(..) => {
|
| ty::Bound(..) => {
|
||||||
// In these cases, we don't know what the actual
|
// In these cases, we don't know what the actual
|
||||||
|
@ -536,20 +536,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(_, _)
|
ty::Alias(ty::Opaque, _) => {
|
||||||
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) =>
|
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) {
|
||||||
{
|
// We do not generate an auto impl candidate for `impl Trait`s which already
|
||||||
// We do not generate an auto impl candidate for `impl Trait`s which already
|
// reference our auto trait.
|
||||||
// reference our auto trait.
|
//
|
||||||
//
|
// For example during candidate assembly for `impl Send: Send`, we don't have
|
||||||
// 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
|
||||||
// to look at the constituent types for this opaque types to figure out that this
|
// trivially holds.
|
||||||
// trivially holds.
|
//
|
||||||
//
|
// Note that this is only sound as projection candidates of opaque types
|
||||||
// Note that this is only sound as projection candidates of opaque types
|
// are always applicable for auto traits.
|
||||||
// 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::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
|
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 {}
|
LL | impl<T: Send> AnotherTrait for T {}
|
||||||
| -------------------------------- first implementation here
|
| -------------------------------- first implementation here
|
12
tests/ui/impl-trait/auto-trait-coherence.old.stderr
Normal file
12
tests/ui/impl-trait/auto-trait-coherence.old.stderr
Normal file
|
@ -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`.
|
|
@ -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
|
// Tests that type alias impls traits do not leak auto-traits for
|
||||||
// the purposes of coherence checking
|
// the purposes of coherence checking
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
Loading…
Add table
Add a link
Reference in a new issue