mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Equate types instead of using Unsize
This commit is contained in:
parent
56de9da1f8
commit
073f3a263b
@ -38,6 +38,7 @@ use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
|
||||
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
@ -49,6 +50,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::ResultsCursor;
|
||||
|
||||
use crate::renumber::RegionCtxt;
|
||||
use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
|
||||
use crate::{
|
||||
borrow_set::BorrowSet,
|
||||
@ -2335,51 +2337,39 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
&& src_tty.principal().is_some()
|
||||
&& dst_tty.principal().is_some()
|
||||
{
|
||||
// Erase trait object lifetimes, to allow casts like `*mut dyn FnOnce()` -> `*mut dyn FnOnce() + 'static`
|
||||
// and remove auto traits.
|
||||
// Remove auto traits.
|
||||
// Auto trait checks are handled in `rustc_hir_typeck` as FCW.
|
||||
let src_obj = tcx.mk_ty_from_kind(ty::Dynamic(
|
||||
tcx.mk_poly_existential_predicates(
|
||||
&src_tty.without_auto_traits().collect::<Vec<_>>(),
|
||||
),
|
||||
tcx.lifetimes.re_erased,
|
||||
tcx.lifetimes.re_static,
|
||||
ty::Dyn,
|
||||
));
|
||||
let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
|
||||
tcx.mk_poly_existential_predicates(
|
||||
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
|
||||
),
|
||||
tcx.lifetimes.re_erased,
|
||||
tcx.lifetimes.re_static,
|
||||
ty::Dyn,
|
||||
));
|
||||
|
||||
// FIXME:
|
||||
// this currently does nothing, but once we make `ptr_cast_add_auto_to_object`
|
||||
// into a hard error, we can remove the above removal of auto traits and only
|
||||
// keep this.
|
||||
let src_obj = erase_single_trait_object_lifetime(tcx, src_obj);
|
||||
let dst_obj = erase_single_trait_object_lifetime(tcx, dst_obj);
|
||||
|
||||
let trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::Unsize, Some(span)),
|
||||
[src_obj, dst_obj],
|
||||
);
|
||||
// Replace trait object lifetimes with fresh vars, to allow casts like
|
||||
// `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`,
|
||||
let src_obj =
|
||||
freshen_single_trait_object_lifetime(self.infcx, src_obj);
|
||||
let dst_obj =
|
||||
freshen_single_trait_object_lifetime(self.infcx, dst_obj);
|
||||
|
||||
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
|
||||
|
||||
self.prove_trait_ref(
|
||||
trait_ref,
|
||||
self.eq_types(
|
||||
src_obj,
|
||||
dst_obj,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Cast {
|
||||
unsize_to: Some(tcx.fold_regions(dst_obj, |r, _| {
|
||||
if let ty::ReVar(_) = r.kind() {
|
||||
tcx.lifetimes.re_erased
|
||||
} else {
|
||||
r
|
||||
}
|
||||
})),
|
||||
},
|
||||
);
|
||||
ConstraintCategory::Cast { unsize_to: None },
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -2905,14 +2895,15 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn erase_single_trait_object_lifetime<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let &ty::Dynamic(tty, region, dyn_kind @ ty::Dyn) = ty.kind() else {
|
||||
bug!("expected trait object")
|
||||
};
|
||||
fn freshen_single_trait_object_lifetime<'tcx>(
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") };
|
||||
|
||||
if region.is_erased() {
|
||||
return ty;
|
||||
}
|
||||
|
||||
tcx.mk_ty_from_kind(ty::Dynamic(tty, tcx.lifetimes.re_erased, dyn_kind))
|
||||
let fresh = infcx
|
||||
.next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || {
|
||||
RegionCtxt::Unknown
|
||||
});
|
||||
infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind))
|
||||
}
|
||||
|
@ -34,8 +34,7 @@ use crate::errors;
|
||||
use crate::type_error_struct;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{codes::*, Applicability, Diag, ErrorGuaranteed};
|
||||
use rustc_hir::{self as hir, ExprKind, LangItem};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_hir::{self as hir, ExprKind};
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::Mutability;
|
||||
@ -835,9 +834,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
(Some(src_principal), Some(dst_principal)) => {
|
||||
let tcx = fcx.tcx;
|
||||
|
||||
// Check that the traits are actually the same
|
||||
// (this is required as the `Unsize` check below would allow upcasting, etc)
|
||||
// N.B.: this is only correct as long as we don't support `trait A<T>: A<()>`.
|
||||
// Check that the traits are actually the same.
|
||||
// The `dyn Src = dyn Dst` check below would suffice,
|
||||
// but this may produce a better diagnostic.
|
||||
//
|
||||
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
|
||||
// and is unaffected by this check.
|
||||
@ -867,20 +866,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
ty::Dyn,
|
||||
));
|
||||
|
||||
// `dyn Src: Unsize<dyn Dst>`, this checks for matching generics
|
||||
let cause = fcx.misc(self.span);
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
cause,
|
||||
fcx.param_env,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::Unsize, Some(self.span)),
|
||||
[src_obj, dst_obj],
|
||||
),
|
||||
);
|
||||
|
||||
fcx.register_predicate(obligation);
|
||||
// `dyn Src = dyn Dst`, this checks for matching traits/generics
|
||||
fcx.demand_eqtype(self.span, src_obj, dst_obj);
|
||||
|
||||
// Check that `SrcAuto` is a superset of `DstAuto`.
|
||||
// Emit an FCW otherwise.
|
||||
|
@ -18,14 +18,14 @@ fn main() {
|
||||
let b: *const dyn B = a as _; //~ error: casting `*const dyn A` as `*const dyn B` is invalid
|
||||
|
||||
let x: *const dyn Trait<X> = &();
|
||||
let y: *const dyn Trait<Y> = x as _; //~ error: the trait bound `dyn Trait<X>: Unsize<dyn Trait<Y>>` is not satisfied
|
||||
let y: *const dyn Trait<Y> = x as _; //~ error: mismatched types
|
||||
|
||||
_ = (b, y);
|
||||
}
|
||||
|
||||
fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
|
||||
let _: *const dyn Trait<T> = x as _; //~ error: the trait bound `dyn Trait<X>: Unsize<dyn Trait<T>>` is not satisfied
|
||||
let _: *const dyn Trait<X> = t as _; //~ error: the trait bound `dyn Trait<T>: Unsize<dyn Trait<X>>` is not satisfied
|
||||
let _: *const dyn Trait<T> = x as _; //~ error: mismatched types
|
||||
let _: *const dyn Trait<X> = t as _; //~ error: mismatched types
|
||||
}
|
||||
|
||||
trait Assocked {
|
||||
@ -33,5 +33,5 @@ trait Assocked {
|
||||
}
|
||||
|
||||
fn change_assoc(x: *mut dyn Assocked<Assoc = u8>) -> *mut dyn Assocked<Assoc = u32> {
|
||||
x as _ //~ error: the trait bound `dyn Assocked<Assoc = u8>: Unsize<dyn Assocked<Assoc = u32>>` is not satisfied
|
||||
x as _ //~ error: mismatched types
|
||||
}
|
||||
|
@ -6,47 +6,48 @@ LL | let b: *const dyn B = a as _;
|
||||
|
|
||||
= note: vtable kinds may not match
|
||||
|
||||
error[E0277]: the trait bound `dyn Trait<X>: Unsize<dyn Trait<Y>>` is not satisfied
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ptr-to-trait-obj-different-args.rs:21:34
|
||||
|
|
||||
LL | let y: *const dyn Trait<Y> = x as _;
|
||||
| ^^^^^^ the trait `Unsize<dyn Trait<Y>>` is not implemented for `dyn Trait<X>`
|
||||
| ^^^^^^ expected `X`, found `Y`
|
||||
|
|
||||
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
|
||||
= note: expected trait object `dyn Trait<X>`
|
||||
found trait object `dyn Trait<Y>`
|
||||
|
||||
error[E0277]: the trait bound `dyn Trait<X>: Unsize<dyn Trait<T>>` is not satisfied
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ptr-to-trait-obj-different-args.rs:27:34
|
||||
|
|
||||
LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
|
||||
| - found this type parameter
|
||||
LL | let _: *const dyn Trait<T> = x as _;
|
||||
| ^^^^^^ the trait `Unsize<dyn Trait<T>>` is not implemented for `dyn Trait<X>`
|
||||
| ^^^^^^ expected `X`, found type parameter `T`
|
||||
|
|
||||
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) where dyn Trait<X>: Unsize<dyn Trait<T>> {
|
||||
| ++++++++++++++++++++++++++++++++++++++++
|
||||
= note: expected trait object `dyn Trait<X>`
|
||||
found trait object `dyn Trait<T>`
|
||||
|
||||
error[E0277]: the trait bound `dyn Trait<T>: Unsize<dyn Trait<X>>` is not satisfied
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ptr-to-trait-obj-different-args.rs:28:34
|
||||
|
|
||||
LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) {
|
||||
| - expected this type parameter
|
||||
LL | let _: *const dyn Trait<T> = x as _;
|
||||
LL | let _: *const dyn Trait<X> = t as _;
|
||||
| ^^^^^^ the trait `Unsize<dyn Trait<X>>` is not implemented for `dyn Trait<T>`
|
||||
| ^^^^^^ expected type parameter `T`, found `X`
|
||||
|
|
||||
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | fn generic<T>(x: *const dyn Trait<X>, t: *const dyn Trait<T>) where dyn Trait<T>: Unsize<dyn Trait<X>> {
|
||||
| ++++++++++++++++++++++++++++++++++++++++
|
||||
= note: expected trait object `dyn Trait<T>`
|
||||
found trait object `dyn Trait<X>`
|
||||
|
||||
error[E0277]: the trait bound `dyn Assocked<Assoc = u8>: Unsize<dyn Assocked<Assoc = u32>>` is not satisfied
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ptr-to-trait-obj-different-args.rs:36:5
|
||||
|
|
||||
LL | x as _
|
||||
| ^^^^^^ the trait `Unsize<dyn Assocked<Assoc = u32>>` is not implemented for `dyn Assocked<Assoc = u8>`
|
||||
| ^^^^^^ expected `u8`, found `u32`
|
||||
|
|
||||
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
|
||||
= note: expected trait object `dyn Assocked<Assoc = u8>`
|
||||
found trait object `dyn Assocked<Assoc = u32>`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0606.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0308, E0606.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -57,7 +57,7 @@ pub fn user2() -> &'static dyn Trait<u8, u16> {
|
||||
fn main() {
|
||||
let p: *const dyn Trait<u8, u8> = &();
|
||||
let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
|
||||
//~^ error: the trait bound `dyn Trait<u8, u8>: Unsize<dyn Trait<u8, u16>>` is not satisfied
|
||||
//~^ error: mismatched types
|
||||
let p = p as *const dyn Super<u16>; // <- this upcast accesses improper vtable entry
|
||||
// accessing from L__unnamed_2 the position for the 'Super<u16> vtable (pointer)',
|
||||
// thus reading 'null pointer for missing_method'
|
||||
|
@ -1,11 +1,13 @@
|
||||
error[E0277]: the trait bound `dyn Trait<u8, u8>: Unsize<dyn Trait<u8, u16>>` is not satisfied
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/upcast_soundness_bug.rs:59:13
|
||||
|
|
||||
LL | let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<dyn Trait<u8, u16>>` is not implemented for `dyn Trait<u8, u8>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
|
||||
|
|
||||
= note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
|
||||
= note: expected trait object `dyn Trait<u8, u8>`
|
||||
found trait object `dyn Trait<u8, u16>`
|
||||
= help: `dyn Trait<u8, u16>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
Loading…
Reference in New Issue
Block a user