Check allow instantiating object trait binder when upcasting and in new solver

This commit is contained in:
Michael Goulet 2024-09-25 19:19:22 -04:00
parent 58420a065b
commit d4ee408afc
8 changed files with 70 additions and 51 deletions

View File

@ -896,7 +896,7 @@ where
&& ecx
.probe(|_| ProbeKind::UpcastProjectionCompatibility)
.enter(|ecx| -> Result<(), NoSolution> {
ecx.eq(param_env, source_projection, target_projection)?;
ecx.sub(param_env, source_projection, target_projection)?;
let _ = ecx.try_evaluate_added_goals()?;
Ok(())
})
@ -909,7 +909,7 @@ where
// Check that a's supertrait (upcast_principal) is compatible
// with the target (b_ty).
ty::ExistentialPredicate::Trait(target_principal) => {
ecx.eq(
ecx.sub(
param_env,
upcast_principal.unwrap(),
bound.rebind(target_principal),
@ -934,7 +934,7 @@ where
Certainty::AMBIGUOUS,
);
}
ecx.eq(param_env, source_projection, target_projection)?;
ecx.sub(param_env, source_projection, target_projection)?;
}
// Check that b_ty's auto traits are present in a_ty's bounds.
ty::ExistentialPredicate::AutoTrait(def_id) => {

View File

@ -2582,12 +2582,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
nested.extend(
self.infcx
.at(&obligation.cause, obligation.param_env)
.eq(
.sup(
DefineOpaqueTypes::Yes,
bound.rebind(target_principal),
upcast_principal.map_bound(|trait_ref| {
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
}),
bound.rebind(target_principal),
)
.map_err(|_| SelectionError::Unimplemented)?
.into_obligations(),
@ -2620,7 +2620,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
nested.extend(
self.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, source_projection, target_projection)
.sup(DefineOpaqueTypes::Yes, target_projection, source_projection)
.map_err(|_| SelectionError::Unimplemented)?
.into_obligations(),
);

View File

@ -0,0 +1,27 @@
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// Verify that the unsize goal can cast a higher-ranked trait goal to
// a non-higer-ranked instantiation.
#![feature(unsize)]
use std::marker::Unsize;
fn test<T: ?Sized, U: ?Sized>()
where
T: Unsize<U>,
{
}
fn main() {
test::<dyn for<'a> Fn(&'a ()) -> &'a (), dyn Fn(&'static ()) -> &'static ()>();
trait Foo<'a, 'b> {}
test::<dyn for<'a, 'b> Foo<'a, 'b>, dyn for<'a> Foo<'a, 'a>>();
trait Bar<'a> {}
test::<dyn for<'a> Bar<'a>, dyn Bar<'_>>();
}

View File

@ -1,22 +0,0 @@
error[E0308]: mismatched types
--> $DIR/higher-ranked-upcasting-ok.rs:17:5
|
LL | x
| ^ one type is more general than the other
|
= note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
found existential trait ref `for<'a> Supertrait<'a, 'a>`
error[E0308]: mismatched types
--> $DIR/higher-ranked-upcasting-ok.rs:17:5
|
LL | x
| ^ one type is more general than the other
|
= note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
found existential trait ref `for<'a> Supertrait<'a, 'a>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,14 +0,0 @@
error[E0308]: mismatched types
--> $DIR/higher-ranked-upcasting-ok.rs:17:5
|
LL | fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
| ------------------------------- expected `&dyn for<'a> Supertrait<'a, 'a>` because of return type
LL | x
| ^ expected trait `Supertrait`, found trait `Subtrait`
|
= note: expected reference `&dyn for<'a> Supertrait<'a, 'a>`
found reference `&dyn for<'a, 'b> Subtrait<'a, 'b>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -1,19 +1,21 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass
// We should be able to instantiate a binder during trait upcasting.
// This test could be `check-pass`, but we should make sure that we
// do so in both trait solvers.
#![feature(trait_upcasting)]
#![crate_type = "rlib"]
trait Supertrait<'a, 'b> {}
#![feature(trait_upcasting)]
trait Supertrait<'a, 'b> {}
trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
impl<'a> Supertrait<'a, 'a> for () {}
impl<'a> Subtrait<'a, 'a> for () {}
fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
x //~ ERROR mismatched types
//[current]~^ ERROR mismatched types
x
}
fn main() {}

View File

@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | x
| ^ one type is more general than the other
|
= note: expected existential trait ref `for<'a> Supertrait<'a, 'a>`
found existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
= note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
found existential trait ref `for<'a> Supertrait<'a, 'a>`
error[E0308]: mismatched types
--> $DIR/higher-ranked-upcasting-ub.rs:22:5
@ -13,8 +13,8 @@ error[E0308]: mismatched types
LL | x
| ^ one type is more general than the other
|
= note: expected existential trait ref `for<'a> Supertrait<'a, 'a>`
found existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
= note: expected existential trait ref `for<'a, 'b> Supertrait<'a, 'b>`
found existential trait ref `for<'a> Supertrait<'a, 'a>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,26 @@
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// Verify that the unsize goal can cast a higher-ranked trait goal to
// a non-higer-ranked instantiation.
#![feature(unsize)]
use std::marker::Unsize;
fn test<T: ?Sized, U: ?Sized>()
where
T: Unsize<U>,
{
}
fn main() {
test::<dyn for<'a> Fn(&'a ()) -> &'a (), dyn FnOnce(&'static ()) -> &'static ()>();
trait Foo: for<'a> Bar<'a> {}
trait Bar<'a> {}
test::<dyn Foo, dyn Bar<'static>>();
test::<dyn Foo, dyn Bar<'_>>();
}