Skip to content

Commit e6c91b3

Browse files
committed
Start using BoundNameAliasType for non-generic typealiases in generic contexts
Currently, when we reference a (non-generic) typealias within a generic context, we would completely lose type sugar for the typealias, replacing it with the underlying type. Instead, use BoundNameAliasType for this purpose, which allows us to maintain all of the type sugar as well as storing complete substitutions for later use.
1 parent 80eae20 commit e6c91b3

File tree

7 files changed

+45
-10
lines changed

7 files changed

+45
-10
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,12 @@ class TypeAccessScopeChecker : private TypeWalker, AccessScopeChecker {
13221322
ValueDecl *VD;
13231323
if (auto *TAD = dyn_cast<NameAliasType>(T.getPointer()))
13241324
VD = TAD->getDecl();
1325+
else if (auto *BNAD = dyn_cast<BoundNameAliasType>(T.getPointer())) {
1326+
if (CanonicalizeParentTypes)
1327+
VD = nullptr;
1328+
else
1329+
VD = BNAD->getDecl();
1330+
}
13251331
else if (auto *NTD = T->getAnyNominal())
13261332
VD = NTD;
13271333
else
@@ -1340,6 +1346,11 @@ class TypeAccessScopeChecker : private TypeWalker, AccessScopeChecker {
13401346
nominalParentTy = genericTy->getParent();
13411347
for (auto genericArg : genericTy->getGenericArgs())
13421348
genericArg.walk(*this);
1349+
} else if (auto boundNameAliasTy =
1350+
dyn_cast<BoundNameAliasType>(T.getPointer())) {
1351+
// The parent type would have been lost previously, so look right through
1352+
// this type.
1353+
Type(boundNameAliasTy->getSinglyDesugaredType()).walk(*this);
13431354
} else {
13441355
return Action::Continue;
13451356
}

lib/Sema/TypeCheckType.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,7 +3179,8 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
31793179
}
31803180
}
31813181

3182-
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(member)) {
3182+
auto *aliasDecl = dyn_cast<TypeAliasDecl>(member);
3183+
if (aliasDecl) {
31833184
// FIXME: If this is a protocol typealias and we haven't built the
31843185
// protocol's generic environment yet, do so now, to ensure the
31853186
// typealias's underlying type has fully resolved dependent
@@ -3201,7 +3202,15 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
32013202

32023203
auto subs = baseTy->getContextSubstitutionMap(
32033204
module, member->getDeclContext());
3204-
return memberType.subst(subs, SubstFlags::UseErrorType);
3205+
Type resultType = memberType.subst(subs, SubstFlags::UseErrorType);
3206+
3207+
// If we're referring to a typealias within a generic context, build
3208+
// a sugared alias type.
3209+
if (aliasDecl && aliasDecl->getGenericSignature()) {
3210+
resultType = BoundNameAliasType::get(aliasDecl, baseTy, subs, resultType);
3211+
}
3212+
3213+
return resultType;
32053214
}
32063215

32073216
Type TypeChecker::getSuperClassOf(Type type) {

test/ClangImporter/objc_generics_conformance.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ protocol WithAssocOther {
2121
}
2222

2323
extension GenericClass : WithAssocOther {
24-
typealias Other = [T] // expected-error{{'GenericClass.Other' involving Objective-C type parameter cannot be used for associated type 'Other' of protocol 'WithAssocOther'}}
24+
typealias Other = [T] // expected-error{{type 'GenericClass<T>.Other' involving Objective-C type parameter 'T' cannot be used for associated type 'Other' of protocol 'WithAssocOther'}}
2525
}
2626

2727
protocol WithAssocElement {

test/Compatibility/accessibility_typealias.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private func privateFuncWithFileprivateAlias() -> Generic<Int>.Dependent {
3939
return 3
4040
}
4141

42-
var y = privateFuncWithFileprivateAlias()
42+
var y = privateFuncWithFileprivateAlias() // expected-warning{{variable should be declared fileprivate because its type 'Generic<Int>.Dependent' (aka 'Int') uses a fileprivate type}}
4343

4444

4545
private typealias FnType = (_ x: Int) -> Void // expected-note * {{type declared here}}

test/decl/typealias/dependent_types.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ struct GenericStruct<T> { // expected-note 2{{generic type 'GenericStruct' decla
3333
func methodTwo() -> MetaAlias {}
3434

3535
func methodOne() -> Alias.BadType {}
36-
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct.Alias'}}
36+
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct<T>.Alias'}}
3737
func methodTwo() -> MetaAlias.BadType {}
38-
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct.MetaAlias'}}
38+
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct<T>.MetaAlias'}}
3939

4040
var propertyOne: Alias.BadType
41-
// expected-error@-1 {{'BadType' is not a member type of 'T'}}
41+
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct<T>.Alias' (aka 'T')}}
4242
var propertyTwo: MetaAlias.BadType
43-
// expected-error@-1 {{'BadType' is not a member type of 'T.Type'}}
43+
// expected-error@-1 {{'BadType' is not a member type of 'GenericStruct<T>.MetaAlias' (aka 'T.Type')}}
4444
}
4545

4646
// This was accepted in Swift 3.0 and sort of worked... but we can't

test/decl/typealias/generic.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,18 @@ takesInt(10)
417417

418418
func failsRequirementCheck(_: Element<Int>) {}
419419
// expected-error@-1 {{type 'Int' does not conform to protocol 'Sequence'}}
420+
421+
//
422+
// Sugar in base types of a typealias.
423+
//
424+
struct X<T, U> {
425+
typealias GY<V> = [V]
426+
}
427+
428+
typealias GX<T> = X<T, T>
429+
430+
func testSugar(_ gx: GX<Int>, _ gy: GX<Int>.GY<Double>, gz: GX<Int>.GY<Double>.Element) {
431+
let i: Int = gx // expected-error{{cannot convert value of type 'GX<Int>' (aka 'X<Int, Int>') to specified type 'Int'}}
432+
let i2: Int = gy // expected-error{{cannot convert value of type 'GX<Int>.GY<Double>' (aka 'Array<Double>') to specified type 'Int'}}
433+
let i3: Int = gz // expected-error{{cannot convert value of type 'GX<Int>.GY<Double>.Element' (aka 'Double') to specified type 'Int'}}
434+
}

validation-test/compiler_crashers/28812-getgenericparams.swift renamed to validation-test/compiler_crashers_fixed/28812-getgenericparams.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// REQUIRES: asserts
9-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
9+
// RUN: not %target-swift-frontend %s -emit-ir
1010
class a<a{{}
1111
let d=a
1212
& a

0 commit comments

Comments
 (0)