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

View File

@ -2582,12 +2582,12 @@ fn match_upcast_principal(
nested.extend( nested.extend(
self.infcx self.infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq( .sup(
DefineOpaqueTypes::Yes, DefineOpaqueTypes::Yes,
bound.rebind(target_principal),
upcast_principal.map_bound(|trait_ref| { upcast_principal.map_bound(|trait_ref| {
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
}), }),
bound.rebind(target_principal),
) )
.map_err(|_| SelectionError::Unimplemented)? .map_err(|_| SelectionError::Unimplemented)?
.into_obligations(), .into_obligations(),
@ -2620,7 +2620,7 @@ fn match_upcast_principal(
nested.extend( nested.extend(
self.infcx self.infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::Yes, source_projection, target_projection) .sup(DefineOpaqueTypes::Yes, target_projection, source_projection)
.map_err(|_| SelectionError::Unimplemented)? .map_err(|_| SelectionError::Unimplemented)?
.into_obligations(), .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 //@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
//@ check-pass
// We should be able to instantiate a binder during trait upcasting. // We should be able to instantiate a binder during trait upcasting.
// This test could be `check-pass`, but we should make sure that we // This test could be `check-pass`, but we should make sure that we
// do so in both trait solvers. // 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> {} trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
impl<'a> Supertrait<'a, 'a> for () {} impl<'a> Supertrait<'a, 'a> for () {}
impl<'a> Subtrait<'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> { fn ok(x: &dyn for<'a, 'b> Subtrait<'a, 'b>) -> &dyn for<'a> Supertrait<'a, 'a> {
x //~ ERROR mismatched types x
//[current]~^ ERROR mismatched types
} }
fn main() {}

View File

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