Auto merge of #36331 - petrochenkov:tyadt, r=eddyb
Refactor `TyStruct`/`TyEnum`/`TyUnion` into `TyAdt` r? @eddyb
This commit is contained in:
commit
f1f40f850e
@ -488,10 +488,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
// if they are both "path types", there's a chance of ambiguity
|
||||
// due to different versions of the same crate
|
||||
match (&exp_found.expected.sty, &exp_found.found.sty) {
|
||||
(&ty::TyEnum(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) |
|
||||
(&ty::TyStruct(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
|
||||
(&ty::TyEnum(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
|
||||
(&ty::TyStruct(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) => {
|
||||
(&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
|
||||
report_path_match(err, exp_adt.did, found_adt.did);
|
||||
},
|
||||
_ => ()
|
||||
|
@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
||||
ty::TyInt(..) |
|
||||
ty::TyUint(..) |
|
||||
ty::TyFloat(..) |
|
||||
ty::TyEnum(..) |
|
||||
ty::TyAdt(..) |
|
||||
ty::TyBox(..) |
|
||||
ty::TyStr |
|
||||
ty::TyError |
|
||||
@ -167,8 +167,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
||||
ty::TyFnDef(..) |
|
||||
ty::TyFnPtr(_) |
|
||||
ty::TyTrait(..) |
|
||||
ty::TyStruct(..) |
|
||||
ty::TyUnion(..) |
|
||||
ty::TyClosure(..) |
|
||||
ty::TyNever |
|
||||
ty::TyTuple(..) |
|
||||
|
@ -86,8 +86,6 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
|
||||
use ty::TypeVariants::{TyEnum, TyStruct, TyUnion};
|
||||
|
||||
let def = self.tcx.expect_def(id);
|
||||
|
||||
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
|
||||
@ -95,11 +93,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
|
||||
if self.tcx.trait_of_item(def.def_id()).is_some() => {
|
||||
if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
|
||||
match substs.substs.type_at(0).sty {
|
||||
TyEnum(tyid, _) | TyStruct(tyid, _) | TyUnion(tyid, _) => {
|
||||
self.check_def_id(tyid.did)
|
||||
}
|
||||
_ => {}
|
||||
if let ty::TyAdt(tyid, _) = substs.substs.type_at(0).sty {
|
||||
self.check_def_id(tyid.did);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,23 +128,27 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
|
||||
fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
|
||||
match self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.insert_def_id(def.struct_variant().field_named(name).did);
|
||||
}
|
||||
_ => span_bug!(lhs.span, "named field access on non-struct/union"),
|
||||
_ => span_bug!(lhs.span, "named field access on non-ADT"),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
|
||||
if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
self.insert_def_id(def.struct_variant().fields[idx].did);
|
||||
match self.tcx.expr_ty_adjusted(lhs).sty {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.insert_def_id(def.struct_variant().fields[idx].did);
|
||||
}
|
||||
ty::TyTuple(..) => {}
|
||||
_ => span_bug!(lhs.span, "numeric field access on non-ADT"),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
|
||||
pats: &[codemap::Spanned<hir::FieldPat>]) {
|
||||
let variant = match self.tcx.node_id_to_type(lhs.id).sty {
|
||||
ty::TyStruct(adt, _) | ty::TyUnion(adt, _) | ty::TyEnum(adt, _) => {
|
||||
ty::TyAdt(adt, _) => {
|
||||
adt.variant_of_def(self.tcx.expect_def(lhs.id))
|
||||
}
|
||||
_ => span_bug!(lhs.span, "non-ADT in struct pattern")
|
||||
|
@ -200,8 +200,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
hir::ExprField(ref base_expr, field) => {
|
||||
if let ty::TyUnion(..) = self.tcx.expr_ty_adjusted(base_expr).sty {
|
||||
self.require_unsafe(field.span, "access to union field");
|
||||
if let ty::TyAdt(adt, ..) = self.tcx.expr_ty_adjusted(base_expr).sty {
|
||||
if adt.is_union() {
|
||||
self.require_unsafe(field.span, "access to union field");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -212,9 +214,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
|
||||
fn visit_pat(&mut self, pat: &hir::Pat) {
|
||||
if let PatKind::Struct(_, ref fields, _) = pat.node {
|
||||
if let ty::TyUnion(..) = self.tcx.pat_ty(pat).sty {
|
||||
for field in fields {
|
||||
self.require_unsafe(field.span, "matching on union field");
|
||||
if let ty::TyAdt(adt, ..) = self.tcx.pat_ty(pat).sty {
|
||||
if adt.is_union() {
|
||||
for field in fields {
|
||||
self.require_unsafe(field.span, "matching on union field");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -671,28 +671,31 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Select just those fields of the `with`
|
||||
// expression that will actually be used
|
||||
if let ty::TyStruct(def, substs) = with_cmt.ty.sty {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for with_field in &def.struct_variant().fields {
|
||||
if !contains_field_named(with_field, fields) {
|
||||
let cmt_field = self.mc.cat_field(
|
||||
&*with_expr,
|
||||
with_cmt.clone(),
|
||||
with_field.name,
|
||||
with_field.ty(self.tcx(), substs)
|
||||
);
|
||||
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
|
||||
match with_cmt.ty.sty {
|
||||
ty::TyAdt(adt, substs) if adt.is_struct() => {
|
||||
// Consume those fields of the with expression that are needed.
|
||||
for with_field in &adt.struct_variant().fields {
|
||||
if !contains_field_named(with_field, fields) {
|
||||
let cmt_field = self.mc.cat_field(
|
||||
&*with_expr,
|
||||
with_cmt.clone(),
|
||||
with_field.name,
|
||||
with_field.ty(self.tcx(), substs)
|
||||
);
|
||||
self.delegate_consume(with_expr.id, with_expr.span, cmt_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the base expression should always evaluate to a
|
||||
// struct; however, when EUV is run during typeck, it
|
||||
// may not. This will generate an error earlier in typeck,
|
||||
// so we can just ignore it.
|
||||
if !self.tcx().sess.has_errors() {
|
||||
span_bug!(
|
||||
with_expr.span,
|
||||
"with expression doesn't evaluate to a struct");
|
||||
_ => {
|
||||
// the base expression should always evaluate to a
|
||||
// struct; however, when EUV is run during typeck, it
|
||||
// may not. This will generate an error earlier in typeck,
|
||||
// so we can just ignore it.
|
||||
if !self.tcx().sess.has_errors() {
|
||||
span_bug!(
|
||||
with_expr.span,
|
||||
"with expression doesn't evaluate to a struct");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,7 @@ fn deref_kind(t: Ty, context: DerefKindContext) -> McResult<deref_kind> {
|
||||
Ok(deref_ptr(UnsafePtr(mt.mutbl)))
|
||||
}
|
||||
|
||||
ty::TyEnum(..) |
|
||||
ty::TyStruct(..) => { // newtype
|
||||
ty::TyAdt(..) => { // newtype
|
||||
Ok(deref_interior(InteriorField(PositionalField(0))))
|
||||
}
|
||||
|
||||
@ -1154,7 +1153,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
Def::Struct(..) => {
|
||||
match self.pat_ty(&pat)?.sty {
|
||||
ty::TyStruct(adt_def, _) => {
|
||||
ty::TyAdt(adt_def, _) => {
|
||||
adt_def.struct_variant().fields.len()
|
||||
}
|
||||
ref ty => {
|
||||
|
@ -20,7 +20,7 @@ use lint;
|
||||
use middle::cstore::LOCAL_CRATE;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::{self, TyCtxt, AdtKind};
|
||||
use middle::privacy::AccessLevels;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
@ -561,17 +561,19 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
|
||||
hir::ExprField(ref base_e, ref field) => {
|
||||
span = field.span;
|
||||
match tcx.expr_ty_adjusted(base_e).sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
def.struct_variant().field_named(field.node).did
|
||||
}
|
||||
_ => span_bug!(e.span,
|
||||
"stability::check_expr: named field access on non-struct/union")
|
||||
"stability::check_expr: named field access on non-ADT")
|
||||
}
|
||||
}
|
||||
hir::ExprTupField(ref base_e, ref field) => {
|
||||
span = field.span;
|
||||
match tcx.expr_ty_adjusted(base_e).sty {
|
||||
ty::TyStruct(def, _) => def.struct_variant().fields[field.node].did,
|
||||
ty::TyAdt(def, _) => {
|
||||
def.struct_variant().fields[field.node].did
|
||||
}
|
||||
ty::TyTuple(..) => return,
|
||||
_ => span_bug!(e.span,
|
||||
"stability::check_expr: unnamed field access on \
|
||||
@ -579,31 +581,28 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
|
||||
}
|
||||
}
|
||||
hir::ExprStruct(_, ref expr_fields, _) => {
|
||||
let type_ = tcx.expr_ty(e);
|
||||
match type_.sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
// check the stability of each field that appears
|
||||
// in the construction expression.
|
||||
for field in expr_fields {
|
||||
let did = def.struct_variant()
|
||||
.field_named(field.name.node)
|
||||
.did;
|
||||
maybe_do_stability_check(tcx, did, field.span, cb);
|
||||
}
|
||||
match tcx.expr_ty(e).sty {
|
||||
ty::TyAdt(adt, ..) => match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
// check the stability of each field that appears
|
||||
// in the construction expression.
|
||||
for field in expr_fields {
|
||||
let did = adt.struct_variant().field_named(field.name.node).did;
|
||||
maybe_do_stability_check(tcx, did, field.span, cb);
|
||||
}
|
||||
|
||||
// we're done.
|
||||
return
|
||||
}
|
||||
// we don't look at stability attributes on
|
||||
// struct-like enums (yet...), but it's definitely not
|
||||
// a bug to have construct one.
|
||||
ty::TyEnum(..) => return,
|
||||
_ => {
|
||||
span_bug!(e.span,
|
||||
"stability::check_expr: struct construction \
|
||||
of non-struct/union, type {:?}",
|
||||
type_);
|
||||
}
|
||||
// we're done.
|
||||
return
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
// we don't look at stability attributes on
|
||||
// struct-like enums (yet...), but it's definitely not
|
||||
// a bug to have construct one.
|
||||
return
|
||||
}
|
||||
},
|
||||
ref ty => span_bug!(e.span, "stability::check_expr: struct \
|
||||
construction of non-ADT type: {:?}", ty)
|
||||
}
|
||||
}
|
||||
_ => return
|
||||
@ -648,10 +647,9 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
|
||||
debug!("check_pat(pat = {:?})", pat);
|
||||
if is_internal(tcx, pat.span) { return; }
|
||||
|
||||
let v = match tcx.pat_ty_opt(pat) {
|
||||
Some(&ty::TyS { sty: ty::TyStruct(def, _), .. }) |
|
||||
Some(&ty::TyS { sty: ty::TyUnion(def, _), .. }) => def.struct_variant(),
|
||||
Some(_) | None => return,
|
||||
let v = match tcx.pat_ty_opt(pat).map(|ty| &ty.sty) {
|
||||
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(),
|
||||
_ => return,
|
||||
};
|
||||
match pat.node {
|
||||
// Foo(a, b, c)
|
||||
|
@ -40,7 +40,7 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
|
||||
LvalueTy::Ty { ty } =>
|
||||
ty,
|
||||
LvalueTy::Downcast { adt_def, substs, variant_index: _ } =>
|
||||
tcx.mk_enum(adt_def, substs),
|
||||
tcx.mk_adt(adt_def, substs),
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,8 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
|
||||
}
|
||||
ProjectionElem::Downcast(adt_def1, index) =>
|
||||
match self.to_ty(tcx).sty {
|
||||
ty::TyEnum(adt_def, substs) => {
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
assert!(adt_def.is_enum());
|
||||
assert!(index < adt_def.variants.len());
|
||||
assert_eq!(adt_def, adt_def1);
|
||||
LvalueTy::Downcast { adt_def: adt_def,
|
||||
@ -83,7 +84,7 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
|
||||
variant_index: index }
|
||||
}
|
||||
_ => {
|
||||
bug!("cannot downcast non-enum type: `{:?}`", self)
|
||||
bug!("cannot downcast non-ADT type: `{:?}`", self)
|
||||
}
|
||||
},
|
||||
ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
|
||||
|
@ -224,7 +224,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyBox(..) | ty::TyRef(..) =>
|
||||
true,
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) =>
|
||||
ty::TyAdt(def, _) =>
|
||||
def.is_fundamental(),
|
||||
ty::TyTrait(ref data) =>
|
||||
tcx.has_attr(data.principal.def_id(), "fundamental"),
|
||||
@ -260,9 +260,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
|
||||
infer_is_local.0
|
||||
}
|
||||
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
def.did.is_local()
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ use super::{
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use hir::def_id::DefId;
|
||||
use infer::{self, InferCtxt, TypeOrigin};
|
||||
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::error::ExpectedFound;
|
||||
use ty::fast_reject;
|
||||
use ty::fold::TypeFolder;
|
||||
@ -151,32 +151,30 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
ty::TyBool => Some(0),
|
||||
ty::TyChar => Some(1),
|
||||
ty::TyStr => Some(2),
|
||||
ty::TyInt(..) | ty::TyUint(..) |
|
||||
ty::TyInfer(ty::IntVar(..)) => Some(3),
|
||||
ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3),
|
||||
ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4),
|
||||
ty::TyEnum(..) => Some(5),
|
||||
ty::TyStruct(..) => Some(6),
|
||||
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(7),
|
||||
ty::TyArray(..) | ty::TySlice(..) => Some(8),
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(9),
|
||||
ty::TyTrait(..) => Some(10),
|
||||
ty::TyClosure(..) => Some(11),
|
||||
ty::TyTuple(..) => Some(12),
|
||||
ty::TyProjection(..) => Some(13),
|
||||
ty::TyParam(..) => Some(14),
|
||||
ty::TyAnon(..) => Some(15),
|
||||
ty::TyNever => Some(16),
|
||||
ty::TyUnion(..) => Some(17),
|
||||
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
|
||||
ty::TyArray(..) | ty::TySlice(..) => Some(6),
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
|
||||
ty::TyTrait(..) => Some(8),
|
||||
ty::TyClosure(..) => Some(9),
|
||||
ty::TyTuple(..) => Some(10),
|
||||
ty::TyProjection(..) => Some(11),
|
||||
ty::TyParam(..) => Some(12),
|
||||
ty::TyAnon(..) => Some(13),
|
||||
ty::TyNever => Some(14),
|
||||
ty::TyAdt(adt, ..) => match adt.adt_kind() {
|
||||
AdtKind::Struct => Some(15),
|
||||
AdtKind::Union => Some(16),
|
||||
AdtKind::Enum => Some(17),
|
||||
},
|
||||
ty::TyInfer(..) | ty::TyError => None
|
||||
}
|
||||
}
|
||||
|
||||
match (type_category(a), type_category(b)) {
|
||||
(Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) {
|
||||
(&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) |
|
||||
(&ty::TyUnion(def_a, _), &ty::TyUnion(def_b, _)) |
|
||||
(&ty::TyEnum(def_a, _), &ty::TyEnum(def_b, _)) =>
|
||||
def_a == def_b,
|
||||
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b,
|
||||
_ => cat_a == cat_b
|
||||
},
|
||||
// infer and error can be equated to all types
|
||||
|
@ -1638,7 +1638,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
(&ty::TyArray(..), &ty::TySlice(_)) => true,
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
(&ty::TyStruct(def_id_a, _), &ty::TyStruct(def_id_b, _)) => {
|
||||
(&ty::TyAdt(def_id_a, _), &ty::TyAdt(def_id_b, _)) if def_id_a.is_struct() => {
|
||||
def_id_a == def_id_b
|
||||
}
|
||||
|
||||
@ -1780,8 +1780,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let sized_crit = def.sized_constraint(self.tcx());
|
||||
// (*) binder moved here
|
||||
Where(ty::Binder(match sized_crit.sty {
|
||||
@ -1837,8 +1836,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
Where(ty::Binder(tys.to_vec()))
|
||||
}
|
||||
|
||||
ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) |
|
||||
ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
|
||||
ty::TyAdt(..) | ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
|
||||
// Fallback to whatever user-defined impls exist in this case.
|
||||
None
|
||||
}
|
||||
@ -1930,11 +1928,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// for `PhantomData<T>`, we pass `T`
|
||||
ty::TyStruct(def, substs) if def.is_phantom_data() => {
|
||||
ty::TyAdt(def, substs) if def.is_phantom_data() => {
|
||||
substs.types().collect()
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
def.all_fields()
|
||||
.map(|f| f.ty(self.tcx(), substs))
|
||||
.collect()
|
||||
@ -2566,7 +2564,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
(&ty::TyStruct(def, substs_a), &ty::TyStruct(_, substs_b)) => {
|
||||
(&ty::TyAdt(def, substs_a), &ty::TyAdt(_, substs_b)) => {
|
||||
let fields = def
|
||||
.all_fields()
|
||||
.map(|f| f.unsubst_ty())
|
||||
@ -2621,7 +2619,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
k
|
||||
}
|
||||
});
|
||||
let new_struct = tcx.mk_struct(def, Substs::new(tcx, params));
|
||||
let new_struct = tcx.mk_adt(def, Substs::new(tcx, params));
|
||||
let origin = TypeOrigin::Misc(obligation.cause.span);
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.sub_types(false, origin, new_struct, target)
|
||||
|
@ -65,7 +65,7 @@ impl<'tcx> CastTy<'tcx> {
|
||||
ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
|
||||
ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
|
||||
ty::TyFloat(_) => Some(CastTy::Float),
|
||||
ty::TyEnum(d,_) if d.is_payloadfree() =>
|
||||
ty::TyAdt(d,_) if d.is_enum() && d.is_payloadfree() =>
|
||||
Some(CastTy::Int(IntTy::CEnum)),
|
||||
ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
|
||||
ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
|
||||
|
@ -224,8 +224,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
|ty| tc_ty(tcx, *ty, cache))
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let mut res =
|
||||
TypeContents::union(&def.variants, |v| {
|
||||
TypeContents::union(&v.fields, |f| {
|
||||
|
@ -27,7 +27,7 @@ use ty::subst::Substs;
|
||||
use traits;
|
||||
use ty::{self, TraitRef, Ty, TypeAndMut};
|
||||
use ty::{TyS, TypeVariants};
|
||||
use ty::{AdtDef, ClosureSubsts, Region};
|
||||
use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
|
||||
use hir::FreevarMap;
|
||||
use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject};
|
||||
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
|
||||
@ -620,7 +620,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn intern_adt_def(self,
|
||||
did: DefId,
|
||||
kind: ty::AdtKind,
|
||||
kind: AdtKind,
|
||||
variants: Vec<ty::VariantDefData<'gcx, 'gcx>>)
|
||||
-> ty::AdtDefMaster<'gcx> {
|
||||
let def = ty::AdtDefData::new(self, did, kind, variants);
|
||||
@ -1032,8 +1032,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
pub fn print_debug_stats(self) {
|
||||
sty_debug_print!(
|
||||
self,
|
||||
TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyTrait,
|
||||
TyStruct, TyUnion, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
|
||||
TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
|
||||
TyTrait, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
|
||||
|
||||
println!("Substs interner: #{}", self.interners.substs.borrow().len());
|
||||
println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
|
||||
@ -1227,9 +1227,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
|
||||
}
|
||||
|
||||
pub fn mk_enum(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||
pub fn mk_adt(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||
// take a copy of substs so that we own the vectors inside
|
||||
self.mk_ty(TyEnum(def, substs))
|
||||
self.mk_ty(TyAdt(def, substs))
|
||||
}
|
||||
|
||||
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
@ -1316,16 +1316,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_ty(TyProjection(inner))
|
||||
}
|
||||
|
||||
pub fn mk_struct(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||
// take a copy of substs so that we own the vectors inside
|
||||
self.mk_ty(TyStruct(def, substs))
|
||||
}
|
||||
|
||||
pub fn mk_union(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||
// take a copy of substs so that we own the vectors inside
|
||||
self.mk_ty(TyUnion(def, substs))
|
||||
}
|
||||
|
||||
pub fn mk_closure(self,
|
||||
closure_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
|
@ -216,7 +216,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
|
||||
ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
|
||||
|
||||
ty::TyEnum(def, _) => format!("enum `{}`", tcx.item_path_str(def.did)),
|
||||
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
|
||||
ty::TyBox(_) => "box".to_string(),
|
||||
ty::TyArray(_, n) => format!("array of {} elements", n),
|
||||
ty::TySlice(_) => "slice".to_string(),
|
||||
@ -244,12 +244,6 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
||||
ty::TyTrait(ref inner) => {
|
||||
format!("trait {}", tcx.item_path_str(inner.principal.def_id()))
|
||||
}
|
||||
ty::TyStruct(def, _) => {
|
||||
format!("struct `{}`", tcx.item_path_str(def.did))
|
||||
}
|
||||
ty::TyUnion(def, _) => {
|
||||
format!("union `{}`", tcx.item_path_str(def.did))
|
||||
}
|
||||
ty::TyClosure(..) => "closure".to_string(),
|
||||
ty::TyTuple(_) => "tuple".to_string(),
|
||||
ty::TyInfer(ty::TyVar(_)) => "inferred type".to_string(),
|
||||
|
@ -22,15 +22,13 @@ pub enum SimplifiedType {
|
||||
IntSimplifiedType(ast::IntTy),
|
||||
UintSimplifiedType(ast::UintTy),
|
||||
FloatSimplifiedType(ast::FloatTy),
|
||||
EnumSimplifiedType(DefId),
|
||||
AdtSimplifiedType(DefId),
|
||||
StrSimplifiedType,
|
||||
VecSimplifiedType,
|
||||
PtrSimplifiedType,
|
||||
NeverSimplifiedType,
|
||||
TupleSimplifiedType(usize),
|
||||
TraitSimplifiedType(DefId),
|
||||
StructSimplifiedType(DefId),
|
||||
UnionSimplifiedType(DefId),
|
||||
ClosureSimplifiedType(DefId),
|
||||
AnonSimplifiedType(DefId),
|
||||
FunctionSimplifiedType(usize),
|
||||
@ -57,19 +55,13 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)),
|
||||
ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)),
|
||||
ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)),
|
||||
ty::TyEnum(def, _) => Some(EnumSimplifiedType(def.did)),
|
||||
ty::TyAdt(def, _) => Some(AdtSimplifiedType(def.did)),
|
||||
ty::TyStr => Some(StrSimplifiedType),
|
||||
ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType),
|
||||
ty::TyRawPtr(_) => Some(PtrSimplifiedType),
|
||||
ty::TyTrait(ref trait_info) => {
|
||||
Some(TraitSimplifiedType(trait_info.principal.def_id()))
|
||||
}
|
||||
ty::TyStruct(def, _) => {
|
||||
Some(StructSimplifiedType(def.did))
|
||||
}
|
||||
ty::TyUnion(def, _) => {
|
||||
Some(UnionSimplifiedType(def.did))
|
||||
}
|
||||
ty::TyRef(_, mt) => {
|
||||
// since we introduce auto-refs during method lookup, we
|
||||
// just treat &T and T as equivalent from the point of
|
||||
@ -79,7 +71,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
ty::TyBox(_) => {
|
||||
// treat like we would treat `Box`
|
||||
match tcx.lang_items.require_owned_box() {
|
||||
Ok(def_id) => Some(StructSimplifiedType(def_id)),
|
||||
Ok(def_id) => Some(AdtSimplifiedType(def_id)),
|
||||
Err(msg) => tcx.sess.fatal(&msg),
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ impl FlagComputation {
|
||||
}
|
||||
}
|
||||
|
||||
&ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) | &ty::TyUnion(_, substs) => {
|
||||
&ty::TyAdt(_, substs) => {
|
||||
self.add_substs(substs);
|
||||
}
|
||||
|
||||
|
@ -262,9 +262,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
// impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
|
||||
// anything other than a simple path.
|
||||
match self_ty.sty {
|
||||
ty::TyStruct(adt_def, substs) |
|
||||
ty::TyUnion(adt_def, substs) |
|
||||
ty::TyEnum(adt_def, substs) => {
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
if substs.types().next().is_none() { // ignore regions
|
||||
self.push_item_path(buffer, adt_def.did);
|
||||
} else {
|
||||
@ -320,9 +318,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// decisions and we may want to adjust it later.
|
||||
pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
|
||||
match ty.sty {
|
||||
ty::TyStruct(adt_def, _) |
|
||||
ty::TyUnion(adt_def, _) |
|
||||
ty::TyEnum(adt_def, _) => Some(adt_def.did),
|
||||
ty::TyAdt(adt_def, _) => Some(adt_def.did),
|
||||
|
||||
ty::TyTrait(ref data) => Some(data.principal.def_id()),
|
||||
|
||||
|
@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||
}
|
||||
|
||||
// Is this the NonZero lang item wrapping a pointer or integer type?
|
||||
(&Univariant { non_zero: true, .. }, &ty::TyStruct(def, substs)) => {
|
||||
(&Univariant { non_zero: true, .. }, &ty::TyAdt(def, substs)) => {
|
||||
let fields = &def.struct_variant().fields;
|
||||
assert_eq!(fields.len(), 1);
|
||||
match *fields[0].ty(tcx, substs).layout(infcx)? {
|
||||
@ -573,7 +573,7 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||
|
||||
// Perhaps one of the fields of this struct is non-zero
|
||||
// let's recurse and find out
|
||||
(_, &ty::TyStruct(def, substs)) => {
|
||||
(_, &ty::TyAdt(def, substs)) if def.is_struct() => {
|
||||
Struct::non_zero_field_path(infcx, def.struct_variant().fields
|
||||
.iter().map(|field| {
|
||||
field.ty(tcx, substs)
|
||||
@ -694,7 +694,7 @@ pub enum Layout {
|
||||
non_zero: bool
|
||||
},
|
||||
|
||||
/// SIMD vectors, from TyStruct marked with #[repr(simd)].
|
||||
/// SIMD vectors, from structs marked with #[repr(simd)].
|
||||
Vector {
|
||||
element: Primitive,
|
||||
count: u64
|
||||
@ -715,7 +715,7 @@ pub enum Layout {
|
||||
non_zero: bool
|
||||
},
|
||||
|
||||
// Remaining variants are all ADTs such as TyStruct, TyEnum or TyTuple.
|
||||
// Remaining variants are all ADTs such as structs, enums or tuples.
|
||||
|
||||
/// C-like enums; basically an integer.
|
||||
CEnum {
|
||||
@ -918,47 +918,26 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
Univariant { variant: st, non_zero: false }
|
||||
}
|
||||
|
||||
// ADTs.
|
||||
ty::TyStruct(def, substs) => {
|
||||
if ty.is_simd() {
|
||||
// SIMD vector types.
|
||||
let element = ty.simd_type(tcx);
|
||||
match *element.layout(infcx)? {
|
||||
Scalar { value, .. } => {
|
||||
return success(Vector {
|
||||
element: value,
|
||||
count: ty.simd_size(tcx) as u64
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
|
||||
a non-machine element type `{}`",
|
||||
ty, element));
|
||||
}
|
||||
// SIMD vector types.
|
||||
ty::TyAdt(def, ..) if def.is_simd() => {
|
||||
let element = ty.simd_type(tcx);
|
||||
match *element.layout(infcx)? {
|
||||
Scalar { value, .. } => {
|
||||
return success(Vector {
|
||||
element: value,
|
||||
count: ty.simd_size(tcx) as u64
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
|
||||
a non-machine element type `{}`",
|
||||
ty, element));
|
||||
}
|
||||
}
|
||||
let fields = def.struct_variant().fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
});
|
||||
let packed = tcx.lookup_packed(def.did);
|
||||
let mut st = Struct::new(dl, packed);
|
||||
st.extend(dl, fields, ty)?;
|
||||
}
|
||||
|
||||
Univariant {
|
||||
variant: st,
|
||||
non_zero: Some(def.did) == tcx.lang_items.non_zero()
|
||||
}
|
||||
}
|
||||
ty::TyUnion(def, substs) => {
|
||||
let fields = def.struct_variant().fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
});
|
||||
let packed = tcx.lookup_packed(def.did);
|
||||
let mut un = Union::new(dl, packed);
|
||||
un.extend(dl, fields, ty)?;
|
||||
UntaggedUnion { variants: un }
|
||||
}
|
||||
ty::TyEnum(def, substs) => {
|
||||
// ADTs.
|
||||
ty::TyAdt(def, substs) => {
|
||||
let hint = *tcx.lookup_repr_hints(def.did).get(0)
|
||||
.unwrap_or(&attr::ReprAny);
|
||||
|
||||
@ -973,7 +952,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
});
|
||||
}
|
||||
|
||||
if def.variants.iter().all(|v| v.fields.is_empty()) {
|
||||
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
|
||||
// All bodies empty -> intlike
|
||||
let (mut min, mut max) = (i64::MAX, i64::MIN);
|
||||
for v in &def.variants {
|
||||
@ -991,28 +970,37 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
});
|
||||
}
|
||||
|
||||
if def.variants.len() == 1 {
|
||||
// Struct, or union, or univariant enum equivalent to a struct.
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
assert!(!def.is_enum() || hint == attr::ReprAny);
|
||||
let fields = def.variants[0].fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
});
|
||||
let packed = tcx.lookup_packed(def.did);
|
||||
let layout = if def.is_union() {
|
||||
let mut un = Union::new(dl, packed);
|
||||
un.extend(dl, fields, ty)?;
|
||||
UntaggedUnion { variants: un }
|
||||
} else {
|
||||
let mut st = Struct::new(dl, packed);
|
||||
st.extend(dl, fields, ty)?;
|
||||
let non_zero = Some(def.did) == tcx.lang_items.non_zero();
|
||||
Univariant { variant: st, non_zero: non_zero }
|
||||
};
|
||||
return success(layout);
|
||||
}
|
||||
|
||||
// Since there's at least one
|
||||
// non-empty body, explicit discriminants should have
|
||||
// been rejected by a checker before this point.
|
||||
for (i, v) in def.variants.iter().enumerate() {
|
||||
if i as u64 != v.disr_val.to_u64_unchecked() {
|
||||
bug!("non-C-like enum {} with specified discriminants",
|
||||
tcx.item_path_str(def.did));
|
||||
tcx.item_path_str(def.did));
|
||||
}
|
||||
}
|
||||
|
||||
if def.variants.len() == 1 {
|
||||
// Equivalent to a struct/tuple/newtype.
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
assert_eq!(hint, attr::ReprAny);
|
||||
let fields = def.variants[0].fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
});
|
||||
let mut st = Struct::new(dl, false);
|
||||
st.extend(dl, fields, ty)?;
|
||||
return success(Univariant { variant: st, non_zero: false });
|
||||
}
|
||||
|
||||
// Cache the substituted and normalized variant field types.
|
||||
let variants = def.variants.iter().map(|v| {
|
||||
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
|
||||
@ -1042,8 +1030,8 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
}
|
||||
_ => {
|
||||
bug!("Layout::compute: `{}`'s non-zero \
|
||||
`{}` field not scalar?!",
|
||||
ty, variants[discr][0])
|
||||
`{}` field not scalar?!",
|
||||
ty, variants[discr][0])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1317,9 +1305,9 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
// Only newtypes and enums w/ nullable pointer optimization.
|
||||
if def.variants.is_empty() || def.variants.len() > 2 {
|
||||
if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
|
@ -952,9 +952,7 @@ impl<'tcx> TraitPredicate<'tcx> {
|
||||
self.input_types()
|
||||
.flat_map(|t| t.walk())
|
||||
.filter_map(|t| match t.sty {
|
||||
ty::TyStruct(adt_def, _) |
|
||||
ty::TyUnion(adt_def, _) |
|
||||
ty::TyEnum(adt_def, _) =>
|
||||
ty::TyAdt(adt_def, _) =>
|
||||
Some(adt_def.did),
|
||||
_ =>
|
||||
None
|
||||
@ -1573,18 +1571,49 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
|
||||
self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_struct(&self) -> bool {
|
||||
!self.is_union() && !self.is_enum()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_union(&self) -> bool {
|
||||
self.flags.get().intersects(AdtFlags::IS_UNION)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_enum(&self) -> bool {
|
||||
self.flags.get().intersects(AdtFlags::IS_ENUM)
|
||||
}
|
||||
|
||||
/// Returns the kind of the ADT - Struct or Enum.
|
||||
#[inline]
|
||||
pub fn adt_kind(&self) -> AdtKind {
|
||||
if self.flags.get().intersects(AdtFlags::IS_ENUM) {
|
||||
if self.is_enum() {
|
||||
AdtKind::Enum
|
||||
} else if self.flags.get().intersects(AdtFlags::IS_UNION) {
|
||||
} else if self.is_union() {
|
||||
AdtKind::Union
|
||||
} else {
|
||||
AdtKind::Struct
|
||||
}
|
||||
}
|
||||
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self.adt_kind() {
|
||||
AdtKind::Struct => "struct",
|
||||
AdtKind::Union => "union",
|
||||
AdtKind::Enum => "enum",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn variant_descr(&self) -> &'static str {
|
||||
match self.adt_kind() {
|
||||
AdtKind::Struct => "struct",
|
||||
AdtKind::Union => "union",
|
||||
AdtKind::Enum => "variant",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this is a dtorck type. If this returns
|
||||
/// true, this type being safe for destruction requires it to be
|
||||
/// alive; Otherwise, only the contents are required to be.
|
||||
@ -1622,8 +1651,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
|
||||
/// Asserts this is a struct and returns the struct's unique
|
||||
/// variant.
|
||||
pub fn struct_variant(&self) -> &VariantDefData<'gcx, 'container> {
|
||||
let adt_kind = self.adt_kind();
|
||||
assert!(adt_kind == AdtKind::Struct || adt_kind == AdtKind::Union);
|
||||
assert!(!self.is_enum());
|
||||
&self.variants[0]
|
||||
}
|
||||
|
||||
@ -1832,7 +1860,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
TyEnum(adt, substs) | TyStruct(adt, substs) | TyUnion(adt, substs) => {
|
||||
TyAdt(adt, substs) => {
|
||||
// recursive case
|
||||
let adt = tcx.lookup_adt_def_master(adt.did);
|
||||
adt.calculate_sized_constraint_inner(tcx, stack);
|
||||
|
@ -172,9 +172,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
ty::TyUint(..) | // OutlivesScalar
|
||||
ty::TyFloat(..) | // OutlivesScalar
|
||||
ty::TyNever | // ...
|
||||
ty::TyEnum(..) | // OutlivesNominalType
|
||||
ty::TyStruct(..) | // OutlivesNominalType
|
||||
ty::TyUnion(..) | // OutlivesNominalType
|
||||
ty::TyAdt(..) | // OutlivesNominalType
|
||||
ty::TyBox(..) | // OutlivesNominalType (ish)
|
||||
ty::TyAnon(..) | // OutlivesNominalType (ish)
|
||||
ty::TyStr | // OutlivesScalar (ish)
|
||||
|
@ -414,11 +414,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
(&ty::TyEnum(a_def, a_substs), &ty::TyEnum(b_def, b_substs))
|
||||
(&ty::TyAdt(a_def, a_substs), &ty::TyAdt(b_def, b_substs))
|
||||
if a_def == b_def =>
|
||||
{
|
||||
let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?;
|
||||
Ok(tcx.mk_enum(a_def, substs))
|
||||
Ok(tcx.mk_adt(a_def, substs))
|
||||
}
|
||||
|
||||
(&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) =>
|
||||
@ -440,20 +440,6 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
}))
|
||||
}
|
||||
|
||||
(&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs))
|
||||
if a_def == b_def =>
|
||||
{
|
||||
let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?;
|
||||
Ok(tcx.mk_struct(a_def, substs))
|
||||
}
|
||||
|
||||
(&ty::TyUnion(a_def, a_substs), &ty::TyUnion(b_def, b_substs))
|
||||
if a_def == b_def =>
|
||||
{
|
||||
let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?;
|
||||
Ok(tcx.mk_union(a_def, substs))
|
||||
}
|
||||
|
||||
(&ty::TyClosure(a_id, a_substs),
|
||||
&ty::TyClosure(b_id, b_substs))
|
||||
if a_id == b_id =>
|
||||
|
@ -482,7 +482,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
ty::TyRawPtr(tm) => ty::TyRawPtr(tm.fold_with(folder)),
|
||||
ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
|
||||
ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
|
||||
ty::TyEnum(tid, substs) => ty::TyEnum(tid, substs.fold_with(folder)),
|
||||
ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)),
|
||||
ty::TyTrait(ref trait_ty) => ty::TyTrait(trait_ty.fold_with(folder)),
|
||||
ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)),
|
||||
ty::TyFnDef(def_id, substs, f) => {
|
||||
@ -494,8 +494,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
ty::TyRef(ref r, tm) => {
|
||||
ty::TyRef(r.fold_with(folder), tm.fold_with(folder))
|
||||
}
|
||||
ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)),
|
||||
ty::TyUnion(did, substs) => ty::TyUnion(did, substs.fold_with(folder)),
|
||||
ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
|
||||
ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
|
||||
ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
|
||||
@ -516,7 +514,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
ty::TyRawPtr(ref tm) => tm.visit_with(visitor),
|
||||
ty::TyArray(typ, _sz) => typ.visit_with(visitor),
|
||||
ty::TySlice(typ) => typ.visit_with(visitor),
|
||||
ty::TyEnum(_tid, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyAdt(_, substs) => substs.visit_with(visitor),
|
||||
ty::TyTrait(ref trait_ty) => trait_ty.visit_with(visitor),
|
||||
ty::TyTuple(ts) => ts.visit_with(visitor),
|
||||
ty::TyFnDef(_, substs, ref f) => {
|
||||
@ -524,8 +522,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
}
|
||||
ty::TyFnPtr(ref f) => f.visit_with(visitor),
|
||||
ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
|
||||
ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyUnion(_did, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyProjection(ref data) => data.visit_with(visitor),
|
||||
ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
|
||||
|
@ -106,24 +106,13 @@ pub enum TypeVariants<'tcx> {
|
||||
/// A primitive floating-point type. For example, `f64`.
|
||||
TyFloat(ast::FloatTy),
|
||||
|
||||
/// An enumerated type, defined with `enum`.
|
||||
/// Structures, enumerations and unions.
|
||||
///
|
||||
/// Substs here, possibly against intuition, *may* contain `TyParam`s.
|
||||
/// That is, even after substitution it is possible that there are type
|
||||
/// variables. This happens when the `TyEnum` corresponds to an enum
|
||||
/// definition and not a concrete use of it. This is true for `TyStruct`
|
||||
/// and `TyUnion` as well.
|
||||
TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>),
|
||||
|
||||
/// A structure type, defined with `struct`.
|
||||
///
|
||||
/// See warning about substitutions for enumerated types.
|
||||
TyStruct(AdtDef<'tcx>, &'tcx Substs<'tcx>),
|
||||
|
||||
/// A union type, defined with `union`.
|
||||
///
|
||||
/// See warning about substitutions for enumerated types.
|
||||
TyUnion(AdtDef<'tcx>, &'tcx Substs<'tcx>),
|
||||
/// variables. This happens when the `TyAdt` corresponds to an ADT
|
||||
/// definition and not a concrete use of it.
|
||||
TyAdt(AdtDef<'tcx>, &'tcx Substs<'tcx>),
|
||||
|
||||
/// `Box<T>`; this is nominally a struct in the documentation, but is
|
||||
/// special-cased internally. For example, it is possible to implicitly
|
||||
@ -922,7 +911,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
// FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
|
||||
// more complete.
|
||||
match self.sty {
|
||||
TyEnum(def, _) | TyStruct(def, _) | TyUnion(def, _) => def.is_empty(),
|
||||
TyAdt(def, _) => def.is_empty(),
|
||||
|
||||
// FIXME(canndrew): There's no reason why these can't be uncommented, they're tested
|
||||
// and they don't break anything. But I'm keeping my changes small for now.
|
||||
@ -950,7 +939,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
|
||||
pub fn is_phantom_data(&self) -> bool {
|
||||
if let TyStruct(def, _) = self.sty {
|
||||
if let TyAdt(def, _) = self.sty {
|
||||
def.is_phantom_data()
|
||||
} else {
|
||||
false
|
||||
@ -985,8 +974,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
|
||||
pub fn is_structural(&self) -> bool {
|
||||
match self.sty {
|
||||
TyStruct(..) | TyUnion(..) | TyTuple(..) | TyEnum(..) |
|
||||
TyArray(..) | TyClosure(..) => true,
|
||||
TyAdt(..) | TyTuple(..) | TyArray(..) | TyClosure(..) => true,
|
||||
_ => self.is_slice() | self.is_trait()
|
||||
}
|
||||
}
|
||||
@ -994,7 +982,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
#[inline]
|
||||
pub fn is_simd(&self) -> bool {
|
||||
match self.sty {
|
||||
TyStruct(def, _) => def.is_simd(),
|
||||
TyAdt(def, _) => def.is_simd(),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
@ -1009,7 +997,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
|
||||
pub fn simd_type(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
match self.sty {
|
||||
TyStruct(def, substs) => {
|
||||
TyAdt(def, substs) => {
|
||||
def.struct_variant().fields[0].ty(tcx, substs)
|
||||
}
|
||||
_ => bug!("simd_type called on invalid type")
|
||||
@ -1018,7 +1006,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
|
||||
pub fn simd_size(&self, _cx: TyCtxt) -> usize {
|
||||
match self.sty {
|
||||
TyStruct(def, _) => def.struct_variant().fields.len(),
|
||||
TyAdt(def, _) => def.struct_variant().fields.len(),
|
||||
_ => bug!("simd_size called on invalid type")
|
||||
}
|
||||
}
|
||||
@ -1203,9 +1191,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
pub fn ty_to_def_id(&self) -> Option<DefId> {
|
||||
match self.sty {
|
||||
TyTrait(ref tt) => Some(tt.principal.def_id()),
|
||||
TyStruct(def, _) |
|
||||
TyUnion(def, _) |
|
||||
TyEnum(def, _) => Some(def.did),
|
||||
TyAdt(def, _) => Some(def.did),
|
||||
TyClosure(id, _) => Some(id),
|
||||
_ => None
|
||||
}
|
||||
@ -1213,7 +1199,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
|
||||
pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> {
|
||||
match self.sty {
|
||||
TyStruct(adt, _) | TyUnion(adt, _) | TyEnum(adt, _) => Some(adt),
|
||||
TyAdt(adt, _) => Some(adt),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@ -1231,10 +1217,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
v.extend(obj.principal.skip_binder().substs.regions());
|
||||
v
|
||||
}
|
||||
TyEnum(_, substs) |
|
||||
TyStruct(_, substs) |
|
||||
TyUnion(_, substs) |
|
||||
TyAnon(_, substs) => {
|
||||
TyAdt(_, substs) | TyAnon(_, substs) => {
|
||||
substs.regions().collect()
|
||||
}
|
||||
TyClosure(_, ref substs) => {
|
||||
|
@ -14,7 +14,7 @@ use hir::def_id::DefId;
|
||||
use infer::InferCtxt;
|
||||
use hir::pat_util;
|
||||
use traits::{self, Reveal};
|
||||
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
|
||||
use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
|
||||
use ty::{Disr, ParameterEnvironment};
|
||||
use ty::fold::TypeVisitor;
|
||||
use ty::layout::{Layout, LayoutError};
|
||||
@ -138,28 +138,30 @@ impl<'tcx> ParameterEnvironment<'tcx> {
|
||||
// FIXME: (@jroesch) float this code up
|
||||
tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| {
|
||||
let adt = match self_type.sty {
|
||||
ty::TyStruct(struct_def, substs) | ty::TyUnion(struct_def, substs) => {
|
||||
for field in struct_def.all_fields() {
|
||||
let field_ty = field.ty(tcx, substs);
|
||||
if infcx.type_moves_by_default(field_ty, span) {
|
||||
return Err(CopyImplementationError::InfrigingField(
|
||||
field.name))
|
||||
}
|
||||
}
|
||||
struct_def
|
||||
}
|
||||
ty::TyEnum(enum_def, substs) => {
|
||||
for variant in &enum_def.variants {
|
||||
for field in &variant.fields {
|
||||
ty::TyAdt(adt, substs) => match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
for field in adt.all_fields() {
|
||||
let field_ty = field.ty(tcx, substs);
|
||||
if infcx.type_moves_by_default(field_ty, span) {
|
||||
return Err(CopyImplementationError::InfrigingVariant(
|
||||
variant.name))
|
||||
return Err(CopyImplementationError::InfrigingField(
|
||||
field.name))
|
||||
}
|
||||
}
|
||||
adt
|
||||
}
|
||||
enum_def
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
for variant in &adt.variants {
|
||||
for field in &variant.fields {
|
||||
let field_ty = field.ty(tcx, substs);
|
||||
if infcx.type_moves_by_default(field_ty, span) {
|
||||
return Err(CopyImplementationError::InfrigingVariant(
|
||||
variant.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
adt
|
||||
}
|
||||
},
|
||||
_ => return Err(CopyImplementationError::NotAnAdt)
|
||||
};
|
||||
|
||||
@ -183,7 +185,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
for field in def.all_fields() {
|
||||
let field_ty = field.ty(self, substs);
|
||||
if let TyError = field_ty.sty {
|
||||
@ -203,16 +205,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
i: usize,
|
||||
variant: Option<DefId>) -> Option<Ty<'tcx>> {
|
||||
match (&ty.sty, variant) {
|
||||
(&TyStruct(def, substs), None) |
|
||||
(&TyUnion(def, substs), None) => {
|
||||
def.struct_variant().fields.get(i).map(|f| f.ty(self, substs))
|
||||
(&TyAdt(adt, substs), Some(vid)) => {
|
||||
adt.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
|
||||
}
|
||||
(&TyEnum(def, substs), Some(vid)) => {
|
||||
def.variant_with_id(vid).fields.get(i).map(|f| f.ty(self, substs))
|
||||
}
|
||||
(&TyEnum(def, substs), None) => {
|
||||
assert!(def.is_univariant());
|
||||
def.variants[0].fields.get(i).map(|f| f.ty(self, substs))
|
||||
(&TyAdt(adt, substs), None) => {
|
||||
// Don't use `struct_variant`, this may be a univariant enum.
|
||||
adt.variants[0].fields.get(i).map(|f| f.ty(self, substs))
|
||||
}
|
||||
(&TyTuple(ref v), None) => v.get(i).cloned(),
|
||||
_ => None
|
||||
@ -226,12 +224,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
n: Name,
|
||||
variant: Option<DefId>) -> Option<Ty<'tcx>> {
|
||||
match (&ty.sty, variant) {
|
||||
(&TyStruct(def, substs), None) |
|
||||
(&TyUnion(def, substs), None) => {
|
||||
def.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
|
||||
(&TyAdt(adt, substs), Some(vid)) => {
|
||||
adt.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
|
||||
}
|
||||
(&TyEnum(def, substs), Some(vid)) => {
|
||||
def.variant_with_id(vid).find_field_named(n).map(|f| f.ty(self, substs))
|
||||
(&TyAdt(adt, substs), None) => {
|
||||
adt.struct_variant().find_field_named(n).map(|f| f.ty(self, substs))
|
||||
}
|
||||
_ => return None
|
||||
}
|
||||
@ -256,7 +253,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// if not a structure at all. Corresponds to the only possible unsized
|
||||
/// field, and its type can be used to determine unsizing strategy.
|
||||
pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
while let TyStruct(def, substs) = ty.sty {
|
||||
while let TyAdt(def, substs) = ty.sty {
|
||||
if !def.is_struct() {
|
||||
break
|
||||
}
|
||||
match def.struct_variant().fields.last() {
|
||||
Some(f) => ty = f.ty(self, substs),
|
||||
None => break
|
||||
@ -275,15 +275,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
target: Ty<'tcx>)
|
||||
-> (Ty<'tcx>, Ty<'tcx>) {
|
||||
let (mut a, mut b) = (source, target);
|
||||
while let (&TyStruct(a_def, a_substs), &TyStruct(b_def, b_substs)) = (&a.sty, &b.sty) {
|
||||
if a_def != b_def {
|
||||
break;
|
||||
while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) {
|
||||
if a_def != b_def || !a_def.is_struct() {
|
||||
break
|
||||
}
|
||||
if let Some(f) = a_def.struct_variant().fields.last() {
|
||||
a = f.ty(self, a_substs);
|
||||
b = f.ty(self, b_substs);
|
||||
} else {
|
||||
break;
|
||||
match a_def.struct_variant().fields.last() {
|
||||
Some(f) => {
|
||||
a = f.ty(self, a_substs);
|
||||
b = f.ty(self, b_substs);
|
||||
}
|
||||
_ => break
|
||||
}
|
||||
}
|
||||
(a, b)
|
||||
@ -431,9 +432,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> {
|
||||
TyInt(i) => self.hash(i),
|
||||
TyUint(u) => self.hash(u),
|
||||
TyFloat(f) => self.hash(f),
|
||||
TyStruct(d, _) |
|
||||
TyUnion(d, _) |
|
||||
TyEnum(d, _) => self.def_id(d.did),
|
||||
TyAdt(d, _) => self.def_id(d.did),
|
||||
TyArray(_, n) => self.hash(n),
|
||||
TyRawPtr(m) |
|
||||
TyRef(_, m) => self.hash(m.mutbl),
|
||||
@ -560,8 +559,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
mutbl: hir::MutMutable, ..
|
||||
}) => Some(true),
|
||||
|
||||
TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
|
||||
TyClosure(..) | TyEnum(..) | TyStruct(..) | TyUnion(..) | TyAnon(..) |
|
||||
TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) |
|
||||
TyClosure(..) | TyAdt(..) | TyAnon(..) |
|
||||
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
|
||||
}.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
|
||||
|
||||
@ -601,7 +600,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
|
||||
TyStr | TyTrait(..) | TySlice(_) => Some(false),
|
||||
|
||||
TyEnum(..) | TyStruct(..) | TyUnion(..) | TyProjection(..) | TyParam(..) |
|
||||
TyAdt(..) | TyProjection(..) | TyParam(..) |
|
||||
TyInfer(..) | TyAnon(..) | TyError => None
|
||||
}.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
|
||||
|
||||
@ -663,7 +662,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
TyArray(ty, _) => {
|
||||
is_type_structurally_recursive(tcx, sp, seen, ty)
|
||||
}
|
||||
TyStruct(def, substs) | TyUnion(def, substs) | TyEnum(def, substs) => {
|
||||
TyAdt(def, substs) => {
|
||||
find_nonrepresentable(tcx,
|
||||
sp,
|
||||
seen,
|
||||
@ -680,7 +679,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
|
||||
fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
TyStruct(ty_def, _) | TyUnion(ty_def, _) | TyEnum(ty_def, _) => {
|
||||
TyAdt(ty_def, _) => {
|
||||
ty_def == def
|
||||
}
|
||||
_ => false
|
||||
@ -689,9 +688,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
|
||||
fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
|
||||
match (&a.sty, &b.sty) {
|
||||
(&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
|
||||
(&TyUnion(did_a, ref substs_a), &TyUnion(did_b, ref substs_b)) |
|
||||
(&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
|
||||
(&TyAdt(did_a, substs_a), &TyAdt(did_b, substs_b)) => {
|
||||
if did_a != did_b {
|
||||
return false;
|
||||
}
|
||||
@ -713,7 +710,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
||||
debug!("is_type_structurally_recursive: {:?}", ty);
|
||||
|
||||
match ty.sty {
|
||||
TyStruct(def, _) | TyUnion(def, _) | TyEnum(def, _) => {
|
||||
TyAdt(def, _) => {
|
||||
{
|
||||
// Iterate through stack of previously seen types.
|
||||
let mut iter = seen.iter();
|
||||
|
@ -93,10 +93,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
|
||||
pred.0.ty
|
||||
}).rev());
|
||||
}
|
||||
ty::TyEnum(_, ref substs) |
|
||||
ty::TyStruct(_, ref substs) |
|
||||
ty::TyUnion(_, ref substs) |
|
||||
ty::TyAnon(_, ref substs) => {
|
||||
ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => {
|
||||
stack.extend(substs.types().rev());
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
|
@ -336,9 +336,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||
self.compute_projection(data);
|
||||
}
|
||||
|
||||
ty::TyEnum(def, substs) |
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyUnion(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
// WfNominalType
|
||||
let obligations = self.nominal_obligations(def.did, substs);
|
||||
self.out.extend(obligations);
|
||||
|
@ -11,7 +11,7 @@
|
||||
use hir::def_id::DefId;
|
||||
use ty::subst::{self, Subst, Substs};
|
||||
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
|
||||
use ty::{TyBool, TyChar, TyStruct, TyUnion, TyEnum};
|
||||
use ty::{TyBool, TyChar, TyAdt};
|
||||
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
|
||||
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
|
||||
use ty::TyClosure;
|
||||
@ -868,7 +868,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
|
||||
TyInfer(infer_ty) => write!(f, "{}", infer_ty),
|
||||
TyError => write!(f, "[type error]"),
|
||||
TyParam(ref param_ty) => write!(f, "{}", param_ty),
|
||||
TyEnum(def, substs) | TyStruct(def, substs) | TyUnion(def, substs) => {
|
||||
TyAdt(def, substs) => {
|
||||
ty::tls::with(|tcx| {
|
||||
if def.did.is_local() &&
|
||||
!tcx.tcache.borrow().contains_key(&def.did) {
|
||||
|
@ -796,9 +796,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||
}
|
||||
LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => {
|
||||
match lp_base.to_type().sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor() => {
|
||||
ty::TyAdt(def, _) if def.has_dtor() => {
|
||||
// In the case where the owner implements drop, then
|
||||
// the path must be initialized to prevent a case of
|
||||
// partial reinitialization
|
||||
|
@ -21,7 +21,7 @@ use borrowck::LoanPathElem::{LpDeref, LpInterior};
|
||||
use borrowck::move_data::InvalidMovePathIndex;
|
||||
use borrowck::move_data::{MoveData, MovePathIndex};
|
||||
use rustc::hir::def_id::{DefId};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, AdtKind, TyCtxt};
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
|
||||
use std::mem;
|
||||
@ -422,8 +422,8 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
|
||||
variant_did);
|
||||
};
|
||||
|
||||
match (&parent_ty.sty, enum_variant_info) {
|
||||
(&ty::TyTuple(ref v), None) => {
|
||||
match parent_ty.sty {
|
||||
ty::TyTuple(ref v) => {
|
||||
let tuple_idx = match *origin_field_name {
|
||||
mc::PositionalField(tuple_idx) => tuple_idx,
|
||||
mc::NamedField(_) =>
|
||||
@ -438,69 +438,68 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::TyStruct(def, _), None) => {
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
for f in &def.struct_variant().fields {
|
||||
if f.name == ast_name {
|
||||
continue;
|
||||
ty::TyAdt(def, ..) => match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
for f in &def.struct_variant().fields {
|
||||
if f.name == ast_name {
|
||||
continue;
|
||||
}
|
||||
let field_name = mc::NamedField(f.name);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
let field_name = mc::NamedField(f.name);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
}
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
for (i, _f) in def.struct_variant().fields.iter().enumerate() {
|
||||
if i == tuple_idx {
|
||||
continue
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
for (i, _f) in def.struct_variant().fields.iter().enumerate() {
|
||||
if i == tuple_idx {
|
||||
continue
|
||||
}
|
||||
let field_name = mc::PositionalField(i);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
let field_name = mc::PositionalField(i);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::TyUnion(..), None) => {
|
||||
// Do nothing, all union fields are moved/assigned together.
|
||||
}
|
||||
|
||||
(&ty::TyEnum(def, _), ref enum_variant_info) => {
|
||||
let variant = match *enum_variant_info {
|
||||
Some((vid, ref _lp2)) => def.variant_with_id(vid),
|
||||
None => {
|
||||
assert!(def.is_univariant());
|
||||
&def.variants[0]
|
||||
}
|
||||
};
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
for field in &variant.fields {
|
||||
if field.name == ast_name {
|
||||
continue;
|
||||
}
|
||||
let field_name = mc::NamedField(field.name);
|
||||
add_fragment_sibling_local(field_name, Some(variant.did));
|
||||
AdtKind::Union => {
|
||||
// Do nothing, all union fields are moved/assigned together.
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
let variant = match enum_variant_info {
|
||||
Some((vid, ref _lp2)) => def.variant_with_id(vid),
|
||||
None => {
|
||||
assert!(def.is_univariant());
|
||||
&def.variants[0]
|
||||
}
|
||||
}
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
for (i, _f) in variant.fields.iter().enumerate() {
|
||||
if tuple_idx == i {
|
||||
continue;
|
||||
};
|
||||
match *origin_field_name {
|
||||
mc::NamedField(ast_name) => {
|
||||
for field in &variant.fields {
|
||||
if field.name == ast_name {
|
||||
continue;
|
||||
}
|
||||
let field_name = mc::NamedField(field.name);
|
||||
add_fragment_sibling_local(field_name, Some(variant.did));
|
||||
}
|
||||
}
|
||||
mc::PositionalField(tuple_idx) => {
|
||||
for (i, _f) in variant.fields.iter().enumerate() {
|
||||
if tuple_idx == i {
|
||||
continue;
|
||||
}
|
||||
let field_name = mc::PositionalField(i);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
let field_name = mc::PositionalField(i);
|
||||
add_fragment_sibling_local(field_name, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ref sty_and_variant_info => {
|
||||
ref ty => {
|
||||
let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
|
||||
span_bug!(opt_span.unwrap_or(DUMMY_SP),
|
||||
"type {:?} ({:?}) is not fragmentable",
|
||||
parent_ty,
|
||||
sty_and_variant_info);
|
||||
parent_ty, ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
Categorization::Interior(ref b, mc::InteriorField(_)) |
|
||||
Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
|
||||
match b.ty.sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
if def.has_dtor() {
|
||||
Some(cmt.clone())
|
||||
} else {
|
||||
|
@ -148,9 +148,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
Categorization::Downcast(ref b, _) |
|
||||
Categorization::Interior(ref b, mc::InteriorField(_)) => {
|
||||
match b.ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor() => {
|
||||
ty::TyAdt(def, _) if def.has_dtor() => {
|
||||
let mut err = struct_span_err!(bccx, move_from.span, E0509,
|
||||
"cannot move out of type `{}`, \
|
||||
which implements the `Drop` trait",
|
||||
|
@ -103,8 +103,8 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
|
||||
let base_ty = cmt_base.ty;
|
||||
let result = self.restrict(cmt_base);
|
||||
// Borrowing one union field automatically borrows all its fields.
|
||||
if let ty::TyUnion(ref adt_def, _) = base_ty.sty {
|
||||
match result {
|
||||
match base_ty.sty {
|
||||
ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
|
||||
RestrictionResult::Safe => RestrictionResult::Safe,
|
||||
RestrictionResult::SafeIf(base_lp, mut base_vec) => {
|
||||
for field in &adt_def.struct_variant().fields {
|
||||
@ -124,9 +124,8 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
|
||||
LpInterior(opt_variant_id, interior)));
|
||||
RestrictionResult::SafeIf(lp, base_vec)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.extend(result, &cmt, LpInterior(opt_variant_id, interior))
|
||||
},
|
||||
_ => self.extend(result, &cmt, LpInterior(opt_variant_id, interior))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,7 +709,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
|
||||
let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
match ty.sty {
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
self.open_drop_for_adt(c, def, substs)
|
||||
}
|
||||
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
|
||||
@ -893,7 +893,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
|
||||
match ty.sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
if def.has_dtor() {
|
||||
self.tcx.sess.span_warn(
|
||||
c.source_info.span,
|
||||
|
@ -261,7 +261,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
|
||||
lv, ty);
|
||||
true
|
||||
}
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) | ty::TyEnum(def, _) if def.has_dtor() => {
|
||||
ty::TyAdt(def, _) if def.has_dtor() => {
|
||||
debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} Drop => false",
|
||||
lv, ty);
|
||||
true
|
||||
|
@ -367,20 +367,22 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
kind: MoveKind) {
|
||||
// Moving one union field automatically moves all its fields.
|
||||
if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
|
||||
if let ty::TyUnion(ref adt_def, _) = base_lp.ty.sty {
|
||||
for field in &adt_def.struct_variant().fields {
|
||||
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
|
||||
let field_ty = if field == interior {
|
||||
lp.ty
|
||||
} else {
|
||||
tcx.types.err // Doesn't matter
|
||||
};
|
||||
let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
|
||||
LpInterior(opt_variant_id, field));
|
||||
let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
|
||||
self.add_move_helper(tcx, sibling_lp, id, kind);
|
||||
if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
|
||||
if adt_def.is_union() {
|
||||
for field in &adt_def.struct_variant().fields {
|
||||
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
|
||||
let field_ty = if field == interior {
|
||||
lp.ty
|
||||
} else {
|
||||
tcx.types.err // Doesn't matter
|
||||
};
|
||||
let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
|
||||
LpInterior(opt_variant_id, field));
|
||||
let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
|
||||
self.add_move_helper(tcx, sibling_lp, id, kind);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,20 +424,23 @@ impl<'a, 'tcx> MoveData<'tcx> {
|
||||
mode: euv::MutateMode) {
|
||||
// Assigning to one union field automatically assigns to all its fields.
|
||||
if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
|
||||
if let ty::TyUnion(ref adt_def, _) = base_lp.ty.sty {
|
||||
for field in &adt_def.struct_variant().fields {
|
||||
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
|
||||
let field_ty = if field == interior {
|
||||
lp.ty
|
||||
} else {
|
||||
tcx.types.err // Doesn't matter
|
||||
};
|
||||
let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
|
||||
LpInterior(opt_variant_id, field));
|
||||
let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
|
||||
self.add_assignment_helper(tcx, sibling_lp, assign_id, span, assignee_id, mode);
|
||||
if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
|
||||
if adt_def.is_union() {
|
||||
for field in &adt_def.struct_variant().fields {
|
||||
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
|
||||
let field_ty = if field == interior {
|
||||
lp.ty
|
||||
} else {
|
||||
tcx.types.err // Doesn't matter
|
||||
};
|
||||
let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
|
||||
LpInterior(opt_variant_id, field));
|
||||
let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
|
||||
self.add_assignment_helper(tcx, sibling_lp, assign_id,
|
||||
span, assignee_id, mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,21 +245,23 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
|
||||
pat.walk(|p| {
|
||||
if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node {
|
||||
let pat_ty = cx.tcx.pat_ty(p);
|
||||
if let ty::TyEnum(edef, _) = pat_ty.sty {
|
||||
if let Def::Local(..) = cx.tcx.expect_def(p.id) {
|
||||
if edef.variants.iter().any(|variant| {
|
||||
variant.name == name.node && variant.kind == VariantKind::Unit
|
||||
}) {
|
||||
let ty_path = cx.tcx.item_path_str(edef.did);
|
||||
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
name.node, ty_path);
|
||||
help!(err,
|
||||
"if you meant to match on a variant, \
|
||||
consider making the path in the pattern qualified: `{}::{}`",
|
||||
ty_path, name.node);
|
||||
err.emit();
|
||||
if let ty::TyAdt(edef, _) = pat_ty.sty {
|
||||
if edef.is_enum() {
|
||||
if let Def::Local(..) = cx.tcx.expect_def(p.id) {
|
||||
if edef.variants.iter().any(|variant| {
|
||||
variant.name == name.node && variant.kind == VariantKind::Unit
|
||||
}) {
|
||||
let ty_path = cx.tcx.item_path_str(edef.did);
|
||||
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
name.node, ty_path);
|
||||
help!(err,
|
||||
"if you meant to match on a variant, \
|
||||
consider making the path in the pattern qualified: `{}::{}`",
|
||||
ty_path, name.node);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -566,7 +568,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
let pat = match left_ty.sty {
|
||||
ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None),
|
||||
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) | ty::TyUnion(adt, _) => {
|
||||
ty::TyAdt(adt, _) => {
|
||||
let v = ctor.variant_for_adt(adt);
|
||||
match v.kind {
|
||||
VariantKind::Struct => {
|
||||
@ -659,7 +661,8 @@ fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
|
||||
[true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
|
||||
ty::TySlice(_) =>
|
||||
(0..max_slice_length+1).map(|length| Slice(length)).collect(),
|
||||
ty::TyEnum(def, _) => def.variants.iter().map(|v| Variant(v.did)).collect(),
|
||||
ty::TyAdt(def, _) if def.is_enum() =>
|
||||
def.variants.iter().map(|v| Variant(v.did)).collect(),
|
||||
_ => vec![Single]
|
||||
}
|
||||
}
|
||||
@ -837,7 +840,7 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us
|
||||
_ => bug!()
|
||||
},
|
||||
ty::TyRef(..) => 1,
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) | ty::TyUnion(adt, _) => {
|
||||
ty::TyAdt(adt, _) => {
|
||||
ctor.variant_for_adt(adt).fields.len()
|
||||
}
|
||||
ty::TyArray(_, n) => n,
|
||||
|
@ -257,8 +257,11 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
span,
|
||||
format!("floating point constants cannot be used in patterns"));
|
||||
}
|
||||
ty::TyEnum(adt_def, _) |
|
||||
ty::TyStruct(adt_def, _) => {
|
||||
ty::TyAdt(adt_def, _) if adt_def.is_union() => {
|
||||
// Matching on union fields is unsafe, we can't hide it in constants
|
||||
tcx.sess.span_err(span, "cannot use unions in constant patterns");
|
||||
}
|
||||
ty::TyAdt(adt_def, _) => {
|
||||
if !tcx.has_attr(adt_def.did, "structural_match") {
|
||||
tcx.sess.add_lint(
|
||||
lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
|
||||
@ -271,10 +274,6 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tcx.item_path_str(adt_def.did)));
|
||||
}
|
||||
}
|
||||
ty::TyUnion(..) => {
|
||||
// Matching on union fields is unsafe, we can't hide it in constants
|
||||
tcx.sess.span_err(span, "cannot use unions in constant patterns");
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
let pat = match expr.node {
|
||||
@ -1039,7 +1038,7 @@ fn infer<'a, 'tcx>(i: ConstInt,
|
||||
(&ty::TyInt(ity), i) => Err(TypeMismatch(ity.to_string(), i)),
|
||||
(&ty::TyUint(ity), i) => Err(TypeMismatch(ity.to_string(), i)),
|
||||
|
||||
(&ty::TyEnum(ref adt, _), i) => {
|
||||
(&ty::TyAdt(adt, _), i) if adt.is_enum() => {
|
||||
let hints = tcx.lookup_repr_hints(adt.did);
|
||||
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
||||
infer(i, tcx, &int_ty.to_ty(tcx).sty)
|
||||
@ -1230,7 +1229,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
|
||||
infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral)
|
||||
},
|
||||
None => Ok(Integral(Infer(n))),
|
||||
Some(&ty::TyEnum(ref adt, _)) => {
|
||||
Some(&ty::TyAdt(adt, _)) => {
|
||||
let hints = tcx.lookup_repr_hints(adt.did);
|
||||
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
||||
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
|
||||
|
@ -468,21 +468,21 @@ impl LateLintPass for MissingCopyImplementations {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_struct(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
}
|
||||
hir::ItemUnion(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_union(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
}
|
||||
hir::ItemEnum(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return;
|
||||
}
|
||||
let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
|
||||
(def, cx.tcx.mk_enum(def, Substs::empty(cx.tcx)))
|
||||
(def, cx.tcx.mk_adt(def, Substs::empty(cx.tcx)))
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{Layout, Primitive};
|
||||
use rustc::traits::Reveal;
|
||||
use middle::const_val::ConstVal;
|
||||
@ -431,110 +431,112 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
match ty.sty {
|
||||
ty::TyStruct(def, substs) => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
return FfiUnsafe(
|
||||
"found struct without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to \
|
||||
the type");
|
||||
}
|
||||
|
||||
// We can't completely trust repr(C) markings; make sure the
|
||||
// fields are actually safe.
|
||||
if def.struct_variant().fields.is_empty() {
|
||||
return FfiUnsafe(
|
||||
"found zero-size struct in foreign module, consider \
|
||||
adding a member to this struct");
|
||||
}
|
||||
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
ty::TyUnion(def, substs) => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
return FfiUnsafe(
|
||||
"found union without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to \
|
||||
the type");
|
||||
}
|
||||
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadUnion(def.did, s); }
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
ty::TyEnum(def, substs) => {
|
||||
if def.variants.is_empty() {
|
||||
// Empty enums are okay... although sort of useless.
|
||||
return FfiSafe
|
||||
}
|
||||
|
||||
// Check for a repr() attribute to specify the size of the
|
||||
// discriminant.
|
||||
let repr_hints = cx.lookup_repr_hints(def.did);
|
||||
match &repr_hints[..] {
|
||||
&[] => {
|
||||
// Special-case types like `Option<extern fn()>`.
|
||||
if !is_repr_nullable_ptr(cx, def, substs) {
|
||||
return FfiUnsafe(
|
||||
"found enum without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(...)] attribute to \
|
||||
the type")
|
||||
}
|
||||
}
|
||||
&[ref hint] => {
|
||||
if !hint.is_ffi_safe() {
|
||||
// FIXME: This shouldn't be reachable: we should check
|
||||
// this earlier.
|
||||
return FfiUnsafe(
|
||||
"enum has unexpected #[repr(...)] attribute")
|
||||
}
|
||||
|
||||
// Enum with an explicitly sized discriminant; either
|
||||
// a C-style enum or a discriminated union.
|
||||
|
||||
// The layout of enum variants is implicitly repr(C).
|
||||
// FIXME: Is that correct?
|
||||
}
|
||||
_ => {
|
||||
// FIXME: This shouldn't be reachable: we should check
|
||||
// this earlier.
|
||||
ty::TyAdt(def, substs) => match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
return FfiUnsafe(
|
||||
"enum has too many #[repr(...)] attributes");
|
||||
"found struct without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to \
|
||||
the type");
|
||||
}
|
||||
}
|
||||
|
||||
// Check the contained variants.
|
||||
for variant in &def.variants {
|
||||
for field in &variant.fields {
|
||||
let arg = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, arg);
|
||||
// We can't completely trust repr(C) markings; make sure the
|
||||
// fields are actually safe.
|
||||
if def.struct_variant().fields.is_empty() {
|
||||
return FfiUnsafe(
|
||||
"found zero-size struct in foreign module, consider \
|
||||
adding a member to this struct");
|
||||
}
|
||||
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
|
||||
FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
AdtKind::Union => {
|
||||
if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
|
||||
return FfiUnsafe(
|
||||
"found union without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(C)] attribute to \
|
||||
the type");
|
||||
}
|
||||
|
||||
for field in &def.struct_variant().fields {
|
||||
let field_ty = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, field_ty);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadUnion(def.did, s); }
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
if def.variants.is_empty() {
|
||||
// Empty enums are okay... although sort of useless.
|
||||
return FfiSafe
|
||||
}
|
||||
|
||||
// Check for a repr() attribute to specify the size of the
|
||||
// discriminant.
|
||||
let repr_hints = cx.lookup_repr_hints(def.did);
|
||||
match &repr_hints[..] {
|
||||
&[] => {
|
||||
// Special-case types like `Option<extern fn()>`.
|
||||
if !is_repr_nullable_ptr(cx, def, substs) {
|
||||
return FfiUnsafe(
|
||||
"found enum without foreign-function-safe \
|
||||
representation annotation in foreign module, \
|
||||
consider adding a #[repr(...)] attribute to \
|
||||
the type")
|
||||
}
|
||||
}
|
||||
&[ref hint] => {
|
||||
if !hint.is_ffi_safe() {
|
||||
// FIXME: This shouldn't be reachable: we should check
|
||||
// this earlier.
|
||||
return FfiUnsafe(
|
||||
"enum has unexpected #[repr(...)] attribute")
|
||||
}
|
||||
|
||||
// Enum with an explicitly sized discriminant; either
|
||||
// a C-style enum or a discriminated union.
|
||||
|
||||
// The layout of enum variants is implicitly repr(C).
|
||||
// FIXME: Is that correct?
|
||||
}
|
||||
_ => {
|
||||
// FIXME: This shouldn't be reachable: we should check
|
||||
// this earlier.
|
||||
return FfiUnsafe(
|
||||
"enum has too many #[repr(...)] attributes");
|
||||
}
|
||||
}
|
||||
|
||||
// Check the contained variants.
|
||||
for variant in &def.variants {
|
||||
for field in &variant.fields {
|
||||
let arg = cx.normalize_associated_type(&field.ty(cx, substs));
|
||||
let r = self.check_type_for_ffi(cache, arg);
|
||||
match r {
|
||||
FfiSafe => {}
|
||||
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
|
||||
FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
|
||||
}
|
||||
}
|
||||
}
|
||||
FfiSafe
|
||||
}
|
||||
},
|
||||
|
||||
ty::TyChar => {
|
||||
FfiUnsafe("found Rust type `char` in foreign module, while \
|
||||
|
@ -136,9 +136,7 @@ impl LateLintPass for UnusedResults {
|
||||
ty::TyTuple(ref tys) if tys.is_empty() => return,
|
||||
ty::TyNever => return,
|
||||
ty::TyBool => return,
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) |
|
||||
ty::TyEnum(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
let attrs = cx.tcx.get_attrs(def.did);
|
||||
check_must_use(cx, &attrs[..], s.span)
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::{DefId, DefIndex};
|
||||
use middle::lang_items;
|
||||
use rustc::ty::{ImplContainer, TraitContainer};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, VariantKind};
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
@ -453,23 +453,19 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd,
|
||||
let mut ctor_did = None;
|
||||
let (kind, variants) = match item_family(doc) {
|
||||
Enum => {
|
||||
(ty::AdtKind::Enum,
|
||||
get_enum_variants(cdata, doc))
|
||||
(AdtKind::Enum, get_enum_variants(cdata, doc))
|
||||
}
|
||||
Struct(..) => {
|
||||
// Use separate constructor id for unit/tuple structs and reuse did for braced structs.
|
||||
ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| {
|
||||
translated_def_id(cdata, ctor_doc)
|
||||
});
|
||||
(ty::AdtKind::Struct,
|
||||
vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))])
|
||||
(AdtKind::Struct, vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))])
|
||||
}
|
||||
Union => {
|
||||
(ty::AdtKind::Union,
|
||||
vec![get_struct_variant(cdata, doc, did)])
|
||||
(AdtKind::Union, vec![get_struct_variant(cdata, doc, did)])
|
||||
}
|
||||
_ => bug!("get_adt_def called on a non-ADT {:?} - {:?}",
|
||||
item_family(doc), did)
|
||||
_ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", item_family(doc), did)
|
||||
};
|
||||
|
||||
let adt = tcx.intern_adt_def(did, kind, variants);
|
||||
@ -481,8 +477,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd,
|
||||
// this needs to be done *after* the variant is interned,
|
||||
// to support recursive structures
|
||||
for variant in &adt.variants {
|
||||
if variant.kind == ty::VariantKind::Tuple &&
|
||||
adt.adt_kind() == ty::AdtKind::Enum {
|
||||
if variant.kind == ty::VariantKind::Tuple && adt.is_enum() {
|
||||
// tuple-like enum variant fields aren't real items - get the types
|
||||
// from the ctor.
|
||||
debug!("evaluating the ctor-type of {:?}",
|
||||
|
@ -358,14 +358,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
|
||||
}
|
||||
}
|
||||
'c' => return tcx.types.char,
|
||||
't' => {
|
||||
assert_eq!(self.next(), '[');
|
||||
let did = self.parse_def();
|
||||
let substs = self.parse_substs();
|
||||
assert_eq!(self.next(), ']');
|
||||
let def = self.tcx.lookup_adt_def(did);
|
||||
return tcx.mk_enum(def, substs);
|
||||
}
|
||||
'x' => {
|
||||
assert_eq!(self.next(), '[');
|
||||
let trait_ref = ty::Binder(self.parse_existential_trait_ref());
|
||||
@ -470,15 +462,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
|
||||
let substs = self.parse_substs();
|
||||
assert_eq!(self.next(), ']');
|
||||
let def = self.tcx.lookup_adt_def(did);
|
||||
return self.tcx.mk_struct(def, substs);
|
||||
}
|
||||
'U' => {
|
||||
assert_eq!(self.next(), '[');
|
||||
let did = self.parse_def();
|
||||
let substs = self.parse_substs();
|
||||
assert_eq!(self.next(), ']');
|
||||
let def = self.tcx.lookup_adt_def(did);
|
||||
return self.tcx.mk_union(def, substs);
|
||||
return self.tcx.mk_adt(def, substs);
|
||||
}
|
||||
'k' => {
|
||||
assert_eq!(self.next(), '[');
|
||||
|
@ -97,11 +97,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
|
||||
ast::FloatTy::F64 => write!(w, "MF"),
|
||||
};
|
||||
}
|
||||
ty::TyEnum(def, substs) => {
|
||||
write!(w, "t[{}|", (cx.ds)(cx.tcx, def.did));
|
||||
enc_substs(w, cx, substs);
|
||||
write!(w, "]");
|
||||
}
|
||||
ty::TyTrait(ref obj) => {
|
||||
write!(w, "x[");
|
||||
enc_existential_trait_ref(w, cx, obj.principal.0);
|
||||
@ -165,16 +160,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
|
||||
ty::TyParam(p) => {
|
||||
write!(w, "p[{}|{}]", p.idx, p.name);
|
||||
}
|
||||
ty::TyStruct(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did));
|
||||
enc_substs(w, cx, substs);
|
||||
write!(w, "]");
|
||||
}
|
||||
ty::TyUnion(def, substs) => {
|
||||
write!(w, "U[{}|", (cx.ds)(cx.tcx, def.did));
|
||||
enc_substs(w, cx, substs);
|
||||
write!(w, "]");
|
||||
}
|
||||
ty::TyClosure(def, substs) => {
|
||||
write!(w, "k[{}|", (cx.ds)(cx.tcx, def));
|
||||
enc_substs(w, cx, substs.func_substs);
|
||||
|
@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ExprKind::Adt {
|
||||
adt_def, variant_index, substs, fields, base
|
||||
} => { // see (*) above
|
||||
let is_union = adt_def.adt_kind() == ty::AdtKind::Union;
|
||||
let is_union = adt_def.is_union();
|
||||
let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
|
||||
|
||||
// first process the set of fields that were provided
|
||||
|
@ -19,7 +19,7 @@ use rustc::hir::def::Def;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::ty::{self, VariantDef, Ty};
|
||||
use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
||||
use rustc::ty::cast::CastKind as TyCastKind;
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::hir;
|
||||
@ -459,48 +459,50 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
|
||||
hir::ExprStruct(_, ref fields, ref base) => {
|
||||
match expr_ty.sty {
|
||||
ty::TyStruct(adt, substs) | ty::TyUnion(adt, substs) => {
|
||||
let field_refs = field_refs(&adt.variants[0], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: base.as_ref().map(|base| {
|
||||
FruInfo {
|
||||
base: base.to_ref(),
|
||||
field_types: cx.tcx.tables
|
||||
.borrow()
|
||||
.fru_field_types[&expr.id]
|
||||
.clone()
|
||||
}
|
||||
})
|
||||
ty::TyAdt(adt, substs) => match adt.adt_kind() {
|
||||
AdtKind::Struct | AdtKind::Union => {
|
||||
let field_refs = field_refs(&adt.variants[0], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: base.as_ref().map(|base| {
|
||||
FruInfo {
|
||||
base: base.to_ref(),
|
||||
field_types: cx.tcx.tables
|
||||
.borrow()
|
||||
.fru_field_types[&expr.id]
|
||||
.clone()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::TyEnum(adt, substs) => {
|
||||
match cx.tcx.expect_def(expr.id) {
|
||||
Def::Variant(enum_id, variant_id) => {
|
||||
debug_assert!(adt.did == enum_id);
|
||||
assert!(base.is_none());
|
||||
AdtKind::Enum => {
|
||||
match cx.tcx.expect_def(expr.id) {
|
||||
Def::Variant(enum_id, variant_id) => {
|
||||
debug_assert!(adt.did == enum_id);
|
||||
assert!(base.is_none());
|
||||
|
||||
let index = adt.variant_index_with_id(variant_id);
|
||||
let field_refs = field_refs(&adt.variants[index], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: index,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: None
|
||||
let index = adt.variant_index_with_id(variant_id);
|
||||
let field_refs = field_refs(&adt.variants[index], fields);
|
||||
ExprKind::Adt {
|
||||
adt_def: adt,
|
||||
variant_index: index,
|
||||
substs: substs,
|
||||
fields: field_refs,
|
||||
base: None
|
||||
}
|
||||
}
|
||||
ref def => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"unexpected def: {:?}",
|
||||
def);
|
||||
}
|
||||
}
|
||||
ref def => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"unexpected def: {:?}",
|
||||
def);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
span_bug!(
|
||||
expr.span,
|
||||
@ -579,13 +581,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
body: block::to_expr_ref(cx, body) },
|
||||
hir::ExprField(ref source, name) => {
|
||||
let index = match cx.tcx.expr_ty_adjusted(source).sty {
|
||||
ty::TyStruct(adt_def, _) | ty::TyUnion(adt_def, _) =>
|
||||
ty::TyAdt(adt_def, _) =>
|
||||
adt_def.variants[0].index_of_field_named(name.node),
|
||||
ref ty =>
|
||||
span_bug!(
|
||||
expr.span,
|
||||
"field of non-struct: {:?}",
|
||||
ty),
|
||||
span_bug!(expr.span, "field of non-ADT: {:?}", ty),
|
||||
};
|
||||
let index = index.unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
@ -680,7 +679,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
ty::TyFnDef(..) => def_id,
|
||||
// A unit struct which is used as a value. We return a completely different ExprKind
|
||||
// here to account for this special case.
|
||||
ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
|
||||
ty::TyAdt(adt_def, substs) => return ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
@ -694,7 +693,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
// expression.
|
||||
ty::TyFnDef(..) => variant_id,
|
||||
// A unit variant, similar special case to the struct case above.
|
||||
ty::TyEnum(adt_def, substs) => {
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
debug_assert!(adt_def.did == enum_id);
|
||||
let index = adt_def.variant_index_with_id(variant_id);
|
||||
return ExprKind::Adt {
|
||||
|
@ -198,8 +198,8 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
|
||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let adt_def = match pat_ty.sty {
|
||||
ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
|
||||
_ => span_bug!(pat.span, "tuple struct pattern not applied to struct or enum"),
|
||||
ty::TyAdt(adt_def, _) => adt_def,
|
||||
_ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
|
||||
};
|
||||
let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
|
||||
|
||||
@ -217,13 +217,11 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let adt_def = match pat_ty.sty {
|
||||
ty::TyStruct(adt_def, _) |
|
||||
ty::TyUnion(adt_def, _) |
|
||||
ty::TyEnum(adt_def, _) => adt_def,
|
||||
ty::TyAdt(adt_def, _) => adt_def,
|
||||
_ => {
|
||||
span_bug!(
|
||||
pat.span,
|
||||
"struct pattern not applied to struct or enum");
|
||||
"struct pattern not applied to an ADT");
|
||||
}
|
||||
};
|
||||
let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
|
||||
|
@ -218,7 +218,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
}
|
||||
ProjectionElem::Downcast(adt_def1, index) =>
|
||||
match base_ty.sty {
|
||||
ty::TyEnum(adt_def, substs) if adt_def == adt_def1 => {
|
||||
ty::TyAdt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
|
||||
if index >= adt_def.variants.len() {
|
||||
LvalueTy::Ty {
|
||||
ty: span_mirbug_and_err!(
|
||||
@ -281,10 +281,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
(&adt_def.variants[variant_index], substs)
|
||||
}
|
||||
LvalueTy::Ty { ty } => match ty.sty {
|
||||
ty::TyStruct(adt_def, substs) |
|
||||
ty::TyUnion(adt_def, substs) |
|
||||
ty::TyEnum(adt_def, substs)
|
||||
if adt_def.is_univariant() => {
|
||||
ty::TyAdt(adt_def, substs) if adt_def.is_univariant() => {
|
||||
(&adt_def.variants[0], substs)
|
||||
}
|
||||
ty::TyTuple(tys) | ty::TyClosure(_, ty::ClosureSubsts {
|
||||
@ -364,7 +361,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
StatementKind::SetDiscriminant{ ref lvalue, variant_index } => {
|
||||
let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx);
|
||||
let adt = match lvalue_type.sty {
|
||||
TypeVariants::TyEnum(adt, _) => adt,
|
||||
TypeVariants::TyAdt(adt, _) if adt.is_enum() => adt,
|
||||
_ => {
|
||||
span_bug!(stmt.source_info.span,
|
||||
"bad set discriminant ({:?} = {:?}): lhs is not an enum",
|
||||
@ -444,9 +441,10 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
TerminatorKind::Switch { ref discr, adt_def, ref targets } => {
|
||||
let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
|
||||
match discr_ty.sty {
|
||||
ty::TyEnum(def, _)
|
||||
if def == adt_def && adt_def.variants.len() == targets.len()
|
||||
=> {},
|
||||
ty::TyAdt(def, _) if def.is_enum() &&
|
||||
def == adt_def &&
|
||||
adt_def.variants.len() == targets.len()
|
||||
=> {},
|
||||
_ => {
|
||||
span_mirbug!(self, term, "bad Switch ({:?} on {:?})",
|
||||
adt_def, discr_ty);
|
||||
|
@ -439,9 +439,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
/// instead of producing errors.
|
||||
fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node_ty: Ty<'tcx>) {
|
||||
match node_ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) |
|
||||
ty::TyEnum(def, _) if def.has_dtor() => {
|
||||
ty::TyAdt(def, _) if def.has_dtor() => {
|
||||
v.add_qualif(ConstQualif::NEEDS_DROP);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -384,11 +384,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||
|
||||
// Checks that a field is in scope.
|
||||
fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
|
||||
if def.adt_kind() != ty::AdtKind::Enum &&
|
||||
!field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
|
||||
let kind_descr = if def.adt_kind() == ty::AdtKind::Union { "union" } else { "struct" };
|
||||
if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
|
||||
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
|
||||
field.name, kind_descr, self.tcx.item_path_str(def.did))
|
||||
field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
|
||||
.span_label(span, &format!("field `{}` is private", field.name))
|
||||
.emit();
|
||||
}
|
||||
@ -438,7 +436,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
// (i.e. `all_fields - fields`), just check them all,
|
||||
// unless the ADT is a union, then unmentioned fields
|
||||
// are not checked.
|
||||
if adt.adt_kind() == ty::AdtKind::Union {
|
||||
if adt.is_union() {
|
||||
for expr_field in expr_fields {
|
||||
self.check_field(expr.span, adt, variant.field_named(expr_field.name.node));
|
||||
}
|
||||
@ -511,7 +509,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
PatKind::TupleStruct(_, ref fields, ddpos) => {
|
||||
match self.tcx.pat_ty(pattern).sty {
|
||||
ty::TyStruct(def, _) => {
|
||||
// enum fields have no privacy at this time
|
||||
ty::TyAdt(def, _) if !def.is_enum() => {
|
||||
let expected_len = def.struct_variant().fields.len();
|
||||
for (i, field) in fields.iter().enumerate_and_adjust(expected_len, ddpos) {
|
||||
if let PatKind::Wild = field.node {
|
||||
@ -520,9 +519,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
|
||||
self.check_field(field.span, def, &def.struct_variant().fields[i]);
|
||||
}
|
||||
}
|
||||
ty::TyEnum(..) => {
|
||||
// enum fields have no privacy at this time
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -1356,7 +1356,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
|
||||
};
|
||||
let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
|
||||
match *ty {
|
||||
ty::TyStruct(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
|
||||
if !self.span.filter_generated(sub_span, ex.span) {
|
||||
self.dumper.variable_ref(VariableRefData {
|
||||
|
@ -431,7 +431,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
};
|
||||
match self.tcx.expr_ty_adjusted(&hir_node).sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) if !def.is_enum() => {
|
||||
let f = def.struct_variant().field_named(ident.node.name);
|
||||
let sub_span = self.span_utils.span_for_last_ident(expr.span);
|
||||
filter!(self.span_utils, sub_span, expr.span, None);
|
||||
@ -443,14 +443,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}));
|
||||
}
|
||||
_ => {
|
||||
debug!("Expected struct type, found {:?}", ty);
|
||||
debug!("Expected struct or union type, found {:?}", ty);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Struct(ref path, ..) => {
|
||||
match self.tcx.expr_ty_adjusted(&hir_node).sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) if !def.is_enum() => {
|
||||
let sub_span = self.span_utils.span_for_last_ident(path.span);
|
||||
filter!(self.span_utils, sub_span, path.span, None);
|
||||
Some(Data::TypeRefData(TypeRefData {
|
||||
@ -461,9 +461,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}))
|
||||
}
|
||||
_ => {
|
||||
// FIXME ty could legitimately be a TyEnum, but then we will fail
|
||||
// FIXME ty could legitimately be an enum, but then we will fail
|
||||
// later if we try to look up the fields.
|
||||
debug!("expected TyStruct, found {:?}", ty);
|
||||
debug!("expected struct or union, found {:?}", ty);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ use std::rc::Rc;
|
||||
|
||||
use llvm::{ValueRef, True, IntEQ, IntNE};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::IntType;
|
||||
@ -179,172 +179,174 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
ty::TyTuple(ref elems) => {
|
||||
Univariant(mk_struct(cx, &elems[..], false, t))
|
||||
}
|
||||
ty::TyStruct(def, substs) => {
|
||||
let ftys = def.struct_variant().fields.iter().map(|field| {
|
||||
monomorphize::field_ty(cx.tcx(), substs, field)
|
||||
}).collect::<Vec<_>>();
|
||||
let packed = cx.tcx().lookup_packed(def.did);
|
||||
|
||||
Univariant(mk_struct(cx, &ftys[..], packed, t))
|
||||
}
|
||||
ty::TyUnion(def, substs) => {
|
||||
let ftys = def.struct_variant().fields.iter().map(|field| {
|
||||
monomorphize::field_ty(cx.tcx(), substs, field)
|
||||
}).collect::<Vec<_>>();
|
||||
let packed = cx.tcx().lookup_packed(def.did);
|
||||
UntaggedUnion(mk_union(cx, &ftys[..], packed, t))
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
Univariant(mk_struct(cx, &substs.upvar_tys, false, t))
|
||||
}
|
||||
ty::TyEnum(def, substs) => {
|
||||
let cases = get_cases(cx.tcx(), def, substs);
|
||||
let hint = *cx.tcx().lookup_repr_hints(def.did).get(0)
|
||||
.unwrap_or(&attr::ReprAny);
|
||||
ty::TyAdt(def, substs) => match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
let ftys = def.struct_variant().fields.iter().map(|field| {
|
||||
monomorphize::field_ty(cx.tcx(), substs, field)
|
||||
}).collect::<Vec<_>>();
|
||||
let packed = cx.tcx().lookup_packed(def.did);
|
||||
|
||||
if cases.is_empty() {
|
||||
// Uninhabitable; represent as unit
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
assert_eq!(hint, attr::ReprAny);
|
||||
return Univariant(mk_struct(cx, &[], false, t));
|
||||
Univariant(mk_struct(cx, &ftys[..], packed, t))
|
||||
}
|
||||
|
||||
if cases.iter().all(|c| c.tys.is_empty()) {
|
||||
// All bodies empty -> intlike
|
||||
let discrs: Vec<_> = cases.iter().map(|c| Disr::from(c.discr)).collect();
|
||||
let bounds = IntBounds {
|
||||
ulo: discrs.iter().min().unwrap().0,
|
||||
uhi: discrs.iter().max().unwrap().0,
|
||||
slo: discrs.iter().map(|n| n.0 as i64).min().unwrap(),
|
||||
shi: discrs.iter().map(|n| n.0 as i64).max().unwrap()
|
||||
};
|
||||
return mk_cenum(cx, hint, &bounds);
|
||||
AdtKind::Union => {
|
||||
let ftys = def.struct_variant().fields.iter().map(|field| {
|
||||
monomorphize::field_ty(cx.tcx(), substs, field)
|
||||
}).collect::<Vec<_>>();
|
||||
let packed = cx.tcx().lookup_packed(def.did);
|
||||
UntaggedUnion(mk_union(cx, &ftys[..], packed, t))
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
let cases = get_cases(cx.tcx(), def, substs);
|
||||
let hint = *cx.tcx().lookup_repr_hints(def.did).get(0)
|
||||
.unwrap_or(&attr::ReprAny);
|
||||
|
||||
// Since there's at least one
|
||||
// non-empty body, explicit discriminants should have
|
||||
// been rejected by a checker before this point.
|
||||
if !cases.iter().enumerate().all(|(i,c)| c.discr == Disr::from(i)) {
|
||||
bug!("non-C-like enum {} with specified discriminants",
|
||||
cx.tcx().item_path_str(def.did));
|
||||
}
|
||||
if cases.is_empty() {
|
||||
// Uninhabitable; represent as unit
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
assert_eq!(hint, attr::ReprAny);
|
||||
return Univariant(mk_struct(cx, &[], false, t));
|
||||
}
|
||||
|
||||
if cases.len() == 1 && hint == attr::ReprAny {
|
||||
// Equivalent to a struct/tuple/newtype.
|
||||
return Univariant(mk_struct(cx, &cases[0].tys, false, t));
|
||||
}
|
||||
if cases.iter().all(|c| c.tys.is_empty()) {
|
||||
// All bodies empty -> intlike
|
||||
let discrs: Vec<_> = cases.iter().map(|c| Disr::from(c.discr)).collect();
|
||||
let bounds = IntBounds {
|
||||
ulo: discrs.iter().min().unwrap().0,
|
||||
uhi: discrs.iter().max().unwrap().0,
|
||||
slo: discrs.iter().map(|n| n.0 as i64).min().unwrap(),
|
||||
shi: discrs.iter().map(|n| n.0 as i64).max().unwrap()
|
||||
};
|
||||
return mk_cenum(cx, hint, &bounds);
|
||||
}
|
||||
|
||||
if cases.len() == 2 && hint == attr::ReprAny {
|
||||
// Nullable pointer optimization
|
||||
let mut discr = 0;
|
||||
while discr < 2 {
|
||||
if cases[1 - discr].is_zerolen(cx, t) {
|
||||
let st = mk_struct(cx, &cases[discr].tys,
|
||||
false, t);
|
||||
match cases[discr].find_ptr(cx) {
|
||||
Some(ref df) if df.len() == 1 && st.fields.len() == 1 => {
|
||||
return RawNullablePointer {
|
||||
nndiscr: Disr::from(discr),
|
||||
nnty: st.fields[0],
|
||||
nullfields: cases[1 - discr].tys.clone()
|
||||
};
|
||||
// Since there's at least one
|
||||
// non-empty body, explicit discriminants should have
|
||||
// been rejected by a checker before this point.
|
||||
if !cases.iter().enumerate().all(|(i,c)| c.discr == Disr::from(i)) {
|
||||
bug!("non-C-like enum {} with specified discriminants",
|
||||
cx.tcx().item_path_str(def.did));
|
||||
}
|
||||
|
||||
if cases.len() == 1 && hint == attr::ReprAny {
|
||||
// Equivalent to a struct/tuple/newtype.
|
||||
return Univariant(mk_struct(cx, &cases[0].tys, false, t));
|
||||
}
|
||||
|
||||
if cases.len() == 2 && hint == attr::ReprAny {
|
||||
// Nullable pointer optimization
|
||||
let mut discr = 0;
|
||||
while discr < 2 {
|
||||
if cases[1 - discr].is_zerolen(cx, t) {
|
||||
let st = mk_struct(cx, &cases[discr].tys,
|
||||
false, t);
|
||||
match cases[discr].find_ptr(cx) {
|
||||
Some(ref df) if df.len() == 1 && st.fields.len() == 1 => {
|
||||
return RawNullablePointer {
|
||||
nndiscr: Disr::from(discr),
|
||||
nnty: st.fields[0],
|
||||
nullfields: cases[1 - discr].tys.clone()
|
||||
};
|
||||
}
|
||||
Some(mut discrfield) => {
|
||||
discrfield.push(0);
|
||||
discrfield.reverse();
|
||||
return StructWrappedNullablePointer {
|
||||
nndiscr: Disr::from(discr),
|
||||
nonnull: st,
|
||||
discrfield: discrfield,
|
||||
nullfields: cases[1 - discr].tys.clone()
|
||||
};
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Some(mut discrfield) => {
|
||||
discrfield.push(0);
|
||||
discrfield.reverse();
|
||||
return StructWrappedNullablePointer {
|
||||
nndiscr: Disr::from(discr),
|
||||
nonnull: st,
|
||||
discrfield: discrfield,
|
||||
nullfields: cases[1 - discr].tys.clone()
|
||||
};
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
discr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The general case.
|
||||
assert!((cases.len() - 1) as i64 >= 0);
|
||||
let bounds = IntBounds { ulo: 0, uhi: (cases.len() - 1) as u64,
|
||||
slo: 0, shi: (cases.len() - 1) as i64 };
|
||||
let min_ity = range_to_inttype(cx, hint, &bounds);
|
||||
|
||||
// Create the set of structs that represent each variant
|
||||
// Use the minimum integer type we figured out above
|
||||
let fields : Vec<_> = cases.iter().map(|c| {
|
||||
let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity));
|
||||
ftys.extend_from_slice(&c.tys);
|
||||
mk_struct(cx, &ftys, false, t)
|
||||
}).collect();
|
||||
|
||||
|
||||
// Check to see if we should use a different type for the
|
||||
// discriminant. If the overall alignment of the type is
|
||||
// the same as the first field in each variant, we can safely use
|
||||
// an alignment-sized type.
|
||||
// We increase the size of the discriminant to avoid LLVM copying
|
||||
// padding when it doesn't need to. This normally causes unaligned
|
||||
// load/stores and excessive memcpy/memset operations. By using a
|
||||
// bigger integer size, LLVM can be sure about it's contents and
|
||||
// won't be so conservative.
|
||||
// This check is needed to avoid increasing the size of types when
|
||||
// the alignment of the first field is smaller than the overall
|
||||
// alignment of the type.
|
||||
let (_, align) = union_size_and_align(&fields);
|
||||
let mut use_align = true;
|
||||
for st in &fields {
|
||||
// Get the first non-zero-sized field
|
||||
let field = st.fields.iter().skip(1).filter(|ty| {
|
||||
let t = type_of::sizing_type_of(cx, **ty);
|
||||
machine::llsize_of_real(cx, t) != 0 ||
|
||||
// This case is only relevant for zero-sized types with large alignment
|
||||
machine::llalign_of_min(cx, t) != 1
|
||||
}).next();
|
||||
|
||||
if let Some(field) = field {
|
||||
let field_align = type_of::align_of(cx, *field);
|
||||
if field_align != align {
|
||||
use_align = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
discr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The general case.
|
||||
assert!((cases.len() - 1) as i64 >= 0);
|
||||
let bounds = IntBounds { ulo: 0, uhi: (cases.len() - 1) as u64,
|
||||
slo: 0, shi: (cases.len() - 1) as i64 };
|
||||
let min_ity = range_to_inttype(cx, hint, &bounds);
|
||||
// If the alignment is smaller than the chosen discriminant size, don't use the
|
||||
// alignment as the final size.
|
||||
let min_ty = ll_inttype(&cx, min_ity);
|
||||
let min_size = machine::llsize_of_real(cx, min_ty);
|
||||
if (align as u64) < min_size {
|
||||
use_align = false;
|
||||
}
|
||||
|
||||
// Create the set of structs that represent each variant
|
||||
// Use the minimum integer type we figured out above
|
||||
let fields : Vec<_> = cases.iter().map(|c| {
|
||||
let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity));
|
||||
ftys.extend_from_slice(&c.tys);
|
||||
mk_struct(cx, &ftys, false, t)
|
||||
}).collect();
|
||||
|
||||
|
||||
// Check to see if we should use a different type for the
|
||||
// discriminant. If the overall alignment of the type is
|
||||
// the same as the first field in each variant, we can safely use
|
||||
// an alignment-sized type.
|
||||
// We increase the size of the discriminant to avoid LLVM copying
|
||||
// padding when it doesn't need to. This normally causes unaligned
|
||||
// load/stores and excessive memcpy/memset operations. By using a
|
||||
// bigger integer size, LLVM can be sure about it's contents and
|
||||
// won't be so conservative.
|
||||
// This check is needed to avoid increasing the size of types when
|
||||
// the alignment of the first field is smaller than the overall
|
||||
// alignment of the type.
|
||||
let (_, align) = union_size_and_align(&fields);
|
||||
let mut use_align = true;
|
||||
for st in &fields {
|
||||
// Get the first non-zero-sized field
|
||||
let field = st.fields.iter().skip(1).filter(|ty| {
|
||||
let t = type_of::sizing_type_of(cx, **ty);
|
||||
machine::llsize_of_real(cx, t) != 0 ||
|
||||
// This case is only relevant for zero-sized types with large alignment
|
||||
machine::llalign_of_min(cx, t) != 1
|
||||
}).next();
|
||||
|
||||
if let Some(field) = field {
|
||||
let field_align = type_of::align_of(cx, *field);
|
||||
if field_align != align {
|
||||
use_align = false;
|
||||
break;
|
||||
let ity = if use_align {
|
||||
// Use the overall alignment
|
||||
match align {
|
||||
1 => attr::UnsignedInt(ast::UintTy::U8),
|
||||
2 => attr::UnsignedInt(ast::UintTy::U16),
|
||||
4 => attr::UnsignedInt(ast::UintTy::U32),
|
||||
8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 =>
|
||||
attr::UnsignedInt(ast::UintTy::U64),
|
||||
_ => min_ity // use min_ity as a fallback
|
||||
}
|
||||
}
|
||||
} else {
|
||||
min_ity
|
||||
};
|
||||
|
||||
let fields : Vec<_> = cases.iter().map(|c| {
|
||||
let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
|
||||
ftys.extend_from_slice(&c.tys);
|
||||
mk_struct(cx, &ftys[..], false, t)
|
||||
}).collect();
|
||||
|
||||
ensure_enum_fits_in_address_space(cx, &fields[..], t);
|
||||
|
||||
General(ity, fields)
|
||||
}
|
||||
|
||||
// If the alignment is smaller than the chosen discriminant size, don't use the
|
||||
// alignment as the final size.
|
||||
let min_ty = ll_inttype(&cx, min_ity);
|
||||
let min_size = machine::llsize_of_real(cx, min_ty);
|
||||
if (align as u64) < min_size {
|
||||
use_align = false;
|
||||
}
|
||||
|
||||
let ity = if use_align {
|
||||
// Use the overall alignment
|
||||
match align {
|
||||
1 => attr::UnsignedInt(ast::UintTy::U8),
|
||||
2 => attr::UnsignedInt(ast::UintTy::U16),
|
||||
4 => attr::UnsignedInt(ast::UintTy::U32),
|
||||
8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 =>
|
||||
attr::UnsignedInt(ast::UintTy::U64),
|
||||
_ => min_ity // use min_ity as a fallback
|
||||
}
|
||||
} else {
|
||||
min_ity
|
||||
};
|
||||
|
||||
let fields : Vec<_> = cases.iter().map(|c| {
|
||||
let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
|
||||
ftys.extend_from_slice(&c.tys);
|
||||
mk_struct(cx, &ftys[..], false, t)
|
||||
}).collect();
|
||||
|
||||
ensure_enum_fits_in_address_space(cx, &fields[..], t);
|
||||
|
||||
General(ity, fields)
|
||||
}
|
||||
},
|
||||
_ => bug!("adt::represent_type called on non-ADT type: {}", t)
|
||||
}
|
||||
}
|
||||
@ -376,7 +378,7 @@ fn find_discr_field_candidate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty::TyFnPtr(_) => Some(path),
|
||||
|
||||
// Is this the NonZero lang item wrapping a pointer or integer type?
|
||||
ty::TyStruct(def, substs) if Some(def.did) == tcx.lang_items.non_zero() => {
|
||||
ty::TyAdt(def, substs) if Some(def.did) == tcx.lang_items.non_zero() => {
|
||||
let nonzero_fields = &def.struct_variant().fields;
|
||||
assert_eq!(nonzero_fields.len(), 1);
|
||||
let field_ty = monomorphize::field_ty(tcx, substs, &nonzero_fields[0]);
|
||||
@ -395,7 +397,7 @@ fn find_discr_field_candidate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
// Perhaps one of the fields of this struct is non-zero
|
||||
// let's recurse and find out
|
||||
ty::TyStruct(def, substs) => {
|
||||
ty::TyAdt(def, substs) if def.is_struct() => {
|
||||
for (j, field) in def.struct_variant().fields.iter().enumerate() {
|
||||
let field_ty = monomorphize::field_ty(tcx, substs, field);
|
||||
if let Some(mut fpath) = find_discr_field_candidate(tcx, field_ty, path.clone()) {
|
||||
|
@ -467,8 +467,7 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
|
||||
// This can be extended to enums and tuples in the future.
|
||||
// (&ty::TyEnum(def_id_a, _), &ty::TyEnum(def_id_b, _)) |
|
||||
(&ty::TyStruct(def_a, _), &ty::TyStruct(def_b, _)) => {
|
||||
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
let src_repr = adt::represent_type(bcx.ccx(), src_ty);
|
||||
|
@ -743,9 +743,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
// If the type implements Drop, also add a translation item for the
|
||||
// monomorphized Drop::drop() implementation.
|
||||
let destructor_did = match ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) |
|
||||
ty::TyEnum(def, _) => def.destructor(),
|
||||
ty::TyAdt(def, _) => def.destructor(),
|
||||
_ => None
|
||||
};
|
||||
|
||||
@ -798,9 +796,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
ty::TyTrait(_) => {
|
||||
/* nothing to do */
|
||||
}
|
||||
ty::TyStruct(ref adt_def, substs) |
|
||||
ty::TyUnion(ref adt_def, substs) |
|
||||
ty::TyEnum(ref adt_def, substs) => {
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
for field in adt_def.all_fields() {
|
||||
let field_type = monomorphize::apply_param_substs(scx,
|
||||
substs,
|
||||
@ -989,8 +985,8 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::TyStruct(source_adt_def, source_substs),
|
||||
&ty::TyStruct(target_adt_def, target_substs)) => {
|
||||
(&ty::TyAdt(source_adt_def, source_substs),
|
||||
&ty::TyAdt(target_adt_def, target_substs)) => {
|
||||
assert_eq!(source_adt_def, target_adt_def);
|
||||
|
||||
let kind = custom_coerce_unsize_info(scx, source_ty, target_ty);
|
||||
|
@ -88,8 +88,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
||||
return false;
|
||||
}
|
||||
match ty.sty {
|
||||
ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) |
|
||||
ty::TyTuple(..) | ty::TyArray(..) | ty::TyClosure(..) => {
|
||||
ty::TyAdt(..) | ty::TyTuple(..) | ty::TyArray(..) | ty::TyClosure(..) => {
|
||||
let llty = sizing_type_of(ccx, ty);
|
||||
llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
|
||||
}
|
||||
@ -101,7 +100,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
||||
pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||
-> Option<[Ty<'tcx>; 2]> {
|
||||
match ty.sty {
|
||||
ty::TyEnum(adt, substs) | ty::TyStruct(adt, substs) => {
|
||||
ty::TyAdt(adt, substs) => {
|
||||
assert_eq!(adt.variants.len(), 1);
|
||||
let fields = &adt.variants[0].fields;
|
||||
if fields.len() != 2 {
|
||||
@ -205,7 +204,7 @@ impl<'a, 'tcx> VariantInfo<'tcx> {
|
||||
-> Self
|
||||
{
|
||||
match ty.sty {
|
||||
ty::TyStruct(adt, substs) | ty::TyUnion(adt, substs) | ty::TyEnum(adt, substs) => {
|
||||
ty::TyAdt(adt, substs) => {
|
||||
let variant = match opt_def {
|
||||
None => adt.struct_variant(),
|
||||
Some(def) => adt.variant_of_def(def)
|
||||
|
@ -223,13 +223,9 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
|
||||
let def_ids: Vec<DefId> =
|
||||
key.walk()
|
||||
.filter_map(|t| match t.sty {
|
||||
ty::TyStruct(adt_def, _) |
|
||||
ty::TyEnum(adt_def, _) =>
|
||||
Some(adt_def.did),
|
||||
ty::TyProjection(ref proj) =>
|
||||
Some(proj.trait_ref.def_id),
|
||||
_ =>
|
||||
None
|
||||
ty::TyAdt(adt_def, _) => Some(adt_def.did),
|
||||
ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
DepNode::TraitSelect(def_ids)
|
||||
|
@ -30,7 +30,7 @@ use rustc::hir;
|
||||
use {type_of, adt, machine, monomorphize};
|
||||
use common::CrateContext;
|
||||
use type_::Type;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::{self, AdtKind, Ty};
|
||||
use session::config;
|
||||
use util::nodemap::FnvHashMap;
|
||||
use util::common::path2cstr;
|
||||
@ -176,18 +176,10 @@ impl<'tcx> TypeMap<'tcx> {
|
||||
ty::TyFloat(_) => {
|
||||
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
||||
},
|
||||
ty::TyEnum(def, substs) => {
|
||||
unique_type_id.push_str("enum ");
|
||||
ty::TyAdt(def, substs) => {
|
||||
unique_type_id.push_str(&(String::from(def.descr()) + " "));
|
||||
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
|
||||
},
|
||||
ty::TyStruct(def, substs) => {
|
||||
unique_type_id.push_str("struct ");
|
||||
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
|
||||
},
|
||||
ty::TyUnion(def, substs) => {
|
||||
unique_type_id.push_str("union ");
|
||||
from_def_id_and_substs(self, cx, def.did, substs, &mut unique_type_id);
|
||||
},
|
||||
}
|
||||
ty::TyTuple(component_types) if component_types.is_empty() => {
|
||||
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
||||
},
|
||||
@ -705,13 +697,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
ty::TyTuple(ref elements) if elements.is_empty() => {
|
||||
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
||||
}
|
||||
ty::TyEnum(def, _) => {
|
||||
prepare_enum_metadata(cx,
|
||||
t,
|
||||
def.did,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyArray(typ, len) => {
|
||||
fixed_vec_metadata(cx, unique_type_id, typ, Some(len as u64), usage_site_span)
|
||||
}
|
||||
@ -779,18 +764,27 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyStruct(..) => {
|
||||
prepare_struct_metadata(cx,
|
||||
ty::TyAdt(def, ..) => match def.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
prepare_struct_metadata(cx,
|
||||
t,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
AdtKind::Union => {
|
||||
prepare_union_metadata(cx,
|
||||
t,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
ty::TyUnion(..) => {
|
||||
prepare_union_metadata(cx,
|
||||
t,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
prepare_enum_metadata(cx,
|
||||
t,
|
||||
def.did,
|
||||
unique_type_id,
|
||||
usage_site_span).finalize(cx)
|
||||
}
|
||||
},
|
||||
ty::TyTuple(ref elements) => {
|
||||
prepare_tuple_metadata(cx,
|
||||
t,
|
||||
@ -1134,8 +1128,8 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let struct_llvm_type = type_of::in_memory_type_of(cx, struct_type);
|
||||
|
||||
let (struct_def_id, variant, substs) = match struct_type.sty {
|
||||
ty::TyStruct(def, substs) => (def.did, def.struct_variant(), substs),
|
||||
_ => bug!("prepare_struct_metadata on a non-struct")
|
||||
ty::TyAdt(def, substs) => (def.did, def.struct_variant(), substs),
|
||||
_ => bug!("prepare_struct_metadata on a non-ADT")
|
||||
};
|
||||
|
||||
let (containing_scope, _) = get_namespace_and_span_for_item(cx, struct_def_id);
|
||||
@ -1250,8 +1244,8 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let union_llvm_type = type_of::in_memory_type_of(cx, union_type);
|
||||
|
||||
let (union_def_id, variant, substs) = match union_type.sty {
|
||||
ty::TyUnion(def, substs) => (def.did, def.struct_variant(), substs),
|
||||
_ => bug!("prepare_union_metadata on a non-union")
|
||||
ty::TyAdt(def, substs) => (def.did, def.struct_variant(), substs),
|
||||
_ => bug!("prepare_union_metadata on a non-ADT")
|
||||
};
|
||||
|
||||
let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id);
|
||||
|
@ -421,7 +421,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
// Only "class" methods are generally understood by LLVM,
|
||||
// so avoid methods on other types (e.g. `<*mut T>::null`).
|
||||
match impl_self_ty.sty {
|
||||
ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) => {
|
||||
ty::TyAdt(..) => {
|
||||
Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
|
||||
}
|
||||
_ => None
|
||||
|
@ -44,9 +44,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
|
||||
ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
|
||||
ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyUnion(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
push_item_name(cx, def.did, qualified, output);
|
||||
push_type_params(cx, substs, output);
|
||||
},
|
||||
|
@ -19,7 +19,7 @@ use llvm::{ValueRef, get_param};
|
||||
use middle::lang_items::ExchangeFreeFnLangItem;
|
||||
use rustc::ty::subst::{Substs};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
|
||||
use adt;
|
||||
use base::*;
|
||||
use build::*;
|
||||
@ -338,7 +338,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
|
||||
return (C_undef(llty), C_undef(llty));
|
||||
}
|
||||
match t.sty {
|
||||
ty::TyStruct(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let ccx = bcx.ccx();
|
||||
// First get the size of all statically known fields.
|
||||
// Don't use type_of::sizing_type_of because that expects t to be sized,
|
||||
@ -487,16 +487,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
|
||||
DebugLoc::None);
|
||||
bcx
|
||||
}
|
||||
ty::TyStruct(def, _) | ty::TyEnum(def, _)
|
||||
if def.dtor_kind().is_present() && !skip_dtor => {
|
||||
trans_custom_dtor(bcx, t, v0, false)
|
||||
ty::TyAdt(def, ..) if def.dtor_kind().is_present() && !skip_dtor => {
|
||||
trans_custom_dtor(bcx, t, v0, def.is_union())
|
||||
}
|
||||
ty::TyUnion(def, _) => {
|
||||
if def.dtor_kind().is_present() && !skip_dtor {
|
||||
trans_custom_dtor(bcx, t, v0, true)
|
||||
} else {
|
||||
bcx
|
||||
}
|
||||
ty::TyAdt(def, ..) if def.is_union() => {
|
||||
bcx
|
||||
}
|
||||
_ => {
|
||||
if bcx.fcx.type_needs_drop(t) {
|
||||
@ -544,23 +539,6 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
|
||||
let mut cx = cx;
|
||||
match t.sty {
|
||||
ty::TyStruct(..) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
|
||||
for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
|
||||
let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr::from(discr), i);
|
||||
|
||||
let val = if type_is_sized(cx.tcx(), field_ty) {
|
||||
llfld_a
|
||||
} else {
|
||||
let scratch = alloc_ty(cx, field_ty, "__fat_ptr_iter");
|
||||
Store(cx, llfld_a, get_dataptr(cx, scratch));
|
||||
Store(cx, value.meta, get_meta(cx, scratch));
|
||||
scratch
|
||||
};
|
||||
cx = drop_ty(cx, val, field_ty, DebugLoc::None);
|
||||
}
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() {
|
||||
@ -587,63 +565,86 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
cx = drop_ty(cx, llfld_a, *arg, DebugLoc::None);
|
||||
}
|
||||
}
|
||||
ty::TyEnum(en, substs) => {
|
||||
let fcx = cx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
ty::TyAdt(adt, substs) => match adt.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
|
||||
for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
|
||||
let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr::from(discr), i);
|
||||
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let n_variants = en.variants.len();
|
||||
|
||||
// NB: we must hit the discriminant first so that structural
|
||||
// comparison know not to proceed when the discriminants differ.
|
||||
|
||||
match adt::trans_switch(cx, &repr, av, false) {
|
||||
(adt::BranchKind::Single, None) => {
|
||||
if n_variants != 0 {
|
||||
assert!(n_variants == 1);
|
||||
cx = iter_variant(cx, &repr, adt::MaybeSizedValue::sized(av),
|
||||
&en.variants[0], substs);
|
||||
}
|
||||
let val = if type_is_sized(cx.tcx(), field_ty) {
|
||||
llfld_a
|
||||
} else {
|
||||
let scratch = alloc_ty(cx, field_ty, "__fat_ptr_iter");
|
||||
Store(cx, llfld_a, get_dataptr(cx, scratch));
|
||||
Store(cx, value.meta, get_meta(cx, scratch));
|
||||
scratch
|
||||
};
|
||||
cx = drop_ty(cx, val, field_ty, DebugLoc::None);
|
||||
}
|
||||
(adt::BranchKind::Switch, Some(lldiscrim_a)) => {
|
||||
cx = drop_ty(cx, lldiscrim_a, cx.tcx().types.isize, DebugLoc::None);
|
||||
|
||||
// Create a fall-through basic block for the "else" case of
|
||||
// the switch instruction we're about to generate. Note that
|
||||
// we do **not** use an Unreachable instruction here, even
|
||||
// though most of the time this basic block will never be hit.
|
||||
//
|
||||
// When an enum is dropped it's contents are currently
|
||||
// overwritten to DTOR_DONE, which means the discriminant
|
||||
// could have changed value to something not within the actual
|
||||
// range of the discriminant. Currently this function is only
|
||||
// used for drop glue so in this case we just return quickly
|
||||
// from the outer function, and any other use case will only
|
||||
// call this for an already-valid enum in which case the `ret
|
||||
// void` will never be hit.
|
||||
let ret_void_cx = fcx.new_block("enum-iter-ret-void");
|
||||
RetVoid(ret_void_cx, DebugLoc::None);
|
||||
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb, n_variants);
|
||||
let next_cx = fcx.new_block("enum-iter-next");
|
||||
|
||||
for variant in &en.variants {
|
||||
let variant_cx = fcx.new_block(&format!("enum-iter-variant-{}",
|
||||
&variant.disr_val
|
||||
.to_string()));
|
||||
let case_val = adt::trans_case(cx, &repr, Disr::from(variant.disr_val));
|
||||
AddCase(llswitch, case_val, variant_cx.llbb);
|
||||
let variant_cx = iter_variant(variant_cx,
|
||||
&repr,
|
||||
value,
|
||||
variant,
|
||||
substs);
|
||||
Br(variant_cx, next_cx.llbb, DebugLoc::None);
|
||||
}
|
||||
cx = next_cx;
|
||||
}
|
||||
_ => ccx.sess().unimpl("value from adt::trans_switch in drop_structural_ty"),
|
||||
}
|
||||
}
|
||||
AdtKind::Union => {
|
||||
bug!("Union in `glue::drop_structural_ty`");
|
||||
}
|
||||
AdtKind::Enum => {
|
||||
let fcx = cx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let n_variants = adt.variants.len();
|
||||
|
||||
// NB: we must hit the discriminant first so that structural
|
||||
// comparison know not to proceed when the discriminants differ.
|
||||
|
||||
match adt::trans_switch(cx, &repr, av, false) {
|
||||
(adt::BranchKind::Single, None) => {
|
||||
if n_variants != 0 {
|
||||
assert!(n_variants == 1);
|
||||
cx = iter_variant(cx, &repr, adt::MaybeSizedValue::sized(av),
|
||||
&adt.variants[0], substs);
|
||||
}
|
||||
}
|
||||
(adt::BranchKind::Switch, Some(lldiscrim_a)) => {
|
||||
cx = drop_ty(cx, lldiscrim_a, cx.tcx().types.isize, DebugLoc::None);
|
||||
|
||||
// Create a fall-through basic block for the "else" case of
|
||||
// the switch instruction we're about to generate. Note that
|
||||
// we do **not** use an Unreachable instruction here, even
|
||||
// though most of the time this basic block will never be hit.
|
||||
//
|
||||
// When an enum is dropped it's contents are currently
|
||||
// overwritten to DTOR_DONE, which means the discriminant
|
||||
// could have changed value to something not within the actual
|
||||
// range of the discriminant. Currently this function is only
|
||||
// used for drop glue so in this case we just return quickly
|
||||
// from the outer function, and any other use case will only
|
||||
// call this for an already-valid enum in which case the `ret
|
||||
// void` will never be hit.
|
||||
let ret_void_cx = fcx.new_block("enum-iter-ret-void");
|
||||
RetVoid(ret_void_cx, DebugLoc::None);
|
||||
let llswitch = Switch(cx, lldiscrim_a, ret_void_cx.llbb, n_variants);
|
||||
let next_cx = fcx.new_block("enum-iter-next");
|
||||
|
||||
for variant in &adt.variants {
|
||||
let variant_cx = fcx.new_block(&format!("enum-iter-variant-{}",
|
||||
&variant.disr_val
|
||||
.to_string()));
|
||||
let case_val = adt::trans_case(cx, &repr, Disr::from(variant.disr_val));
|
||||
AddCase(llswitch, case_val, variant_cx.llbb);
|
||||
let variant_cx = iter_variant(variant_cx,
|
||||
&repr,
|
||||
value,
|
||||
variant,
|
||||
substs);
|
||||
Br(variant_cx, next_cx.llbb, DebugLoc::None);
|
||||
}
|
||||
cx = next_cx;
|
||||
}
|
||||
_ => ccx.sess().unimpl("value from adt::trans_switch in drop_structural_ty"),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
cx.sess().unimpl(&format!("type in drop_structural_ty: {}", t))
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
(_, "discriminant_value") => {
|
||||
let val_ty = substs.type_at(0);
|
||||
match val_ty.sty {
|
||||
ty::TyEnum(..) => {
|
||||
ty::TyAdt(adt, ..) if adt.is_enum() => {
|
||||
let repr = adt::represent_type(ccx, val_ty);
|
||||
adt::trans_get_discr(bcx, &repr, llargs[0],
|
||||
Some(llret_ty), true)
|
||||
|
@ -396,9 +396,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty::TyUint(ast::UintTy::U64) => output.push_str("u64"),
|
||||
ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
|
||||
ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
|
||||
ty::TyStruct(adt_def, substs) |
|
||||
ty::TyUnion(adt_def, substs) |
|
||||
ty::TyEnum(adt_def, substs) => {
|
||||
ty::TyAdt(adt_def, substs) => {
|
||||
push_item_name(tcx, adt_def.did, output);
|
||||
push_type_params(tcx, substs, &[], output);
|
||||
},
|
||||
|
@ -89,7 +89,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
||||
Type::nil(cx)
|
||||
}
|
||||
|
||||
ty::TyStruct(..) if t.is_simd() => {
|
||||
ty::TyAdt(..) if t.is_simd() => {
|
||||
let e = t.simd_type(cx.tcx());
|
||||
if !e.is_machine() {
|
||||
cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
|
||||
@ -102,8 +102,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
||||
Type::vector(&llet, n)
|
||||
}
|
||||
|
||||
ty::TyTuple(..) | ty::TyStruct(..) | ty::TyUnion(..) |
|
||||
ty::TyEnum(..) | ty::TyClosure(..) => {
|
||||
ty::TyTuple(..) | ty::TyAdt(..) | ty::TyClosure(..) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::sizing_type_of(cx, &repr, false)
|
||||
}
|
||||
@ -294,7 +293,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::type_of(cx, &repr)
|
||||
}
|
||||
ty::TyStruct(..) if t.is_simd() => {
|
||||
ty::TyAdt(..) if t.is_simd() => {
|
||||
let e = t.simd_type(cx.tcx());
|
||||
if !e.is_machine() {
|
||||
cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
|
||||
@ -306,9 +305,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
ensure_array_fits_in_address_space(cx, llet, n, t);
|
||||
Type::vector(&llet, n)
|
||||
}
|
||||
ty::TyStruct(def, ref substs) |
|
||||
ty::TyUnion(def, ref substs) |
|
||||
ty::TyEnum(def, ref substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
// Only create the named struct, but don't fill it in. We
|
||||
// fill it in *after* placing it into the type cache. This
|
||||
// avoids creating more than one copy of the enum when one
|
||||
@ -331,8 +328,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
|
||||
// If this was an enum or struct, fill in the type now.
|
||||
match t.sty {
|
||||
ty::TyEnum(..) | ty::TyStruct(..) | ty::TyUnion(..) | ty::TyClosure(..)
|
||||
if !t.is_simd() => {
|
||||
ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::finish_type_of(cx, &repr, &mut llty);
|
||||
}
|
||||
|
@ -617,7 +617,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if subpats.len() == variant.fields.len() ||
|
||||
subpats.len() < variant.fields.len() && ddpos.is_some() {
|
||||
let substs = match pat_ty.sty {
|
||||
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
|
||||
ty::TyAdt(_, substs) => substs,
|
||||
ref ty => bug!("unexpected pattern type {:?}", ty),
|
||||
};
|
||||
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
|
||||
@ -657,9 +657,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let (substs, kind_name) = match adt_ty.sty {
|
||||
ty::TyEnum(_, substs) => (substs, "variant"),
|
||||
ty::TyStruct(_, substs) => (substs, "struct"),
|
||||
ty::TyUnion(_, substs) => (substs, "union"),
|
||||
ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
|
||||
_ => span_bug!(span, "struct pattern is not an ADT")
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
match t.sty {
|
||||
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
|
||||
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())),
|
||||
ty::TyStruct(def, substs) => {
|
||||
ty::TyAdt(def, substs) if def.is_struct() => {
|
||||
// FIXME(arielb1): do some kind of normalization
|
||||
match def.struct_variant().fields.last() {
|
||||
None => None,
|
||||
|
@ -16,7 +16,7 @@ use middle::free_region::FreeRegionMap;
|
||||
use rustc::infer;
|
||||
use middle::region;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
|
||||
use rustc::traits::{self, Reveal};
|
||||
use util::nodemap::FnvHashSet;
|
||||
|
||||
@ -44,9 +44,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()>
|
||||
let dtor_self_type = ccx.tcx.lookup_item_type(drop_impl_did).ty;
|
||||
let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did);
|
||||
match dtor_self_type.sty {
|
||||
ty::TyEnum(adt_def, self_to_impl_substs) |
|
||||
ty::TyUnion(adt_def, self_to_impl_substs) |
|
||||
ty::TyStruct(adt_def, self_to_impl_substs) => {
|
||||
ty::TyAdt(adt_def, self_to_impl_substs) => {
|
||||
ensure_drop_params_and_item_params_correspond(ccx,
|
||||
drop_impl_did,
|
||||
dtor_self_type,
|
||||
@ -301,13 +299,13 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
|
||||
TypeContext::ADT { def_id, variant, field } => {
|
||||
let adt = tcx.lookup_adt_def(def_id);
|
||||
let variant_name = match adt.adt_kind() {
|
||||
ty::AdtKind::Enum => format!("enum {} variant {}",
|
||||
tcx.item_path_str(def_id),
|
||||
variant),
|
||||
ty::AdtKind::Struct => format!("struct {}",
|
||||
tcx.item_path_str(def_id)),
|
||||
ty::AdtKind::Union => format!("union {}",
|
||||
tcx.item_path_str(def_id)),
|
||||
AdtKind::Enum => format!("enum {} variant {}",
|
||||
tcx.item_path_str(def_id),
|
||||
variant),
|
||||
AdtKind::Struct => format!("struct {}",
|
||||
tcx.item_path_str(def_id)),
|
||||
AdtKind::Union => format!("union {}",
|
||||
tcx.item_path_str(def_id)),
|
||||
};
|
||||
span_note!(
|
||||
&mut err,
|
||||
@ -435,14 +433,14 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
|
||||
cx, context, ity, depth+1)
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) if def.is_phantom_data() => {
|
||||
ty::TyAdt(def, substs) if def.is_phantom_data() => {
|
||||
// PhantomData<T> - behaves identically to T
|
||||
let ity = substs.type_at(0);
|
||||
iterate_over_potentially_unsafe_regions_in_type(
|
||||
cx, context, ity, depth+1)
|
||||
}
|
||||
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let did = def.did;
|
||||
for variant in &def.variants {
|
||||
for field in variant.fields.iter() {
|
||||
@ -497,7 +495,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
|
||||
fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
def.is_dtorck(tcx)
|
||||
}
|
||||
ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
|
||||
|
@ -292,9 +292,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
self.assemble_inherent_candidates_from_object(self_ty, data.principal);
|
||||
self.assemble_inherent_impl_candidates_for_type(data.principal.def_id());
|
||||
}
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(def.did);
|
||||
}
|
||||
ty::TyBox(_) => {
|
||||
|
@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if let Some(expr) = rcvr_expr {
|
||||
for (ty, _) in self.autoderef(span, rcvr_ty) {
|
||||
match ty.sty {
|
||||
ty::TyStruct(def, substs) | ty::TyUnion(def, substs) => {
|
||||
ty::TyAdt(def, substs) if !def.is_enum() => {
|
||||
if let Some(field) = def.struct_variant().
|
||||
find_field_named(item_name) {
|
||||
let snippet = tcx.sess.codemap().span_to_snippet(expr.span);
|
||||
@ -359,9 +359,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
rcvr_expr: Option<&hir::Expr>) -> bool {
|
||||
fn is_local(ty: Ty) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyEnum(def, _) | ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
def.did.is_local()
|
||||
}
|
||||
ty::TyAdt(def, _) => def.did.is_local(),
|
||||
|
||||
ty::TyTrait(ref tr) => tr.principal.def_id().is_local(),
|
||||
|
||||
|
@ -1200,7 +1200,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) {
|
||||
let t = tcx.node_id_to_type(id);
|
||||
match t.sty {
|
||||
ty::TyStruct(def, substs) => {
|
||||
ty::TyAdt(def, substs) if def.is_struct() => {
|
||||
let fields = &def.struct_variant().fields;
|
||||
if fields.is_empty() {
|
||||
span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
|
||||
@ -2911,7 +2911,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let mut autoderef = self.autoderef(expr.span, expr_t);
|
||||
while let Some((base_t, autoderefs)) = autoderef.next() {
|
||||
match base_t.sty {
|
||||
ty::TyStruct(base_def, substs) | ty::TyUnion(base_def, substs) => {
|
||||
ty::TyAdt(base_def, substs) if !base_def.is_enum() => {
|
||||
debug!("struct named {:?}", base_t);
|
||||
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
|
||||
let field_ty = self.field_ty(expr.span, field, substs);
|
||||
@ -2957,7 +2957,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
field.node, actual)
|
||||
}, expr_t);
|
||||
match expr_t.sty {
|
||||
ty::TyStruct(def, _) | ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) if !def.is_enum() => {
|
||||
if let Some(suggested_field_name) =
|
||||
Self::suggest_field_name(def.struct_variant(), field, vec![]) {
|
||||
err.span_help(field.span,
|
||||
@ -3009,7 +3009,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let mut autoderef = self.autoderef(expr.span, expr_t);
|
||||
while let Some((base_t, autoderefs)) = autoderef.next() {
|
||||
let field = match base_t.sty {
|
||||
ty::TyStruct(base_def, substs) => {
|
||||
ty::TyAdt(base_def, substs) if base_def.is_struct() => {
|
||||
tuple_like = base_def.struct_variant().kind == ty::VariantKind::Tuple;
|
||||
if !tuple_like { continue }
|
||||
|
||||
@ -3074,14 +3074,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
kind_name: &str) {
|
||||
let mut err = self.type_error_struct_with_diag(
|
||||
field.name.span,
|
||||
|actual| if let ty::TyEnum(..) = ty.sty {
|
||||
struct_span_err!(self.tcx.sess, field.name.span, E0559,
|
||||
"{} `{}::{}` has no field named `{}`",
|
||||
kind_name, actual, variant.name.as_str(), field.name.node)
|
||||
} else {
|
||||
struct_span_err!(self.tcx.sess, field.name.span, E0560,
|
||||
"{} `{}` has no field named `{}`",
|
||||
kind_name, actual, field.name.node)
|
||||
|actual| match ty.sty {
|
||||
ty::TyAdt(adt, ..) if adt.is_enum() => {
|
||||
struct_span_err!(self.tcx.sess, field.name.span, E0559,
|
||||
"{} `{}::{}` has no field named `{}`",
|
||||
kind_name, actual, variant.name.as_str(), field.name.node)
|
||||
}
|
||||
_ => {
|
||||
struct_span_err!(self.tcx.sess, field.name.span, E0560,
|
||||
"{} `{}` has no field named `{}`",
|
||||
kind_name, actual, field.name.node)
|
||||
}
|
||||
},
|
||||
ty);
|
||||
// prevent all specified fields from being suggested
|
||||
@ -3102,9 +3105,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
check_completeness: bool) {
|
||||
let tcx = self.tcx;
|
||||
let (substs, kind_name) = match adt_ty.sty {
|
||||
ty::TyEnum(_, substs) => (substs, "variant"),
|
||||
ty::TyStruct(_, substs) => (substs, "struct"),
|
||||
ty::TyUnion(_, substs) => (substs, "union"),
|
||||
ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
|
||||
_ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
|
||||
};
|
||||
|
||||
@ -3199,8 +3200,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
Def::TyAlias(did) => {
|
||||
match self.tcx.opt_lookup_item_type(did).map(|scheme| &scheme.ty.sty) {
|
||||
Some(&ty::TyStruct(adt, _)) |
|
||||
Some(&ty::TyUnion(adt, _)) => Some((did, adt.struct_variant())),
|
||||
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => {
|
||||
Some((did, adt.struct_variant()))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -3246,7 +3248,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if let &Some(ref base_expr) = base_expr {
|
||||
self.check_expr_has_type(base_expr, struct_ty);
|
||||
match struct_ty.sty {
|
||||
ty::TyStruct(adt, substs) => {
|
||||
ty::TyAdt(adt, substs) if adt.is_struct() => {
|
||||
self.tables.borrow_mut().fru_field_types.insert(
|
||||
expr.id,
|
||||
adt.struct_variant().fields.iter().map(|f| {
|
||||
|
@ -22,9 +22,9 @@ use rustc::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc::traits::{self, Reveal};
|
||||
use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId};
|
||||
use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
|
||||
use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
|
||||
use rustc::ty::{Ty, TyBool, TyChar, TyError};
|
||||
use rustc::ty::{TyParam, TyRawPtr};
|
||||
use rustc::ty::{TyRef, TyStruct, TyUnion, TyTrait, TyNever, TyTuple};
|
||||
use rustc::ty::{TyRef, TyAdt, TyTrait, TyNever, TyTuple};
|
||||
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
|
||||
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
|
||||
use rustc::ty::{TyProjection, TyAnon};
|
||||
@ -69,9 +69,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
// Returns the def ID of the base type, if there is one.
|
||||
fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
|
||||
match ty.sty {
|
||||
TyEnum(def, _) |
|
||||
TyStruct(def, _) |
|
||||
TyUnion(def, _) => {
|
||||
TyAdt(def, _) => {
|
||||
Some(def.did)
|
||||
}
|
||||
|
||||
@ -241,9 +239,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
|
||||
let self_type = tcx.lookup_item_type(impl_did);
|
||||
match self_type.ty.sty {
|
||||
ty::TyEnum(type_def, _) |
|
||||
ty::TyStruct(type_def, _) |
|
||||
ty::TyUnion(type_def, _) => {
|
||||
ty::TyAdt(type_def, _) => {
|
||||
type_def.set_destructor(method_def_id.def_id());
|
||||
}
|
||||
_ => {
|
||||
@ -426,7 +422,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
|
||||
check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
|
||||
}
|
||||
|
||||
(&ty::TyStruct(def_a, substs_a), &ty::TyStruct(def_b, substs_b)) => {
|
||||
(&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b))
|
||||
if def_a.is_struct() && def_b.is_struct() => {
|
||||
if def_a != def_b {
|
||||
let source_path = tcx.item_path_str(def_a.did);
|
||||
let target_path = tcx.item_path_str(def_b.did);
|
||||
|
@ -75,9 +75,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
self.tcx.map.node_to_string(item.id));
|
||||
let self_ty = self.tcx.lookup_item_type(def_id).ty;
|
||||
match self_ty.sty {
|
||||
ty::TyEnum(def, _) |
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyUnion(def, _) => {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.check_def_id(item, def.did);
|
||||
}
|
||||
ty::TyTrait(ref data) => {
|
||||
@ -294,14 +292,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
{
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let opt_self_def_id = match self_ty.sty {
|
||||
ty::TyStruct(self_def, _) |
|
||||
ty::TyUnion(self_def, _) |
|
||||
ty::TyEnum(self_def, _) =>
|
||||
Some(self_def.did),
|
||||
ty::TyBox(..) =>
|
||||
self.tcx.lang_items.owned_box(),
|
||||
_ =>
|
||||
None
|
||||
ty::TyAdt(self_def, _) => Some(self_def.did),
|
||||
ty::TyBox(..) => self.tcx.lang_items.owned_box(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let msg = match opt_self_def_id {
|
||||
|
@ -67,7 +67,7 @@ use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
|
||||
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
|
||||
use rustc::ty::{VariantKind};
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rscope::*;
|
||||
@ -1062,7 +1062,7 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let ctor_id = if !def.is_struct() { Some(ccx.tcx.map.local_def_id(def.id())) } else { None };
|
||||
let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
|
||||
ConstInt::Infer(0), def)];
|
||||
let adt = ccx.tcx.intern_adt_def(did, ty::AdtKind::Struct, variants);
|
||||
let adt = ccx.tcx.intern_adt_def(did, AdtKind::Struct, variants);
|
||||
if let Some(ctor_id) = ctor_id {
|
||||
// Make adt definition available through constructor id as well.
|
||||
ccx.tcx.insert_adt_def(ctor_id, adt);
|
||||
@ -1077,7 +1077,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
{
|
||||
let did = ccx.tcx.map.local_def_id(it.id);
|
||||
let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
|
||||
ccx.tcx.intern_adt_def(did, ty::AdtKind::Union, variants)
|
||||
ccx.tcx.intern_adt_def(did, AdtKind::Union, variants)
|
||||
}
|
||||
|
||||
fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
|
||||
@ -1157,7 +1157,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
let did = tcx.map.local_def_id(v.node.data.id());
|
||||
convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
|
||||
}).collect();
|
||||
tcx.intern_adt_def(tcx.map.local_def_id(it.id), ty::AdtKind::Enum, variants)
|
||||
tcx.intern_adt_def(tcx.map.local_def_id(it.id), AdtKind::Enum, variants)
|
||||
}
|
||||
|
||||
/// Ensures that the super-predicates of the trait with def-id
|
||||
@ -1581,17 +1581,17 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
ItemEnum(ref ei, ref generics) => {
|
||||
let def = convert_enum_def(ccx, item, ei);
|
||||
let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
|
||||
ccx.tcx.mk_enum(def, substs)
|
||||
ccx.tcx.mk_adt(def, substs)
|
||||
}
|
||||
ItemStruct(ref si, ref generics) => {
|
||||
let def = convert_struct_def(ccx, item, si);
|
||||
let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
|
||||
ccx.tcx.mk_struct(def, substs)
|
||||
ccx.tcx.mk_adt(def, substs)
|
||||
}
|
||||
ItemUnion(ref un, ref generics) => {
|
||||
let def = convert_union_def(ccx, item, un);
|
||||
let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
|
||||
ccx.tcx.mk_union(def, substs)
|
||||
ccx.tcx.mk_adt(def, substs)
|
||||
}
|
||||
ItemDefaultImpl(..) |
|
||||
ItemTrait(..) |
|
||||
|
@ -344,9 +344,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyEnum(def, substs) |
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyUnion(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let item_type = self.tcx().lookup_item_type(def.did);
|
||||
|
||||
// This edge is actually implied by the call to
|
||||
|
@ -238,7 +238,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let t = tcx.lookup_item_type(did);
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
match t.ty.sty {
|
||||
ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => {
|
||||
ty::TyAdt(edef, _) if edef.is_enum() && !tcx.sess.cstore.is_typedef(did) => {
|
||||
return clean::EnumItem(clean::Enum {
|
||||
generics: (t.generics, &predicates).clean(cx),
|
||||
variants_stripped: false,
|
||||
|
@ -41,7 +41,7 @@ use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
|
||||
use rustc::hir::fold::Folder;
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty;
|
||||
use rustc::ty::{self, AdtKind};
|
||||
use rustc::middle::stability;
|
||||
use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
|
||||
@ -1811,14 +1811,12 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
|
||||
decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
|
||||
abi: fty.abi,
|
||||
}),
|
||||
ty::TyStruct(def, substs) |
|
||||
ty::TyUnion(def, substs) |
|
||||
ty::TyEnum(def, substs) => {
|
||||
ty::TyAdt(def, substs) => {
|
||||
let did = def.did;
|
||||
let kind = match self.sty {
|
||||
ty::TyStruct(..) => TypeStruct,
|
||||
ty::TyUnion(..) => TypeUnion,
|
||||
_ => TypeEnum,
|
||||
let kind = match def.adt_kind() {
|
||||
AdtKind::Struct => TypeStruct,
|
||||
AdtKind::Union => TypeUnion,
|
||||
AdtKind::Enum => TypeEnum,
|
||||
};
|
||||
inline::record_extern_fqn(cx, did, kind);
|
||||
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
|
||||
|
@ -75,13 +75,13 @@ pub mod testtypes {
|
||||
fn foo_method(&self) -> usize;
|
||||
}
|
||||
|
||||
// Tests TyStruct
|
||||
// Tests struct
|
||||
pub struct FooStruct {
|
||||
pub pub_foo_field: usize,
|
||||
foo_field: usize
|
||||
}
|
||||
|
||||
// Tests TyEnum
|
||||
// Tests enum
|
||||
pub enum FooEnum {
|
||||
VarA(usize),
|
||||
VarB(usize, usize)
|
||||
|
Loading…
Reference in New Issue
Block a user