mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Fix crash when attempting typo correction on class-bound archetype
Also clean up some of the badness here just a little bit. Fixes <rdar://problem/31093620>.
This commit is contained in:
@@ -493,7 +493,7 @@ static void lookupVisibleMemberDeclsImpl(
|
|||||||
VisitedSet &Visited) {
|
VisitedSet &Visited) {
|
||||||
// Just look through l-valueness. It doesn't affect name lookup.
|
// Just look through l-valueness. It doesn't affect name lookup.
|
||||||
assert(BaseTy && "lookup into null type");
|
assert(BaseTy && "lookup into null type");
|
||||||
BaseTy = BaseTy->getRValueType();
|
assert(!BaseTy->isLValueType());
|
||||||
|
|
||||||
// Handle metatype references, as in "some_type.some_member". These are
|
// Handle metatype references, as in "some_type.some_member". These are
|
||||||
// special and can't have extensions.
|
// special and can't have extensions.
|
||||||
@@ -674,7 +674,10 @@ public:
|
|||||||
|
|
||||||
OverrideFilteringConsumer(Type BaseTy, const DeclContext *DC,
|
OverrideFilteringConsumer(Type BaseTy, const DeclContext *DC,
|
||||||
LazyResolver *resolver)
|
LazyResolver *resolver)
|
||||||
: BaseTy(BaseTy->getRValueType()), DC(DC), TypeResolver(resolver) {
|
: BaseTy(BaseTy), DC(DC), TypeResolver(resolver) {
|
||||||
|
assert(!BaseTy->isLValueType());
|
||||||
|
if (auto *MetaTy = BaseTy->getAs<AnyMetatypeType>())
|
||||||
|
BaseTy = MetaTy->getInstanceType();
|
||||||
assert(DC && BaseTy);
|
assert(DC && BaseTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,11 +727,24 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Does it make sense to substitute types?
|
// Does it make sense to substitute types?
|
||||||
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
|
|
||||||
!BaseTy->is<AnyMetatypeType>() &&
|
// Don't pass UnboundGenericType here. If you see this assertion
|
||||||
!BaseTy->isExistentialType() &&
|
// being hit, fix the caller, don't remove it.
|
||||||
|
assert(!BaseTy->hasUnboundGenericType());
|
||||||
|
|
||||||
|
// If the base type is AnyObject, we might be doing a dynamic
|
||||||
|
// lookup, so the base type won't match the type of the member's
|
||||||
|
// context type.
|
||||||
|
//
|
||||||
|
// If the base type is not a nominal type, we can't substitute
|
||||||
|
// the member type.
|
||||||
|
//
|
||||||
|
// If the member is a free function and not a member of a type,
|
||||||
|
// don't substitute either.
|
||||||
|
bool shouldSubst = (!BaseTy->isAnyObject() &&
|
||||||
!BaseTy->hasTypeVariable() &&
|
!BaseTy->hasTypeVariable() &&
|
||||||
VD->getDeclContext()->isTypeContext();
|
BaseTy->getNominalOrBoundGenericNominal() &&
|
||||||
|
VD->getDeclContext()->isTypeContext());
|
||||||
ModuleDecl *M = DC->getParentModule();
|
ModuleDecl *M = DC->getParentModule();
|
||||||
|
|
||||||
auto FoundSignature = VD->getOverloadSignature();
|
auto FoundSignature = VD->getOverloadSignature();
|
||||||
@@ -860,7 +876,7 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
|
|||||||
if (ExtendedType)
|
if (ExtendedType)
|
||||||
BaseDecl = ExtendedType->getNominalOrBoundGenericNominal();
|
BaseDecl = ExtendedType->getNominalOrBoundGenericNominal();
|
||||||
} else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) {
|
} else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) {
|
||||||
ExtendedType = ND->getDeclaredType();
|
ExtendedType = ND->getDeclaredTypeInContext();
|
||||||
BaseDecl = ND;
|
BaseDecl = ND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3113,14 +3113,14 @@ public:
|
|||||||
NeedLeadingDot = !HaveDot;
|
NeedLeadingDot = !HaveDot;
|
||||||
|
|
||||||
// This is horrible
|
// This is horrible
|
||||||
|
ExprType = ExprType->getRValueType();
|
||||||
this->ExprType = ExprType;
|
this->ExprType = ExprType;
|
||||||
if (ExprType->hasTypeParameter()) {
|
if (ExprType->hasTypeParameter()) {
|
||||||
DeclContext *DC;
|
DeclContext *DC;
|
||||||
if (VD) {
|
if (VD) {
|
||||||
DC = VD->getInnermostDeclContext();
|
DC = VD->getInnermostDeclContext();
|
||||||
this->ExprType = DC->mapTypeIntoContext(ExprType);
|
this->ExprType = DC->mapTypeIntoContext(ExprType);
|
||||||
} else if (auto NTD = ExprType->getRValueType()->getRValueInstanceType()
|
} else if (auto NTD = ExprType->getRValueInstanceType()->getAnyNominal()) {
|
||||||
->getAnyNominal()) {
|
|
||||||
DC = NTD;
|
DC = NTD;
|
||||||
this->ExprType = DC->mapTypeIntoContext(ExprType);
|
this->ExprType = DC->mapTypeIntoContext(ExprType);
|
||||||
}
|
}
|
||||||
@@ -3138,7 +3138,7 @@ public:
|
|||||||
Done = true;
|
Done = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto *TT = ExprType->getRValueType()->getAs<TupleType>()) {
|
if (auto *TT = ExprType->getAs<TupleType>()) {
|
||||||
getTupleExprCompletions(TT);
|
getTupleExprCompletions(TT);
|
||||||
Done = true;
|
Done = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,3 +84,38 @@ _ = [Any]().withUnsafeBufferPointer { (buf) -> [Any] in
|
|||||||
guard let base = buf.baseAddress else { return [] }
|
guard let base = buf.baseAddress else { return [] }
|
||||||
return (base ..< base + buf.count).m // expected-error {{value of type 'CountableRange<_>' has no member 'm'}}
|
return (base ..< base + buf.count).m // expected-error {{value of type 'CountableRange<_>' has no member 'm'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Typo correction with class-bound archetypes.
|
||||||
|
class SomeClass {
|
||||||
|
func match1() {}
|
||||||
|
// expected-note@-1 {{did you mean 'match1'?}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func takesSomeClassArchetype<T : SomeClass>(_ t: T) {
|
||||||
|
t.match0()
|
||||||
|
// expected-error@-1 {{value of type 'T' has no member 'match0'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typo correction of unqualified lookup from generic context.
|
||||||
|
struct Generic<T> {
|
||||||
|
func match1() {}
|
||||||
|
// expected-note@-1 {{did you mean 'match1'?}}
|
||||||
|
|
||||||
|
class Inner {
|
||||||
|
func doStuff() {
|
||||||
|
match0()
|
||||||
|
// expected-error@-1 {{use of unresolved identifier 'match0'}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typo correction with AnyObject.
|
||||||
|
func takesAnyObject(_ t: AnyObject) {
|
||||||
|
_ = t.rawPointer
|
||||||
|
// expected-error@-1 {{value of type 'AnyObject' has no member 'rawPointer'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func takesAnyObjectArchetype<T : AnyObject>(_ t: T) {
|
||||||
|
_ = t.rawPointer
|
||||||
|
// expected-error@-1 {{value of type 'T' has no member 'rawPointer'}}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user