type parameters have unit metadata if they are sized
This commit is contained in:
parent
6d7684101a
commit
ef0ba1d2ce
3 changed files with 47 additions and 14 deletions
|
@ -2244,12 +2244,13 @@ impl<'tcx> Ty<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type of metadata for (potentially fat) pointers to this type.
|
/// Returns the type of metadata for (potentially fat) pointers to this type,
|
||||||
|
/// and a boolean signifying if this is conditional on this type being `Sized`.
|
||||||
pub fn ptr_metadata_ty(
|
pub fn ptr_metadata_ty(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
|
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> (Ty<'tcx>, bool) {
|
||||||
let tail = tcx.struct_tail_with_normalize(self, normalize);
|
let tail = tcx.struct_tail_with_normalize(self, normalize);
|
||||||
match tail.kind() {
|
match tail.kind() {
|
||||||
// Sized types
|
// Sized types
|
||||||
|
@ -2269,28 +2270,31 @@ impl<'tcx> Ty<'tcx> {
|
||||||
| ty::Closure(..)
|
| ty::Closure(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Error(_)
|
| ty::Error(_)
|
||||||
|
// Extern types have metadata = ().
|
||||||
| ty::Foreign(..)
|
| ty::Foreign(..)
|
||||||
// If returned by `struct_tail_without_normalization` this is a unit struct
|
// If returned by `struct_tail_without_normalization` this is a unit struct
|
||||||
// without any fields, or not a struct, and therefore is Sized.
|
// without any fields, or not a struct, and therefore is Sized.
|
||||||
| ty::Adt(..)
|
| ty::Adt(..)
|
||||||
// If returned by `struct_tail_without_normalization` this is the empty tuple,
|
// If returned by `struct_tail_without_normalization` this is the empty tuple,
|
||||||
// a.k.a. unit type, which is Sized
|
// a.k.a. unit type, which is Sized
|
||||||
| ty::Tuple(..) => tcx.types.unit,
|
| ty::Tuple(..) => (tcx.types.unit, false),
|
||||||
|
|
||||||
ty::Str | ty::Slice(_) => tcx.types.usize,
|
ty::Str | ty::Slice(_) => (tcx.types.usize, false),
|
||||||
ty::Dynamic(..) => {
|
ty::Dynamic(..) => {
|
||||||
let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap();
|
let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap();
|
||||||
tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()])
|
(tcx.type_of(dyn_metadata).subst(tcx, &[self.into()]), false)
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::Projection(_)
|
// type parameters only have unit metadata if they're sized, so return true
|
||||||
| ty::Param(_)
|
// to make sure we double check this during confirmation
|
||||||
| ty::Opaque(..)
|
ty::Param(_) | ty::Projection(_) => (tcx.types.unit, true),
|
||||||
|
|
||||||
|
ty::Opaque(..)
|
||||||
| ty::Infer(ty::TyVar(_))
|
| ty::Infer(ty::TyVar(_))
|
||||||
| ty::Bound(..)
|
| ty::Bound(..)
|
||||||
| ty::Placeholder(..)
|
| ty::Placeholder(..)
|
||||||
| ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
| ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||||
bug!("`ptr_metadata_ty` applied to unexpected type: {:?}", tail)
|
bug!("`ptr_metadata_ty` applied to unexpected type: {:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1399,6 +1399,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
||||||
|
|
||||||
let tail = selcx.tcx().struct_tail_with_normalize(self_ty, |ty| {
|
let tail = selcx.tcx().struct_tail_with_normalize(self_ty, |ty| {
|
||||||
|
// We throw away any obligations we get from this, since we normalize
|
||||||
|
// and confirm these obligations once again during confirmation
|
||||||
normalize_with_depth(
|
normalize_with_depth(
|
||||||
selcx,
|
selcx,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
@ -1415,7 +1417,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
| ty::Uint(_)
|
| ty::Uint(_)
|
||||||
| ty::Float(_)
|
| ty::Float(_)
|
||||||
| ty::Foreign(_)
|
|
||||||
| ty::Str
|
| ty::Str
|
||||||
| ty::Array(..)
|
| ty::Array(..)
|
||||||
| ty::Slice(_)
|
| ty::Slice(_)
|
||||||
|
@ -1428,6 +1429,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
| ty::Generator(..)
|
| ty::Generator(..)
|
||||||
| ty::GeneratorWitness(..)
|
| ty::GeneratorWitness(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
|
// Extern types have unit metadata, according to RFC 2850
|
||||||
|
| ty::Foreign(_)
|
||||||
// If returned by `struct_tail_without_normalization` this is a unit struct
|
// If returned by `struct_tail_without_normalization` this is a unit struct
|
||||||
// without any fields, or not a struct, and therefore is Sized.
|
// without any fields, or not a struct, and therefore is Sized.
|
||||||
| ty::Adt(..)
|
| ty::Adt(..)
|
||||||
|
@ -1436,9 +1439,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
// Integers and floats are always Sized, and so have unit type metadata.
|
// Integers and floats are always Sized, and so have unit type metadata.
|
||||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
||||||
|
|
||||||
ty::Projection(..)
|
// type parameters and unnormalized projections have pointer metadata if they're still known to be sized
|
||||||
| ty::Opaque(..)
|
ty::Param(_) | ty::Projection(..) => tail.is_sized(selcx.tcx().at(obligation.cause.span), obligation.param_env),
|
||||||
| ty::Param(..)
|
|
||||||
|
ty::Opaque(..)
|
||||||
| ty::Bound(..)
|
| ty::Bound(..)
|
||||||
| ty::Placeholder(..)
|
| ty::Placeholder(..)
|
||||||
| ty::Infer(..)
|
| ty::Infer(..)
|
||||||
|
@ -1657,7 +1661,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
|
||||||
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
||||||
|
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
let metadata_ty = self_ty.ptr_metadata_ty(tcx, |ty| {
|
let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| {
|
||||||
normalize_with_depth_to(
|
normalize_with_depth_to(
|
||||||
selcx,
|
selcx,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
@ -1667,6 +1671,19 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
|
||||||
&mut obligations,
|
&mut obligations,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
if check_is_sized {
|
||||||
|
let sized_predicate = ty::Binder::dummy(ty::TraitRef::new(
|
||||||
|
tcx.require_lang_item(LangItem::Sized, None),
|
||||||
|
tcx.mk_substs_trait(self_ty, &[]),
|
||||||
|
))
|
||||||
|
.without_const()
|
||||||
|
.to_predicate(tcx);
|
||||||
|
obligations.push(Obligation::new(
|
||||||
|
obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
|
sized_predicate,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let substs = tcx.mk_substs([self_ty.into()].iter());
|
let substs = tcx.mk_substs([self_ty.into()].iter());
|
||||||
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
|
let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None);
|
||||||
|
|
12
src/test/ui/traits/pointee-tail-is-generic.rs
Normal file
12
src/test/ui/traits/pointee-tail-is-generic.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
#![feature(ptr_metadata)]
|
||||||
|
|
||||||
|
fn a<T>() {
|
||||||
|
b::<T>();
|
||||||
|
b::<std::cell::Cell<T>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b<T: std::ptr::Pointee<Metadata = ()>>() {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue