Rollup merge of #116689 - lcnr:auto-trait-hidden-ty-leak, r=compiler-errors

explicitly handle auto trait leakage in coherence

does not impact behavior but may avoid weird bugs in the future, cc https://github.com/rust-lang/trait-system-refactor-initiative/issues/65

r? ``@compiler-errors``
This commit is contained in:
Matthias Krüger 2023-10-14 13:48:20 +02:00 committed by GitHub
commit 45bcef3cd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 17 deletions

View File

@ -136,12 +136,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `assemble_candidates_after_normalizing_self_ty`, and we'd
// just be registering an identical candidate here.
//
// Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence`
// since we'll always be registering an ambiguous candidate in
// We always return `Err(NoSolution)` here in `SolverMode::Coherence`
// since we'll always register an ambiguous candidate in
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
// the TAIT.
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
if matches!(goal.param_env.reveal(), Reveal::All)
|| matches!(ecx.solver_mode(), SolverMode::Coherence)
|| opaque_ty
.def_id
.as_local()

View File

@ -492,7 +492,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// this trait and type.
}
ty::Param(..)
| ty::Alias(ty::Projection | ty::Inherent, ..)
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
| ty::Placeholder(..)
| ty::Bound(..) => {
// In these cases, we don't know what the actual
@ -536,20 +536,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
}
ty::Alias(_, _)
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) =>
{
// We do not generate an auto impl candidate for `impl Trait`s which already
// reference our auto trait.
//
// 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
// trivially holds.
//
// Note that this is only sound as projection candidates of opaque types
// are always applicable for auto traits.
ty::Alias(ty::Opaque, _) => {
if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) {
// We do not generate an auto impl candidate for `impl Trait`s which already
// reference our auto trait.
//
// 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
// trivially holds.
//
// Note that this is only sound as projection candidates of opaque types
// 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::Char

View File

@ -1,5 +1,5 @@
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 {}
| -------------------------------- first implementation here

View 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`.

View File

@ -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
// the purposes of coherence checking
#![feature(type_alias_impl_trait)]