Skip to content

Commit 612a2e7

Browse files
authored
Merge pull request #66657 from hborla/variadic-macro-specialization
[ConstraintSystem] Use an explicit generic argument constraint for `UnresolvedSpecializeExpr`.
2 parents 85d59d2 + d357315 commit 612a2e7

File tree

4 files changed

+79
-92
lines changed

4 files changed

+79
-92
lines changed

lib/Sema/CSGen.cpp

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,60 +1808,14 @@ namespace {
18081808
}
18091809

18101810
if (AnyMetatypeType *meta = baseTy->getAs<AnyMetatypeType>()) {
1811-
if (BoundGenericType *bgt
1812-
= meta->getInstanceType()->getAs<BoundGenericType>()) {
1813-
ArrayRef<Type> typeVars = bgt->getGenericArgs();
1814-
auto specializations = expr->getUnresolvedParams();
1815-
1816-
// If we have too many generic arguments, complain.
1817-
if (specializations.size() > typeVars.size()) {
1818-
de.diagnose(expr->getSubExpr()->getLoc(),
1819-
diag::type_parameter_count_mismatch,
1820-
bgt->getDecl()->getName(), typeVars.size(),
1821-
specializations.size(),
1822-
/*too many arguments*/ false,
1823-
/*isParameterPack?*/ false)
1824-
.highlight(
1825-
SourceRange(expr->getLAngleLoc(), expr->getRAngleLoc()));
1826-
de.diagnose(bgt->getDecl(), diag::kind_declname_declared_here,
1827-
DescriptiveDeclKind::GenericType,
1828-
bgt->getDecl()->getName());
1829-
return Type();
1830-
}
1831-
1832-
// Bind the specified generic arguments to the type variables in the
1833-
// open type.
1834-
auto *const locator = CS.getConstraintLocator(expr);
1835-
auto options =
1836-
TypeResolutionOptions(TypeResolverContext::InExpression);
1837-
for (size_t i = 0, e = specializations.size(); i < e; ++i) {
1838-
PackExpansionExpr *elementEnv = nullptr;
1839-
if (!PackElementEnvironments.empty()) {
1840-
options |= TypeResolutionFlags::AllowPackReferences;
1841-
elementEnv = PackElementEnvironments.back();
1842-
}
1843-
1844-
const auto result = TypeResolution::resolveContextualType(
1845-
specializations[i], CS.DC, options,
1846-
// Introduce type variables for unbound generics.
1847-
OpenUnboundGenericType(CS, locator),
1848-
HandlePlaceholderType(CS, locator),
1849-
OpenPackElementType(CS, locator, elementEnv));
1850-
if (result->hasError())
1851-
return Type();
1852-
1853-
CS.addConstraint(ConstraintKind::Bind, typeVars[i], result,
1854-
locator);
1855-
}
1856-
1857-
return baseTy;
1858-
} else {
1859-
de.diagnose(expr->getSubExpr()->getLoc(), diag::not_a_generic_type,
1860-
meta->getInstanceType());
1861-
de.diagnose(expr->getLAngleLoc(),
1862-
diag::while_parsing_as_left_angle_bracket);
1811+
auto *overloadLocator = CS.getConstraintLocator(expr->getSubExpr());
1812+
if (addSpecializationConstraint(overloadLocator,
1813+
meta->getInstanceType(),
1814+
expr->getUnresolvedParams())) {
18631815
return Type();
18641816
}
1817+
1818+
return baseTy;
18651819
}
18661820

18671821
// FIXME: If the base type is a type variable, constrain it to a metatype

lib/Sema/CSSimplify.cpp

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13535,18 +13535,32 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1353513535
if (simplifiedBoundType->isTypeVariableOrMember())
1353613536
return formUnsolved();
1353713537

13538-
// If the overload hasn't been resolved, we can't simplify this constraint.
13539-
auto overloadLocator = getCalleeLocator(getConstraintLocator(locator));
13540-
auto selectedOverload = findSelectedOverloadFor(overloadLocator);
13541-
if (!selectedOverload)
13542-
return formUnsolved();
13538+
ValueDecl *decl;
13539+
SmallVector<OpenedType, 2> openedTypes;
13540+
if (auto *bound = dyn_cast<TypeAliasType>(type1.getPointer())) {
13541+
decl = bound->getDecl();
13542+
for (auto argType : bound->getDirectGenericArgs()) {
13543+
auto *typeVar = argType->getAs<TypeVariableType>();
13544+
auto *genericParam = typeVar->getImpl().getGenericParameter();
13545+
openedTypes.push_back({genericParam, typeVar});
13546+
}
13547+
} else {
13548+
// If the overload hasn't been resolved, we can't simplify this constraint.
13549+
auto overloadLocator = getCalleeLocator(getConstraintLocator(locator));
13550+
auto selectedOverload = findSelectedOverloadFor(overloadLocator);
13551+
if (!selectedOverload)
13552+
return formUnsolved();
1354313553

13544-
auto overloadChoice = selectedOverload->choice;
13545-
if (!overloadChoice.isDecl()) {
13546-
return SolutionKind::Error;
13554+
auto overloadChoice = selectedOverload->choice;
13555+
if (!overloadChoice.isDecl()) {
13556+
return SolutionKind::Error;
13557+
}
13558+
13559+
decl = overloadChoice.getDecl();
13560+
auto openedOverloadTypes = getOpenedTypes(overloadLocator);
13561+
openedTypes.append(openedOverloadTypes.begin(), openedOverloadTypes.end());
1354713562
}
1354813563

13549-
auto decl = overloadChoice.getDecl();
1355013564
auto genericContext = decl->getAsGenericContext();
1355113565
if (!genericContext)
1355213566
return SolutionKind::Error;
@@ -13560,9 +13574,28 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1356013574
// Map the generic parameters we have over to their opened types.
1356113575
SmallVector<Type, 2> openedGenericParams;
1356213576
auto genericParamDepth = genericParams->getParams()[0]->getDepth();
13563-
for (const auto &openedType : getOpenedTypes(overloadLocator)) {
13577+
for (const auto &openedType : openedTypes) {
1356413578
if (openedType.first->getDepth() == genericParamDepth) {
13565-
openedGenericParams.push_back(Type(openedType.second));
13579+
// A generic argument list containing pack references expects
13580+
// those packs to be wrapped in pack expansion types. If this
13581+
// opened type represents the generic argument for a parameter
13582+
// pack, wrap generate the appropriate shape constraints and
13583+
// add a pack expansion to the argument list.
13584+
if (openedType.first->isParameterPack()) {
13585+
auto patternType = openedType.second;
13586+
auto *shapeLoc = getConstraintLocator(
13587+
locator.withPathElement(ConstraintLocator::PackShape));
13588+
auto *shapeType = createTypeVariable(shapeLoc,
13589+
TVO_CanBindToPack |
13590+
TVO_CanBindToHole);
13591+
addConstraint(ConstraintKind::ShapeOf,
13592+
shapeType, patternType, shapeLoc);
13593+
13594+
auto *expansion = PackExpansionType::get(patternType, shapeType);
13595+
openedGenericParams.push_back(expansion);
13596+
} else {
13597+
openedGenericParams.push_back(Type(openedType.second));
13598+
}
1356613599
}
1356713600
}
1356813601
assert(openedGenericParams.size() == genericParams->size());

test/Macros/macro_expand_variadic.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,32 @@
22

33
// RUN: %empty-directory(%t)
44
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/variadic_macros.swift -g -no-toolchain-stdlib-rpath
5-
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5
6-
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser -swift-version 5
5+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5
6+
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser -swift-version 5
77
// RUN: %target-codesign %t/main
88
// RUN: %target-run %t/main | %FileCheck %s
99

1010
@freestanding(expression) macro print<each Value>(_ value: repeat each Value) = #externalMacro(module: "MacroDefinition", type: "PrintMacro")
1111

12+
@freestanding(expression) macro Print<each Value>(_ value: repeat each Value) = #externalMacro(module: "MacroDefinition", type: "PrintMacro")
13+
14+
struct Print<each Value> {
15+
init() {}
16+
}
17+
18+
func testAmbiguity() {
19+
let _ = Print<Int>()
20+
}
21+
1222
func testIt() {
1323
// CHECK: hello
1424
// CHECK: [1, 2, 3, 4, 5]
1525
#print("hello", [1, 2, 3, 4, 5])
1626

27+
// CHECK: hello
28+
// CHECK: [1, 2, 3, 4, 5]
29+
#print<String, [Int]>("hello", [1, 2, 3, 4, 5])
30+
1731
// CHECK: world
1832
#print("world")
1933
}

test/decl/typealias/generic.swift

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
struct MyType<TyA, TyB> { // expected-note {{generic type 'MyType' declared here}}
44
// expected-note @-1 {{arguments to generic parameter 'TyB' ('S' and 'Int') are expected to be equal}}
5-
// expected-note @-2 6 {{arguments to generic parameter 'TyA' ('Float' and 'Int') are expected to be equal}}
6-
// expected-note @-3 2 {{arguments to generic parameter 'TyA' ('Float' and 'Double') are expected to be equal}}
7-
// expected-note @-4 2 {{arguments to generic parameter 'TyB' ('Int' and 'Float') are expected to be equal}}
8-
// expected-note @-5 2 {{arguments to generic parameter 'TyB' ('Double' and 'Float') are expected to be equal}}
5+
96
var a : TyA, b : TyB
107
}
118

@@ -255,23 +252,13 @@ let _: ConcreteStruct.O<Int> = ConcreteStruct.O(123)
255252
let _: ConcreteStruct.O<Int> = ConcreteStruct.O<Int>(123)
256253

257254
// Qualified lookup of generic typealiases nested inside generic contexts
258-
//
259-
// FIXME marks cases which still don't work correctly, and either produce a
260-
// spurious diagnostic, or are actually invalid and do not diagnose.
261-
//
262-
// This occurs because the constraint solver does the wrong thing with an
263-
// UnresolvedSpecializeExpr applied to a generic typealias.
264-
//
265-
// In the other cases, we manage to fold the UnresolvedSpecializeExpr in the
266-
// precheckExpression() phase, which handles generic typealiases correctly.
267255

268256
do {
269-
let x1 = GenericClass.TA<Float>(a: 4.0, b: 1) // FIXME
270-
let x2 = GenericClass.TA<Float>(a: 1, b: 4.0) // FIXME
257+
let x1 = GenericClass.TA<Float>(a: 4.0, b: 1)
258+
let x2 = GenericClass.TA<Float>(a: 1, b: 4.0)
271259

272-
// FIXME: Should not diagnose
273-
let _: MyType<Double, Float> = x1 // expected-error {{cannot assign value of type 'MyType<Float, Int>' to type 'MyType<Double, Float>'}}
274-
let _: MyType<Int, Float> = x2 // expected-error {{cannot assign value of type 'MyType<Float, Double>' to type 'MyType<Int, Float>'}}
260+
let _: MyType<Double, Float> = x1
261+
let _: MyType<Int, Float> = x2
275262
}
276263

277264
let _ = GenericClass<Int>.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
@@ -284,12 +271,11 @@ let _: GenericClass.TA = GenericClass.TA(a: 4.0, b: 1)
284271
let _: GenericClass.TA = GenericClass.TA(a: 1, b: 4.0)
285272

286273
do {
287-
let x1: GenericClass.TA = GenericClass.TA<Float>(a: 4.0, b: 1) // FIXME
288-
let x2: GenericClass.TA = GenericClass.TA<Float>(a: 1, b: 4.0) // FIXME
274+
let x1: GenericClass.TA = GenericClass.TA<Float>(a: 4.0, b: 1)
275+
let x2: GenericClass.TA = GenericClass.TA<Float>(a: 1, b: 4.0)
289276

290-
// FIXME: Should not diagnose
291-
let _: MyType<Double, Float> = x1 // expected-error {{cannot assign value of type 'MyType<Float, Int>' to type 'MyType<Double, Float>'}}
292-
let _: MyType<Int, Float> = x2 // expected-error {{cannot assign value of type 'MyType<Float, Double>' to type 'MyType<Int, Float>'}}
277+
let _: MyType<Double, Float> = x1
278+
let _: MyType<Int, Float> = x2
293279
}
294280

295281
let _: GenericClass.TA = GenericClass<Int>.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
@@ -301,8 +287,8 @@ let _: GenericClass.TA = GenericClass<Int>.TA<Float>(a: 1, b: 4.0)
301287
let _: GenericClass<Int>.TA = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
302288
let _: GenericClass<Int>.TA = GenericClass.TA(a: 1, b: 4.0)
303289

304-
let _: GenericClass<Int>.TA = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType<Float, Int>' to type 'MyType<Int, Int>'}}
305-
let _: GenericClass<Int>.TA = GenericClass.TA<Float>(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType<Float, Double>' to type 'MyType<Int, Double>'}}
290+
let _: GenericClass<Int>.TA = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
291+
let _: GenericClass<Int>.TA = GenericClass.TA<Float>(a: 1, b: 4.0)
306292

307293
let _: GenericClass<Int>.TA = GenericClass<Int>.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
308294
let _: GenericClass<Int>.TA = GenericClass<Int>.TA(a: 1, b: 4.0)
@@ -313,8 +299,8 @@ let _: GenericClass<Int>.TA = GenericClass<Int>.TA<Float>(a: 1, b: 4.0)
313299
let _: GenericClass<Int>.TA<Float> = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
314300
let _: GenericClass<Int>.TA<Float> = GenericClass.TA(a: 1, b: 4.0)
315301

316-
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'GenericClass<Int>.TA<Float>' (aka 'MyType<Int, Float>')}}
317-
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'GenericClass<Int>.TA<Float>' (aka 'MyType<Int, Float>')}}
302+
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
303+
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 1, b: 4.0)
318304

319305
let _: GenericClass<Int>.TA<Float> = GenericClass<Int>.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
320306
let _: GenericClass<Int>.TA<Float> = GenericClass<Int>.TA(a: 1, b: 4.0)

0 commit comments

Comments
 (0)