@@ -206,8 +206,10 @@ TypeVariableSubstitution* TypeInference::unify(const IR::Node* errorPosition,
206
206
return tvs;
207
207
}
208
208
209
- const IR::IndexedVector<IR::StructField>*
210
- TypeInference::canonicalizeFields (const IR::Type_StructLike* type) {
209
+ const IR::Type*
210
+ TypeInference::canonicalizeFields (
211
+ const IR::Type_StructLike* type,
212
+ std::function<const IR::Type*(const IR::IndexedVector<IR::StructField>*)> constructor) {
211
213
bool changes = false ;
212
214
auto fields = new IR::IndexedVector<IR::StructField>();
213
215
for (auto field : type->fields ) {
@@ -221,9 +223,9 @@ TypeInference::canonicalizeFields(const IR::Type_StructLike* type) {
221
223
fields->push_back (newField);
222
224
}
223
225
if (changes)
224
- return fields;
226
+ return constructor ( fields) ;
225
227
else
226
- return & type-> fields ;
228
+ return type;
227
229
}
228
230
229
231
const IR::ParameterList* TypeInference::canonicalizeParameters (const IR::ParameterList* params) {
@@ -492,39 +494,22 @@ const IR::Type* TypeInference::canonicalize(const IR::Type* type) {
492
494
if (changes)
493
495
resultType = new IR::Type_Method (mt->getSourceInfo (), tps, res, pl);
494
496
return resultType;
495
- } else if (type->is <IR::Type_Header>()) {
496
- auto hdr = type->to <IR::Type_Header>();
497
- auto fields = canonicalizeFields (hdr);
498
- if (fields == nullptr )
499
- return nullptr ;
500
- const IR::Type* canon;
501
- if (fields != &hdr->fields )
502
- canon = new IR::Type_Header (hdr->srcInfo , hdr->name , hdr->annotations , *fields);
503
- else
504
- canon = hdr;
505
- return canon;
506
- } else if (type->is <IR::Type_Struct>()) {
507
- auto str = type->to <IR::Type_Struct>();
508
- auto fields = canonicalizeFields (str);
509
- if (fields == nullptr )
510
- return nullptr ;
511
- const IR::Type* canon;
512
- if (fields != &str->fields )
513
- canon = new IR::Type_Struct (str->srcInfo , str->name , str->annotations , *fields);
514
- else
515
- canon = str;
516
- return canon;
517
- } else if (type->is <IR::Type_HeaderUnion>()) {
518
- auto str = type->to <IR::Type_HeaderUnion>();
519
- auto fields = canonicalizeFields (str);
520
- if (fields == nullptr )
521
- return nullptr ;
522
- const IR::Type* canon;
523
- if (fields != &str->fields )
524
- canon = new IR::Type_HeaderUnion (str->srcInfo , str->name , str->annotations , *fields);
525
- else
526
- canon = str;
527
- return canon;
497
+ } else if (auto hdr = type->to <IR::Type_Header>()) {
498
+ return canonicalizeFields (hdr, [hdr](const IR::IndexedVector<IR::StructField>* fields) {
499
+ return new IR::Type_Header (hdr->srcInfo , hdr->name , hdr->annotations , *fields);
500
+ });
501
+ } else if (auto str = type->to <IR::Type_Struct>()) {
502
+ return canonicalizeFields (str, [str](const IR::IndexedVector<IR::StructField>* fields) {
503
+ return new IR::Type_Struct (str->srcInfo , str->name , str->annotations , *fields);
504
+ });
505
+ } else if (auto hu = type->to <IR::Type_HeaderUnion>()) {
506
+ return canonicalizeFields (hu, [hu](const IR::IndexedVector<IR::StructField>* fields) {
507
+ return new IR::Type_HeaderUnion (hu->srcInfo , hu->name , hu->annotations , *fields);
508
+ });
509
+ } else if (auto su = type->to <IR::Type_UnknownStruct>()) {
510
+ return canonicalizeFields (su, [su](const IR::IndexedVector<IR::StructField>* fields) {
511
+ return new IR::Type_UnknownStruct (su->srcInfo , su->name , su->annotations , *fields);
512
+ });
528
513
} else if (type->is <IR::Type_Specialized>()) {
529
514
auto st = type->to <IR::Type_Specialized>();
530
515
auto baseCanon = canonicalize (st->baseType );
@@ -752,6 +737,20 @@ TypeInference::assignment(const IR::Node* errorPosition, const IR::Type* destTyp
752
737
setType (sourceExpression, destType);
753
738
setCompileTimeConstant (sourceExpression);
754
739
}
740
+ if (initType->is <IR::Type_UnknownStruct>()) {
741
+ if (auto ts = destType->to <IR::Type_StructLike>()) {
742
+ auto si = sourceExpression->to <IR::StructInitializerExpression>();
743
+ CHECK_NULL (si);
744
+ bool cst = isCompileTimeConstant (sourceExpression);
745
+ auto type = new IR::Type_Name (ts->name );
746
+ sourceExpression = new IR::StructInitializerExpression (
747
+ type, type, si->components );
748
+ setType (sourceExpression, destType);
749
+ if (cst)
750
+ setCompileTimeConstant (sourceExpression);
751
+ }
752
+ }
753
+
755
754
return sourceExpression;
756
755
}
757
756
@@ -1522,6 +1521,53 @@ const IR::Node* TypeInference::postorder(IR::Operation_Relation* expression) {
1522
1521
}
1523
1522
defined = true ;
1524
1523
} else {
1524
+ auto ls = ltype->to <IR::Type_UnknownStruct>();
1525
+ auto rs = rtype->to <IR::Type_UnknownStruct>();
1526
+ if (ls != nullptr || rs != nullptr ) {
1527
+ if (ls != nullptr && rs != nullptr ) {
1528
+ typeError (" %1%: cannot compare initializers with unknown types" , expression);
1529
+ return expression;
1530
+ }
1531
+
1532
+ bool lcst = isCompileTimeConstant (expression->left );
1533
+ bool rcst = isCompileTimeConstant (expression->right );
1534
+
1535
+ auto tvs = unify (expression, ltype, rtype);
1536
+ if (tvs == nullptr )
1537
+ // error already signalled
1538
+ return expression;
1539
+ if (!tvs->isIdentity ()) {
1540
+ ConstantTypeSubstitution cts (tvs, refMap, typeMap, this );
1541
+ expression->left = cts.convert (expression->left );
1542
+ expression->right = cts.convert (expression->right );
1543
+ }
1544
+
1545
+ if (ls != nullptr ) {
1546
+ auto l = expression->left ->to <IR::StructInitializerExpression>();
1547
+ CHECK_NULL (l); // struct initializers are the only expressions that can
1548
+ // have StructUnknown types
1549
+ BUG_CHECK (rtype->is <IR::Type_StructLike>(), " %1%: expected a struct" , rtype);
1550
+ auto type = new IR::Type_Name (rtype->to <IR::Type_StructLike>()->name );
1551
+ expression->left = new IR::StructInitializerExpression (
1552
+ expression->left ->srcInfo , type, type, l->components );
1553
+ setType (expression->left , rtype);
1554
+ if (lcst)
1555
+ setCompileTimeConstant (expression->left );
1556
+ } else {
1557
+ auto r = expression->right ->to <IR::StructInitializerExpression>();
1558
+ CHECK_NULL (r); // struct initializers are the only expressions that can
1559
+ // have StructUnknown types
1560
+ BUG_CHECK (ltype->is <IR::Type_StructLike>(), " %1%: expected a struct" , ltype);
1561
+ auto type = new IR::Type_Name (ltype->to <IR::Type_StructLike>()->name );
1562
+ expression->right = new IR::StructInitializerExpression (
1563
+ expression->right ->srcInfo , type, type, r->components );
1564
+ setType (expression->right , rtype);
1565
+ if (rcst)
1566
+ setCompileTimeConstant (expression->right );
1567
+ }
1568
+ defined = true ;
1569
+ }
1570
+
1525
1571
// comparison between structs and list expressions is allowed only
1526
1572
// if the expression with tuple type is a list expression
1527
1573
if ((ltype->is <IR::Type_StructLike>() &&
@@ -1769,23 +1815,32 @@ const IR::Node* TypeInference::postorder(IR::StructInitializerExpression* expres
1769
1815
components->push_back (new IR::StructField (c->name , type));
1770
1816
}
1771
1817
1772
- const IR::Type* structType;
1773
- if (expression->isHeader )
1774
- structType = new IR::Type_Header (
1775
- expression->srcInfo , expression->name , *components);
1776
- else
1777
- structType = new IR::Type_Struct (
1778
- expression->srcInfo , expression->name , *components);
1779
- auto type = canonicalize (structType);
1780
- if (type == nullptr )
1781
- return expression;
1782
- setType (getOriginal (), type);
1783
- setType (expression, type);
1818
+ const IR::Type* structType = new IR::Type_UnknownStruct (
1819
+ expression->srcInfo , " unknown struct" , *components);
1820
+ structType = canonicalize (structType);
1821
+
1822
+ const IR::Expression* result = expression;
1823
+ if (expression->typeName != nullptr ) {
1824
+ // We know the exact type of the initializer
1825
+ auto desired = getTypeType (expression->typeName );
1826
+ if (desired == nullptr )
1827
+ return expression;
1828
+ auto tvs = unify (expression, desired, structType);
1829
+ if (tvs == nullptr )
1830
+ return expression;
1831
+ if (!tvs->isIdentity ()) {
1832
+ ConstantTypeSubstitution cts (tvs, refMap, typeMap, this );
1833
+ result = cts.convert (expression);
1834
+ }
1835
+ structType = desired;
1836
+ }
1837
+ setType (getOriginal (), structType);
1838
+ setType (expression, structType);
1784
1839
if (constant) {
1785
1840
setCompileTimeConstant (expression);
1786
1841
setCompileTimeConstant (getOriginal<IR::Expression>());
1787
1842
}
1788
- return expression ;
1843
+ return result ;
1789
1844
}
1790
1845
1791
1846
const IR::Node* TypeInference::postorder (IR::ArrayIndex* expression) {
0 commit comments