Skip to content

Reenable calls to getMinimalCanonicalType() in re-declaration checking #41733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5201,7 +5201,8 @@ ASTContext::getOpenedArchetypeSignature(Type type, GenericSignature parentSig) {
type = existential->getConstraintType();

const CanType constraint = type->getCanonicalType();
assert(!constraint->hasTypeParameter() && "This only works with archetypes");
assert(parentSig || !constraint->hasTypeParameter() &&
"Interface type here requires a parent signature");

// The opened archetype signature for a protocol type is identical
// to the protocol's own canonical generic signature if there aren't any
Expand All @@ -5216,11 +5217,13 @@ ASTContext::getOpenedArchetypeSignature(Type type, GenericSignature parentSig) {
// generic parameters. This ensures that we keep e.g. generic superclass
// existentials contained in a well-formed generic context.
auto canParentSig = parentSig.getCanonicalSignature();
auto found = getImpl().ExistentialSignatures.find({constraint, canParentSig.getPointer()});
auto key = std::make_pair(constraint, canParentSig.getPointer());
auto found = getImpl().ExistentialSignatures.find(key);
if (found != getImpl().ExistentialSignatures.end())
return found->second;

auto genericParam = OpenedArchetypeType::getSelfInterfaceTypeFromContext(canParentSig, type->getASTContext())
auto genericParam = OpenedArchetypeType::getSelfInterfaceTypeFromContext(
canParentSig, type->getASTContext())
->castTo<GenericTypeParamType>();
Requirement requirement(RequirementKind::Conformance, genericParam,
constraint);
Expand All @@ -5231,7 +5234,7 @@ ASTContext::getOpenedArchetypeSignature(Type type, GenericSignature parentSig) {
CanGenericSignature canGenericSig(genericSig);

auto result = getImpl().ExistentialSignatures.insert(
std::make_pair(std::make_pair(constraint, canParentSig.getPointer()), canGenericSig));
std::make_pair(key, canGenericSig));
assert(result.second);
(void) result;

Expand Down
6 changes: 3 additions & 3 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2926,7 +2926,7 @@ CanType ValueDecl::getOverloadSignatureType() const {
/*topLevelFunction=*/true, isMethod,
/*isInitializer=*/isa<ConstructorDecl>(afd),
getNumCurryLevels())
->getCanonicalType();
->getMinimalCanonicalType(afd);
}

if (isa<AbstractStorageDecl>(this)) {
Expand All @@ -2942,7 +2942,7 @@ CanType ValueDecl::getOverloadSignatureType() const {
/*topLevelFunction=*/true,
/*isMethod=*/false,
/*isInitializer=*/false, getNumCurryLevels())
->getCanonicalType();
->getMinimalCanonicalType(cast<SubscriptDecl>(this));
}

// We want to curry the default signature type with the 'self' type of the
Expand All @@ -2957,7 +2957,7 @@ CanType ValueDecl::getOverloadSignatureType() const {
auto mappedType = mapSignatureFunctionType(
getASTContext(), getInterfaceType(), /*topLevelFunction=*/false,
/*isMethod=*/false, /*isInitializer=*/false, getNumCurryLevels());
return mappedType->getCanonicalType();
return mappedType->getMinimalCanonicalType(getDeclContext());
}

// Note: If you add more cases to this function, you should update the
Expand Down
23 changes: 11 additions & 12 deletions test/type/subclass_composition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,29 @@ struct Unrelated {}

//
// If a class conforms to a protocol concretely, the resulting protocol
// composition type should be equivalent to the class type.
//
// FIXME: Disabled for now.
// composition type should be equivalent to the class type for redeclaration
// checking purposes.
//

func alreadyConforms<T>(_: Base<T>) {} // expected-note {{'alreadyConforms' previously declared here}}
func alreadyConforms<T>(_: Base<T> & P1) {} // FIXME e/xpected-error {{invalid redeclaration of 'alreadyConforms'}} expected-note {{'alreadyConforms' previously declared here}}
func alreadyConforms<T>(_: Base<T>) {} // expected-note 3 {{'alreadyConforms' previously declared here}}
func alreadyConforms<T>(_: Base<T> & P1) {} // expected-error {{invalid redeclaration of 'alreadyConforms'}}
func alreadyConforms<T>(_: Base<T> & AnyObject) {} // expected-error {{invalid redeclaration of 'alreadyConforms'}}
func alreadyConforms<T>(_: Base<T> & P1 & AnyObject) {} // expected-error {{invalid redeclaration of 'alreadyConforms'}}

func alreadyConformsMeta<T>(_: Base<T>.Type) {} // expected-note {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta<T>(_: (Base<T> & P1).Type) {} // FIXME e/xpected-error {{invalid redeclaration of 'alreadyConformsMeta'}} expected-note {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta<T>(_: (Base<T> & P1).Protocol) {} // FIXME e/xpected-error {{invalid redeclaration of 'alreadyConformsMeta'}} expected-note 3 {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta<T>(_: Base<T>.Type) {} // expected-note 7 {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta<T>(_: (Base<T> & P1).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (Base<T> & P1).Protocol) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (any Base<T> & P1).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (Base<T> & AnyObject).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (Base<T> & P1 & AnyObject).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (Base<T> & P1 & AnyObject).Protocol) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta<T>(_: (any Base<T> & P1 & AnyObject).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}

func alreadyConforms(_: P3) {} // e/xpected-note {{'alreadyConforms' previously declared here}}
func alreadyConforms(_: P3 & AnyObject) {} // FIXME e/xpected-error {{invalid redeclaration of 'alreadyConforms'}}
func alreadyConforms(_: P3) {} // expected-note {{'alreadyConforms' previously declared here}}
func alreadyConforms(_: P3 & AnyObject) {} // expected-error {{invalid redeclaration of 'alreadyConforms'}}

func alreadyConformsMeta(_: P3.Type) {} // FIXME e/xpected-note {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta(_: (P3 & AnyObject).Type) {} // FIXME ex/pected-error {{invalid redeclaration of 'alreadyConformsMeta'}}
func alreadyConformsMeta(_: P3.Type) {} // expected-note {{'alreadyConformsMeta' previously declared here}}
func alreadyConformsMeta(_: (P3 & AnyObject).Type) {} // expected-error {{invalid redeclaration of 'alreadyConformsMeta'}}

// SE-0156 stipulates that a composition can contain multiple classes, as long
// as they are all the same.
Expand Down