Skip to content

Small crasher fixes #11265

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 5 commits into from
Aug 6, 2017
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
8 changes: 7 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,7 +701,10 @@ CanType ASTContext::getAnyObjectType() const {
}

CanType ASTContext::getNeverType() const {
return getNeverDecl()->getDeclaredType()->getCanonicalType();
auto neverDecl = getNeverDecl();
if (!neverDecl)
return CanType();
return neverDecl->getDeclaredType()->getCanonicalType();
}

TypeAliasDecl *ASTContext::getVoidDecl() const {
Expand Down Expand Up @@ -885,6 +888,9 @@ FuncDecl *ASTContext::getEqualIntDecl() const {
if (Impl.EqualIntDecl)
return Impl.EqualIntDecl;

if (!getIntDecl() || !getBoolDecl())
return nullptr;

auto intType = getIntDecl()->getDeclaredType();
auto boolType = getBoolDecl()->getDeclaredType();
SmallVector<ValueDecl *, 30> equalFuncs;
Expand Down
11 changes: 9 additions & 2 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,8 +1062,12 @@ static ValueDecl *getIntToFPWithOverflowOperation(ASTContext &Context,

static ValueDecl *getUnreachableOperation(ASTContext &Context,
Identifier Id) {
auto NeverTy = Context.getNeverType();
if (!NeverTy)
return nullptr;

// () -> Never
return getBuiltinFunction(Id, {}, Context.getNeverType());
return getBuiltinFunction(Id, {}, NeverTy);
}

static ValueDecl *getOnceOperation(ASTContext &Context,
Expand Down Expand Up @@ -1295,8 +1299,11 @@ getSwiftFunctionTypeForIntrinsic(unsigned iid, ArrayRef<Type> TypeArgs,
llvm::Intrinsic::getAttributes(getGlobalLLVMContext(), ID);
Info = FunctionType::ExtInfo();
if (attrs.hasAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoReturn))
llvm::Attribute::NoReturn)) {
ResultTy = Context.getNeverType();
if (!ResultTy)
return false;
}

return true;
}
Expand Down
38 changes: 19 additions & 19 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -855,29 +855,29 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
return;
}
}
}

// Check the generic parameters if our context is a generic type or
// extension thereof.
GenericParamList *dcGenericParams = nullptr;
if (auto nominal = dyn_cast<NominalTypeDecl>(DC))
dcGenericParams = nominal->getGenericParams();
else if (auto ext = dyn_cast<ExtensionDecl>(DC))
dcGenericParams = ext->getGenericParams();
else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
dcGenericParams = subscript->getGenericParams();

while (dcGenericParams) {
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.checkGenericParams(dcGenericParams);
// Check the generic parameters if our context is a generic type or
// extension thereof.
GenericParamList *dcGenericParams = nullptr;
if (auto nominal = dyn_cast<NominalTypeDecl>(DC))
dcGenericParams = nominal->getGenericParams();
else if (auto ext = dyn_cast<ExtensionDecl>(DC))
dcGenericParams = ext->getGenericParams();
else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
dcGenericParams = subscript->getGenericParams();

while (dcGenericParams) {
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
localVal.checkGenericParams(dcGenericParams);

if (!Results.empty())
return;
if (!Results.empty())
return;

if (!isa<ExtensionDecl>(DC))
break;
if (!isa<ExtensionDecl>(DC))
break;

dcGenericParams = dcGenericParams->getOuterParameters();
}
dcGenericParams = dcGenericParams->getOuterParameters();
}

DC = DC->getParentForLookup();
Expand Down
2 changes: 2 additions & 0 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,8 @@ namespace {
ProtocolDecl *protocols[]
= {cxt.getProtocol(KnownProtocolKind::RawRepresentable),
cxt.getProtocol(KnownProtocolKind::Equatable)};
if (!protocols[0] || !protocols[1])
return nullptr;

auto options = getDefaultMakeStructRawValuedOptions();
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
Expand Down
26 changes: 18 additions & 8 deletions lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ namespace {
// of the exit(3) libc function as "func exit(Int32)", not as
// "func exit(CInt)".
static Type unwrapCType(Type T) {
if (auto *NAT = dyn_cast_or_null<NameAliasType>(T.getPointer()))
// Handle missing or invalid stdlib declarations
if (!T || T->hasError())
return Type();
if (auto *NAT = dyn_cast<NameAliasType>(T.getPointer()))
return NAT->getSinglyDesugaredType();
return T;
}
Expand Down Expand Up @@ -334,11 +337,14 @@ namespace {
// that 'Unsafe[Mutable]Pointer<T>' implicitly converts to
// 'Unsafe[Mutable]RawPointer' for interoperability.
if (pointeeQualType->isVoidType()) {
return {
(quals.hasConst() ? Impl.SwiftContext.getUnsafeRawPointerDecl()
: Impl.SwiftContext.getUnsafeMutableRawPointerDecl())
->getDeclaredType(),
ImportHint::OtherPointer};
auto pointerTypeDecl =
(quals.hasConst()
? Impl.SwiftContext.getUnsafeRawPointerDecl()
: Impl.SwiftContext.getUnsafeMutableRawPointerDecl());
if (!pointerTypeDecl)
return Type();
return {pointerTypeDecl->getDeclaredType(),
ImportHint::OtherPointer};
}

// All other C pointers to concrete types map to
Expand All @@ -359,9 +365,13 @@ namespace {

// If the pointed-to type is unrepresentable in Swift, import as
// OpaquePointer.
if (!pointeeType)
return {Impl.SwiftContext.getOpaquePointerDecl()->getDeclaredType(),
if (!pointeeType) {
auto opaquePointer = Impl.SwiftContext.getOpaquePointerDecl();
if (!opaquePointer)
return Type();
return {opaquePointer->getDeclaredType(),
ImportHint::OtherPointer};
}

if (pointeeQualType->isFunctionType()) {
auto funcTy = pointeeType->castTo<FunctionType>();
Expand Down
15 changes: 11 additions & 4 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3792,12 +3792,15 @@ static bool trySequenceSubsequenceConversionFixIts(InFlightDiagnostic &diag,
ConstraintSystem &CS,
Type fromType, Type toType,
Expr *expr) {
if (CS.TC.Context.getStdlibModule() == nullptr) {
if (CS.TC.Context.getStdlibModule() == nullptr)
return false;
}

auto String = CS.TC.getStringType(CS.DC);
auto Substring = CS.TC.getSubstringType(CS.DC);

if (!String || !Substring)
return false;

/// FIXME: Remove this flag when void subscripts are implemented.
/// Make this unconditional and remove the if statement.
if (CS.TC.getLangOpts().FixStringToSubstringConversions) {
Expand Down Expand Up @@ -4744,13 +4747,17 @@ static bool diagnoseImplicitSelfErrors(Expr *fnExpr, Expr *argExpr,
// matches what the user actually wrote instead of what the typechecker
// expects.
SmallVector<TupleTypeElt, 4> elts;
for (auto *el : argTuple->getElements()) {
for (unsigned i = 0, e = argTuple->getNumElements(); i < e; ++i) {
ConcreteDeclRef ref = nullptr;
auto *el = argTuple->getElement(i);
auto typeResult =
TC.getTypeOfExpressionWithoutApplying(el, CS.DC, ref);
if (!typeResult)
return false;
elts.push_back(typeResult);
auto flags = ParameterTypeFlags().withInOut(typeResult->is<InOutType>());
elts.push_back(TupleTypeElt(typeResult->getInOutObjectType(),
argTuple->getElementName(i),
flags));
}

argType = TupleType::get(elts, CS.getASTContext());
Expand Down
5 changes: 3 additions & 2 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,9 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
diag.fixItInsert(resultLoc, fix);
}

FD->getBodyResultTypeLoc() = TypeLoc::withoutLoc(
TC.Context.getNeverType());
auto neverType = TC.Context.getNeverType();
if (neverType)
FD->getBodyResultTypeLoc() = TypeLoc::withoutLoc(neverType);
}
}

Expand Down
9 changes: 8 additions & 1 deletion lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2185,8 +2185,15 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
options |= TR_EditorPlaceholder;
}

// FIXME: initTy should be the same as resultTy; now that typeCheckExpression()
// returns a Type and not bool, we should be able to simplify the listener
// implementation here.
auto initTy = listener.getInitType();
if (initTy->hasDependentMember())
return true;

// Apply the solution to the pattern as well.
if (coercePatternToType(pattern, DC, listener.getInitType(), options,
if (coercePatternToType(pattern, DC, initTy, options,
nullptr, TypeLoc(), listener.isInOut())) {
return true;
}
Expand Down
4 changes: 3 additions & 1 deletion lib/Sema/TypeCheckPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,9 @@ bool TypeChecker::coercePatternToType(Pattern *&P, DeclContext *dc, Type type,
}

EnumElementDecl *elementDecl = Context.getOptionalSomeDecl(optionalKind);
assert(elementDecl && "missing optional some decl?!");
if (!elementDecl)
return true;

OP->setElementDecl(elementDecl);

Pattern *sub = OP->getSubPattern();
Expand Down
2 changes: 2 additions & 0 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5608,6 +5608,8 @@ bool TypeChecker::useObjectiveCBridgeableConformances(DeclContext *dc,
auto keyType = args[0];
auto *hashableProto =
TC.Context.getProtocol(KnownProtocolKind::Hashable);
if (!hashableProto)
return Action::Stop;

auto result = TC.conformsToProtocol(
keyType, hashableProto, DC, options,
Expand Down
4 changes: 3 additions & 1 deletion lib/Sema/TypeCheckStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ static void tryDiagnoseUnnecessaryCastOverOptionSet(ASTContext &Ctx,
auto *NTD = ResultType->getAnyNominal();
if (!NTD)
return;
auto optionSetType = dyn_cast<ProtocolDecl>(Ctx.getOptionSetDecl());
auto optionSetType = dyn_cast_or_null<ProtocolDecl>(Ctx.getOptionSetDecl());
if (!optionSetType)
return;
SmallVector<ProtocolConformance *, 4> conformances;
if (!(optionSetType &&
NTD->lookupConformance(module, optionSetType, conformances)))
Expand Down
10 changes: 8 additions & 2 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,13 @@ Type TypeChecker::resolveTypeInContext(

assert(foundDC);

// selfType is the self type of the context, unless the
// context is a protocol type, in which case we might have
// to use the existential type or superclass bound as a
// parent type instead.
Type selfType;
if (isa<NominalTypeDecl>(typeDecl)) {
if (isa<NominalTypeDecl>(typeDecl) &&
typeDecl->getDeclContext()->getAsProtocolOrProtocolExtensionContext()) {
// When looking up a nominal type declaration inside of a
// protocol extension, always use the nominal type and
// not the protocol 'Self' type.
Expand All @@ -292,7 +297,8 @@ Type TypeChecker::resolveTypeInContext(

if (selfType->is<GenericTypeParamType>() &&
typeDecl->getDeclContext()->getAsClassOrClassExtensionContext()) {
// We found a member of a class from a protocol extension.
// We found a member of a class from a protocol or protocol
// extension.
//
// Get the superclass of the 'Self' type parameter.
auto *sig = foundDC->getGenericSignatureOfContext();
Expand Down
12 changes: 12 additions & 0 deletions test/Constraints/members.swift
Original file line number Diff line number Diff line change
Expand Up @@ -417,3 +417,15 @@ extension Array where Element == Int {
// expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min()'}}
}
}

// Crash in diagnoseImplicitSelfErrors()

struct Aardvark {
var snout: Int

mutating func burrow() {
dig(&snout, .y) // expected-error {{type 'Int' has no member 'y'}}
}

func dig(_: inout Int, _: Int) {}
}
4 changes: 4 additions & 0 deletions test/decl/ext/protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ protocol ConformedProtocol {
class BaseWithAlias<T> : ConformedProtocol {
typealias ConcreteAlias = T

struct NestedNominal {}

func baseMethod(_: T) {}
}

Expand All @@ -261,6 +263,8 @@ extension ExtendedProtocol where Self : DerivedWithAlias {
func f3(x: AbstractConformanceAlias) {
let _: DerivedWithAlias = x
}

func f4(x: NestedNominal) {}
}

// ----------------------------------------------------------------------------
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// RUN: not %target-sil-opt %s
func n->a{return:}class a
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

// REQUIRES: asserts
// RUN: not --crash %target-swift-frontend %s -emit-ir
// RUN: not %target-swift-frontend %s -emit-ir
protocol A{{}protocol A{func a:Self.a}typealias e:A.a
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

// REQUIRES: asserts
// RUN: not --crash %target-swift-frontend %s -emit-ir
// RUN: not %target-swift-frontend %s -emit-ir
protocol b:a{init(t:a}class a{class a