diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ef14fa9a12248..ad89e1dca8697 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3278,7 +3278,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, variant: &'tcx ty::VariantDef, ast_fields: &'gcx [hir::Field], - check_completeness: bool) { + check_completeness: bool) -> bool { let tcx = self.tcx; let adt_ty_hint = @@ -3380,6 +3380,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { truncated_fields_error)) .emit(); } + error_happened } fn check_struct_fields_on_error(&self, @@ -3478,24 +3479,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields, - base_expr.is_none()); + let error_happened = self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, + variant, fields, base_expr.is_none()); if let &Some(ref base_expr) = base_expr { - self.check_expr_has_type_or_error(base_expr, struct_ty); - match struct_ty.sty { - ty::TyAdt(adt, substs) if adt.is_struct() => { - let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| { - self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) - }).collect(); - - self.tables - .borrow_mut() - .fru_field_types_mut() - .insert(expr.hir_id, fru_field_types); - } - _ => { - span_err!(self.tcx.sess, base_expr.span, E0436, - "functional record update syntax requires a struct"); + // If check_expr_struct_fields hit an error, do not attempt to populate + // the fields with the base_expr. This could cause us to hit errors later + // when certain fields are assumed to exist that in fact do not. + if !error_happened { + self.check_expr_has_type_or_error(base_expr, struct_ty); + match struct_ty.sty { + ty::TyAdt(adt, substs) if adt.is_struct() => { + let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| { + self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) + }).collect(); + + self.tables + .borrow_mut() + .fru_field_types_mut() + .insert(expr.hir_id, fru_field_types); + } + _ => { + span_err!(self.tcx.sess, base_expr.span, E0436, + "functional record update syntax requires a struct"); + } } } } diff --git a/src/test/ui/issue-50618.rs b/src/test/ui/issue-50618.rs new file mode 100644 index 0000000000000..ed427c293df47 --- /dev/null +++ b/src/test/ui/issue-50618.rs @@ -0,0 +1,29 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Point { + pub x: u64, + pub y: u64, +} + +const TEMPLATE: Point = Point { + x: 0, + y: 0 +}; + +fn main() { + let _ = || { + Point { + nonexistent: 0, + //~^ ERROR struct `Point` has no field named `nonexistent` + ..TEMPLATE + } + }; +} diff --git a/src/test/ui/issue-50618.stderr b/src/test/ui/issue-50618.stderr new file mode 100644 index 0000000000000..07cc5a1318aa4 --- /dev/null +++ b/src/test/ui/issue-50618.stderr @@ -0,0 +1,11 @@ +error[E0560]: struct `Point` has no field named `nonexistent` + --> $DIR/issue-50618.rs:24:13 + | +LL | nonexistent: 0, + | ^^^^^^^^^^^ `Point` does not have this field + | + = note: available fields are: `x`, `y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0560`.