Skip to content

Commit 3f4227e

Browse files
authored
Merge pull request #18655 from slavapestov/legacy-tuple-cleanup
More legacy tuple cleanup
2 parents 9825111 + 4329240 commit 3f4227e

File tree

9 files changed

+59
-151
lines changed

9 files changed

+59
-151
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,6 @@ ERROR(wrong_argument_labels,none,
974974
"incorrect argument label%select{|s}0 in %select{call|subscript}3 "
975975
"(have '%1', expected '%2')",
976976
(bool, StringRef, StringRef, bool))
977-
ERROR(extra_named_single_element_tuple,none,
978-
"cannot treat single-element named tuple as a scalar; use '.%0' to "
979-
"access its element", (StringRef))
980977
ERROR(argument_out_of_order_named_named,none,
981978
"argument %0 must precede argument %1", (Identifier, Identifier))
982979
ERROR(argument_out_of_order_named_unnamed,none,

include/swift/AST/Types.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,16 +1876,6 @@ class TupleType final : public TypeBase, public llvm::FoldingSetNode,
18761876
/// return the element index, otherwise return -1.
18771877
int getNamedElementId(Identifier I) const;
18781878

1879-
/// getElementForScalarInit - If a tuple of this type can be initialized with
1880-
/// a scalar, return the element number that the scalar is assigned to. If
1881-
/// not, return -1.
1882-
int getElementForScalarInit() const;
1883-
1884-
/// If this tuple has a varargs element to it, return the base type of the
1885-
/// varargs element (i.e., if it is "Int...", this returns Int, not [Int]).
1886-
/// Otherwise, this returns Type().
1887-
Type getVarArgsBaseType() const;
1888-
18891879
/// Returns true if this tuple has inout elements.
18901880
bool hasInOutElement() const {
18911881
return static_cast<bool>(Bits.TupleType.HasInOutElement);

lib/AST/Type.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,45 +2422,6 @@ int TupleType::getNamedElementId(Identifier I) const {
24222422
return -1;
24232423
}
24242424

2425-
/// getElementForScalarInit - If a tuple of this type can be initialized with a
2426-
/// scalar, return the field number that the scalar is assigned to. If not,
2427-
/// return -1.
2428-
int TupleType::getElementForScalarInit() const {
2429-
if (Bits.TupleType.Count == 0) return -1;
2430-
2431-
int FieldWithoutDefault = -1;
2432-
for (unsigned i = 0, e = Bits.TupleType.Count; i != e; ++i) {
2433-
// If we already saw a non-vararg field missing a default value, then we
2434-
// cannot assign a scalar to this tuple.
2435-
if (FieldWithoutDefault != -1) {
2436-
// Vararg fields are okay; they'll just end up being empty.
2437-
if (getTrailingObjects<TupleTypeElt>()[i].isVararg())
2438-
continue;
2439-
2440-
return -1;
2441-
}
2442-
2443-
// Otherwise, remember this field number.
2444-
FieldWithoutDefault = i;
2445-
}
2446-
2447-
// If all the elements have default values, the scalar initializes the first
2448-
// value in the tuple.
2449-
return FieldWithoutDefault == -1 ? 0 : FieldWithoutDefault;
2450-
}
2451-
2452-
/// If this tuple has a varargs element to it, return the base type of the
2453-
/// varargs element (i.e., if it is "Int...", this returns Int, not [Int]).
2454-
/// Otherwise, this returns Type().
2455-
Type TupleType::getVarArgsBaseType() const {
2456-
for (unsigned i = 0, e = Bits.TupleType.Count; i != e; ++i) {
2457-
if (getTrailingObjects<TupleTypeElt>()[i].isVararg())
2458-
return getTrailingObjects<TupleTypeElt>()[i].getVarargBaseTy();
2459-
}
2460-
2461-
return Type();
2462-
}
2463-
24642425

24652426
ArchetypeType::ArchetypeType(
24662427
const ASTContext &Ctx,

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6606,19 +6606,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
66066606
/*isImplicit*/ true));
66076607
}
66086608

6609-
// If we're actually turning this into an lvalue tuple element, don't
6610-
// load.
6611-
bool performLoad = true;
6612-
if (auto toTuple = toType->getAs<TupleType>()) {
6613-
int scalarIdx = toTuple->getElementForScalarInit();
6614-
if (scalarIdx >= 0 &&
6615-
toTuple->getElement(scalarIdx).isInOut())
6616-
performLoad = false;
6617-
}
6618-
6619-
if (performLoad) {
6620-
return coerceToType(addImplicitLoadExpr(cs, expr), toType, locator);
6621-
}
6609+
return coerceToType(addImplicitLoadExpr(cs, expr), toType, locator);
66226610
}
66236611

66246612
// Coercions to tuple type.

lib/Sema/CSDiag.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3482,9 +3482,24 @@ static Optional<unsigned> getElementForScalarInitOfArg(
34823482

34833483
auto getElementForScalarInitSimple =
34843484
[](const TupleType *tupleTy) -> Optional<unsigned> {
3485-
int index = tupleTy->getElementForScalarInit();
3486-
if (index < 0) return None;
3487-
return index;
3485+
Optional<unsigned> result = None;
3486+
for (unsigned i = 0, e = tupleTy->getNumElements(); i != e; ++i) {
3487+
// If we already saw a non-vararg field, then we have more than
3488+
// one candidate field.
3489+
if (result.hasValue()) {
3490+
// Vararg fields are okay; they'll just end up being empty.
3491+
if (tupleTy->getElement(i).isVararg())
3492+
continue;
3493+
3494+
// Give up.
3495+
return None;
3496+
}
3497+
3498+
// Otherwise, remember this field number.
3499+
result = i;
3500+
}
3501+
3502+
return result;
34883503
};
34893504

34903505
// If there aren't any candidates, we're done.
@@ -8281,7 +8296,16 @@ bool FailureDiagnosis::visitTupleExpr(TupleExpr *TE) {
82818296
}
82828297

82838298
if (!variadicArgs.empty()) {
8284-
auto varargsTy = contextualTT->getVarArgsBaseType();
8299+
Type varargsTy;
8300+
for (auto &elt : contextualTT->getElements()) {
8301+
if (elt.isVararg()) {
8302+
varargsTy = elt.getVarargBaseTy();
8303+
break;
8304+
}
8305+
}
8306+
8307+
assert(varargsTy);
8308+
82858309
for (unsigned i = 0, e = variadicArgs.size(); i != e; ++i) {
82868310
unsigned inArgNo = variadicArgs[i];
82878311

lib/Sema/CSSolver.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -314,21 +314,6 @@ static SmallVector<Type, 4>
314314
enumerateDirectSupertypes(TypeChecker &tc, Type type) {
315315
SmallVector<Type, 4> result;
316316

317-
if (auto tupleTy = type->getAs<TupleType>()) {
318-
// A tuple that can be constructed from a scalar has a value of that
319-
// scalar type as its supertype.
320-
// FIXME: There is a way more general property here, where we can drop
321-
// one label from the tuple, maintaining the rest.
322-
int scalarIdx = tupleTy->getElementForScalarInit();
323-
if (scalarIdx >= 0) {
324-
auto &elt = tupleTy->getElement(scalarIdx);
325-
if (elt.isVararg()) // FIXME: Should we keep the name?
326-
result.push_back(elt.getVarargBaseTy());
327-
else if (elt.hasName())
328-
result.push_back(elt.getType());
329-
}
330-
}
331-
332317
if (type->mayHaveSuperclass()) {
333318
// FIXME: Can also weaken to the set of protocol constraints, but only
334319
// if there are any protocols that the type conforms to but the superclass
@@ -729,16 +714,6 @@ bool ConstraintSystem::tryTypeVariableBindings(
729714
}
730715

731716
if (binding.Kind == AllowedBindingKind::Subtypes) {
732-
if (auto tupleTy = type->getAs<TupleType>()) {
733-
int scalarIdx = tupleTy->getElementForScalarInit();
734-
if (scalarIdx >= 0) {
735-
auto eltType = tupleTy->getElementType(scalarIdx);
736-
if (exploredTypes.insert(eltType->getCanonicalType()).second)
737-
newBindings.push_back(
738-
{eltType, binding.Kind, binding.BindingSource});
739-
}
740-
}
741-
742717
// If we were unsuccessful solving for T?, try solving for T.
743718
if (auto objTy = type->getOptionalObjectType()) {
744719
if (exploredTypes.insert(objTy->getCanonicalType()).second) {

lib/Sema/MiscDiagnostics.cpp

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,39 +1768,16 @@ bool swift::diagnoseArgumentLabelError(ASTContext &ctx,
17681768
auto &diags = ctx.Diags;
17691769
auto tuple = dyn_cast<TupleExpr>(expr);
17701770
if (!tuple) {
1771-
llvm::SmallString<16> str;
1772-
// If the diagnostic is local, flush it before returning.
1773-
// This makes sure it's emitted before 'str' is destroyed.
1774-
SWIFT_DEFER { diagOpt.reset(); };
1775-
17761771
if (newNames[0].empty()) {
1777-
// This is probably a conversion from a value of labeled tuple type to
1778-
// a scalar.
1779-
// FIXME: We want this issue to disappear completely when single-element
1780-
// labeled tuples go away.
1781-
if (auto tupleTy = expr->getType()->getRValueType()->getAs<TupleType>()) {
1782-
int scalarFieldIdx = tupleTy->getElementForScalarInit();
1783-
if (scalarFieldIdx >= 0) {
1784-
auto &field = tupleTy->getElement(scalarFieldIdx);
1785-
if (field.hasName()) {
1786-
str = ".";
1787-
str += field.getName().str();
1788-
if (!existingDiag) {
1789-
diagOpt.emplace(
1790-
diags.diagnose(expr->getStartLoc(),
1791-
diag::extra_named_single_element_tuple,
1792-
field.getName().str()));
1793-
}
1794-
getDiag().fixItInsertAfter(expr->getEndLoc(), str);
1795-
return true;
1796-
}
1797-
}
1798-
}
1799-
18001772
// We don't know what to do with this.
18011773
return false;
18021774
}
18031775

1776+
llvm::SmallString<16> str;
1777+
// If the diagnostic is local, flush it before returning.
1778+
// This makes sure it's emitted before 'str' is destroyed.
1779+
SWIFT_DEFER { diagOpt.reset(); };
1780+
18041781
// This is a scalar-to-tuple conversion. Add the name. We "know"
18051782
// that we're inside a ParenExpr, because ParenExprs are required
18061783
// by the syntax and locator resolution looks through on level of

lib/Sema/TypeCheckError.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,7 @@ class ApplyClassifier {
674674
return classifyShuffleRethrowsArgument(shuffle, paramTupleType);
675675
}
676676

677-
int scalarElt = paramTupleType->getElementForScalarInit();
678-
if (scalarElt < 0) {
677+
if (paramTupleType->getNumElements() != 1) {
679678
// Otherwise, we're passing an opaque tuple expression, and we
680679
// should treat it as contributing to 'rethrows' if the original
681680
// parameter type included a throwing function type.
@@ -684,7 +683,10 @@ class ApplyClassifier {
684683
PotentialReason::forRethrowsArgument(arg));
685684
}
686685

687-
paramType = paramTupleType->getElementType(scalarElt);
686+
// FIXME: There's a case where we can end up with an ApplyExpr that
687+
// has a single-element-tuple argument type, but the argument is just
688+
// a ClosureExpr and not a TupleExpr/TupleShuffleExpr.
689+
paramType = paramTupleType->getElementType(0);
688690
}
689691

690692
// Otherwise, if the original parameter type was not a throwing

lib/Sema/TypeCheckPattern.cpp

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,9 @@ bool TypeChecker::coerceParameterListToType(ParameterList *P, ClosureExpr *CE,
16461646
auto hasParenSugar = [](ArrayRef<AnyFunctionType::Param> params) -> bool {
16471647
if (params.size() == 1) {
16481648
const auto &param = params.front();
1649-
return !param.hasLabel() && !param.isVariadic();
1649+
return (!param.hasLabel() &&
1650+
!param.isVariadic() &&
1651+
!param.isInOut());
16501652
}
16511653

16521654
return false;
@@ -1661,36 +1663,28 @@ bool TypeChecker::coerceParameterListToType(ParameterList *P, ClosureExpr *CE,
16611663
return type;
16621664
};
16631665

1664-
// Check if parameter list only contains one single tuple.
1665-
// If it is, then parameter type would be sugared ParenType
1666-
// with a single underlying TupleType. In that case, check if
1667-
// the closure argument is also one to avoid the tuple splat
1668-
// from happening.
1666+
// If the closure is called with a single argument of tuple type
1667+
// but the closure body expects multiple parameters, explode the
1668+
// tuple.
1669+
//
1670+
// FIXME: This looks like the wrong place for this; the constraint
1671+
// solver should have inserted an explicit conversion already.
1672+
//
1673+
// The only reason we can get away with this, I think, is that
1674+
// at the SIL level, recursive tuple expansion lowers
1675+
// ((T, U)) -> () and (T, U) -> () to the same function type,
1676+
// and SILGen doesn't enforce AST invariaints very strictly.
16691677
if (!hadError && hasParenSugar(params)) {
1670-
auto underlyingTy = params.front().getType();
1671-
1672-
if (underlyingTy->is<TupleType>() &&
1673-
!underlyingTy->castTo<TupleType>()->getVarArgsBaseType()) {
1678+
auto underlyingTy = params.front().getPlainType();
1679+
if (underlyingTy->is<TupleType>()) {
1680+
// If we're actually expecting a single parameter, handle it normally.
16741681
if (P->size() == 1)
16751682
return handleParameter(P->get(0), underlyingTy, /*mutable*/false);
1676-
}
16771683

1678-
// pass (strip paren sugar)
1679-
params.clear();
1680-
FunctionType::decomposeInput(underlyingTy, params);
1681-
}
1682-
1683-
// The context type must be a tuple.
1684-
if (hasParenSugar(params) && !hadError) {
1685-
const auto &param = params.front();
1686-
if (P->size() == 1) {
1687-
assert(P->size() == params.size());
1688-
return handleParameter(P->get(0), getType(param),
1689-
/*mutable*/ param.isInOut());
1684+
// Otherwise, explode the tuple.
1685+
params.clear();
1686+
FunctionType::decomposeInput(underlyingTy, params);
16901687
}
1691-
diagnose(P->getStartLoc(), diag::tuple_pattern_in_non_tuple_context,
1692-
param.getType());
1693-
hadError = true;
16941688
}
16951689

16961690
// The number of elements must match exactly.

0 commit comments

Comments
 (0)