use rustc_target::spec::abi::Abi;
use rustc::infer::opaque_types::OpaqueTypeDecl;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc::middle::region;
use rustc::mir::interpret::{ConstValue, GlobalId};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{
- self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility,
+ self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind, Visibility,
ToPolyTraitRef, ToPredicate, RegionKind, UserType
};
use rustc::ty::adjustment::{
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
-
+ check_transparent(tcx, span, def_id);
check_packed(tcx, span, def_id);
}
return;
}
+ if adt.is_enum() {
+ if !tcx.features().transparent_enums {
+ emit_feature_err(&tcx.sess.parse_sess,
+ sym::transparent_enums,
+ sp,
+ GateIssue::Language,
+ "transparent enums are unstable");
+ }
+ if adt.variants.len() != 1 {
+ let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
+ tcx.hir().span_if_local(variant.def_id).unwrap()
+ }).collect();
+ let mut err = struct_span_err!(tcx.sess, sp, E0731,
+ "transparent enum needs exactly one variant, but has {}",
+ adt.variants.len());
+ if !variant_spans.is_empty() {
+ err.span_note(variant_spans, &format!("the following variants exist on `{}`",
+ tcx.def_path_str(def_id)));
+ }
+ err.emit();
+ if adt.variants.is_empty() {
+ // Don't bother checking the fields. No variants (and thus no fields) exist.
+ return;
+ }
+ }
+ }
+
+ if adt.is_union() && !tcx.features().transparent_unions {
+ emit_feature_err(&tcx.sess.parse_sess,
+ sym::transparent_unions,
+ sp,
+ GateIssue::Language,
+ "transparent unions are unstable");
+ }
+
// For each field, figure out if it's known to be a ZST and align(1)
- let field_infos = adt.non_enum_variant().fields.iter().map(|field| {
+ let field_infos = adt.all_fields().map(|field| {
let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
let param_env = tcx.param_env(field.did);
let layout = tcx.layout_of(param_env.and(ty));
let non_zst_count = non_zst_fields.clone().count();
if non_zst_count != 1 {
let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect();
- struct_span_err!(tcx.sess, sp, E0690,
- "transparent struct needs exactly one non-zero-sized field, but has {}",
- non_zst_count)
- .span_note(field_spans, "non-zero-sized field")
- .emit();
+
+ let mut err = struct_span_err!(tcx.sess, sp, E0690,
+ "{}transparent {} needs exactly one non-zero-sized field, but has {}",
+ if adt.is_enum() { "the variant of a " } else { "" },
+ adt.descr(),
+ non_zst_count);
+ if !field_spans.is_empty() {
+ err.span_note(field_spans,
+ &format!("the following non-zero-sized fields exist on `{}`:",
+ tcx.def_path_str(def_id)));
+ }
+ err.emit();
}
for (span, zst, align1) in field_infos {
if zst && !align1 {
span_err!(tcx.sess, span, E0691,
- "zero-sized field in transparent struct has alignment larger than 1");
+ "zero-sized field in transparent {} has alignment larger than 1",
+ adt.descr());
}
}
}
}
check_representable(tcx, sp, def_id);
+ check_transparent(tcx, sp, def_id);
}
fn report_unexpected_variant_res<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
})
}
- fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>)
- -> Option<ty::Region<'tcx>> {
+ fn re_infer(
+ &self,
+ def: Option<&ty::GenericParamDef>,
+ span: Span,
+ ) -> Option<ty::Region<'tcx>> {
let v = match def {
Some(def) => infer::EarlyBoundRegion(span, def.name),
None => infer::MiscVariable(span)
Some(self.next_region_var(v))
}
- fn ty_infer(&self, span: Span) -> Ty<'tcx> {
- self.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span,
- })
+ fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
+ if let Some(param) = param {
+ if let UnpackedKind::Type(ty) = self.var_for_def(span, param).unpack() {
+ return ty;
+ }
+ unreachable!()
+ } else {
+ self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ })
+ }
}
- fn ty_infer_for_def(&self,
- ty_param_def: &ty::GenericParamDef,
- span: Span) -> Ty<'tcx> {
- if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def).unpack() {
- return ty;
+ fn ct_infer(
+ &self,
+ ty: Ty<'tcx>,
+ param: Option<&ty::GenericParamDef>,
+ span: Span,
+ ) -> &'tcx Const<'tcx> {
+ if let Some(param) = param {
+ if let UnpackedKind::Const(ct) = self.var_for_def(span, param).unpack() {
+ return ct;
+ }
+ unreachable!()
+ } else {
+ self.next_const_var(ty, ConstVariableOrigin {
+ kind: ConstVariableOriginKind::ConstInference,
+ span,
+ })
}
- unreachable!()
}
fn projected_ty_from_poly_trait_ref(&self,
if !infer_args_for_err.contains(&index) {
// Check whether the user has provided generic arguments.
if let Some(ref data) = segments[index].args {
- return (Some(data), segments[index].infer_types);
+ return (Some(data), segments[index].infer_args);
}
}
- return (None, segments[index].infer_types);
+ return (None, segments[index].infer_args);
}
(None, true)
}
},
// Provide substitutions for parameters for which arguments are inferred.
- |substs, param, infer_types| {
+ |substs, param, infer_args| {
match param.kind {
GenericParamDefKind::Lifetime => {
- self.re_infer(span, Some(param)).unwrap().into()
+ self.re_infer(Some(param), span).unwrap().into()
}
GenericParamDefKind::Type { has_default, .. } => {
- if !infer_types && has_default {
+ if !infer_args && has_default {
// If we have a default, then we it doesn't matter that we're not
// inferring the type arguments: we provide the default where any
// is missing.