@@ -43,32 +43,97 @@ 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
+
58
+ if (maybe_item)
59
+ {
60
+ tl::optional<HirId> definition_id
61
+ = mappings.lookup_node_to_hir (ref_node_id);
62
+ rust_assert (definition_id.has_value ());
63
+ HirId def_id = definition_id.value ();
64
+
65
+ tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
66
+ // If the path refrerences an item, it must be constants or structs.
67
+ if (hir_item.has_value ())
68
+ {
69
+ HIR::Item *item = hir_item.value ();
70
+
71
+ if (item->get_item_kind () != HIR::Item::ItemKind::Constant
72
+ && item->get_item_kind () != HIR::Item::ItemKind::Struct)
73
+ {
74
+ HIR::Item *item = hir_item.value ();
75
+ std::string item_kind
76
+ = HIR::Item::item_kind_string (item->get_item_kind ());
77
+
78
+ std::string path_buf;
79
+ for (size_t i = 0 ; i < pattern.get_segments ().size (); i++)
80
+ {
81
+ HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
82
+ path_buf += seg.as_string ();
83
+ if (i != pattern.get_segments ().size () - 1 )
84
+ path_buf += " ::" ;
85
+ }
86
+
87
+ rich_location rich_locus (
88
+ line_table, pattern.get_final_segment ().get_locus ());
89
+ rich_locus.add_fixit_replace (
90
+ " not a unit struct, unit variant or constatnt" );
91
+ rust_error_at (rich_locus, ErrorCode::E0532 ,
92
+ " expected unit struct, unit variant or constant, "
93
+ " found %s %<%s%>" ,
94
+ item_kind.c_str (), path_buf.c_str ());
95
+ return ;
96
+ }
97
+ }
98
+ }
53
99
54
- rust_assert (infered->get_kind () == TyTy::TypeKind::ADT);
55
- TyTy::ADTType *adt = static_cast <TyTy::ADTType *> (infered);
100
+ // If the path is of type ADT, it must be a unit struct or unit variants.
101
+ if (pattern_ty->get_kind () == TyTy::TypeKind::ADT)
102
+ {
103
+ TyTy::ADTType *adt = static_cast <TyTy::ADTType *> (pattern_ty);
104
+ rust_assert (adt->get_variants ().size () > 0 );
56
105
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);
106
+ TyTy::VariantDef *variant = adt->get_variants ().at (0 );
107
+ if (adt->is_enum ())
108
+ {
109
+ HirId variant_id = UNKNOWN_HIRID;
110
+ bool ok = context->lookup_variant_definition (
111
+ pattern.get_mappings ().get_hirid (), &variant_id);
112
+ rust_assert (ok);
62
113
63
- TyTy::VariantDef *variant = nullptr ;
64
- ok = adt->lookup_variant_by_id (variant_id, &variant);
114
+ ok = adt->lookup_variant_by_id (variant_id, &variant);
115
+ rust_assert (ok);
116
+ }
65
117
66
- TyTy::VariantDef::VariantType vty = variant->get_variant_type ();
118
+ if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
119
+ {
120
+ std::string variant_type = TyTy::VariantDef::variant_type_string (
121
+ variant->get_variant_type ());
122
+
123
+ rich_location rich_locus (line_table,
124
+ pattern.get_final_segment ().get_locus ());
125
+ rich_locus.add_fixit_replace (
126
+ " not a unit struct, unit variant or constatnt" );
127
+ rust_error_at (rich_locus, ErrorCode::E0532 ,
128
+ " expected unit struct, unit variant or constant, "
129
+ " found %s variant %<%s::%s%>" ,
130
+ variant_type.c_str (), adt->get_name ().c_str (),
131
+ variant->get_identifier ().c_str ());
132
+ return ;
133
+ }
67
134
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" );
135
+ infered = pattern_ty;
136
+ }
72
137
}
73
138
74
139
void
@@ -100,8 +165,8 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
100
165
rust_assert (ok);
101
166
}
102
167
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
168
+ // error[E0532]: expected tuple struct or tuple variant, found struct
169
+ // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
105
170
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
106
171
{
107
172
std::string variant_type
@@ -203,8 +268,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
203
268
rust_assert (ok);
204
269
}
205
270
206
- // error[E0532]: expected tuple struct or tuple variant, found struct variant
207
- // `Foo::D`
271
+ // error[E0532]: expected tuple struct or tuple variant, found struct
272
+ // variant `Foo::D`
208
273
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
209
274
{
210
275
std::string variant_type
0 commit comments