Skip to content

Commit a397b60

Browse files
committed
Resolve partially resolved paths in struct patterns/expressions
Treat Def::Err correctly in struct patterns Make instantiate_path and instantiate_type a bit closer to each other
1 parent 49ea3d4 commit a397b60

15 files changed

+156
-206
lines changed

src/librustc/hir/pat_util.rs

-15
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
6767
}
6868
}
6969

70-
pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
71-
match pat.node {
72-
PatKind::TupleStruct(..) |
73-
PatKind::Path(..) |
74-
PatKind::Struct(..) => {
75-
match dm.get(&pat.id).map(|d| d.full_def()) {
76-
Some(Def::Variant(..)) | Some(Def::Struct(..)) |
77-
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => true,
78-
_ => false
79-
}
80-
}
81-
_ => false
82-
}
83-
}
84-
8570
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
8671
match pat.node {
8772
PatKind::Path(..) | PatKind::QPath(..) => {

src/librustc_typeck/check/_match.rs

+38-43
Original file line numberDiff line numberDiff line change
@@ -489,39 +489,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
489489
}
490490

491491
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
492-
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
493-
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
494-
etc: bool, expected: Ty<'tcx>) {
495-
let tcx = self.tcx;
496-
497-
let def = tcx.expect_def(pat.id);
498-
let variant = match self.def_struct_variant(def, path.span) {
499-
Some((_, variant)) => variant,
500-
None => {
501-
let name = pprust::path_to_string(path);
502-
span_err!(tcx.sess, pat.span, E0163,
503-
"`{}` does not name a struct or a struct variant", name);
504-
self.write_error(pat.id);
505-
506-
for field in fields {
507-
self.check_pat(&field.node.pat, tcx.types.err);
508-
}
509-
return;
492+
fn check_pat_struct(&self,
493+
pat: &'gcx hir::Pat,
494+
path: &hir::Path,
495+
fields: &'gcx [Spanned<hir::FieldPat>],
496+
etc: bool,
497+
expected: Ty<'tcx>)
498+
{
499+
// Resolve the path and check the definition for errors.
500+
let def = self.finish_resolving_struct_path(path, pat.id, pat.span);
501+
let variant = if let Some(variant) = self.check_struct_path(def, path, pat.span) {
502+
variant
503+
} else {
504+
self.write_error(pat.id);
505+
for field in fields {
506+
self.check_pat(&field.node.pat, self.tcx.types.err);
510507
}
508+
return;
511509
};
512510

513-
let pat_ty = self.instantiate_type(def.def_id(), path);
514-
let item_substs = match pat_ty.sty {
511+
// Type check the path.
512+
let pat_ty = self.instantiate_type_path(def.def_id(), path, pat.id);
513+
self.demand_eqtype(pat.span, expected, pat_ty);
514+
515+
// Type check subpatterns.
516+
let substs = match pat_ty.sty {
515517
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
516518
_ => span_bug!(pat.span, "struct variant is not an ADT")
517519
};
518-
self.demand_eqtype(pat.span, expected, pat_ty);
519-
self.check_struct_pat_fields(pat.span, fields, variant, &item_substs, etc);
520-
521-
self.write_ty(pat.id, pat_ty);
522-
self.write_substs(pat.id, ty::ItemSubsts {
523-
substs: item_substs
524-
});
520+
self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
525521
}
526522

527523
fn check_pat_path(&self,
@@ -539,8 +535,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
539535
};
540536

541537
// Resolve the path and check the definition for errors.
542-
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
543-
opt_self_ty, path, pat.span, pat.id);
538+
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
539+
pat.id, pat.span);
544540
match def {
545541
Def::Err => {
546542
self.set_tainted_by_errors();
@@ -565,8 +561,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
565561
// Type check the path.
566562
let scheme = tcx.lookup_item_type(def.def_id());
567563
let predicates = tcx.lookup_predicates(def.def_id());
568-
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
569-
let pat_ty = self.node_ty(pat.id);
564+
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
565+
opt_ty, def, pat.span, pat.id);
570566
self.demand_suptype(pat.span, expected, pat_ty);
571567
}
572568

@@ -597,9 +593,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
597593
};
598594

599595
// Resolve the path and check the definition for errors.
600-
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id),
601-
None, path, pat.span, pat.id);
602-
match def {
596+
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
597+
let variant = match def {
603598
Def::Err => {
604599
self.set_tainted_by_errors();
605600
on_error();
@@ -609,10 +604,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
609604
report_unexpected_def(false);
610605
return;
611606
}
612-
Def::Variant(..) | Def::Struct(..) => {} // OK
607+
Def::Variant(..) | Def::Struct(..) => {
608+
tcx.expect_variant_def(def)
609+
}
613610
_ => bug!("unexpected pattern definition {:?}", def)
614-
}
615-
let variant = tcx.expect_variant_def(def);
611+
};
616612
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
617613
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
618614
// is allowed for backward compatibility.
@@ -633,20 +629,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
633629
scheme
634630
};
635631
let predicates = tcx.lookup_predicates(def.def_id());
636-
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id);
637-
let pat_ty = self.node_ty(pat.id);
632+
let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
633+
opt_ty, def, pat.span, pat.id);
638634
self.demand_eqtype(pat.span, expected, pat_ty);
639635

640636
// Type check subpatterns.
641637
if subpats.len() == variant.fields.len() ||
642638
subpats.len() < variant.fields.len() && ddpos.is_some() {
643-
let expected_substs = match pat_ty.sty {
644-
ty::TyEnum(_, expected_substs) => expected_substs,
645-
ty::TyStruct(_, expected_substs) => expected_substs,
639+
let substs = match pat_ty.sty {
640+
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
646641
ref ty => bug!("unexpected pattern type {:?}", ty),
647642
};
648643
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
649-
let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs);
644+
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
650645
self.check_pat(&subpat, field_ty);
651646
}
652647
} else {

0 commit comments

Comments
 (0)