use rustc_data_structures::indexed_vec::Idx;
use rustc_target::spec::abi::Abi;
use rustc::infer::opaque_types::OpaqueTypeDecl;
-use rustc::infer::type_variable::{TypeVariableOrigin};
+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::{
/// hard constraint exists, creates a fresh type variable.
fn coercion_target_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'tcx> {
self.only_has_type(fcx)
- .unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span)))
+ .unwrap_or_else(|| {
+ fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span,
+ })
+ })
}
}
/// eventually).
param_env: ty::ParamEnv<'tcx>,
- // Number of errors that had been reported when we started
- // checking this function. On exit, if we find that *more* errors
- // have been reported, we will skip regionck and other work that
- // expects the types within the function to be consistent.
+ /// Number of errors that had been reported when we started
+ /// checking this function. On exit, if we find that *more* errors
+ /// have been reported, we will skip regionck and other work that
+ /// expects the types within the function to be consistent.
err_count_on_creation: usize,
ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>,
match ty_opt {
None => {
// infer the variable's type
- let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
+ let var_ty = self.fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ });
self.fcx.locals.borrow_mut().insert(nid, LocalTy {
decl_ty: var_ty,
revealed_ty: var_ty
// Don't descend into the bodies of nested closures
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
_: hir::BodyId, _: Span, _: hir::HirId) { }
-
- fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
- match s {
- // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
- // a `NodeId` w/out a type, as it is only used for getting the name of the original
- // pattern for diagnostics where only an `hir::Arg` is present.
- hir::ArgSource::AsyncFn(..) => {},
- _ => intravisit::walk_argument_source(self, s),
- }
- }
}
/// When `check_fn` is invoked on a generator (i.e., a body that
let span = body.value.span;
if body.is_generator && can_be_generator.is_some() {
- let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
+ let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ });
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
fcx.yield_ty = Some(yield_ty);
}
// This ensures that all nested generators appear before the entry of this generator.
// resolve_generator_interiors relies on this property.
let gen_ty = if can_be_generator.is_some() && body.is_generator {
- let interior = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span));
+ let interior = fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span,
+ });
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior));
Some(GeneratorTypes {
yield_ty: fcx.yield_ty.unwrap(),
let mut actual_return_ty = coercion.complete(&fcx);
if actual_return_ty.is_never() {
actual_return_ty = fcx.next_diverging_ty_var(
- TypeVariableOrigin::DivergingFn(span));
+ TypeVariableOrigin {
+ kind: TypeVariableOriginKind::DivergingFn,
+ span,
+ },
+ );
}
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
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::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 some lookup succeeds, write callee into table and extract index/element
// type from the method signature.
// If some lookup succeeded, install method in table
- let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
+ let input_ty = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::AutoDeref,
+ span: base_expr.span,
+ });
let method = self.try_overloaded_place_op(
expr.span, self_ty, &[input_ty], needs, PlaceOp::Index);
assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id),
"expression with never type wound up being adjusted");
let adj_ty = self.next_diverging_ty_var(
- TypeVariableOrigin::AdjustmentType(expr.span));
+ TypeVariableOrigin {
+ kind: TypeVariableOriginKind::AdjustmentType,
+ span: expr.span,
+ },
+ );
self.apply_adjustments(expr, vec![Adjustment {
kind: Adjust::NeverToAny,
target: adj_ty
});
let element_ty = if !args.is_empty() {
- let coerce_to = uty.unwrap_or_else(
- || self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)));
+ let coerce_to = uty.unwrap_or_else(|| {
+ self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span: expr.span,
+ })
+ });
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
assert_eq!(self.diverges.get(), Diverges::Maybe);
for e in args {
}
coerce.complete(self)
} else {
- self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))
+ self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span: expr.span,
+ })
};
tcx.mk_array(element_ty, args.len() as u64)
}
(uty, uty)
}
None => {
- let ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
+ let ty = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: element.span,
+ });
let element_ty = self.check_expr_has_type_or_error(&element, ty);
(element_ty, ty)
}
Err(ErrorReported) => return (tcx.types.err, res),
};
let path_segs = match res {
- Res::Local(_) | Res::Upvar(..) => Vec::new(),
+ Res::Local(_) => vec![],
Res::Def(kind, def_id) =>
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
_ => bug!("instantiate_value_path on {:?}", res),
}
}));
- match res {
- Res::Local(hid) | Res::Upvar(hid, ..) => {
- let ty = self.local_ty(span, hid).decl_ty;
- let ty = self.normalize_associated_types_in(span, &ty);
- self.write_ty(hir_id, ty);
- return (ty, res);
- }
- _ => {}
+ if let Res::Local(hid) = res {
+ let ty = self.local_ty(span, hid).decl_ty;
+ let ty = self.normalize_associated_types_in(span, &ty);
+ self.write_ty(hir_id, ty);
+ return (ty, res);
}
if generics_has_err {
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.