- // Resolve the path.
- let def = lookup_full_def(tcx, path.span, id);
- let struct_id = match def {
- def::DefVariant(enum_id, variant_id, true) => {
- if let &Some(ref base_expr) = base_expr {
- span_err!(tcx.sess, base_expr.span, E0436,
- "functional record update syntax requires a struct");
- fcx.write_error(base_expr.id);
- }
- check_struct_enum_variant(fcx, id, expr.span, enum_id,
- variant_id, &fields[..]);
- enum_id
- }
- def::DefTrait(def_id) => {
- span_err!(tcx.sess, path.span, E0159,
- "use of trait `{}` as a struct constructor",
- pprust::path_to_string(path));
- check_struct_fields_on_error(fcx,
- id,
- &fields[..],
- base_expr);
- def_id
- },
- def => {
- // Verify that this was actually a struct.
- let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
- match typ.ty.sty {
- ty::TyStruct(struct_did, _) => {
- check_struct_constructor(fcx,
- id,
- expr.span,
- struct_did,
- &fields[..],
- base_expr.as_ref().map(|e| &**e));
- }
- _ => {
- span_err!(tcx.sess, path.span, E0071,
- "`{}` does not name a structure",
- pprust::path_to_string(path));
- check_struct_fields_on_error(fcx,
- id,
- &fields[..],
- base_expr);
- }
- }
-
- def.def_id()
- }
- };
-
- // Turn the path into a type and verify that that type unifies with
- // the resulting structure type. This is needed to handle type
- // parameters correctly.
- let actual_structure_type = fcx.expr_ty(&*expr);
- if !actual_structure_type.references_error() {
- let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
- match fcx.mk_subty(false,
- infer::Misc(path.span),
- actual_structure_type,
- type_and_substs.ty) {
- Ok(()) => {}
- Err(type_error) => {
- span_err!(fcx.tcx().sess, path.span, E0235,
- "structure constructor specifies a \
- structure of type `{}`, but this \
- structure has type `{}`: {}",
- fcx.infcx()
- .ty_to_string(type_and_substs.ty),
- fcx.infcx()
- .ty_to_string(
- actual_structure_type),
- type_error);
- tcx.note_and_explain_type_err(&type_error, path.span);
- }
- }
- }
-