Allow opaque types in trait impl headers and rely on coherence to reject unsound cases

This commit is contained in:
Oli Scherer 2022-10-24 15:31:38 +00:00
parent 7fe6f36224
commit 2752e328c9
35 changed files with 226 additions and 231 deletions

View File

@ -5,7 +5,6 @@
use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{
@ -47,58 +46,6 @@ fn do_orphan_check_impl<'tcx>(
let sp = tcx.def_span(def_id);
let tr = impl_.of_trait.as_ref().unwrap();
// Ensure no opaque types are present in this impl header. See issues #76202 and #86411 for examples,
// and #84660 where it would otherwise allow unsoundness.
if trait_ref.has_opaque_types() {
trace!("{:#?}", item);
// First we find the opaque type in question.
for ty in trait_ref.substs {
for ty in ty.walk() {
let ty::subst::GenericArgKind::Type(ty) = ty.unpack() else { continue };
let ty::Opaque(def_id, _) = *ty.kind() else { continue };
trace!(?def_id);
// Then we search for mentions of the opaque type's type alias in the HIR
struct SpanFinder<'tcx> {
sp: Span,
def_id: DefId,
tcx: TyCtxt<'tcx>,
}
impl<'v, 'tcx> hir::intravisit::Visitor<'v> for SpanFinder<'tcx> {
#[instrument(level = "trace", skip(self, _id))]
fn visit_path(&mut self, path: &'v hir::Path<'v>, _id: hir::HirId) {
// You can't mention an opaque type directly, so we look for type aliases
if let hir::def::Res::Def(hir::def::DefKind::TyAlias, def_id) = path.res {
// And check if that type alias's type contains the opaque type we're looking for
for arg in self.tcx.type_of(def_id).walk() {
if let GenericArgKind::Type(ty) = arg.unpack() {
if let ty::Opaque(def_id, _) = *ty.kind() {
if def_id == self.def_id {
// Finally we update the span to the mention of the type alias
self.sp = path.span;
return;
}
}
}
}
}
hir::intravisit::walk_path(self, path)
}
}
let mut visitor = SpanFinder { sp, def_id, tcx };
hir::intravisit::walk_item(&mut visitor, item);
let reported = tcx
.sess
.struct_span_err(visitor.sp, "cannot implement trait on type alias impl trait")
.span_note(tcx.def_span(def_id), "type alias impl trait defined here")
.emit();
return Err(reported);
}
}
span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
}
match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
Ok(()) => {}
Err(err) => emit_orphan_check_error(

View File

@ -42,7 +42,6 @@ pub enum SimplifiedTypeGen<D>
ClosureSimplifiedType(D),
GeneratorSimplifiedType(D),
GeneratorWitnessSimplifiedType(usize),
OpaqueSimplifiedType(D),
FunctionSimplifiedType(usize),
PlaceholderSimplifiedType,
}
@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>(
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
TreatParams::AsInfer => None,
},
ty::Projection(_) => match treat_params {
ty::Opaque(..) | ty::Projection(_) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
//
@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>(
}
TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
},
ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
}
@ -151,8 +149,7 @@ pub fn def(self) -> Option<D> {
| ForeignSimplifiedType(d)
| TraitSimplifiedType(d)
| ClosureSimplifiedType(d)
| GeneratorSimplifiedType(d)
| OpaqueSimplifiedType(d) => Some(d),
| GeneratorSimplifiedType(d) => Some(d),
_ => None,
}
}
@ -182,7 +179,6 @@ pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
PlaceholderSimplifiedType => PlaceholderSimplifiedType,
}
@ -229,7 +225,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
match impl_ty.kind() {
// Start by checking whether the type in the impl may unify with
// pretty much everything. Just return `true` in that case.
ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true,
ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
// These types only unify with inference variables or their own
// variant.
ty::Bool
@ -247,8 +243,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
| ty::Never
| ty::Tuple(..)
| ty::FnPtr(..)
| ty::Foreign(..)
| ty::Opaque(..) => {}
| ty::Foreign(..) => {}
ty::FnDef(..)
| ty::Closure(..)
| ty::Generator(..)
@ -328,10 +323,7 @@ pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -
_ => false,
},
// Opaque types in impls should be forbidden, but that doesn't
// stop compilation. So this match arm should never return true
// if compilation succeeds.
ty::Opaque(..) => matches!(k, ty::Opaque(..)),
ty::Opaque(..) => true,
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,

View File

@ -18,7 +18,7 @@
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::CRATE_HIR_ID;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@ -94,7 +94,7 @@ pub fn overlapping_impls<'tcx>(
return None;
}
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
let selcx = &mut SelectionContext::intercrate(&infcx);
let overlaps =
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
@ -105,7 +105,7 @@ pub fn overlapping_impls<'tcx>(
// In the case where we detect an error, run the check again, but
// this time tracking intercrate ambiguity causes for better
// diagnostics. (These take time and can lead to false errors.)
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
let selcx = &mut SelectionContext::intercrate(&infcx);
selcx.enable_tracking_intercrate_ambiguity_causes();
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())

View File

@ -8,7 +8,6 @@ fn defining_use() -> OpaqueClosure {
struct Wrapper<T>(T);
trait Trait {}
impl Trait for Wrapper<OpaqueClosure> {}
//~^ ERROR cannot implement trait on type alias impl trait
impl<T: Sync> Trait for Wrapper<T> {}
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`

View File

@ -1,24 +1,11 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
--> $DIR/coherence-with-closure.rs:12:1
--> $DIR/coherence-with-closure.rs:11:1
|
LL | impl Trait for Wrapper<OpaqueClosure> {}
| ------------------------------------- first implementation here
LL |
LL | impl<T: Sync> Trait for Wrapper<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
error: cannot implement trait on type alias impl trait
--> $DIR/coherence-with-closure.rs:10:24
|
LL | impl Trait for Wrapper<OpaqueClosure> {}
| ^^^^^^^^^^^^^
|
note: type alias impl trait defined here
--> $DIR/coherence-with-closure.rs:3:22
|
LL | type OpaqueClosure = impl Sized;
| ^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -12,7 +12,6 @@ fn defining_use() -> OpaqueGenerator {
struct Wrapper<T>(T);
trait Trait {}
impl Trait for Wrapper<OpaqueGenerator> {}
//~^ ERROR cannot implement trait on type alias impl trait
impl<T: Sync> Trait for Wrapper<T> {}
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`

View File

@ -1,24 +1,11 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
--> $DIR/coherence-with-generator.rs:16:1
--> $DIR/coherence-with-generator.rs:15:1
|
LL | impl Trait for Wrapper<OpaqueGenerator> {}
| --------------------------------------- first implementation here
LL |
LL | impl<T: Sync> Trait for Wrapper<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
error: cannot implement trait on type alias impl trait
--> $DIR/coherence-with-generator.rs:14:24
|
LL | impl Trait for Wrapper<OpaqueGenerator> {}
| ^^^^^^^^^^^^^^^
|
note: type alias impl trait defined here
--> $DIR/coherence-with-generator.rs:3:24
|
LL | type OpaqueGenerator = impl Sized;
| ^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -20,7 +20,6 @@ impl<T: Send> AnotherTrait for T {}
// in the future.)
impl AnotherTrait for D<OpaqueType> {
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
//~| ERROR cannot implement trait on type alias impl trait
}
fn main() {}

View File

@ -7,18 +7,6 @@ LL | impl<T: Send> AnotherTrait for T {}
LL | impl AnotherTrait for D<OpaqueType> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
error: cannot implement trait on type alias impl trait
--> $DIR/auto-trait.rs:21:25
|
LL | impl AnotherTrait for D<OpaqueType> {
| ^^^^^^^^^^
|
note: type alias impl trait defined here
--> $DIR/auto-trait.rs:7:19
|
LL | type OpaqueType = impl OpaqueTrait;
| ^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -18,7 +18,6 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
// This is in error, because we cannot assume that `OpaqueType: !Debug`
impl AnotherTrait for D<OpaqueType> {
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
//~| ERROR cannot implement trait on type alias impl trait
}
fn main() {}

View File

@ -9,18 +9,6 @@ LL | impl AnotherTrait for D<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
|
LL | impl AnotherTrait for D<OpaqueType> {
| ^^^^^^^^^^
|
note: type alias impl trait defined here
--> $DIR/negative-reasoning.rs:7:19
|
LL | type OpaqueType = impl OpaqueTrait;
| ^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -5,13 +5,13 @@
struct Bar;
impl PartialEq<(Foo, i32)> for Bar {
//~^ ERROR cannot implement trait on type alias impl trait
fn eq(&self, _other: &(Foo, i32)) -> bool {
true
}
}
fn foo() -> Foo {
//~^ ERROR can't compare `Bar` with `(Bar, i32)`
Bar
}

View File

@ -1,14 +1,15 @@
error: cannot implement trait on type alias impl trait
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:7:17
error[E0277]: can't compare `Bar` with `(Bar, i32)`
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13
|
LL | impl PartialEq<(Foo, i32)> for Bar {
| ^^^
LL | fn foo() -> Foo {
| ^^^ no implementation for `Bar == (Bar, i32)`
LL |
LL | Bar
| --- return type was inferred to be `Bar` here
|
note: type alias impl trait defined here
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:3:12
|
LL | type Foo = impl PartialEq<(Foo, i32)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar`
= help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -2,11 +2,13 @@
mod a {
type Foo = impl PartialEq<(Foo, i32)>;
//~^ ERROR: unconstrained opaque type
struct Bar;
impl PartialEq<(Bar, i32)> for Bar {
fn eq(&self, _other: &(Foo, i32)) -> bool {
//~^ ERROR: `eq` has an incompatible type for trait
true
}
}
@ -14,12 +16,13 @@ fn eq(&self, _other: &(Foo, i32)) -> bool {
mod b {
type Foo = impl PartialEq<(Foo, i32)>;
//~^ ERROR: unconstrained opaque type
struct Bar;
impl PartialEq<(Foo, i32)> for Bar {
//~^ ERROR cannot implement trait on type alias impl trait
fn eq(&self, _other: &(Bar, i32)) -> bool {
//~^ ERROR: `eq` has an incompatible type for trait
true
}
}

View File

@ -1,14 +1,49 @@
error: cannot implement trait on type alias impl trait
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:20:21
|
LL | impl PartialEq<(Foo, i32)> for Bar {
| ^^^
|
note: type alias impl trait defined here
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:16:16
error: unconstrained opaque type
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
|
LL | type Foo = impl PartialEq<(Foo, i32)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `Foo` must be used in combination with a concrete type within the same module
error: aborting due to previous error
error[E0053]: method `eq` has an incompatible type for trait
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
|
LL | type Foo = impl PartialEq<(Foo, i32)>;
| -------------------------- the found opaque type
...
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
| ^^^^^^^^^^^
| |
| expected struct `a::Bar`, found opaque type
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
= note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _`
found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _`
error: unconstrained opaque type
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
|
LL | type Foo = impl PartialEq<(Foo, i32)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `Foo` must be used in combination with a concrete type within the same module
error[E0053]: method `eq` has an incompatible type for trait
--> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
|
LL | type Foo = impl PartialEq<(Foo, i32)>;
| -------------------------- the expected opaque type
...
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
| ^^^^^^^^^^^
| |
| expected opaque type, found struct `b::Bar`
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
= note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _`
found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0053`.

View File

@ -9,5 +9,4 @@ trait AnotherTrait {}
impl<T: Send> AnotherTrait for T {}
impl AnotherTrait for OpaqueType {}
//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
//~| ERROR cannot implement trait on type alias impl trait
fn main() {}

View File

@ -6,18 +6,6 @@ LL | impl<T: Send> AnotherTrait for T {}
LL | impl AnotherTrait for OpaqueType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
error: cannot implement trait on type alias impl trait
--> $DIR/issue-83613.rs:10:23
|
LL | impl AnotherTrait for OpaqueType {}
| ^^^^^^^^^^
|
note: type alias impl trait defined here
--> $DIR/issue-83613.rs:4:19
|
LL | type OpaqueType = impl OpaqueTrait;
| ^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -12,6 +12,6 @@ fn use_alias<T>(val: T) -> AliasOfForeignType<T> {
}
impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
//~^ ERROR cannot implement trait on type alias impl trait
//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types
fn main() {}

View File

@ -1,14 +1,14 @@
error: cannot implement trait on type alias impl trait
--> $DIR/coherence.rs:14:41
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> $DIR/coherence.rs:14:1
|
LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {}
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------
| | |
| | `AliasOfForeignType<T>` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
note: type alias impl trait defined here
--> $DIR/coherence.rs:9:30
|
LL | type AliasOfForeignType<T> = impl LocalTrait;
| ^^^^^^^^^^^^^^^
= note: define and implement a trait or new type instead
error: aborting due to previous error
For more information about this error, try `rustc --explain E0117`.

View File

@ -0,0 +1,23 @@
// check-pass
#![feature(type_alias_impl_trait)]
trait Foo {
type Assoc;
}
impl Foo for i32 {
type Assoc = u32;
}
type ImplTrait = impl Sized;
fn constrain() -> ImplTrait {
1u64
}
impl Foo for i64 {
type Assoc = ImplTrait;
}
trait Bar<T> {}
impl<T: Foo> Bar<<T as Foo>::Assoc> for T {}
fn main() {}

View File

@ -0,0 +1,21 @@
// compile-flags: --crate-type=lib
// check-pass
#![feature(type_alias_impl_trait)]
type Alias = impl Sized;
fn constrain() -> Alias {
1i32
}
trait HideIt {
type Assoc;
}
impl HideIt for () {
type Assoc = Alias;
}
pub trait Yay {}
impl Yay for <() as HideIt>::Assoc {}

View File

@ -0,0 +1,19 @@
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
type Foo = impl Debug;
pub trait Yay { }
impl Yay for Foo { }
fn foo() {
is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied
is_debug::<u32>(); // OK
is_yay::<Foo>(); // OK
is_debug::<Foo>(); // OK
}
fn is_yay<T: Yay>() { }
fn is_debug<T: Debug>() { }
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0277]: the trait bound `u32: Yay` is not satisfied
--> $DIR/impl_trait_for_tait_bound.rs:10:14
|
LL | is_yay::<u32>();
| ^^^ the trait `Yay` is not implemented for `u32`
|
= help: the trait `Yay` is implemented for `Foo`
note: required by a bound in `is_yay`
--> $DIR/impl_trait_for_tait_bound.rs:16:14
|
LL | fn is_yay<T: Yay>() { }
| ^^^ required by this bound in `is_yay`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,16 @@
#![feature(type_alias_impl_trait)]
use std::fmt::Debug;
type Foo = impl Debug;
pub trait Yay { }
impl Yay for u32 { }
fn foo() {
is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
}
fn is_yay<T: Yay>() { }
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0277]: the trait bound `Foo: Yay` is not satisfied
--> $DIR/impl_trait_for_tait_bound2.rs:11:14
|
LL | is_yay::<Foo>();
| ^^^ the trait `Yay` is not implemented for `Foo`
|
= help: the trait `Yay` is implemented for `u32`
note: required by a bound in `is_yay`
--> $DIR/impl_trait_for_tait_bound2.rs:14:14
|
LL | fn is_yay<T: Yay>() { }
| ^^^ required by this bound in `is_yay`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -8,7 +8,7 @@ impl MyTrait for () {}
type Bar = impl MyTrait;
impl MyTrait for Bar {}
//~^ ERROR: cannot implement trait on type alias impl trait
//~^ ERROR: conflicting implementations of trait `MyTrait` for type `()`
fn bazr() -> Bar { }

View File

@ -1,14 +1,12 @@
error: cannot implement trait on type alias impl trait
--> $DIR/issue-65384.rs:10:18
error[E0119]: conflicting implementations of trait `MyTrait` for type `()`
--> $DIR/issue-65384.rs:10:1
|
LL | impl MyTrait for () {}
| ------------------- first implementation here
...
LL | impl MyTrait for Bar {}
| ^^^
|
note: type alias impl trait defined here
--> $DIR/issue-65384.rs:8:12
|
LL | type Bar = impl MyTrait;
| ^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -1,6 +1,8 @@
// Regression test for issue #76202
// Tests that we don't ICE when we have a trait impl on a TAIT.
// check-pass
#![feature(type_alias_impl_trait)]
trait Dummy {}
@ -14,7 +16,12 @@ trait Test {
}
impl Test for F {
//~^ ERROR cannot implement trait
fn test(self) {}
}
// Ok because `i32` does not implement `Dummy`,
// so it can't possibly be the hidden type of `F`.
impl Test for i32 {
fn test(self) {}
}

View File

@ -1,14 +0,0 @@
error: cannot implement trait on type alias impl trait
--> $DIR/issue-76202-trait-impl-for-tait.rs:16:15
|
LL | impl Test for F {
| ^
|
note: type alias impl trait defined here
--> $DIR/issue-76202-trait-impl-for-tait.rs:9:10
|
LL | type F = impl Dummy;
| ^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,6 +1,8 @@
// Regression test for issues #84660 and #86411: both are variations on #76202.
// Tests that we don't ICE when we have an opaque type appearing anywhere in an impl header.
// check-pass
#![feature(type_alias_impl_trait)]
trait Foo {}
@ -12,7 +14,7 @@ trait TraitArg<T> {
fn f();
}
impl TraitArg<Bar> for () { //~ ERROR cannot implement trait
impl TraitArg<Bar> for () {
fn f() {
println!("ho");
}

View File

@ -1,14 +0,0 @@
error: cannot implement trait on type alias impl trait
--> $DIR/issue-84660-trait-impl-for-tait.rs:15:15
|
LL | impl TraitArg<Bar> for () {
| ^^^
|
note: type alias impl trait defined here
--> $DIR/issue-84660-trait-impl-for-tait.rs:8:12
|
LL | type Bar = impl Foo;
| ^^^^^^^^
error: aborting due to previous error

View File

@ -13,14 +13,14 @@ trait Trait<T, In> {
fn convert(i: In) -> Self::Out;
}
impl<In, Out> Trait<Bar, In> for Out { //~ ERROR cannot implement trait
impl<In, Out> Trait<Bar, In> for Out {
type Out = Out;
fn convert(_i: In) -> Self::Out {
unreachable!();
}
}
impl<In, Out> Trait<(), In> for Out {
impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
type Out = In;
fn convert(i: In) -> Self::Out {
i

View File

@ -1,14 +1,12 @@
error: cannot implement trait on type alias impl trait
--> $DIR/issue-84660-unsoundness.rs:16:21
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
--> $DIR/issue-84660-unsoundness.rs:23:1
|
LL | impl<In, Out> Trait<Bar, In> for Out {
| ^^^
|
note: type alias impl trait defined here
--> $DIR/issue-84660-unsoundness.rs:8:12
|
LL | type Bar = impl Foo;
| ^^^^^^^^
| ------------------------------------ first implementation here
...
LL | impl<In, Out> Trait<(), In> for Out {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0119`.

View File

@ -4,11 +4,11 @@
use std::fmt::Debug;
type FooX = impl Debug;
//~^ ERROR unconstrained opaque type
trait Foo<A> { }
impl Foo<FooX> for () { }
//~^ cannot implement trait on type alias impl trait
fn foo() -> impl Foo<FooX> {
()

View File

@ -1,14 +1,10 @@
error: cannot implement trait on type alias impl trait
--> $DIR/nested-tait-inference3.rs:10:10
|
LL | impl Foo<FooX> for () { }
| ^^^^
|
note: type alias impl trait defined here
error: unconstrained opaque type
--> $DIR/nested-tait-inference3.rs:6:13
|
LL | type FooX = impl Debug;
| ^^^^^^^^^^
|
= note: `FooX` must be used in combination with a concrete type within the same module
error: aborting due to previous error