diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9983438233e1e..fa94aa19abda5 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -703,13 +703,42 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Opaque(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { self.tcx.sess.delay_span_bug( DUMMY_SP, format!("ty_is_local invoked on closure or generator: {:?}", ty), ); ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } + ty::Opaque(..) => { + // This merits some explanation. + // Normally, opaque types are not involved when performing + // coherence checking, since it is illegal to directly + // implement a trait on an opaque type. However, we might + // end up looking at an opaque type during coherence checking + // if an opaque type gets used within another type (e.g. as + // the type of a field) when checking for auto trait or `Sized` + // impls. This requires us to decide whether or not an opaque + // type should be considered 'local' or not. + // + // We choose to treat all opaque types as non-local, even + // those that appear within the same crate. This seems + // somewhat surprising at first, but makes sense when + // you consider that opaque types are supposed to hide + // the underlying type *within the same crate*. When an + // opaque type is used from outside the module + // where it is declared, it should be impossible to observe + // anything about it other than the traits that it implements. + // + // The alternative would be to look at the underlying type + // to determine whether or not the opaque type itself should + // be considered local. However, this could make it a breaking change + // to switch the underlying ('defining') type from a local type + // to a remote type. This would violate the rule that opaque + // types should be completely opaque apart from the traits + // that they implement, so we don't use this behavior. + self.found_non_local_ty(ty) + } }; // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so // the first type we visit is always the self type. diff --git a/src/test/ui/coherence/issue-99663-2.rs b/src/test/ui/coherence/issue-99663-2.rs new file mode 100644 index 0000000000000..10a0a568849bf --- /dev/null +++ b/src/test/ui/coherence/issue-99663-2.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Outer { + i: InnerSend, +} + +type InnerSend = impl Send; + +fn constrain() -> InnerSend { + () +} + +trait SendMustNotImplDrop {} + +#[allow(drop_bounds)] +impl SendMustNotImplDrop for T {} + +impl SendMustNotImplDrop for Outer {} + +fn main() {} diff --git a/src/test/ui/coherence/issue-99663.rs b/src/test/ui/coherence/issue-99663.rs new file mode 100644 index 0000000000000..a2d4d398ce1d5 --- /dev/null +++ b/src/test/ui/coherence/issue-99663.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +struct Send { + i: InnerSend, +} + +type InnerSend = impl Sized; + +fn constrain() -> InnerSend { + () +} + +trait SendMustNotImplDrop {} + +#[allow(drop_bounds)] +impl SendMustNotImplDrop for T {} + +impl SendMustNotImplDrop for Send {} + +fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr index 2eea726a19c5a..479b451855d55 100644 --- a/src/test/ui/impl-trait/negative-reasoning.stderr +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -7,7 +7,7 @@ LL | impl AnotherTrait for T {} LL | impl AnotherTrait for D { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` | - = note: downstream crates may implement trait `std::fmt::Debug` for type `OpaqueType` + = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions error: cannot implement trait on type alias impl trait --> $DIR/negative-reasoning.rs:19:25