mirror of https://github.com/rust-lang/rust.git
Auto merge of #28132 - arielb1:uninstantiable, r=nikomatsakis
It is *very* easy to bypass, and is a relic of a bygone age where the type-checker was *much* less robust. Fixes #27497 r? @nikomatsakis
This commit is contained in:
commit
7780408af6
|
@ -4821,100 +4821,6 @@ impl<'tcx> TyS<'tcx> {
|
|||
|
||||
result
|
||||
}
|
||||
|
||||
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
|
||||
pub fn is_instantiable(&'tcx self, cx: &ctxt<'tcx>) -> bool {
|
||||
fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<AdtDef<'tcx>>,
|
||||
r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
debug!("type_requires({:?}, {:?})?",
|
||||
r_ty, ty);
|
||||
|
||||
let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
|
||||
|
||||
debug!("type_requires({:?}, {:?})? {:?}",
|
||||
r_ty, ty, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<AdtDef<'tcx>>,
|
||||
r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
debug!("subtypes_require({:?}, {:?})?",
|
||||
r_ty, ty);
|
||||
|
||||
let r = match ty.sty {
|
||||
// fixed length vectors need special treatment compared to
|
||||
// normal vectors, since they don't necessarily have the
|
||||
// possibility to have length zero.
|
||||
TyArray(_, 0) => false, // don't need no contents
|
||||
TyArray(ty, _) => type_requires(cx, seen, r_ty, ty),
|
||||
|
||||
TyBool |
|
||||
TyChar |
|
||||
TyInt(_) |
|
||||
TyUint(_) |
|
||||
TyFloat(_) |
|
||||
TyStr |
|
||||
TyBareFn(..) |
|
||||
TyParam(_) |
|
||||
TyProjection(_) |
|
||||
TySlice(_) => {
|
||||
false
|
||||
}
|
||||
TyBox(typ) => {
|
||||
type_requires(cx, seen, r_ty, typ)
|
||||
}
|
||||
TyRef(_, ref mt) => {
|
||||
type_requires(cx, seen, r_ty, mt.ty)
|
||||
}
|
||||
|
||||
TyRawPtr(..) => {
|
||||
false // unsafe ptrs can always be NULL
|
||||
}
|
||||
|
||||
TyTrait(..) => {
|
||||
false
|
||||
}
|
||||
|
||||
TyStruct(def, substs) | TyEnum(def, substs) => {
|
||||
if seen.contains(&def) {
|
||||
// FIXME(#27497) ???
|
||||
false
|
||||
} else if def.is_empty() {
|
||||
// HACK: required for empty types to work. This
|
||||
// check is basically a lint anyway.
|
||||
false
|
||||
} else {
|
||||
seen.push(def);
|
||||
let r = def.variants.iter().all(|v| v.fields.iter().any(|f| {
|
||||
type_requires(cx, seen, r_ty, f.ty(cx, substs))
|
||||
}));
|
||||
seen.pop().unwrap();
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
TyError |
|
||||
TyInfer(_) |
|
||||
TyClosure(..) => {
|
||||
// this check is run on type definitions, so we don't expect to see
|
||||
// inference by-products or closure types
|
||||
cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
|
||||
}
|
||||
|
||||
TyTuple(ref ts) => {
|
||||
ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
|
||||
}
|
||||
};
|
||||
|
||||
debug!("subtypes_require({:?}, {:?})? {:?}",
|
||||
r_ty, ty, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
let mut seen = Vec::new();
|
||||
!subtypes_require(cx, &mut seen, self, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes whether a type is representable. For types that are not
|
||||
|
|
|
@ -117,7 +117,6 @@ use syntax::attr::AttrMetaMethods;
|
|||
use syntax::ast::{self, Visibility};
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::{self, Span};
|
||||
use syntax::feature_gate::emit_feature_err;
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
use syntax::parse::token::{self, InternedString};
|
||||
use syntax::print::pprust;
|
||||
|
@ -669,7 +668,6 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
|
|||
let tcx = ccx.tcx;
|
||||
|
||||
check_representable(tcx, span, id, "struct");
|
||||
check_instantiable(tcx, span, id);
|
||||
|
||||
if tcx.lookup_simd(DefId::local(id)) {
|
||||
check_simd(tcx, span, id);
|
||||
|
@ -4202,22 +4200,6 @@ pub fn check_representable(tcx: &ty::ctxt,
|
|||
return true
|
||||
}
|
||||
|
||||
/// Checks whether a type can be constructed at runtime without
|
||||
/// an existing instance of that type.
|
||||
pub fn check_instantiable(tcx: &ty::ctxt,
|
||||
sp: Span,
|
||||
item_id: ast::NodeId) {
|
||||
let item_ty = tcx.node_id_to_type(item_id);
|
||||
if !item_ty.is_instantiable(tcx) &&
|
||||
!tcx.sess.features.borrow().static_recursion {
|
||||
emit_feature_err(&tcx.sess.parse_sess.span_diagnostic,
|
||||
"static_recursion",
|
||||
sp,
|
||||
"this type cannot be instantiated at runtime \
|
||||
without an instance of itself");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
|
||||
let t = tcx.node_id_to_type(id);
|
||||
match t.sty {
|
||||
|
@ -4352,7 +4334,6 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
|||
do_check(ccx, vs, id, hint);
|
||||
|
||||
check_representable(ccx.tcx, sp, id, "enum");
|
||||
check_instantiable(ccx.tcx, sp, id);
|
||||
}
|
||||
|
||||
// Returns the type parameter count and the type for the given definition.
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct Z(&'static Z);
|
||||
//~^ ERROR this type cannot be instantiated
|
||||
pub struct Z(&'static Z);
|
||||
|
||||
pub fn main() {}
|
Loading…
Reference in New Issue