check_simd(tcx, span, def_id);
}
- // if struct is packed and not aligned, check fields for alignment.
- // Checks for combining packed and align attrs on single struct are done elsewhere.
- if tcx.adt_def(def_id).repr.packed() && tcx.adt_def(def_id).repr.align == 0 {
- check_packed(tcx, span, def_id);
- }
+ check_packed(tcx, span, def_id);
}
fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
+
+ check_packed(tcx, span, def_id);
}
pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) {
}
fn check_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
- if check_packed_inner(tcx, def_id, &mut Vec::new()) {
- struct_span_err!(tcx.sess, sp, E0588,
- "packed struct cannot transitively contain a `[repr(align)]` struct").emit();
+ if tcx.adt_def(def_id).repr.packed() {
+ if tcx.adt_def(def_id).repr.align > 0 {
+ struct_span_err!(tcx.sess, sp, E0587,
+ "type has conflicting packed and align representation hints").emit();
+ }
+ else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
+ struct_span_err!(tcx.sess, sp, E0588,
+ "packed type cannot transitively contain a `[repr(align)]` type").emit();
+ }
}
}
return false;
}
match t.sty {
- ty::TyAdt(def, substs) if def.is_struct() => {
+ ty::TyAdt(def, substs) if def.is_struct() || def.is_union() => {
if tcx.adt_def(def.did).repr.align > 0 {
return true;
}
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Option<ty::Region<'tcx>> {
let v = match def {
- Some(def) => infer::EarlyBoundRegion(span, def.name, def.issue_32330),
+ Some(def) => infer::EarlyBoundRegion(span, def.name),
None => infer::MiscVariable(span)
};
Some(self.next_region_var(v))
format!("did you mean `{}`?", suggested_field_name));
} else {
err.span_label(field.span, "unknown field");
+ let struct_variant_def = def.struct_variant();
+ let field_names = self.available_field_names(struct_variant_def);
+ if !field_names.is_empty() {
+ err.note(&format!("available fields are: {}",
+ self.name_series_display(field_names)));
+ }
};
}
ty::TyRawPtr(..) => {
// Return an hint about the closest match in field names
fn suggest_field_name(variant: &'tcx ty::VariantDef,
field: &Spanned<ast::Name>,
- skip : Vec<InternedString>)
+ skip: Vec<InternedString>)
-> Option<Symbol> {
let name = field.node.as_str();
let names = variant.fields.iter().filter_map(|field| {
}
});
- // only find fits with at least one matching letter
- find_best_match_for_name(names, &name, Some(name.len()))
+ find_best_match_for_name(names, &name, None)
+ }
+
+ fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
+ let mut available = Vec::new();
+ for field in variant.fields.iter() {
+ let (_, def_scope) = self.tcx.adjust(field.name, variant.did, self.body_id);
+ if field.vis.is_accessible_from(def_scope, self.tcx) {
+ available.push(field.name);
+ }
+ }
+ available
+ }
+
+ fn name_series_display(&self, names: Vec<ast::Name>) -> String {
+ // dynamic limit, to never omit just one field
+ let limit = if names.len() == 6 { 6 } else { 5 };
+ let mut display = names.iter().take(limit)
+ .map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
+ if names.len() > limit {
+ display = format!("{} ... and {} others", display, names.len() - limit);
+ }
+ display
}
// Check tuple index expressions
format!("field does not exist - did you mean `{}`?", field_name));
} else {
match ty.sty {
- ty::TyAdt(adt, ..) if adt.is_enum() => {
- err.span_label(field.name.span, format!("`{}::{}` does not have this field",
- ty, variant.name));
- }
- _ => {
- err.span_label(field.name.span, format!("`{}` does not have this field", ty));
+ ty::TyAdt(adt, ..) => {
+ if adt.is_enum() {
+ err.span_label(field.name.span,
+ format!("`{}::{}` does not have this field",
+ ty, variant.name));
+ } else {
+ err.span_label(field.name.span,
+ format!("`{}` does not have this field", ty));
+ }
+ let available_field_names = self.available_field_names(variant);
+ if !available_field_names.is_empty() {
+ err.note(&format!("available fields are: {}",
+ self.name_series_display(available_field_names)));
+ }
}
+ _ => bug!("non-ADT passed to report_unknown_field")
}
};
err.emit();
Ok(def) => def,
Err(error) => {
let def = match error {
- method::MethodError::PrivateMatch(def) => def,
+ method::MethodError::PrivateMatch(def, _) => def,
_ => Def::Err,
};
if item_name != keywords::Invalid.name() {
local: &'gcx hir::Local,
init: &'gcx hir::Expr) -> Ty<'tcx>
{
- let ref_bindings = local.pat.contains_ref_binding();
+ // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed
+ // for #42640.
+ let ref_bindings = local.pat.contains_explicit_ref_binding();
let local_ty = self.local_ty(init.span, local.id);
if let Some(m) = ref_bindings {