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:
Slava Pestov
2017-03-20 13:27:11 -07:00
parent 95267109a3
commit 573e832f35
3 changed files with 62 additions and 11 deletions

View File

@@ -493,7 +493,7 @@ static void lookupVisibleMemberDeclsImpl(
VisitedSet &Visited) {
// Just look through l-valueness. It doesn't affect name lookup.
assert(BaseTy && "lookup into null type");
BaseTy = BaseTy->getRValueType();
assert(!BaseTy->isLValueType());
// Handle metatype references, as in "some_type.some_member". These are
// special and can't have extensions.
@@ -674,7 +674,10 @@ public:
OverrideFilteringConsumer(Type BaseTy, const DeclContext *DC,
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);
}
@@ -724,11 +727,24 @@ public:
}
// Does it make sense to substitute types?
bool shouldSubst = !BaseTy->hasUnboundGenericType() &&
!BaseTy->is<AnyMetatypeType>() &&
!BaseTy->isExistentialType() &&
// Don't pass UnboundGenericType here. If you see this assertion
// 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() &&
VD->getDeclContext()->isTypeContext();
BaseTy->getNominalOrBoundGenericNominal() &&
VD->getDeclContext()->isTypeContext());
ModuleDecl *M = DC->getParentModule();
auto FoundSignature = VD->getOverloadSignature();
@@ -860,7 +876,7 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
if (ExtendedType)
BaseDecl = ExtendedType->getNominalOrBoundGenericNominal();
} else if (auto ND = dyn_cast<NominalTypeDecl>(DC)) {
ExtendedType = ND->getDeclaredType();
ExtendedType = ND->getDeclaredTypeInContext();
BaseDecl = ND;
}

View File

@@ -3113,14 +3113,14 @@ public:
NeedLeadingDot = !HaveDot;
// This is horrible
ExprType = ExprType->getRValueType();
this->ExprType = ExprType;
if (ExprType->hasTypeParameter()) {
DeclContext *DC;
if (VD) {
DC = VD->getInnermostDeclContext();
this->ExprType = DC->mapTypeIntoContext(ExprType);
} else if (auto NTD = ExprType->getRValueType()->getRValueInstanceType()
->getAnyNominal()) {
} else if (auto NTD = ExprType->getRValueInstanceType()->getAnyNominal()) {
DC = NTD;
this->ExprType = DC->mapTypeIntoContext(ExprType);
}
@@ -3138,7 +3138,7 @@ public:
Done = true;
}
}
if (auto *TT = ExprType->getRValueType()->getAs<TupleType>()) {
if (auto *TT = ExprType->getAs<TupleType>()) {
getTupleExprCompletions(TT);
Done = true;
}

View File

@@ -84,3 +84,38 @@ _ = [Any]().withUnsafeBufferPointer { (buf) -> [Any] in
guard let base = buf.baseAddress else { return [] }
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'}}
}