@@ -43,32 +43,100 @@ TypeCheckPattern::Resolve (HIR::Pattern *pattern, TyTy::BaseType *parent)
43
43
void
44
44
TypeCheckPattern::visit (HIR::PathInExpression &pattern)
45
45
{
46
- infered = TypeCheckExpr::Resolve (&pattern);
47
-
48
- /*
49
- * We are compiling a PathInExpression, which can't be a Struct or Tuple
50
- * pattern. We should check that the declaration we are referencing IS NOT a
51
- * struct pattern or tuple with values.
52
- */
46
+ // Pattern must be enum variants, sturcts, constants, or associated constansts
47
+ TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (&pattern);
48
+
49
+ NodeId ref_node_id = UNKNOWN_NODEID;
50
+ bool maybe_item = false ;
51
+ maybe_item
52
+ |= resolver->lookup_resolved_name (pattern.get_mappings ().get_nodeid (),
53
+ &ref_node_id);
54
+ maybe_item
55
+ |= resolver->lookup_resolved_type (pattern.get_mappings ().get_nodeid (),
56
+ &ref_node_id);
57
+ bool path_is_const_item = false ;
58
+
59
+ if (maybe_item)
60
+ {
61
+ tl::optional<HirId> definition_id
62
+ = mappings.lookup_node_to_hir (ref_node_id);
63
+ rust_assert (definition_id.has_value ());
64
+ HirId def_id = definition_id.value ();
65
+
66
+ tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
67
+ // If the path refrerences an item, it must be constants or structs.
68
+ if (hir_item.has_value ())
69
+ {
70
+ HIR::Item *item = hir_item.value ();
71
+ if (item->get_item_kind () == HIR::Item::ItemKind::Constant)
72
+ {
73
+ path_is_const_item = true ;
74
+ }
75
+ else if (item->get_item_kind () != HIR::Item::ItemKind::Struct)
76
+ {
77
+ HIR::Item *item = hir_item.value ();
78
+ std::string item_kind
79
+ = HIR::Item::item_kind_string (item->get_item_kind ());
80
+
81
+ std::string path_buf;
82
+ for (size_t i = 0 ; i < pattern.get_segments ().size (); i++)
83
+ {
84
+ HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
85
+ path_buf += seg.as_string ();
86
+ if (i != pattern.get_segments ().size () - 1 )
87
+ path_buf += " ::" ;
88
+ }
89
+
90
+ rich_location rich_locus (
91
+ line_table, pattern.get_final_segment ().get_locus ());
92
+ rich_locus.add_fixit_replace (
93
+ " not a unit struct, unit variant or constatnt" );
94
+ rust_error_at (rich_locus, ErrorCode::E0532 ,
95
+ " expected unit struct, unit variant or constant, "
96
+ " found %s %<%s%>" ,
97
+ item_kind.c_str (), path_buf.c_str ());
98
+ return ;
99
+ }
100
+ }
101
+ }
53
102
54
- rust_assert (infered->get_kind () == TyTy::TypeKind::ADT);
55
- TyTy::ADTType *adt = static_cast <TyTy::ADTType *> (infered);
103
+ // If the path is a constructor, it must be a unit struct or unit variants.
104
+ if (!path_is_const_item && pattern_ty->get_kind () == TyTy::TypeKind::ADT)
105
+ {
106
+ TyTy::ADTType *adt = static_cast <TyTy::ADTType *> (pattern_ty);
107
+ rust_assert (adt->get_variants ().size () > 0 );
56
108
57
- HirId variant_id = UNKNOWN_HIRID;
58
- bool ok
59
- = context->lookup_variant_definition (pattern.get_mappings ().get_hirid (),
60
- &variant_id);
61
- rust_assert (ok);
109
+ TyTy::VariantDef *variant = adt->get_variants ().at (0 );
110
+ if (adt->is_enum ())
111
+ {
112
+ HirId variant_id = UNKNOWN_HIRID;
113
+ bool ok = context->lookup_variant_definition (
114
+ pattern.get_mappings ().get_hirid (), &variant_id);
115
+ rust_assert (ok);
62
116
63
- TyTy::VariantDef *variant = nullptr ;
64
- ok = adt->lookup_variant_by_id (variant_id, &variant);
117
+ ok = adt->lookup_variant_by_id (variant_id, &variant);
118
+ rust_assert (ok);
119
+ }
65
120
66
- TyTy::VariantDef::VariantType vty = variant->get_variant_type ();
121
+ if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
122
+ {
123
+ std::string variant_type = TyTy::VariantDef::variant_type_string (
124
+ variant->get_variant_type ());
125
+
126
+ rich_location rich_locus (line_table,
127
+ pattern.get_final_segment ().get_locus ());
128
+ rich_locus.add_fixit_replace (
129
+ " not a unit struct, unit variant or constatnt" );
130
+ rust_error_at (rich_locus, ErrorCode::E0532 ,
131
+ " expected unit struct, unit variant or constant, "
132
+ " found %s variant %<%s::%s%>" ,
133
+ variant_type.c_str (), adt->get_name ().c_str (),
134
+ variant->get_identifier ().c_str ());
135
+ return ;
136
+ }
67
137
68
- if (vty != TyTy::VariantDef::VariantType::NUM)
69
- rust_error_at (
70
- pattern.get_final_segment ().get_locus (), ErrorCode::E0532 ,
71
- " expected unit struct, unit variant or constant, found tuple variant" );
138
+ infered = pattern_ty;
139
+ }
72
140
}
73
141
74
142
void
@@ -100,8 +168,8 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
100
168
rust_assert (ok);
101
169
}
102
170
103
- // error[E0532]: expected tuple struct or tuple variant, found struct variant
104
- // `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
171
+ // error[E0532]: expected tuple struct or tuple variant, found struct
172
+ // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
105
173
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
106
174
{
107
175
std::string variant_type
@@ -203,8 +271,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
203
271
rust_assert (ok);
204
272
}
205
273
206
- // error[E0532]: expected tuple struct or tuple variant, found struct variant
207
- // `Foo::D`
274
+ // error[E0532]: expected tuple struct or tuple variant, found struct
275
+ // variant `Foo::D`
208
276
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
209
277
{
210
278
std::string variant_type
0 commit comments