Check allow instantiating object trait binder when upcasting and in new solver
This commit is contained in:
parent
58420a065b
commit
d4ee408afc
@ -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) => {
|
||||||
|
@ -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(),
|
||||||
);
|
);
|
||||||
|
27
tests/ui/coercion/sub-principals.rs
Normal file
27
tests/ui/coercion/sub-principals.rs
Normal 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<'_>>();
|
||||||
|
}
|
@ -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`.
|
|
@ -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`.
|
|
@ -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() {}
|
||||||
|
@ -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
|
||||||
|
26
tests/ui/traits/trait-upcasting/sub.rs
Normal file
26
tests/ui/traits/trait-upcasting/sub.rs
Normal 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<'_>>();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user