@@ -2110,6 +2110,7 @@ namespace {
2110
2110
if (D->isCxxNonTrivial ()) {
2111
2111
properties.setAddressOnly ();
2112
2112
properties.setNonTrivial ();
2113
+ properties.setLexical (IsLexical);
2113
2114
}
2114
2115
2115
2116
auto subMap = structType->getContextSubstitutionMap (&TC.M , D);
@@ -2169,6 +2170,9 @@ namespace {
2169
2170
// may be added resiliently later.
2170
2171
if (D->isIndirect ()) {
2171
2172
properties.setNonTrivial ();
2173
+ properties.setLexical (IsLexical);
2174
+ properties =
2175
+ applyLifetimeAnnotation (D->getLifetimeAnnotation (), properties);
2172
2176
return new (TC) LoadableEnumTypeLowering (enumType, properties,
2173
2177
Expansion);
2174
2178
}
@@ -2184,6 +2188,9 @@ namespace {
2184
2188
// Indirect elements only make the type nontrivial.
2185
2189
if (elt->isIndirect ()) {
2186
2190
properties.setNonTrivial ();
2191
+ properties.setLexical (IsLexical);
2192
+ properties =
2193
+ applyLifetimeAnnotation (elt->getLifetimeAnnotation (), properties);
2187
2194
continue ;
2188
2195
}
2189
2196
@@ -2433,74 +2440,160 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
2433
2440
}
2434
2441
2435
2442
#ifndef NDEBUG
2436
- verifyLowering (*lowering, origType, origSubstType , forExpansion);
2443
+ verifyLowering (*lowering, origType, loweredSubstType , forExpansion);
2437
2444
#endif
2438
2445
2439
2446
return *lowering;
2440
2447
}
2441
2448
2442
2449
#ifndef NDEBUG
2450
+ bool TypeConverter::visitAggregateLeaves (
2451
+ Lowering::AbstractionPattern origType, Type substType,
2452
+ TypeExpansionContext context,
2453
+ std::function<bool (Type, Lowering::AbstractionPattern, ValueDecl *,
2454
+ Optional<unsigned >)>
2455
+ isLeafAggregate,
2456
+ std::function<bool(Type, Lowering::AbstractionPattern, ValueDecl *,
2457
+ Optional<unsigned >)>
2458
+ visit) {
2459
+ llvm::SmallSet<std::tuple<TypeBase *, ValueDecl *, unsigned >, 16 > visited;
2460
+ llvm::SmallVector<
2461
+ std::tuple<TypeBase *, AbstractionPattern, ValueDecl *, unsigned >, 16 >
2462
+ worklist;
2463
+ auto insertIntoWorklist = [&visited,
2464
+ &worklist](Type substTy, AbstractionPattern origTy,
2465
+ ValueDecl *field,
2466
+ Optional<unsigned > maybeIndex) -> bool {
2467
+ unsigned index = maybeIndex.getValueOr (UINT_MAX);
2468
+ if (!visited.insert ({substTy.getPointer (), field, index}).second )
2469
+ return false ;
2470
+ worklist.push_back ({substTy.getPointer (), origTy, field, index});
2471
+ return true ;
2472
+ };
2473
+ auto popFromWorklist = [&worklist]()
2474
+ -> std::tuple<Type, AbstractionPattern, ValueDecl *, Optional<unsigned >> {
2475
+ TypeBase *ty;
2476
+ AbstractionPattern origTy = AbstractionPattern::getOpaque ();
2477
+ ValueDecl *field;
2478
+ unsigned index;
2479
+ std::tie (ty, origTy, field, index) = worklist.pop_back_val ();
2480
+ Optional<unsigned > maybeIndex;
2481
+ if (index != UINT_MAX)
2482
+ maybeIndex = {index};
2483
+ return {ty->getCanonicalType (), origTy, field, index};
2484
+ };
2485
+ auto isAggregate = [](Type ty) {
2486
+ return ty->is <TupleType>() || ty->getEnumOrBoundGenericEnum () ||
2487
+ ty->getStructOrBoundGenericStruct ();
2488
+ };
2489
+ insertIntoWorklist (substType, origType, nullptr , llvm::None);
2490
+ while (!worklist.empty ()) {
2491
+ Type ty;
2492
+ AbstractionPattern origTy = AbstractionPattern::getOpaque ();
2493
+ ValueDecl *field;
2494
+ Optional<unsigned > index;
2495
+ std::tie (ty, origTy, field, index) = popFromWorklist ();
2496
+ if (isAggregate (ty) && !isLeafAggregate (ty, origTy, field, index)) {
2497
+ if (auto tupleTy = ty->getAs <TupleType>()) {
2498
+ for (unsigned tupleIndex = 0 , num = tupleTy->getNumElements ();
2499
+ tupleIndex < num; ++tupleIndex) {
2500
+ auto origElementTy = origTy.getTupleElementType (tupleIndex);
2501
+ auto substElementTy =
2502
+ tupleTy->getElementType (tupleIndex)->getCanonicalType ();
2503
+ substElementTy =
2504
+ computeLoweredRValueType (context, origElementTy, substElementTy);
2505
+ insertIntoWorklist (substElementTy, origElementTy, nullptr ,
2506
+ tupleIndex);
2507
+ }
2508
+ } else if (auto *decl = ty->getStructOrBoundGenericStruct ()) {
2509
+ for (auto *structField : decl->getStoredProperties ()) {
2510
+ auto subMap = ty->getContextSubstitutionMap (&M, decl);
2511
+ auto substFieldTy =
2512
+ structField->getInterfaceType ().subst (subMap)->getCanonicalType ();
2513
+ auto sig =
2514
+ structField->getDeclContext ()->getGenericSignatureOfContext ();
2515
+ auto interfaceTy =
2516
+ structField->getInterfaceType ()->getReducedType (sig);
2517
+ auto origFieldType =
2518
+ origTy.unsafeGetSubstFieldType (structField, interfaceTy);
2519
+ insertIntoWorklist (substFieldTy, origFieldType, structField,
2520
+ llvm::None);
2521
+ }
2522
+ } else if (auto *decl = ty->getEnumOrBoundGenericEnum ()) {
2523
+ auto subMap = ty->getContextSubstitutionMap (&M, decl);
2524
+ for (auto *element : decl->getAllElements ()) {
2525
+ if (!element->hasAssociatedValues ())
2526
+ continue ;
2527
+ // TODO: Callback for indirect elements.
2528
+ if (element->isIndirect ())
2529
+ continue ;
2530
+ auto substElementType = element->getArgumentInterfaceType ()
2531
+ .subst (subMap)
2532
+ ->getCanonicalType ();
2533
+ auto origElementTy = origTy.unsafeGetSubstFieldType (
2534
+ element, element->getArgumentInterfaceType ()->getReducedType (
2535
+ decl->getGenericSignature ()));
2536
+
2537
+ insertIntoWorklist (substElementType, origElementTy, element,
2538
+ llvm::None);
2539
+ }
2540
+ } else {
2541
+ llvm_unreachable (" unknown aggregate kind!" );
2542
+ }
2543
+ continue ;
2544
+ }
2545
+
2546
+ // This type is a leaf. Visit it.
2547
+ auto success = visit (ty, origTy, field, index);
2548
+ if (!success)
2549
+ return false ;
2550
+ }
2551
+ return true ;
2552
+ }
2553
+
2443
2554
void TypeConverter::verifyLowering (const TypeLowering &lowering,
2444
- AbstractionPattern origType,
2445
- Type origSubstType,
2555
+ AbstractionPattern origType, Type substType,
2446
2556
TypeExpansionContext forExpansion) {
2447
2557
// Non-trivial lowerings should always be lexical unless all non-trivial
2448
2558
// fields are eager move.
2449
2559
if (!lowering.isTrivial () && !lowering.isLexical ()) {
2450
- auto getLifetimeAnnotation = [](SILType ty) -> LifetimeAnnotation {
2560
+ if (lowering.getRecursiveProperties ().isInfinite ())
2561
+ return ;
2562
+ auto getLifetimeAnnotation = [](Type ty) -> LifetimeAnnotation {
2451
2563
NominalTypeDecl *nominal;
2452
- if (!(nominal = ty. getASTType (). getAnyNominal ()))
2564
+ if (!(nominal = ty-> getAnyNominal ()))
2453
2565
return LifetimeAnnotation::None;
2454
2566
return nominal->getLifetimeAnnotation ();
2455
2567
};
2456
- auto loweredType = lowering.getLoweredType ();
2457
- bool hasNoNontrivialLexicalLeaf = loweredType.visitAggregateLeaves (
2458
- *this , forExpansion,
2568
+ bool hasNoNontrivialLexicalLeaf = visitAggregateLeaves (
2569
+ origType, substType, forExpansion,
2459
2570
/* isLeaf=*/
2460
- [&](auto parent , auto ty , auto *fieldDecl ) -> bool {
2571
+ [&](auto ty , auto origTy , auto *field, auto index ) -> bool {
2461
2572
// The field's type is an aggregate. Treat it as a leaf if it
2462
2573
// has a lifetime annotation.
2463
2574
2464
- // If we don't have a field decl, it's either a field of a tuple
2465
- // or the top-level type. Either way, there's no var decl on
2466
- // which to look for an attribute.
2467
- //
2468
- // It's a leaf if the type has a lifetime annotation.
2469
- if (!fieldDecl)
2575
+ // If it's a field of a tuple or the top-level type, there's no value
2576
+ // decl on which to look for an attribute. It's a leaf iff the type
2577
+ // has a lifetime annotation.
2578
+ if (index || !field)
2470
2579
return getLifetimeAnnotation (ty).isSome ();
2471
2580
2472
2581
// It's a field of a struct or an enum. It's a leaf if the type
2473
2582
// or the var decl has a lifetime annotation.
2474
- return fieldDecl ->getLifetimeAnnotation ().isSome () ||
2583
+ return field ->getLifetimeAnnotation ().isSome () ||
2475
2584
getLifetimeAnnotation (ty);
2476
2585
},
2477
2586
/* visit=*/
2478
- [&](auto parent , auto ty , auto *fieldDecl ) -> bool {
2587
+ [&](auto ty , auto origTy , auto *field, auto index ) -> bool {
2479
2588
// Look at each leaf: if it is non-trivial, verify that it is
2480
2589
// attributed @_eagerMove.
2481
2590
2482
2591
// If the leaf is the whole type, verify that it is annotated
2483
2592
// @_eagerMove.
2484
- if (ty == loweredType )
2593
+ if (ty-> getCanonicalType () == substType-> getCanonicalType () )
2485
2594
return getLifetimeAnnotation (ty) == LifetimeAnnotation::EagerMove;
2486
2595
2487
- // Get ty's lowering.
2488
- CanGenericSignature sig;
2489
- if (fieldDecl) {
2490
- AbstractionPattern origFieldTy = getAbstractionPattern (fieldDecl);
2491
- CanType substFieldTy;
2492
- if (fieldDecl->hasClangNode ()) {
2493
- substFieldTy = origFieldTy.getType ();
2494
- } else {
2495
- substFieldTy = parent.getASTType ()
2496
- ->getTypeOfMember (&M, fieldDecl)
2497
- ->getCanonicalType ();
2498
- }
2499
- sig = getAbstractionPattern (fieldDecl).getGenericSignatureOrNull ();
2500
- } else {
2501
- sig = CanGenericSignature ();
2502
- }
2503
- auto &tyLowering = getTypeLowering (ty, forExpansion, sig);
2596
+ auto &tyLowering = getTypeLowering (origTy, ty, forExpansion);
2504
2597
2505
2598
// Leaves which are trivial aren't of interest.
2506
2599
if (tyLowering.isTrivial ())
@@ -2510,17 +2603,16 @@ void TypeConverter::verifyLowering(const TypeLowering &lowering,
2510
2603
// not lexical. The leaf must be annotated @_eagerMove.
2511
2604
// Otherwise, the whole type would be lexical.
2512
2605
2513
- if (!fieldDecl) {
2514
- // The field is non-trivial and the whole type is non-lexical.
2515
- // If there's no field decl which might be annotated
2516
- // @_eagerMove, we have a problem.
2517
- return false ;
2606
+ if (index || !field) {
2607
+ // There is no field decl that might be annotated @_eagerMove. The
2608
+ // field is @_eagerMove iff its type is annotated @_eagerMove.
2609
+ return getLifetimeAnnotation (ty) == LifetimeAnnotation::EagerMove;
2518
2610
}
2519
2611
2520
2612
// The field is non-trivial and the whole type is non-lexical.
2521
2613
// That's fine as long as the field or its type is annotated
2522
2614
// @_eagerMove.
2523
- return fieldDecl ->getLifetimeAnnotation () ==
2615
+ return field ->getLifetimeAnnotation () ==
2524
2616
LifetimeAnnotation::EagerMove ||
2525
2617
getLifetimeAnnotation (ty) == LifetimeAnnotation::EagerMove;
2526
2618
});
0 commit comments