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:
bors 2015-09-01 23:51:47 +00:00
commit 7780408af6
3 changed files with 1 additions and 115 deletions

View File

@ -4821,100 +4821,6 @@ impl<'tcx> TyS<'tcx> {
result 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 /// Describes whether a type is representable. For types that are not

View File

@ -117,7 +117,6 @@ use syntax::attr::AttrMetaMethods;
use syntax::ast::{self, Visibility}; use syntax::ast::{self, Visibility};
use syntax::ast_util; use syntax::ast_util;
use syntax::codemap::{self, Span}; use syntax::codemap::{self, Span};
use syntax::feature_gate::emit_feature_err;
use syntax::owned_slice::OwnedSlice; use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::{self, InternedString}; use syntax::parse::token::{self, InternedString};
use syntax::print::pprust; use syntax::print::pprust;
@ -669,7 +668,6 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
check_representable(tcx, span, id, "struct"); check_representable(tcx, span, id, "struct");
check_instantiable(tcx, span, id);
if tcx.lookup_simd(DefId::local(id)) { if tcx.lookup_simd(DefId::local(id)) {
check_simd(tcx, span, id); check_simd(tcx, span, id);
@ -4202,22 +4200,6 @@ pub fn check_representable(tcx: &ty::ctxt,
return true 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) { pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
let t = tcx.node_id_to_type(id); let t = tcx.node_id_to_type(id);
match t.sty { match t.sty {
@ -4352,7 +4334,6 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
do_check(ccx, vs, id, hint); do_check(ccx, vs, id, hint);
check_representable(ccx.tcx, sp, id, "enum"); 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. // Returns the type parameter count and the type for the given definition.

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
struct Z(&'static Z); pub struct Z(&'static Z);
//~^ ERROR this type cannot be instantiated
pub fn main() {} pub fn main() {}