Disable dyn* upcasting
This commit is contained in:
parent
70f8737b2f
commit
c620a972f3
7 changed files with 75 additions and 35 deletions
|
@ -755,20 +755,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
|
|
||||||
if let ty::Dynamic(a_data, _, _) = a.kind()
|
if let ty::Dynamic(a_data, _, _) = a.kind()
|
||||||
&& let ty::Dynamic(b_data, _, _) = b.kind()
|
&& let ty::Dynamic(b_data, _, _) = b.kind()
|
||||||
|
&& a_data.principal_def_id() == b_data.principal_def_id()
|
||||||
{
|
{
|
||||||
if a_data.principal_def_id() == b_data.principal_def_id() {
|
return self.unify_and(a, b, |_| vec![]);
|
||||||
return self.unify_and(a, b, |_| vec![]);
|
|
||||||
} else if !self.tcx().features().trait_upcasting {
|
|
||||||
let mut err = feature_err(
|
|
||||||
&self.tcx.sess.parse_sess,
|
|
||||||
sym::trait_upcasting,
|
|
||||||
self.cause.span,
|
|
||||||
&format!(
|
|
||||||
"cannot cast `{a}` to `{b}`, trait upcasting coercion is experimental"
|
|
||||||
),
|
|
||||||
);
|
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the obligations of the cast -- for example, when casting
|
// Check the obligations of the cast -- for example, when casting
|
||||||
|
@ -796,19 +785,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
])
|
])
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Enforce that the type is `usize`/pointer-sized. For now, only those
|
// Enforce that the type is `usize`/pointer-sized.
|
||||||
// can be coerced to `dyn*`, except for `dyn* -> dyn*` upcasts.
|
obligations.push(Obligation::new(
|
||||||
if !a.is_dyn_star() {
|
self.tcx,
|
||||||
obligations.push(Obligation::new(
|
self.cause.clone(),
|
||||||
self.tcx,
|
self.param_env,
|
||||||
self.cause.clone(),
|
ty::Binder::dummy(
|
||||||
self.param_env,
|
self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]),
|
||||||
ty::Binder::dummy(
|
)
|
||||||
self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]),
|
.to_poly_trait_predicate(),
|
||||||
)
|
));
|
||||||
.to_poly_trait_predicate(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(InferOk {
|
Ok(InferOk {
|
||||||
value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
|
value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
|
||||||
|
|
|
@ -776,9 +776,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
match (source.kind(), target.kind()) {
|
match (source.kind(), target.kind()) {
|
||||||
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
|
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
|
||||||
(&ty::Dynamic(ref data_a, _, dyn_a), &ty::Dynamic(ref data_b, _, dyn_b))
|
(&ty::Dynamic(ref data_a, _, ty::Dyn), &ty::Dynamic(ref data_b, _, ty::Dyn)) => {
|
||||||
if dyn_a == dyn_b =>
|
|
||||||
{
|
|
||||||
// Upcast coercions permit several things:
|
// Upcast coercions permit several things:
|
||||||
//
|
//
|
||||||
// 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
|
// 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
|
||||||
|
|
|
@ -803,9 +803,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
let upcast_trait_ref;
|
let upcast_trait_ref;
|
||||||
match (source.kind(), target.kind()) {
|
match (source.kind(), target.kind()) {
|
||||||
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
// TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
|
||||||
(&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b))
|
(
|
||||||
if repr_a == repr_b =>
|
&ty::Dynamic(ref data_a, r_a, repr_a @ ty::Dyn),
|
||||||
{
|
&ty::Dynamic(ref data_b, r_b, ty::Dyn),
|
||||||
|
) => {
|
||||||
// See `assemble_candidates_for_unsizing` for more info.
|
// See `assemble_candidates_for_unsizing` for more info.
|
||||||
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
|
||||||
let principal_a = data_a.principal().unwrap();
|
let principal_a = data_a.principal().unwrap();
|
||||||
|
@ -831,7 +832,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.map(ty::Binder::dummy),
|
.map(ty::Binder::dummy),
|
||||||
);
|
);
|
||||||
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
|
||||||
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b);
|
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
|
||||||
|
|
||||||
// Require that the traits involved in this upcast are **equal**;
|
// Require that the traits involved in this upcast are **equal**;
|
||||||
// only the **lifetime bound** is changed.
|
// only the **lifetime bound** is changed.
|
||||||
|
|
13
src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
Normal file
13
src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(dyn_star, trait_upcasting)]
|
||||||
|
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
|
||||||
|
trait A: B {}
|
||||||
|
trait B {}
|
||||||
|
impl A for usize {}
|
||||||
|
impl B for usize {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: Box<dyn* A> = Box::new(1usize as dyn* A);
|
||||||
|
let y: Box<dyn* B> = x;
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
23
src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
Normal file
23
src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(dyn_star, trait_upcasting)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/no-unsize-coerce-dyn-trait.rs:11:26
|
||||||
|
|
|
||||||
|
LL | let y: Box<dyn* B> = x;
|
||||||
|
| ----------- ^ expected trait `B`, found trait `A`
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected struct `Box<dyn* B>`
|
||||||
|
found struct `Box<dyn* A>`
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,7 +1,6 @@
|
||||||
// run-pass
|
// known-bug: unknown
|
||||||
|
|
||||||
#![feature(dyn_star, trait_upcasting)]
|
#![feature(dyn_star, trait_upcasting)]
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
trait Foo: Bar {
|
trait Foo: Bar {
|
||||||
fn hello(&self);
|
fn hello(&self);
|
||||||
|
|
20
src/test/ui/dyn-star/upcast.stderr
Normal file
20
src/test/ui/dyn-star/upcast.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/upcast.rs:3:12
|
||||||
|
|
|
||||||
|
LL | #![feature(dyn_star, trait_upcasting)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0277]: `dyn* Foo` needs to be a pointer-sized type
|
||||||
|
--> $DIR/upcast.rs:30:23
|
||||||
|
|
|
||||||
|
LL | let w: dyn* Bar = w;
|
||||||
|
| ^ `dyn* Foo` needs to be a pointer-sized type
|
||||||
|
|
|
||||||
|
= help: the trait `PointerSized` is not implemented for `dyn* Foo`
|
||||||
|
|
||||||
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue