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
|
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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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() {}
|
Loading…
Reference in New Issue