Don't allow single-variant enums to be dereferenced. #6246
I'm not sure if this was even intentional at this point.
This commit is contained in:
parent
89907089c2
commit
18cef3fad4
6 changed files with 3 additions and 97 deletions
|
@ -540,19 +540,6 @@ impl<'a> PrivacyVisitor<'a> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that a dereference of a univariant enum can occur.
|
|
||||||
fn check_variant(&self, span: Span, enum_id: ast::DefId) {
|
|
||||||
let variant_info = ty::enum_variants(self.tcx, enum_id)[0];
|
|
||||||
|
|
||||||
match self.def_privacy(variant_info.id) {
|
|
||||||
Allowable => {}
|
|
||||||
ExternallyDenied | DisallowedBy(..) => {
|
|
||||||
self.tcx.sess.span_err(span, "can only dereference enums \
|
|
||||||
with a single, public variant");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks that a field is in scope.
|
// Checks that a field is in scope.
|
||||||
// FIXME #6993: change type (and name) from Ident to Name
|
// FIXME #6993: change type (and name) from Ident to Name
|
||||||
fn check_field(&mut self, span: Span, id: ast::DefId, ident: ast::Ident) {
|
fn check_field(&mut self, span: Span, id: ast::DefId, ident: ast::Ident) {
|
||||||
|
@ -713,18 +700,6 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
|
||||||
struct type?!"),
|
struct type?!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, ast::UnDeref, operand) => {
|
|
||||||
// In *e, we need to check that if e's type is an
|
|
||||||
// enum type t, then t's first variant is public or
|
|
||||||
// privileged. (We can assume it has only one variant
|
|
||||||
// since typeck already happened.)
|
|
||||||
match ty::get(ty::expr_ty(self.tcx, operand)).sty {
|
|
||||||
ty::ty_enum(id, _) => {
|
|
||||||
self.check_variant(expr.span, id);
|
|
||||||
}
|
|
||||||
_ => { /* No check needed */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -628,37 +628,6 @@ impl Datum {
|
||||||
ty::ty_rptr(_, mt) => {
|
ty::ty_rptr(_, mt) => {
|
||||||
return (Some(deref_ptr(bcx, self, mt.ty)), bcx);
|
return (Some(deref_ptr(bcx, self, mt.ty)), bcx);
|
||||||
}
|
}
|
||||||
ty::ty_enum(did, ref substs) => {
|
|
||||||
// Check whether this enum is a newtype enum:
|
|
||||||
let variants = ty::enum_variants(ccx.tcx, did);
|
|
||||||
if (*variants).len() != 1 || variants[0].args.len() != 1 {
|
|
||||||
return (None, bcx);
|
|
||||||
}
|
|
||||||
|
|
||||||
let repr = adt::represent_type(ccx, self.ty);
|
|
||||||
let ty = ty::subst(ccx.tcx, substs, variants[0].args[0]);
|
|
||||||
return match self.mode {
|
|
||||||
ByRef(_) => {
|
|
||||||
// Recast lv.val as a pointer to the newtype
|
|
||||||
// rather than a ptr to the enum type.
|
|
||||||
(
|
|
||||||
Some(Datum {
|
|
||||||
val: adt::trans_field_ptr(bcx, repr, self.val,
|
|
||||||
0, 0),
|
|
||||||
ty: ty,
|
|
||||||
mode: ByRef(ZeroMem)
|
|
||||||
}),
|
|
||||||
bcx
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ByValue => {
|
|
||||||
// Actually, this case cannot happen right
|
|
||||||
// now, because enums are never immediate.
|
|
||||||
assert!(type_is_immediate(bcx.ccx(), ty));
|
|
||||||
(Some(Datum {ty: ty, ..*self}), bcx)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ty::ty_struct(did, ref substs) => {
|
ty::ty_struct(did, ref substs) => {
|
||||||
// Check whether this struct is a newtype struct.
|
// Check whether this struct is a newtype struct.
|
||||||
let fields = ty::struct_fields(ccx.tcx, did, substs);
|
let fields = ty::struct_fields(ccx.tcx, did, substs);
|
||||||
|
|
|
@ -2631,16 +2631,6 @@ pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
|
||||||
Some(mt)
|
Some(mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_enum(did, ref substs) => {
|
|
||||||
let variants = enum_variants(cx, did);
|
|
||||||
if (*variants).len() == 1u && variants[0].args.len() == 1u {
|
|
||||||
let v_t = subst(cx, substs, variants[0].args[0]);
|
|
||||||
Some(mt {ty: v_t, mutbl: ast::MutImmutable})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ty_struct(did, ref substs) => {
|
ty_struct(did, ref substs) => {
|
||||||
let fields = struct_fields(cx, did, substs);
|
let fields = struct_fields(cx, did, substs);
|
||||||
if fields.len() == 1 && fields[0].ident ==
|
if fields.len() == 1 && fields[0].ident ==
|
||||||
|
|
|
@ -2765,12 +2765,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
match *sty {
|
match *sty {
|
||||||
ty::ty_enum(..) => {
|
|
||||||
tcx.sess.span_err(
|
|
||||||
expr.span,
|
|
||||||
"can only dereference enums with a single variant which \
|
|
||||||
has a single argument");
|
|
||||||
}
|
|
||||||
ty::ty_struct(..) => {
|
ty::ty_struct(..) => {
|
||||||
tcx.sess.span_err(
|
tcx.sess.span_err(
|
||||||
expr.span,
|
expr.span,
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
mod ctr {
|
|
||||||
|
|
||||||
pub enum ctr { priv mkCtr(int) }
|
|
||||||
|
|
||||||
pub fn new(i: int) -> ctr { mkCtr(i) }
|
|
||||||
pub fn inc(c: ctr) -> ctr { mkCtr(*c + 1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let c = ctr::new(42);
|
|
||||||
let c2 = ctr::inc(c);
|
|
||||||
assert!(*c2 == 5); //~ ERROR can only dereference enums with a single, public variant
|
|
||||||
}
|
|
|
@ -32,7 +32,9 @@ fn linear_map<K,V>() -> HashMap<K,V> {
|
||||||
|
|
||||||
impl<K,V> HashMap<K,V> {
|
impl<K,V> HashMap<K,V> {
|
||||||
pub fn len(&mut self) -> uint {
|
pub fn len(&mut self) -> uint {
|
||||||
self.size
|
match *self {
|
||||||
|
HashMap_(l) => l.size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue