ty::TyFnPtr(_) |
ty::TyTrait(..) |
ty::TyStruct(..) |
+ ty::TyUnion(..) |
ty::TyClosure(..) |
ty::TyNever |
ty::TyTuple(..) |
}
ty::TyEnum(def, _) |
- ty::TyStruct(def, _) => {
+ ty::TyStruct(def, _) |
+ ty::TyUnion(def, _) => {
def.did.is_local()
}
ty::TyParam(..) => Some(14),
ty::TyAnon(..) => Some(15),
ty::TyNever => Some(16),
+ ty::TyUnion(..) => Some(17),
ty::TyInfer(..) | ty::TyError => None
}
}
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
}
- ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+ ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
+ ty::TyEnum(def, substs) => {
let sized_crit = def.sized_constraint(self.tcx());
// (*) binder moved here
Where(ty::Binder(match sized_crit.sty {
Where(ty::Binder(tys.to_vec()))
}
- ty::TyStruct(..) | ty::TyEnum(..) |
+ ty::TyStruct(..) | ty::TyUnion(..) | ty::TyEnum(..) |
ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
// Fallback to whatever user-defined impls exist in this case.
None
substs.types().collect()
}
- ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+ ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
def.all_fields()
.map(|f| f.ty(self.tcx(), substs))
.collect()
|ty| tc_ty(tcx, *ty, cache))
}
- ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+ ty::TyStruct(def, substs) | ty::TyUnion(def, substs) |
+ ty::TyEnum(def, substs) => {
let mut res =
TypeContents::union(&def.variants, |v| {
TypeContents::union(&v.fields, |f| {
pub fn print_debug_stats(self) {
sty_debug_print!(
self,
- TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
- TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
+ TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyTrait,
+ TyStruct, TyUnion, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
println!("Substs interner: #{}", self.interners.substs.borrow().len());
println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
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(),
ty::TyStruct(def, _) => {
Some(StructSimplifiedType(def.did))
}
+ ty::TyUnion(..) => {
+ unimplemented_unions!();
+ }
ty::TyRef(_, mt) => {
// since we introduce auto-refs during method lookup, we
// just treat &T and T as equivalent from the point of
}
}
- &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => {
+ &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) | &ty::TyUnion(_, substs) => {
self.add_substs(substs);
}
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::TyTrait(ref data) => Some(data.principal.def_id()),
non_zero: Some(def.did) == tcx.lang_items.non_zero()
}
}
+ ty::TyUnion(..) => {
+ unimplemented_unions!();
+ }
ty::TyEnum(def, substs) => {
let hint = *tcx.lookup_repr_hints(def.did).get(0)
.unwrap_or(&attr::ReprAny);
const IS_PHANTOM_DATA = 1 << 3,
const IS_SIMD = 1 << 4,
const IS_FUNDAMENTAL = 1 << 5,
+ const IS_UNION = 1 << 7,
}
}
}
}
- TyEnum(adt, substs) | TyStruct(adt, substs) => {
+ TyEnum(adt, substs) | TyStruct(adt, substs) | TyUnion(adt, substs) => {
// recursive case
let adt = tcx.lookup_adt_def_master(adt.did);
adt.calculate_sized_constraint_inner(tcx, stack);
ty::TyNever | // ...
ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType
+ ty::TyUnion(..) | // OutlivesNominalType
ty::TyBox(..) | // OutlivesNominalType (ish)
ty::TyAnon(..) | // OutlivesNominalType (ish)
ty::TyStr | // OutlivesScalar (ish)
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)),
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),
/// 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>),
+
/// `Box<T>`; this is nominally a struct in the documentation, but is
/// special-cased internally. For example, it is possible to implicitly
/// move the contents of a box out of that box, and methods of any type
}
TyEnum(_, substs) |
TyStruct(_, substs) |
+ TyUnion(_, substs) |
TyAnon(_, substs) => {
substs.regions().collect()
}
TyUint(u) => self.hash(u),
TyFloat(f) => self.hash(f),
TyStruct(d, _) |
+ TyUnion(d, _) |
TyEnum(d, _) => self.def_id(d.did),
TyArray(_, n) => self.hash(n),
TyRawPtr(m) |
}) => Some(true),
TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
- TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) |
+ TyClosure(..) | TyEnum(..) | TyStruct(..) | TyUnion(..) | TyAnon(..) |
TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
}.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
TyStr | TyTrait(..) | TySlice(_) => Some(false),
- TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
+ TyEnum(..) | TyStruct(..) | TyUnion(..) | TyProjection(..) | TyParam(..) |
TyInfer(..) | TyAnon(..) | TyError => None
}.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
}
ty::TyEnum(_, ref substs) |
ty::TyStruct(_, ref substs) |
+ ty::TyUnion(_, ref substs) |
ty::TyAnon(_, ref substs) => {
stack.extend(substs.types().rev());
}
}
ty::TyEnum(def, substs) |
- ty::TyStruct(def, substs) => {
+ ty::TyStruct(def, substs) |
+ ty::TyUnion(def, substs) => {
// WfNominalType
let obligations = self.nominal_obligations(def.did, substs);
self.out.extend(obligations);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
use hir::def_id::DefId;
use ty::subst::{self, Subst, Substs};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
-use ty::{TyBool, TyChar, TyStruct, TyEnum};
+use ty::{TyBool, TyChar, TyStruct, TyUnion, TyEnum};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::TyClosure;
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) => {
+ TyEnum(def, substs) | TyStruct(def, substs) | TyUnion(def, substs) => {
ty::tls::with(|tcx| {
if def.did.is_local() &&
!tcx.tcache.borrow().contains_key(&def.did) {
FfiSafe,
FfiUnsafe(&'static str),
FfiBadStruct(DefId, &'static str),
- FfiBadEnum(DefId, &'static str)
+ FfiBadUnion(DefId, &'static str),
+ FfiBadEnum(DefId, &'static str),
}
/// Check if this enum can be safely exported based on the
let r = self.check_type_for_ffi(cache, field_ty);
match r {
FfiSafe => {}
- FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+ 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.
let r = self.check_type_for_ffi(cache, arg);
match r {
FfiSafe => {}
- FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+ FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { return r; }
FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
}
}
&format!("found non-foreign-function-safe member in \
struct marked #[repr(C)]: {}", s));
}
+ FfiResult::FfiBadUnion(_, s) => {
+ // FIXME: This diagnostic is difficult to read, and doesn't
+ // point at the relevant field.
+ self.cx.span_lint(IMPROPER_CTYPES, sp,
+ &format!("found non-foreign-function-safe member in \
+ union marked #[repr(C)]: {}", s));
+ }
FfiResult::FfiBadEnum(_, s) => {
// FIXME: This diagnostic is difficult to read, and doesn't
// point at the relevant variant.
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);
/* nothing to do */
}
ty::TyStruct(ref adt_def, substs) |
+ ty::TyUnion(ref adt_def, substs) |
ty::TyEnum(ref adt_def, substs) => {
for field in adt_def.all_fields() {
let field_type = monomorphize::apply_param_substs(scx,
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) => {
push_item_name(cx, def.did, qualified, output);
push_type_params(cx, substs, output);
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) => {
push_item_name(tcx, adt_def.did, output);
push_type_params(tcx, substs, &[], output);
Type::nil(cx)
}
- ty::TyTuple(..) | ty::TyEnum(..) | ty::TyClosure(..) => {
- let repr = adt::represent_type(cx, t);
- adt::sizing_type_of(cx, &repr, false)
+ ty::TyStruct(..) if t.is_simd() => {
+ let e = t.simd_type(cx.tcx());
+ if !e.is_machine() {
+ cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
+ a non-machine element type `{}`",
+ t, e))
+ }
+ let llet = type_of(cx, e);
+ let n = t.simd_size(cx.tcx()) as u64;
+ ensure_array_fits_in_address_space(cx, llet, n, t);
+ Type::vector(&llet, n)
}
- ty::TyStruct(..) => {
- if t.is_simd() {
- let e = t.simd_type(cx.tcx());
- if !e.is_machine() {
- cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
- a non-machine element type `{}`",
- t, e))
- }
- let llet = type_of(cx, e);
- let n = t.simd_size(cx.tcx()) as u64;
- ensure_array_fits_in_address_space(cx, llet, n, t);
- Type::vector(&llet, n)
- } else {
- let repr = adt::represent_type(cx, t);
- adt::sizing_type_of(cx, &repr, false)
- }
+ ty::TyTuple(..) | ty::TyStruct(..) | ty::TyUnion(..) |
+ ty::TyEnum(..) | ty::TyClosure(..) => {
+ let repr = adt::represent_type(cx, t);
+ adt::sizing_type_of(cx, &repr, false)
}
ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
ty::TyUint(t) => Type::uint_from_ty(cx, t),
ty::TyFloat(t) => Type::float_from_ty(cx, t),
ty::TyNever => Type::nil(cx),
- ty::TyEnum(def, ref 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
- // of the enum's variants refers to the enum itself.
- let repr = adt::represent_type(cx, t);
- let name = llvm_type_name(cx, def.did, substs);
- adt::incomplete_type_of(cx, &repr, &name[..])
- }
ty::TyClosure(..) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
adt::type_of(cx, &repr)
}
- ty::TyStruct(def, ref substs) => {
- if t.is_simd() {
- let e = t.simd_type(cx.tcx());
- if !e.is_machine() {
- cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
- a non-machine element type `{}`",
- t, e))
- }
- let llet = in_memory_type_of(cx, e);
- let n = t.simd_size(cx.tcx()) as u64;
- ensure_array_fits_in_address_space(cx, llet, n, t);
- Type::vector(&llet, n)
- } else {
- // Only create the named struct, but don't fill it in. We fill it
- // in *after* placing it into the type cache. This prevents
- // infinite recursion with recursive struct types.
- let repr = adt::represent_type(cx, t);
- let name = llvm_type_name(cx, def.did, substs);
- adt::incomplete_type_of(cx, &repr, &name[..])
+ ty::TyStruct(..) if t.is_simd() => {
+ let e = t.simd_type(cx.tcx());
+ if !e.is_machine() {
+ cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
+ a non-machine element type `{}`",
+ t, e))
}
+ let llet = in_memory_type_of(cx, e);
+ let n = t.simd_size(cx.tcx()) as u64;
+ 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) => {
+ // 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
+ // of the enum's variants refers to the enum itself.
+ let repr = adt::represent_type(cx, t);
+ let name = llvm_type_name(cx, def.did, substs);
+ adt::incomplete_type_of(cx, &repr, &name[..])
}
ty::TyInfer(..) |
cx, context, ity, depth+1)
}
- ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
+ ty::TyStruct(def, substs) | ty::TyUnion(def, substs) | ty::TyEnum(def, substs) => {
let did = def.did;
for variant in &def.variants {
for field in variant.fields.iter() {
use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
use rustc::ty::{TyParam, TyRawPtr};
-use rustc::ty::{TyRef, TyStruct, TyTrait, TyNever, TyTuple};
+use rustc::ty::{TyRef, TyStruct, TyUnion, 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};
fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
match ty.sty {
TyEnum(def, _) |
- TyStruct(def, _) => {
+ TyStruct(def, _) |
+ TyUnion(def, _) => {
Some(def.did)
}
}
ty::TyEnum(def, substs) |
- ty::TyStruct(def, substs) => {
+ ty::TyStruct(def, substs) |
+ ty::TyUnion(def, substs) => {
let item_type = self.tcx().lookup_item_type(def.did);
// This edge is actually implied by the call to
decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
abi: fty.abi,
}),
+ ty::TyUnion(..) => unimplemented_unions!(),
ty::TyStruct(def, substs) |
ty::TyEnum(def, substs) => {
let did = def.did;