From 62d25bae8a87360fd178900a7784840dc06c0b20 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 10 Mar 2023 16:46:10 -0800 Subject: [PATCH 1/2] [ConstraintSystem] Variadics: Pack expansion materialization operates on loaded tuples If the base tuple of `.element` is l-value, it has to be loaded before pack expansion could be materialized. --- lib/Sema/ConstraintSystem.cpp | 8 +++++++- .../pack-expansion-expressions.swift | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index ccbea39cb6956..bc6c64820cc2b 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -3506,7 +3506,13 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, break; case OverloadChoiceKind::MaterializePack: { - auto *tuple = choice.getBaseType()->castTo(); + // Since `.element` is only applicable to single element tuples at the + // moment we can just look through l-value base to load it. + // + // In the future, _if_ the syntax allows for multiple expansions + // this code would have to be adjusted to project l-value from the + // base type just like TupleIndex does. + auto tuple = choice.getBaseType()->getRValueType()->castTo(); auto *expansion = tuple->getElementType(0)->castTo(); adjustedRefType = expansion->getPatternType(); refType = adjustedRefType; diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index 1d2d39fffe44b..18e2f0f5f52bf 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -178,3 +178,21 @@ do { test[data: repeat each args, "", 42] = 0 } } + +func test_pack_expansion_materialization_from_lvalue_base() { + struct Data {} + + struct Test { + var data: (repeat Data) + + init() { + self.data = (repeat Data()) + _ = (repeat each data.element) // Ok + + var tmp = (repeat Data()) // expected-warning {{never mutated}} + _ = (repeat each tmp.element) // Ok + + // TODO: Add subscript test-case when syntax is supported. + } + } +} From a7e49ee0b0e93638cd1ee7b280e788d7d951cf80 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 10 Mar 2023 16:48:48 -0800 Subject: [PATCH 2/2] [CSApply] Variadics: Emit `LoadExpr` for when base of `.element` is l-value --- lib/Sema/CSApply.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 98f05458b3401..0a91370f28375 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -3415,6 +3415,14 @@ namespace { } case OverloadChoiceKind::MaterializePack: { + auto baseTy = solution.getResolvedType(base); + + // Load the base tuple if necessary, materialization + // operates on r-value types only. + if (baseTy->is()) + base = coerceToType(base, baseTy->getRValueType(), + cs.getConstraintLocator(base)); + auto packType = solution.getResolvedType(expr); return cs.cacheType( MaterializePackExpr::create(cs.getASTContext(),