Skip to content

Commit 5db4e97

Browse files
authored
Dyno: simplify array type creation (#27177)
Closes Cray/chapel-private#7334, which required resolving: ```Chapel use ReplicatedDist; var Space = {1..10}; const ReplicatedSpace = Space dmapped new replicatedDist(); var RA: [ReplicatedSpace] int; ``` To be merged after #27171. Clean diff: https://github.com/chapel-lang/chapel/pull/27177/files/47946ac16e576a8d92863f8cffb4efebccb2ff96..132e5f2c0931cfbd96003239e9499ab435abbbd3 The `dom` and `eltType` fields are [required as part of the DSI](https://chapel-lang.org/docs/technotes/dsi.html#id11). In practice, they are relied on in various method on the `_array` builtin record: https://github.com/chapel-lang/chapel/blob/47946ac16e576a8d92863f8cffb4efebccb2ff96/modules/internal/ChapelArray.chpl#L832-L834 https://github.com/chapel-lang/chapel/blob/47946ac16e576a8d92863f8cffb4efebccb2ff96/modules/internal/ChapelArray.chpl#L819-L820 So, instead of special casing various well-known array classes to extract their `dom` and `eltType` fields, simply adjust the InitResolver code to search for these required fields until they are found. While there, it seemed easy enough to add errors for when these things are missing. Reviewed by @arifthpe -- thanks! ## Testing - [x] dyno tests - [x] `test/release/examples/primers/replicated.chpl` resolves - [x] paratest
2 parents 2fbaa92 + 2536a02 commit 5db4e97

File tree

1 file changed

+49
-52
lines changed

1 file changed

+49
-52
lines changed

frontend/lib/resolution/InitResolver.cpp

+49-52
Original file line numberDiff line numberDiff line change
@@ -350,11 +350,47 @@ static auto helpExtractFields(ResolutionContext* rc, const BasicClassType* bct,
350350
return ret;
351351
}
352352

353+
// same as above, but consider parent classes
354+
template <typename FoundEach, typename ...FieldNames, size_t ... Is>
355+
static auto helpExtractFieldsHierarchy(ResolutionContext* rc, const BasicClassType* bct, FoundEach& foundEach, std::index_sequence<Is...>, FieldNames... names) {
356+
typename ImplCreateNTuple<Is...>::type ret;
357+
358+
while (bct) {
359+
auto& rf = fieldsForTypeDecl(rc, bct,
360+
DefaultsPolicy::IGNORE_DEFAULTS);
361+
for (int i = 0; i < rf.numFields(); i++) {
362+
((rf.fieldName(i) == names ?
363+
(std::get<Is>(ret) = rf.fieldType(i),
364+
std::get<Is>(foundEach) += 1,
365+
0) : 0), ...);
366+
}
367+
368+
bct = bct->parentClassType();
369+
370+
// if we've found all of them, stop
371+
if ((std::get<Is>(foundEach) && ...)) {
372+
break;
373+
}
374+
}
375+
376+
return ret;
377+
}
378+
353379
template <typename ...FieldNames>
354380
static auto extractFields(ResolutionContext* rc, const BasicClassType* bct, FieldNames... names) {
355381
return helpExtractFields(rc, bct, std::make_index_sequence<sizeof...(FieldNames)>(), names...);
356382
}
357383

384+
// similar to extractFields, but instead of assuming the fields are in the given
385+
// class, traverse the class hierarchy to find them. Also, the additional
386+
// foundEach template argument is used to count how many times each field
387+
// has occurred. This is useful to know when to stop searching, and to
388+
// issue errors for missing fields.
389+
template <typename FoundEach, typename ...FieldNames>
390+
static auto extractFieldsHierarchy(ResolutionContext* rc, const BasicClassType* bct, FoundEach& foundEach, FieldNames... names) {
391+
return helpExtractFieldsHierarchy(rc, bct, foundEach, std::make_index_sequence<sizeof...(FieldNames)>(), names...);
392+
}
393+
358394
static std::tuple<QualifiedType, QualifiedType, QualifiedType>
359395
extractRectangularInfo(ResolutionContext* rc, const BasicClassType* bct) {
360396
return extractFields(rc, bct, "rank", "idxType", "strides");
@@ -424,60 +460,21 @@ static const ArrayType* arrayTypeFromSubsHelper(
424460
auto [instanceBct, baseArr] = extractBasicSubclassFromInstance(instanceQt);
425461
if (!instanceBct || !baseArr) return genericArray;
426462

427-
if (baseArr->id().symbolPath() == "ChapelDistribution.BaseRectangularArr") {
428-
auto [domInstanceQt] = extractFields(rc, instanceBct, "dom");
429-
auto domain = domainTypeFromInstance(rc, domInstanceQt);
430-
CHPL_ASSERT(domain);
431-
432-
auto [eltType] = extractFields(rc, baseArr, "eltType");
433-
return ArrayType::getArrayType(context, instanceQt,
434-
QualifiedType(QualifiedType::TYPE, domain),
435-
eltType);
436-
} else if (instanceBct->id().symbolPath() ==
437-
"DefaultAssociative.DefaultAssociativeArr" ||
438-
instanceBct->id().symbolPath() ==
439-
"ArrayViewReindex.ArrayViewReindexArr" ||
440-
instanceBct->id().symbolPath() ==
441-
"ArrayViewSlice.ArrayViewSliceArr" ||
442-
instanceBct->id().symbolPath() ==
443-
"ArrayViewRankChange.ArrayViewRankChangeArr") {
444-
auto [domInstanceQt] = extractFields(rc, instanceBct, "dom");
445-
auto domain = domainTypeFromInstance(rc, domInstanceQt);
446-
CHPL_ASSERT(domain);
447-
448-
CHPL_ASSERT(baseArr &&
449-
baseArr->id().symbolPath() == "ChapelDistribution.AbsBaseArr");
450-
auto [eltType] = extractFields(rc, baseArr, "eltType");
451-
452-
return ArrayType::getArrayType(context, instanceQt,
453-
QualifiedType(QualifiedType::TYPE, domain),
454-
eltType);
455-
} else if (baseArr->id().symbolPath() ==
456-
"ChapelDistribution.BaseSparseArrImpl") {
457-
// The Impl doesn't have the data, the parent class does.
458-
auto baseArrSparse = baseArr->parentClassType();
459-
CHPL_ASSERT(baseArrSparse &&
460-
baseArrSparse->id().symbolPath() ==
461-
"ChapelDistribution.BaseSparseArr");
462-
auto absBaseArr = baseArrSparse->parentClassType();
463-
CHPL_ASSERT(absBaseArr &&
464-
absBaseArr->id().symbolPath() ==
465-
"ChapelDistribution.AbsBaseArr");
466-
467-
auto [domInstanceQt] = extractFields(rc, baseArrSparse,"dom");
468-
auto [eltType] = extractFields(rc, absBaseArr, "eltType");
469-
auto domain = domainTypeFromInstance(rc, domInstanceQt);
470-
CHPL_ASSERT(domain);
471-
472-
return ArrayType::getArrayType(context, instanceQt,
473-
QualifiedType(QualifiedType::TYPE, domain),
474-
eltType);
475-
} else {
476-
CHPL_UNIMPL("unknown kind of array class");
463+
auto fieldCounts = std::make_pair(0, 0);
464+
auto [domInstanceQt, eltType] = extractFieldsHierarchy(rc, instanceBct, fieldCounts, "dom", "eltType");
465+
466+
if (fieldCounts.first == 0) {
467+
rc->context()->error(instanceBct->id(), "array implementation class doesn't have required field 'dom'");
477468
}
469+
if (fieldCounts.second == 0) {
470+
rc->context()->error(instanceBct->id(), "array implementation class doesn't have required field 'eltType'");
471+
}
472+
473+
auto domain = domainTypeFromInstance(rc, domInstanceQt);
478474

479-
// If we reach here, we weren't able to resolve the array type
480-
return genericArray;
475+
return ArrayType::getArrayType(context, instanceQt,
476+
QualifiedType(QualifiedType::TYPE, domain),
477+
eltType);
481478
}
482479

483480
static const Type* ctFromSubs(ResolutionContext* rc,

0 commit comments

Comments
 (0)