Merge pull request #17931 from rintaro/4.2-ide-complete-rdar40956846
[4.2][CodeComplete] Fix crasher when completing inout IUO variable
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index e1b37d9..ad3f600 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -885,10 +885,21 @@
ERROR(missing_nullary_call,none,
"function produces expected type %0; did you mean to call it with '()'?",
(Type))
-ERROR(missing_unwrap_optional,none,
- "value of optional type %0 not unwrapped; did you mean to use '!' "
- "or '?'?",
- (Type))
+ERROR(optional_not_unwrapped,none,
+ "value of optional type %0 must be unwrapped to a value of type %1",
+ (Type, Type))
+NOTE(unwrap_with_default_value,none,
+ "coalesce using '?" "?' to provide a default when the optional value "
+ "contains 'nil'", ())
+NOTE(unwrap_with_force_value,none,
+ "force-unwrap using '!' to abort execution if the optional value contains "
+ "'nil'", ())
+ERROR(optional_base_not_unwrapped,none,
+ "value of optional type %0 must be unwrapped to refer to member %1 of "
+ "wrapped base type %2", (Type, DeclName, Type))
+NOTE(optional_base_chain,none,
+ "chain the optional using '?' to access member %0 only for non-'nil' "
+ "base values", (DeclName))
ERROR(missing_unwrap_optional_try,none,
"value of optional type %0 not unwrapped; did you mean to use 'try!' "
"or chain with '?'?",
diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def
index 288837c..d160d0d 100644
--- a/include/swift/AST/KnownIdentifiers.def
+++ b/include/swift/AST/KnownIdentifiers.def
@@ -135,6 +135,7 @@
IDENTIFIER(CastingPrecedence)
IDENTIFIER(DefaultPrecedence)
IDENTIFIER(FunctionArrowPrecedence)
+IDENTIFIER(NilCoalescingPrecedence)
IDENTIFIER(TernaryPrecedence)
// Builtins and literals
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a6ae2f8..f27e02f 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -1293,6 +1293,26 @@
Arguments.push_back("-ldl");
}
+/// Returns true if the compiler depends on features provided by the ObjC
+/// runtime that are not present on the deployment target indicated by
+/// \p triple.
+static bool wantsObjCRuntime(const llvm::Triple &triple) {
+ assert((!triple.isTvOS() || triple.isiOS()) &&
+ "tvOS is considered a kind of iOS");
+
+ // When updating the versions listed here, please record the most recent
+ // feature being depended on and when it was introduced:
+ //
+ // - The hook to override class_getImageName (macOS 10.14 and equivalent)
+ if (triple.isiOS())
+ return triple.isOSVersionLT(12);
+ if (triple.isMacOSX())
+ return triple.isMacOSXVersionLT(10, 14);
+ if (triple.isWatchOS())
+ return triple.isOSVersionLT(5);
+ llvm_unreachable("unknown Darwin OS");
+}
+
ToolChain::InvocationInfo
toolchains::Darwin::constructInvocation(const LinkJobAction &job,
const JobContext &context) const {
@@ -1377,15 +1397,9 @@
if (llvm::sys::fs::exists(CompilerRTPath))
Arguments.push_back(context.Args.MakeArgString(CompilerRTPath));
- bool wantsObjCRuntime = false;
- if (Triple.isiOS())
- wantsObjCRuntime = Triple.isOSVersionLT(9);
- else if (Triple.isMacOSX())
- wantsObjCRuntime = Triple.isMacOSXVersionLT(10, 11);
-
if (context.Args.hasFlag(options::OPT_link_objc_runtime,
options::OPT_no_link_objc_runtime,
- /*Default=*/wantsObjCRuntime)) {
+ /*Default=*/wantsObjCRuntime(Triple))) {
llvm::SmallString<128> ARCLiteLib(D.getSwiftProgramPath());
llvm::sys::path::remove_filename(ARCLiteLib); // 'swift'
llvm::sys::path::remove_filename(ARCLiteLib); // 'bin'
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 7ffb330..5b76ad9 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -599,8 +599,10 @@
KnownProtocolKind::Hashable);
auto conformance = SGF.SGM.M.getSwiftModule()->lookupConformance(
inputSubstType, protocol);
- auto result = SGF.emitAnyHashableErasure(Loc, v, inputSubstType,
- *conformance, ctxt);
+ auto addr = v.getType().isAddress() ? v : v.materialize(SGF, Loc);
+ auto result = SGF.emitAnyHashableErasure(Loc, addr,
+ inputSubstType, *conformance,
+ ctxt);
if (result.isInContext())
return ManagedValue::forInContext();
return std::move(result).getAsSingleValue(SGF, Loc);
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 52c0fea..d69b922 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -7906,6 +7906,27 @@
return exprNeedsParensOutsideFollowingOperator(TC, DC, expr, rootExpr, asPG);
}
+bool swift::exprNeedsParensBeforeAddingNilCoalescing(TypeChecker &TC,
+ DeclContext *DC,
+ Expr *expr) {
+ auto asPG =
+ TC.lookupPrecedenceGroup(DC, DC->getASTContext().Id_NilCoalescingPrecedence,
+ SourceLoc());
+ if (!asPG) return true;
+ return exprNeedsParensInsideFollowingOperator(TC, DC, expr, asPG);
+}
+
+bool swift::exprNeedsParensAfterAddingNilCoalescing(TypeChecker &TC,
+ DeclContext *DC,
+ Expr *expr,
+ Expr *rootExpr) {
+ auto asPG =
+ TC.lookupPrecedenceGroup(DC, DC->getASTContext().Id_NilCoalescingPrecedence,
+ SourceLoc());
+ if (!asPG) return true;
+ return exprNeedsParensOutsideFollowingOperator(TC, DC, expr, rootExpr, asPG);
+}
+
namespace {
class ExprWalker : public ASTWalker {
ExprRewriter &Rewriter;
@@ -8067,7 +8088,7 @@
switch (fix.first.getKind()) {
case FixKind::ForceOptional: {
- const Expr *unwrapped = affected->getValueProvidingExpr();
+ Expr *unwrapped = affected->getValueProvidingExpr();
auto type = solution.simplifyType(getType(affected))
->getRValueObjectType();
@@ -8078,25 +8099,17 @@
"try!");
} else {
- auto diag = TC.diagnose(affected->getLoc(),
- diag::missing_unwrap_optional, type);
- if (affected->canAppendPostfixExpression(true)) {
- diag.fixItInsertAfter(affected->getEndLoc(), "!");
- } else {
- diag.fixItInsert(affected->getStartLoc(), "(")
- .fixItInsertAfter(affected->getEndLoc(), ")!");
- }
+ return diagnoseUnwrap(TC, DC, unwrapped, type);
}
return true;
}
- case FixKind::OptionalChaining: {
+ case FixKind::UnwrapOptionalBase: {
auto type = solution.simplifyType(getType(affected))
->getRValueObjectType();
- auto diag = TC.diagnose(affected->getLoc(),
- diag::missing_unwrap_optional, type);
- diag.fixItInsertAfter(affected->getEndLoc(), "?");
- return true;
+ DeclName memberName = fix.first.getDeclNameArgument(*this);
+ return diagnoseBaseUnwrapForMemberAccess(affected, type, memberName,
+ SourceRange());
}
case FixKind::ForceDowncast: {
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index ea268ec..840834d 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2199,22 +2199,15 @@
// telling us that it knows what it is doing, then believe it.
if (!options.contains(TCC_ForceRecheck)) {
if (CS.TC.isExprBeingDiagnosed(subExpr)) {
- auto exprAndCS = CS.TC.getExprBeingDiagnosed(subExpr);
- auto *savedExpr = exprAndCS.first;
+ auto *savedExpr = CS.TC.getExprBeingDiagnosed(subExpr);
if (subExpr == savedExpr)
return subExpr;
- auto *oldCS = exprAndCS.second;
-
- // The types on the result might have already been cached into
- // another CS, but likely not this one.
- if (oldCS != &CS)
- CS.transferExprTypes(oldCS, savedExpr);
-
+ CS.cacheExprTypes(savedExpr);
return savedExpr;
}
- CS.TC.addExprForDiagnosis(subExpr, std::make_pair(subExpr, &CS));
+ CS.TC.addExprForDiagnosis(subExpr, subExpr);
}
// Validate contextual type before trying to use it.
@@ -2262,15 +2255,6 @@
allowFreeTypeVariables)
TCEOptions |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
- // If we're not passing down contextual type information this time, but the
- // original failure had type info that wasn't an optional type,
- // then set the flag to prefer fixits with force unwrapping.
- if (!convertType) {
- auto previousType = CS.getContextualType();
- if (previousType && previousType->getOptionalObjectType().isNull())
- TCEOptions |= TypeCheckExprFlags::PreferForceUnwrapToOptional;
- }
-
auto resultTy = CS.TC.typeCheckExpression(
subExpr, CS.DC, TypeLoc::withoutLoc(convertType), convertTypePurpose,
TCEOptions, listener, &CS);
@@ -2300,7 +2284,8 @@
SavedTypeData.restore();
}
- CS.TC.addExprForDiagnosis(preCheckedExpr, std::make_pair(subExpr, &CS));
+ if (preCheckedExpr != subExpr)
+ CS.TC.addExprForDiagnosis(preCheckedExpr, subExpr);
return subExpr;
}
@@ -7751,15 +7736,9 @@
}
if (!optionalResult.ViableCandidates.empty()) {
- // By default we assume that the LHS type is not optional.
- StringRef fixIt = "!";
- auto contextualType = CS.getContextualType();
- if (contextualType && isa<OptionalType>(contextualType.getPointer()))
- fixIt = "?";
-
- diagnose(BaseLoc, diag::missing_unwrap_optional, baseObjTy)
- .fixItInsertAfter(baseExpr->getEndLoc(), fixIt);
- return true;
+ if (diagnoseBaseUnwrapForMemberAccess(baseExpr, baseObjTy, memberName,
+ memberRange))
+ return true;
}
}
@@ -8666,3 +8645,76 @@
diagnoseFailureForExpr(expr);
return true;
}
+
+bool swift::diagnoseUnwrap(TypeChecker &TC, DeclContext *DC,
+ Expr *expr, Type type) {
+ Type unwrappedType = type->getOptionalObjectType();
+ if (!unwrappedType)
+ return false;
+
+ TC.diagnose(expr->getLoc(), diag::optional_not_unwrapped, type,
+ unwrappedType);
+
+ // Suggest a default value via ?? <default value>
+ {
+ auto diag =
+ TC.diagnose(expr->getLoc(), diag::unwrap_with_default_value);
+
+ // Figure out what we need to parenthesize.
+ bool needsParensInside =
+ exprNeedsParensBeforeAddingNilCoalescing(TC, DC, expr);
+ bool needsParensOutside =
+ exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, expr);
+
+ llvm::SmallString<2> insertBefore;
+ llvm::SmallString<32> insertAfter;
+ if (needsParensOutside) {
+ insertBefore += "(";
+ }
+ if (needsParensInside) {
+ insertBefore += "(";
+ insertAfter += ")";
+ }
+ insertAfter += " ?? <" "#default value#" ">";
+ if (needsParensOutside)
+ insertAfter += ")";
+
+ if (!insertBefore.empty()) {
+ diag.fixItInsert(expr->getStartLoc(), insertBefore);
+ }
+ diag.fixItInsertAfter(expr->getEndLoc(), insertAfter);
+ }
+
+ // Suggest a force-unwrap.
+ {
+ auto diag =
+ TC.diagnose(expr->getLoc(), diag::unwrap_with_force_value);
+ if (expr->canAppendPostfixExpression(true)) {
+ diag.fixItInsertAfter(expr->getEndLoc(), "!");
+ } else {
+ diag.fixItInsert(expr->getStartLoc(), "(")
+ .fixItInsertAfter(expr->getEndLoc(), ")!");
+ }
+ }
+
+ return true;
+}
+
+bool swift::diagnoseBaseUnwrapForMemberAccess(Expr *baseExpr, Type baseType,
+ DeclName memberName,
+ SourceRange memberRange) {
+ auto unwrappedBaseType = baseType->getOptionalObjectType();
+ if (!unwrappedBaseType)
+ return false;
+
+ ASTContext &ctx = baseType->getASTContext();
+ DiagnosticEngine &diags = ctx.Diags;
+ diags.diagnose(baseExpr->getLoc(), diag::optional_base_not_unwrapped,
+ baseType, memberName, unwrappedBaseType);
+
+ diags.diagnose(baseExpr->getLoc(), diag::optional_base_chain, memberName)
+ .fixItInsertAfter(baseExpr->getEndLoc(), "?");
+ diags.diagnose(baseExpr->getLoc(), diag::unwrap_with_force_value)
+ .fixItInsertAfter(baseExpr->getEndLoc(), "!");
+ return true;
+}
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 5d79878..616d085 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -3548,18 +3548,9 @@
// Value member lookup has some hacks too.
if (shouldAttemptFixes() && baseObjTy->getOptionalObjectType()) {
// If the base type was an optional, look through it.
-
- // Determine whether or not we want to provide an optional chaining fixit or
- // a force unwrap fixit.
- bool optionalChain;
- if (!getContextualType())
- optionalChain = !(Options & ConstraintSystemFlags::PreferForceUnwrapToOptional);
- else
- optionalChain = !getContextualType()->getOptionalObjectType().isNull();
- auto fixKind = optionalChain ? FixKind::OptionalChaining : FixKind::ForceOptional;
- // Note the fix.
- if (recordFix(fixKind, locator))
+ // We're unwrapping the base to perform a member access.
+ if (recordFix(Fix::getUnwrapOptionalBase(*this, member), locator))
return SolutionKind::Error;
// Look through one level of optional.
@@ -4871,8 +4862,8 @@
getDefaultDecompositionOptions(flags) | TMF_ApplyingFix;
switch (fix.getKind()) {
case FixKind::ForceOptional:
- case FixKind::OptionalChaining: {
- // Assume that '!' was applied to the first type.
+ case FixKind::UnwrapOptionalBase: {
+ // Assume that we've unwrapped the first type.
auto result =
matchTypes(type1->getRValueObjectType()->getOptionalObjectType(), type2,
matchKind, subflags, locator);
diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp
index e7b51cc..3bc0b0b 100644
--- a/lib/Sema/CalleeCandidateInfo.cpp
+++ b/lib/Sema/CalleeCandidateInfo.cpp
@@ -992,10 +992,10 @@
// Check for optional near miss.
if (auto argOptType = substitution->getOptionalObjectType()) {
if (isSubstitutableFor(argOptType, paramArchetype, CS.DC)) {
- CS.TC.diagnose(badArgExpr->getLoc(), diag::missing_unwrap_optional,
- argType);
- foundFailure = true;
- break;
+ if (diagnoseUnwrap(CS.TC, CS.DC, badArgExpr, substitution)) {
+ foundFailure = true;
+ break;
+ }
}
}
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index 622cfb1..aec4737 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -487,17 +487,29 @@
return Fix(FixKind::ForceDowncast, index);
}
+Fix Fix::getUnwrapOptionalBase(ConstraintSystem &cs, DeclName memberName) {
+ unsigned index = cs.FixedDeclNames.size();
+ cs.FixedDeclNames.push_back(memberName);
+ return Fix(FixKind::UnwrapOptionalBase, index);
+}
+
Type Fix::getTypeArgument(ConstraintSystem &cs) const {
assert(getKind() == FixKind::ForceDowncast);
return cs.FixedTypes[Data];
}
+/// If this fix has a name argument, retrieve it.
+DeclName Fix::getDeclNameArgument(ConstraintSystem &cs) const {
+ assert(getKind() == FixKind::UnwrapOptionalBase);
+ return cs.FixedDeclNames[Data];
+}
+
StringRef Fix::getName(FixKind kind) {
switch (kind) {
case FixKind::ForceOptional:
return "fix: force optional";
- case FixKind::OptionalChaining:
- return "fix: optional chaining";
+ case FixKind::UnwrapOptionalBase:
+ return "fix: unwrap optional base of member lookup";
case FixKind::ForceDowncast:
return "fix: force downcast";
case FixKind::AddressOf:
diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h
index ca09d09..560a80f 100644
--- a/lib/Sema/Constraint.h
+++ b/lib/Sema/Constraint.h
@@ -233,8 +233,8 @@
/// Introduce a '!' to force an optional unwrap.
ForceOptional,
- /// Introduce a '?.' to begin optional chaining.
- OptionalChaining,
+ /// Unwrap an optional base when we have a member access.
+ UnwrapOptionalBase,
/// Append 'as! T' to force a downcast to the specified type.
ForceDowncast,
@@ -265,17 +265,26 @@
public:
Fix(FixKind kind) : Kind(kind), Data(0) {
assert(kind != FixKind::ForceDowncast && "Use getForceDowncast()");
+ assert(kind != FixKind::UnwrapOptionalBase &&
+ "Use getUnwrapOptionalBase()");
}
/// Produce a new fix that performs a forced downcast to the given type.
static Fix getForcedDowncast(ConstraintSystem &cs, Type toType);
+ /// Produce a new fix that unwraps an optional base for an access to a member
+ /// with the given name.
+ static Fix getUnwrapOptionalBase(ConstraintSystem &cs, DeclName memberName);
+
/// Retrieve the kind of fix.
FixKind getKind() const { return Kind; }
/// If this fix has a type argument, retrieve it.
Type getTypeArgument(ConstraintSystem &cs) const;
+ /// If this fix has a name argument, retrieve it.
+ DeclName getDeclNameArgument(ConstraintSystem &cs) const;
+
/// Return a string representation of a fix.
static llvm::StringRef getName(FixKind kind);
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 763cb66..f655902 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -796,10 +796,6 @@
/// Whether we allow the solver to attempt fixes to the system.
AllowFixes = 0x01,
- /// Set if the client prefers fixits to be in the form of force unwrapping
- /// or optional chaining to return an optional.
- PreferForceUnwrapToOptional = 0x02,
-
/// If set, this is going to prevent constraint system from erasing all
/// discovered solutions except the best one.
ReturnAllDiscoveredSolutions = 0x04,
@@ -1001,6 +997,9 @@
/// Types used in fixes.
std::vector<Type> FixedTypes;
+ /// Declaration names used in fixes.
+ std::vector<DeclName> FixedDeclNames;
+
/// \brief The set of remembered disjunction choices used to reach
/// the current constraint system.
SmallVector<std::pair<ConstraintLocator*, unsigned>, 32>
@@ -1326,30 +1325,6 @@
bool walkToDeclPre(Decl *decl) override { return false; }
};
- class TransferExprTypes : public ASTWalker {
- ConstraintSystem &toCS;
- ConstraintSystem &fromCS;
-
- public:
- TransferExprTypes(ConstraintSystem &toCS, ConstraintSystem &fromCS)
- : toCS(toCS), fromCS(fromCS) {}
-
- Expr *walkToExprPost(Expr *expr) override {
- if (fromCS.hasType(expr))
- toCS.setType(expr, fromCS.getType(expr));
-
- return expr;
- }
-
- /// \brief Ignore statements.
- std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
- return { false, stmt };
- }
-
- /// \brief Ignore declarations.
- bool walkToDeclPre(Decl *decl) override { return false; }
- };
-
public:
void setExprTypes(Expr *expr) {
@@ -1375,10 +1350,6 @@
expr->walk(CacheExprTypes(expr, *this, excludeRoot));
}
- void transferExprTypes(ConstraintSystem *oldCS, Expr *expr) {
- expr->walk(TransferExprTypes(*this, *oldCS));
- }
-
/// \brief The current solver state.
///
/// This will be non-null when we're actively solving the constraint
@@ -3508,6 +3479,36 @@
return { true, expr };
}
};
+
+
+/// Diagnose an attempt to recover when we have a value of optional type
+/// that needs to be unwrapped.
+///
+/// \returns true if a diagnostic was produced.
+bool diagnoseUnwrap(TypeChecker &TC, DeclContext *DC, Expr *expr, Type type);
+
+/// Diagnose an attempt to recover from a member access into a value of
+/// optional type which needed to be unwrapped for the member to be found.
+///
+/// \returns true if a diagnostic was produced.
+bool diagnoseBaseUnwrapForMemberAccess(Expr *baseExpr, Type baseType,
+ DeclName memberName,
+ SourceRange memberRange);
+
+// Return true if, when replacing "<expr>" with "<expr> ?? T", parentheses need
+// to be added around <expr> first in order to maintain the correct precedence.
+bool exprNeedsParensBeforeAddingNilCoalescing(TypeChecker &TC,
+ DeclContext *DC,
+ Expr *expr);
+
+// Return true if, when replacing "<expr>" with "<expr> as T", parentheses need
+// to be added around the new expression in order to maintain the correct
+// precedence.
+bool exprNeedsParensAfterAddingNilCoalescing(TypeChecker &TC,
+ DeclContext *DC,
+ Expr *expr,
+ Expr *rootExpr);
+
} // end namespace swift
#endif // LLVM_SWIFT_SEMA_CONSTRAINT_SYSTEM_H
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 5c1aa59..ccd6bc0 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1856,8 +1856,6 @@
// Construct a constraint system from this expression.
ConstraintSystemOptions csOptions = ConstraintSystemFlags::AllowFixes;
- if (options.contains(TypeCheckExprFlags::PreferForceUnwrapToOptional))
- csOptions |= ConstraintSystemFlags::PreferForceUnwrapToOptional;
ConstraintSystem cs(*this, dc, csOptions);
cs.baseCS = baseCS;
CleanupIllFormedExpressionRAII cleanup(Context, expr);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 1e4b78c..bb4a7d7 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -57,12 +57,6 @@
using ConformanceMap =
llvm::DenseMap<SubstitutableType *, SmallVector<ProtocolConformance *, 2>>;
-/// \brief Used for recursive lookups into an expr that is already
-/// being type-checked and the constraint system in which its type is
-/// stored.
-using ExprAndConstraintSystem =
- std::pair<Expr *, constraints::ConstraintSystem *>;
-
/// Special-case type checking semantics for certain declarations.
enum class DeclTypeCheckingSemantics {
/// A normal declaration.
@@ -248,10 +242,6 @@
/// and so we should not visit bodies of non-single expression closures.
SkipMultiStmtClosures = 0x40,
- /// Set if the client prefers fixits to be in the form of force unwrapping
- /// or optional chaining to return an optional.
- PreferForceUnwrapToOptional = 0x80,
-
/// If set, don't apply a solution.
SkipApplyingSolution = 0x100,
};
@@ -907,7 +897,7 @@
llvm::DenseSet<CanType> CIntegerTypes;
/// The set of expressions currently being analyzed for failures.
- llvm::DenseMap<Expr*, ExprAndConstraintSystem> DiagnosedExprs;
+ llvm::DenseMap<Expr*, Expr*> DiagnosedExprs;
ModuleDecl *StdlibModule = nullptr;
@@ -2497,13 +2487,13 @@
void checkInitializerErrorHandling(Initializer *I, Expr *E);
void checkEnumElementErrorHandling(EnumElementDecl *D);
- void addExprForDiagnosis(Expr *E1, ExprAndConstraintSystem Result) {
+ void addExprForDiagnosis(Expr *E1, Expr *Result) {
DiagnosedExprs[E1] = Result;
}
bool isExprBeingDiagnosed(Expr *E) {
return DiagnosedExprs.count(E);
}
- ExprAndConstraintSystem getExprBeingDiagnosed(Expr *E) {
+ Expr *getExprBeingDiagnosed(Expr *E) {
return DiagnosedExprs[E];
}
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index c364c91..3c3b7dc 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -24,6 +24,7 @@
#include "swift/Runtime/ExistentialContainer.h"
#include "swift/Runtime/HeapObject.h"
#include "swift/Runtime/Mutex.h"
+#include "swift/Runtime/Once.h"
#include "swift/Strings.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
@@ -54,6 +55,7 @@
#endif
#if SWIFT_OBJC_INTEROP
+#include <dlfcn.h>
#include <objc/runtime.h>
#endif
@@ -593,7 +595,7 @@
// Otherwise, the input should already be a Swift class object.
auto theClass = cast<ClassMetadata>(theMetadata);
- assert(theClass->isTypeMetadata() && !theClass->isArtificialSubclass());
+ assert(theClass->isTypeMetadata());
return theClass;
}
@@ -2017,6 +2019,45 @@
return self;
}
+#if SWIFT_OBJC_INTEROP
+
+// FIXME: This is from a later version of <objc/runtime.h>. Once the declaration
+// is available in SDKs, we can remove this typedef.
+typedef BOOL (*objc_hook_getImageName)(
+ Class _Nonnull cls, const char * _Nullable * _Nonnull outImageName);
+
+/// \see customGetImageNameFromClass
+static objc_hook_getImageName defaultGetImageNameFromClass = nullptr;
+
+/// A custom implementation of Objective-C's class_getImageName for Swift
+/// classes, which knows how to handle dynamically-initialized class metadata.
+///
+/// Per the documentation for objc_setHook_getImageName, any non-Swift classes
+/// will still go through the normal implementation of class_getImageName,
+/// which is stored in defaultGetImageNameFromClass.
+static BOOL
+customGetImageNameFromClass(Class _Nonnull objcClass,
+ const char * _Nullable * _Nonnull outImageName) {
+ auto *classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass);
+
+ // Is this a Swift class?
+ if (classAsMetadata->isTypeMetadata() &&
+ !classAsMetadata->isArtificialSubclass()) {
+ const void *descriptor = classAsMetadata->getDescription();
+ assert(descriptor &&
+ "all non-artificial Swift classes should have a descriptor");
+ Dl_info imageInfo = {};
+ if (!dladdr(descriptor, &imageInfo))
+ return NO;
+ *outImageName = imageInfo.dli_fname;
+ return imageInfo.dli_fname != nullptr;
+ }
+
+ // If not, fall back to the default implementation.
+ return defaultGetImageNameFromClass(objcClass, outImageName);
+}
+#endif
+
/// Initialize the field offset vector for a dependent-layout class, using the
/// "Universal" layout strategy.
void
@@ -2025,6 +2066,23 @@
size_t numFields,
const TypeLayout * const *fieldTypes,
size_t *fieldOffsets) {
+#if SWIFT_OBJC_INTEROP
+ // Register our custom implementation of class_getImageName.
+ static swift_once_t onceToken;
+ swift_once(&onceToken, [](void *unused) {
+ (void)unused;
+ // FIXME: This is from a later version of <objc/runtime.h>. Once the
+ // declaration is available in SDKs, we can access this directly instead of
+ // using dlsym.
+ if (void *setHookPtr = dlsym(RTLD_DEFAULT, "objc_setHook_getImageName")) {
+ auto setHook = reinterpret_cast<
+ void(*)(objc_hook_getImageName _Nonnull,
+ objc_hook_getImageName _Nullable * _Nonnull)>(setHookPtr);
+ setHook(customGetImageNameFromClass, &defaultGetImageNameFromClass);
+ }
+ }, nullptr);
+#endif
+
_swift_initializeSuperclass(self);
// Start layout by appending to a standard heap object header.
diff --git a/test/ClangImporter/cfuncs_parse.swift b/test/ClangImporter/cfuncs_parse.swift
index 26089ce..92a7ebb 100644
--- a/test/ClangImporter/cfuncs_parse.swift
+++ b/test/ClangImporter/cfuncs_parse.swift
@@ -16,21 +16,27 @@
func test_cfunc3_a() {
let b = cfunc3( { (a : Double, b : Double) -> Double in a + b } )
- _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') not unwrapped; did you mean to use '!' or '?'?}}
+ _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
_ = b!(1.5, 2.5) as Double
_ = b as Double// expected-error{{cannot convert value of type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') to type 'Double' in coercion}}
}
func test_cfunc3_b() {
let b = cfunc3( { a, b in a + b } )
- _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') not unwrapped; did you mean to use '!' or '?'?}}
+ _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
_ = b!(1.5, 2.5) as Double
_ = b as Double// expected-error{{cannot convert value of type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') to type 'Double' in coercion}}
}
func test_cfunc3_c() {
let b = cfunc3({ $0 + $1 })
- _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') not unwrapped; did you mean to use '!' or '?'?}}
+ _ = b(1.5, 2.5) as Double // expected-error{{value of optional type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
_ = b!(1.5, 2.5) as Double
_ = b as Double// expected-error{{cannot convert value of type 'double_bin_op_block?' (aka 'Optional<(Double, Double) -> Double>') to type 'Double' in coercion}}
}
diff --git a/test/ClangImporter/nullability.swift b/test/ClangImporter/nullability.swift
index cb7e8e0..73bf093 100644
--- a/test/ClangImporter/nullability.swift
+++ b/test/ClangImporter/nullability.swift
@@ -23,14 +23,22 @@
if sc.methodD() == nil { } // expected-warning {{comparing non-optional value of type 'Any' to nil always returns false}}
sc.methodE(sc)
- sc.methodE(osc) // expected-error{{value of optional type 'SomeClass?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=!}}
+ sc.methodE(osc) // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
sc.methodF(sc, second: sc)
- sc.methodF(osc, second: sc) // expected-error{{value of optional type 'SomeClass?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=!}}
- sc.methodF(sc, second: osc) // expected-error{{value of optional type 'SomeClass?' not unwrapped; did you mean to use '!' or '?'?}} {{29-29=!}}
+ sc.methodF(osc, second: sc) // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
+ sc.methodF(sc, second: osc) // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
sc.methodG(sc, second: sc)
- sc.methodG(osc, second: sc) // expected-error{{value of optional type 'SomeClass?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=!}}
+ sc.methodG(osc, second: sc) // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
sc.methodG(sc, second: osc)
let ci: CInt = 1
@@ -41,7 +49,9 @@
let sc3 = SomeClass(double: 1.5)
if sc3 == nil { } // okay
- let sc3a: SomeClass = sc3 // expected-error{{value of optional type 'SomeClass?' not unwrapped}} {{28-28=!}}
+ let sc3a: SomeClass = sc3 // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
_ = sc3a
let sc4 = sc.returnMe()
diff --git a/test/ClangImporter/objc_parse.swift b/test/ClangImporter/objc_parse.swift
index 9da60fa..aed2ec8 100644
--- a/test/ClangImporter/objc_parse.swift
+++ b/test/ClangImporter/objc_parse.swift
@@ -130,7 +130,9 @@
var obj : AnyObject = b
var optStr = obj.nsstringProperty // optStr has type String??
if optStr != nil {
- var s : String = optStr! // expected-error{{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}}
+ var s : String = optStr! // expected-error{{value of optional type 'String?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
var t : String = optStr!!
}
@@ -288,7 +290,9 @@
func optionalMemberAccess(_ w: NSWobbling) {
w.wobble()
- w.wibble() // expected-error{{value of optional type '(() -> Void)?' not unwrapped; did you mean to use '!' or '?'?}} {{11-11=!}}
+ w.wibble() // expected-error{{value of optional type '(() -> Void)?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
let x = w[5]!!
_ = x
}
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index 4e0f99e..5971087 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -282,7 +282,9 @@
func subscribe<Object: AnyObject>(object: Object?, method: (Object, T) -> ()) where Object: Hashable {
let wrappedMethod = { (object: AnyObject, value: T) in }
- // expected-error @+1 {{value of optional type 'Object?' not unwrapped; did you mean to use '!' or '?'?}}
+ // expected-error @+3 {{value of optional type 'Object?' must be unwrapped to a value of type 'Object'}}
+ // expected-note @+2{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+ // expected-note @+1{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
cs.forEach { $0.w.append(value: wrappedMethod, forKey: object) }
}
}
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index d82e9e2..faf8040 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -221,7 +221,9 @@
}
func testStructWithOptionalArray(_ foo: StructWithOptionalArray) -> Int {
- return foo.array[0] // expected-error {{value of optional type '[Int]?' not unwrapped; did you mean to use '!' or '?'?}} {{19-19=!}}
+ return foo.array[0] // expected-error {{value of optional type '[Int]?' must be unwrapped to refer to member 'subscript' of wrapped base type '[Int]'}}
+ // expected-note@-1{{chain the optional using '?' to access member 'subscript' only for non-'nil' base values}}{{19-19=?}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{19-19=!}}
}
@@ -542,7 +544,9 @@
// <rdar://problem/22263468> QoI: Not producing specific argument conversion diagnostic for tuple init
func r22263468(_ a : String?) {
typealias MyTuple = (Int, String)
- _ = MyTuple(42, a) // expected-error {{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}} {{20-20=!}}
+ _ = MyTuple(42, a) // expected-error {{value of optional type 'String?' must be unwrapped to a value of type 'String'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
}
@@ -599,7 +603,9 @@
// <rdar://problem/23560128> QoI: trying to mutate an optional dictionary result produces bogus diagnostic
func r23560128() {
var a : (Int,Int)?
- a.0 = 42 // expected-error {{value of optional type '(Int, Int)?' not unwrapped; did you mean to use '!' or '?'?}} {{4-4=?}}
+ a.0 = 42 // expected-error{{value of optional type '(Int, Int)?' must be unwrapped to refer to member '0' of wrapped base type '(Int, Int)'}}
+ // expected-note@-1{{chain the optional }}
+ // expected-note@-2{{force-unwrap using '!'}}
}
// <rdar://problem/21890157> QoI: wrong error message when accessing properties on optional structs without unwrapping
@@ -607,7 +613,9 @@
var property = "property"
}
var example21890157: ExampleStruct21890157?
-example21890157.property = "confusing" // expected-error {{value of optional type 'ExampleStruct21890157?' not unwrapped; did you mean to use '!' or '?'?}} {{16-16=?}}
+example21890157.property = "confusing" // expected-error {{value of optional type 'ExampleStruct21890157?' must be unwrapped to refer to member 'property' of wrapped base type 'ExampleStruct21890157'}}
+ // expected-note@-1{{chain the optional }}
+ // expected-note@-2{{force-unwrap using '!'}}
struct UnaryOp {}
diff --git a/test/Constraints/fixes.swift b/test/Constraints/fixes.swift
index d480ff2..50cd8f7 100644
--- a/test/Constraints/fixes.swift
+++ b/test/Constraints/fixes.swift
@@ -47,16 +47,28 @@
/// Forgot the '!' to unwrap an optional.
func parseInt() -> Int? { }
+func <(lhs: A, rhs: A) -> A? { return nil }
+
func forgotOptionalBang(_ a: A, obj: AnyObject) {
- var i: Int = parseInt() // expected-error{{value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?}}{{26-26=!}}
+ var i: Int = parseInt() // expected-error{{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}{{26-26= ?? <#default value#>}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{26-26=!}}
var a = A(), b = B()
- b = a as? B // expected-error{{value of optional type 'B?' not unwrapped; did you mean to use '!' or '?'?}}{{7-7=(}}{{14-14=)!}}
+ b = a as? B // expected-error{{value of optional type 'B?' must be unwrapped to a value of type 'B'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}{{14-14= ?? <#default value#>}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{7-7=(}}{{14-14=)!}}
+ a = a < a // expected-error{{value of optional type 'A?' must be unwrapped to a value of type 'A'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}{{7-7=(}}{{12-12=) ?? <#default value#>}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{7-7=(}}{{12-12=)!}}
+
// rdar://problem/20377684 -- take care that the '!' doesn't fall into an
// optional evaluation context
let bo: B? = b
- let b2: B = bo?.createB() // expected-error{{value of optional type 'B?' not unwrapped; did you mean to use '!' or '?'?}}{{15-15=(}}{{28-28=)!}}
+ let b2: B = bo?.createB() // expected-error{{value of optional type 'B?' must be unwrapped to a value of type 'B'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
}
// Crash with one-element tuple with labeled element
@@ -64,7 +76,9 @@
func microwave() -> Dinner {
let d: Dinner? = nil
- return (n: d) // expected-error{{value of optional type 'Dinner?' not unwrapped; did you mean to use '!' or '?'?}} {{16-16=!}}
+ return (n: d) // expected-error{{value of optional type 'Dinner?' must be unwrapped to a value of type 'Dinner'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
}
func forgotAnyObjectBang(_ obj: AnyObject) {
@@ -89,7 +103,9 @@
var i = 7
i = i() // expected-error{{cannot call value of non-function type 'Int'}}{{8-10=}}
- maybeFn()(5) // expected-error{{value of optional type '((Int) -> Int)?' not unwrapped; did you mean to use '!' or '?'?}}{{12-12=!}}
+ maybeFn()(5) // expected-error{{value of optional type '((Int) -> Int)?' must be unwrapped to a value of type '(Int) -> Int'}}
+ // expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+ // expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
}
class U {
@@ -125,17 +141,27 @@
!ciuo // expected-error{{optional type 'C?' cannot be used as a boolean; test for '!= nil' instead}}{{2-2=(}} {{6-6= != nil)}}
// Forgotten ! or ?
-var someInt = co.a // expected-error{{value of optional type 'C?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=?}}
+var someInt = co.a // expected-error{{value of optional type 'C?' must be unwrapped to refer to member 'a' of wrapped base type 'C'}}
+// expected-note@-1{{chain the optional using '?' to access member 'a' only for non-'nil' base values}}{{17-17=?}}
+// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{17-17=!}}
// SR-839
struct Q {
let s: String?
}
let q = Q(s: nil)
-let a: Int? = q.s.utf8 // expected-error{{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}} {{18-18=?}}
-let b: Int = q.s.utf8 // expected-error{{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=!}}
-let d: Int! = q.s.utf8 // expected-error{{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}} {{18-18=?}}
-let c = q.s.utf8 // expected-error{{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}} {{12-12=?}}
+let a: Int? = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
+// expected-note@-1{{chain the optional using '?'}}{{18-18=?}}
+// expected-note@-2{{force-unwrap using '!'}}{{18-18=!}}
+let b: Int = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
+// expected-note@-1{{chain the optional using '?'}}{{17-17=?}}
+// expected-note@-2{{force-unwrap using '!'}}{{17-17=!}}
+let d: Int! = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
+// expected-note@-1{{chain the optional using '?'}}{{18-18=?}}
+// expected-note@-2{{force-unwrap using '!'}}{{18-18=!}}
+let c = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
+// expected-note@-1{{chain the optional using '?' to access member 'utf8' only for non-'nil' base values}}{{12-12=?}}
+// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{12-12=!}}
// SR-1116
struct S1116 {
diff --git a/test/Constraints/if_expr.swift b/test/Constraints/if_expr.swift
index 0f80ec8..ffce5aa 100644
--- a/test/Constraints/if_expr.swift
+++ b/test/Constraints/if_expr.swift
@@ -62,7 +62,9 @@
let ib: Bool! = false
let eb: Bool? = .some(false)
let conditional = ib ? "Broken" : "Heart" // should infer Bool!
-let conditional = eb ? "Broken" : "Heart" // expected-error {{value of optional type 'Bool?' not unwrapped; did you mean to use '!' or '?'?}}
+let conditional = eb ? "Broken" : "Heart" // expected-error {{value of optional type 'Bool?' must be unwrapped}}
+// expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}
+// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
// <rdar://problem/39586166> - crash when IfExpr has UnresolvedType in condition
struct Delegate {
diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift
index 50641d3..e15417c 100644
--- a/test/Constraints/iuo.swift
+++ b/test/Constraints/iuo.swift
@@ -210,8 +210,10 @@
}
func conditionalDowncastToObject(b: B?) -> D {
- return b as? D! // expected-error {{value of optional type 'D?' not unwrapped; did you mean to use '!' or '?'?}}
- // expected-warning@-1 {{using '!' here is deprecated and will be removed in a future release}}
+ return b as? D! // expected-error {{value of optional type 'D?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
+ // expected-warning@-3 {{using '!' here is deprecated and will be removed in a future release}}
}
// Ensure that we select the overload that does *not* involve forcing an IUO.
diff --git a/test/Constraints/iuo_objc.swift b/test/Constraints/iuo_objc.swift
index afd27de..1d11b98 100644
--- a/test/Constraints/iuo_objc.swift
+++ b/test/Constraints/iuo_objc.swift
@@ -5,25 +5,34 @@
func iuo_error(prop: IUOProperty) {
let _: Coat? = prop.iuo.optional()
- // expected-error@-1 {{value of optional type '(() -> Coat?)?' not unwrapped; did you mean to use '!' or '?'?}}
+ // expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped}}
+ // expected-note@-2{{coalesce}}
+ // expected-note@-3{{force-unwrap}}
let _: Coat? = prop.iuo.optional()!
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
let _: Coat? = prop.iuo.optional!()
let _: Coat? = prop.iuo.optional!()!
let _: Coat? = prop.iuo!.optional()
- // expected-error@-1 {{value of optional type '(() -> Coat?)?' not unwrapped; did you mean to use '!' or '?'?}}
+ // expected-error@-1 {{value of optional type '(() -> Coat?)?' must be unwrapped}}
+ // expected-note@-2{{coalesce}}
+ // expected-note@-3{{force-unwrap}}
let _: Coat? = prop.iuo!.optional()!
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
let _: Coat? = prop.iuo!.optional!()
let _: Coat? = prop.iuo!.optional!()!
let _: Coat = prop.iuo.optional()
- // expected-error@-1 {{value of optional type '(() -> Coat)?' not unwrapped; did you mean to use '!' or '?'?}}
+ // expected-error@-1 {{value of optional type '(() -> Coat)?' must be unwrapped}}
+ // expected-note@-2{{coalesce}}
+ // expected-note@-3{{force-unwrap}}
let _: Coat = prop.iuo.optional()!
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
let _: Coat = prop.iuo.optional!()
let _: Coat = prop.iuo.optional!()!
let _: Coat = prop.iuo!.optional()
- // expected-error@-1 {{value of optional type '(() -> Coat)?' not unwrapped; did you mean to use '!' or '?'?}}
+ // expected-error@-1 {{value of optional type '(() -> Coat)?' must be unwrapped}}
+ // expected-note@-2{{coalesce}}
+ // expected-note@-3{{force-unwrap}}
+
let _: Coat = prop.iuo!.optional()!
// expected-error@-1 {{cannot invoke 'optional' with no arguments}}
let _: Coat = prop.iuo!.optional!()
diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift
index c6b5e21..8e5e666 100644
--- a/test/Constraints/overload.swift
+++ b/test/Constraints/overload.swift
@@ -153,7 +153,9 @@
}
let x1 = X1(Int.self)
-let x1check: X1 = x1 // expected-error{{value of optional type 'X1?' not unwrapped; did you mean to use '!' or '?'?}}
+let x1check: X1 = x1 // expected-error{{value of optional type 'X1?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
struct X2 {
@@ -164,7 +166,9 @@
}
let x2 = X2(Int.self)
-let x2check: X2 = x2 // expected-error{{value of optional type 'X2?' not unwrapped; did you mean to use '!' or '?'?}}
+let x2check: X2 = x2 // expected-error{{value of optional type 'X2?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
// rdar://problem/28051973
struct R_28051973 {
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 022c4e1..734d5bb 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -292,7 +292,7 @@
case .init(0): break
case .init(_): break // expected-error{{'_' can only appear in a pattern}}
case .init(let x): break // expected-error{{cannot appear in an expression}}
- case .init(opt: 0): break // expected-error{{not unwrapped}}
+ case .init(opt: 0): break // expected-error{{pattern cannot match values of type 'StaticMembers'}}
case .prop: break
// TODO: repeated error message
@@ -309,7 +309,7 @@
case .method(withLabel: let x): break // expected-error{{cannot appear in an expression}}
case .optMethod: break // expected-error{{cannot match}}
- case .optMethod(0): break // expected-error{{not unwrapped}}
+ case .optMethod(0): break // expected-error{{pattern cannot match values of type 'StaticMembers'}}
}
_ = 0
diff --git a/test/Constraints/rdar42056741.swift b/test/Constraints/rdar42056741.swift
new file mode 100644
index 0000000..a04c981
--- /dev/null
+++ b/test/Constraints/rdar42056741.swift
@@ -0,0 +1,23 @@
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
+// REQUIRES: objc_interop
+
+import Foundation
+
+class A {
+ static var `default` = A()
+
+ func foo(arg: String) -> Bool {
+ return false
+ }
+
+ func foo(arg: String, _ flag: UnsafeMutablePointer<ObjCBool>?) -> Bool {
+ return true
+ }
+}
+
+class B {
+ var bar: Bool = false
+ func baz() {
+ bar = A.default.foo(arg: self.) // expected-error {{expected member name following '.'}}
+ }
+}
diff --git a/test/Driver/linker-arclite.swift b/test/Driver/linker-arclite.swift
index 4b99dd4..73e67aa 100644
--- a/test/Driver/linker-arclite.swift
+++ b/test/Driver/linker-arclite.swift
@@ -11,15 +11,24 @@
// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios8.0 %S/../Inputs/empty.swift | %FileCheck -check-prefix IOS_ARCLITE %s
-// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.11 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
-// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios9.0 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
-// RUN: %swiftc_driver -driver-print-jobs -target arm64-apple-tvos9.0 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
-// RUN: %swiftc_driver -driver-print-jobs -target armv7k-apple-watchos2.0 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
-
// IOS_ARCLITE: bin/ld{{"? }}
// IOS_ARCLITE: -force_load {{[^ ]+/lib/arc/libarclite_iphonesimulator.a}}
// IOS_ARCLITE: -o {{[^ ]+}}
+
+// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.14 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.13 %S/../Inputs/empty.swift | %FileCheck -check-prefix ANY_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios12 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-ios11 %S/../Inputs/empty.swift | %FileCheck -check-prefix ANY_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target arm64-apple-tvos12 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target arm64-apple-tvos11 %S/../Inputs/empty.swift | %FileCheck -check-prefix ANY_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target armv7k-apple-watchos5 %S/../Inputs/empty.swift | %FileCheck -check-prefix NO_ARCLITE %s
+// RUN: %swiftc_driver -driver-print-jobs -target armv7k-apple-watchos4 %S/../Inputs/empty.swift | %FileCheck -check-prefix ANY_ARCLITE %s
+
// NO_ARCLITE: bin/ld{{"? }}
// NO_ARCLITE-NOT: arclite
// NO_ARCLITE: -o {{[^ ]+}}
+
+// ANY_ARCLITE: bin/ld{{"? }}
+// ANY_ARCLITE: -force_load {{[^ ]+}}/lib/arc/libarclite_{{.+}}.a
+// ANY_ARCLITE: -o {{[^ ]+}}
diff --git a/test/Generics/deduction.swift b/test/Generics/deduction.swift
index 355c684..e18d723 100644
--- a/test/Generics/deduction.swift
+++ b/test/Generics/deduction.swift
@@ -316,7 +316,9 @@
let j = min(Int(3), Float(2.5)) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}}
let k = min(A(), A()) // expected-error{{argument type 'A' does not conform to expected type 'Comparable'}}
let oi : Int? = 5
- let l = min(3, oi) // expected-error{{value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?}}
+ let l = min(3, oi) // expected-error{{value of optional type 'Int?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
}
infix operator +&
diff --git a/test/Interpreter/SDK/Inputs/SimpleNSObjectSubclass.swift b/test/Interpreter/SDK/Inputs/SimpleNSObjectSubclass.swift
new file mode 100644
index 0000000..a72c498
--- /dev/null
+++ b/test/Interpreter/SDK/Inputs/SimpleNSObjectSubclass.swift
@@ -0,0 +1,3 @@
+import Foundation
+
+public class SimpleSubclass: NSObject {}
diff --git a/test/Interpreter/SDK/Inputs/class_getImageName-helper.swift b/test/Interpreter/SDK/Inputs/class_getImageName-helper.swift
new file mode 100644
index 0000000..bcbc188
--- /dev/null
+++ b/test/Interpreter/SDK/Inputs/class_getImageName-helper.swift
@@ -0,0 +1,23 @@
+import Foundation
+
+public class SimpleSwiftObject {}
+public class SimpleNSObject: NSObject {
+ @objc public dynamic var observableName: String = ""
+}
+
+public class GenericSwiftObject<T> {}
+public class GenericNSObject<T>: NSObject {}
+
+public class GenericAncestrySwiftObject: GenericSwiftObject<AnyObject> {}
+public class GenericAncestryNSObject: GenericNSObject<AnyObject> {
+ @objc public dynamic var observableName: String = ""
+}
+
+public class ResilientFieldSwiftObject {
+ public var url: URL?
+ public var data: Data?
+}
+public class ResilientFieldNSObject: NSObject {
+ public var url: URL?
+ public var data: Data?
+}
diff --git a/test/Interpreter/SDK/Inputs/class_getImageName-static-helper.h b/test/Interpreter/SDK/Inputs/class_getImageName-static-helper.h
new file mode 100644
index 0000000..8a4e7fc
--- /dev/null
+++ b/test/Interpreter/SDK/Inputs/class_getImageName-static-helper.h
@@ -0,0 +1,7 @@
+static inline const char *getNameOfClassToFind() {
+ return "SimpleNSObjectSubclass.SimpleSubclass";
+}
+
+static inline const char *getHookName() {
+ return "objc_setHook_getImageName";
+}
diff --git a/test/Interpreter/SDK/KVO.swift b/test/Interpreter/SDK/KVO.swift
index ea3500b..2cdfd50 100644
--- a/test/Interpreter/SDK/KVO.swift
+++ b/test/Interpreter/SDK/KVO.swift
@@ -55,3 +55,20 @@
let bar = foo.foo
// CHECK-NEXT: 0
print(bar)
+
+let fooClass: AnyClass = object_getClass(foo)!
+precondition(fooClass !== Foo.self, "no KVO subclass?")
+precondition(fooClass is Foo.Type, "improper KVO subclass")
+precondition(!(fooClass is Observer.Type), "improper KVO subclass")
+
+let fooClassAsObject: AnyObject = fooClass
+precondition(fooClassAsObject !== Foo.self, "no KVO subclass?")
+precondition(fooClassAsObject is Foo.Type, "improper KVO subclass")
+precondition(!(fooClassAsObject is Observer.Type), "improper KVO subclass")
+
+let fooClassAsAny: Any = fooClass
+precondition(fooClassAsAny is Foo.Type, "improper KVO subclass")
+precondition(!(fooClassAsAny is Observer.Type), "improper KVO subclass")
+
+// CHECK-NEXT: class metadata checks okay
+print("class metadata checks okay")
diff --git a/test/Interpreter/SDK/class_getImageName-static.swift b/test/Interpreter/SDK/class_getImageName-static.swift
new file mode 100644
index 0000000..5f4bab5
--- /dev/null
+++ b/test/Interpreter/SDK/class_getImageName-static.swift
@@ -0,0 +1,61 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-library -o %t/libSimpleNSObjectSubclass.dylib %S/Inputs/SimpleNSObjectSubclass.swift -Xlinker -install_name -Xlinker @executable_path/libSimpleNSObjectSubclass.dylib
+// RUN: %target-codesign %t/libSimpleNSObjectSubclass.dylib
+
+// RUN: %target-build-swift %s -o %t/main -lSimpleNSObjectSubclass -L%t -import-objc-header %S/Inputs/class_getImageName-static-helper.h
+// RUN: %target-run %t/main %t/libSimpleNSObjectSubclass.dylib
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import Darwin
+import ObjectiveC
+// import SimpleNSObjectSubclass // Deliberately omitted in favor of dynamic loads.
+
+// Note: The following typealias uses AnyObject instead of AnyClass so that the
+// function type is trivially bridgeable to Objective-C. (The representation of
+// AnyClass is not the same as Objective-C's 'Class' type.)
+typealias GetImageHook = @convention(c) (AnyObject, UnsafeMutablePointer<UnsafePointer<CChar>?>) -> ObjCBool
+var hook: GetImageHook?
+
+func checkThatSwiftHookWasNotInstalled() {
+ // Check that the Swift hook did not get installed.
+ guard let setHookPtr = dlsym(UnsafeMutableRawPointer(bitPattern: -2),
+ getHookName()) else {
+ // If the version of the ObjC runtime we're using doesn't have the hook,
+ // we're good.
+ return
+ }
+
+ let setHook = unsafeBitCast(setHookPtr, to: (@convention(c) (GetImageHook, UnsafeMutablePointer<GetImageHook?>) -> Void).self)
+ setHook({ hook!($0, $1) }, &hook)
+
+ var info: Dl_info = .init()
+ guard 0 != dladdr(unsafeBitCast(hook, to: UnsafeRawPointer.self), &info) else {
+ fatalError("could not get dladdr info for objc_hook_getImageName")
+ }
+
+ precondition(String(cString: info.dli_fname).hasSuffix("libobjc.A.dylib"),
+ "hook was replaced")
+}
+
+// It's important that this test does not register any Swift classes with the
+// Objective-C runtime---that's where Swift sets up its custom hook, and we want
+// to check the behavior /without/ that hook. That includes the buffer types for
+// String and Array. Therefore, we get C strings directly from a bridging
+// header.
+
+guard let theClass = objc_getClass(getNameOfClassToFind()) as! AnyClass? else {
+ fatalError("could not find class")
+}
+
+guard let imageName = class_getImageName(theClass) else {
+ fatalError("could not find image")
+}
+
+checkThatSwiftHookWasNotInstalled()
+
+// Okay, now we can use String.
+
+precondition(String(cString: imageName).hasSuffix("libSimpleNSObjectSubclass.dylib"),
+ "found wrong image")
diff --git a/test/Interpreter/SDK/class_getImageName.swift b/test/Interpreter/SDK/class_getImageName.swift
new file mode 100644
index 0000000..c684d9d
--- /dev/null
+++ b/test/Interpreter/SDK/class_getImageName.swift
@@ -0,0 +1,125 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-library -o %t/libGetImageNameHelper.dylib -emit-module %S/Inputs/class_getImageName-helper.swift -Xlinker -install_name -Xlinker @executable_path/libGetImageNameHelper.dylib
+// RUN: %target-codesign %t/libGetImageNameHelper.dylib
+
+// RUN: %target-build-swift -g %s -I %t -o %t/main -L %t -lGetImageNameHelper
+// RUN: %target-run %t/main %t/libGetImageNameHelper.dylib
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import Darwin
+import ObjectiveC
+import GetImageNameHelper
+import StdlibUnittest
+
+func check(_ cls: AnyClass, in library: String) {
+ guard let imageName = class_getImageName(cls) else {
+ expectUnreachable("could not find image for \(cls)")
+ return
+ }
+ expectTrue(String(cString: imageName).hasSuffix(library),
+ "wrong library for \(cls)")
+}
+
+let isMissingObjCRuntimeHook =
+ (nil == dlsym(UnsafeMutableRawPointer(bitPattern: -2),
+ "objc_setHook_getImageName"))
+
+var testSuite = TestSuite("class_getImageName")
+
+testSuite.test("Simple") {
+ check(SimpleSwiftObject.self, in: "libGetImageNameHelper.dylib")
+ check(SimpleNSObject.self, in: "libGetImageNameHelper.dylib")
+}
+
+testSuite.test("Generic")
+ .xfail(.custom({ isMissingObjCRuntimeHook },
+ reason: "hook for class_getImageName not present"))
+ .code {
+ check(GenericSwiftObject<Int>.self, in: "libGetImageNameHelper.dylib")
+ check(GenericSwiftObject<NSObject>.self, in: "libGetImageNameHelper.dylib")
+
+ check(GenericNSObject<Int>.self, in: "libGetImageNameHelper.dylib")
+ check(GenericNSObject<NSObject>.self, in: "libGetImageNameHelper.dylib")
+}
+
+testSuite.test("GenericAncestry")
+ .xfail(.custom({ isMissingObjCRuntimeHook },
+ reason: "hook for class_getImageName not present"))
+ .code {
+ check(GenericAncestrySwiftObject.self, in: "libGetImageNameHelper.dylib")
+ check(GenericAncestryNSObject.self, in: "libGetImageNameHelper.dylib")
+}
+
+testSuite.test("Resilient") {
+ check(ResilientFieldSwiftObject.self, in: "libGetImageNameHelper.dylib")
+ check(ResilientFieldNSObject.self, in: "libGetImageNameHelper.dylib")
+}
+
+testSuite.test("ObjC") {
+ check(NSObject.self, in: "libobjc.A.dylib")
+}
+
+testSuite.test("KVO/Simple") {
+ // We use object_getClass in this test to not look through KVO's artificial
+ // subclass.
+ let obj = SimpleNSObject()
+ autoreleasepool {
+ let observation = obj.observe(\.observableName) { _, _ in }
+ withExtendedLifetime(observation) {
+ let theClass = object_getClass(obj)
+ precondition(theClass !== SimpleNSObject.self, "no KVO subclass?")
+ expectNil(class_getImageName(theClass),
+ "should match what happens with NSObject (below)")
+ }
+ }
+}
+
+testSuite.test("KVO/GenericAncestry") {
+ // We use object_getClass in this test to not look through KVO's artificial
+ // subclass.
+ let obj = GenericAncestryNSObject()
+ autoreleasepool {
+ let observation = obj.observe(\.observableName) { _, _ in }
+ withExtendedLifetime(observation) {
+ let theClass = object_getClass(obj)
+ precondition(theClass !== GenericAncestryNSObject.self, "no KVO subclass?")
+ expectNil(class_getImageName(theClass),
+ "should match what happens with NSObject (below)")
+ }
+ }
+}
+
+testSuite.test("KVO/ObjC") {
+ // We use object_getClass in this test to not look through KVO's artificial
+ // subclass.
+ let obj = NSObject()
+ autoreleasepool {
+ let observation = obj.observe(\.description) { _, _ in }
+ withExtendedLifetime(observation) {
+ let theClass = object_getClass(obj)
+ precondition(theClass !== NSObject.self, "no KVO subclass?")
+ expectNil(class_getImageName(theClass),
+ "should match what happens with the Swift objects (above)")
+ }
+ }
+}
+
+testSuite.test("dynamic") {
+ let newClass: AnyClass = objc_allocateClassPair(/*superclass*/nil,
+ "CompletelyDynamic",
+ /*extraBytes*/0)!
+ objc_registerClassPair(newClass)
+
+ // We don't actually care what the result is; we just need to not crash.
+ _ = class_getImageName(newClass)
+}
+
+testSuite.test("nil") {
+ // The ObjC runtime should handle this before it even gets to Swift's custom
+ // implementation, but just in case.
+ expectNil(class_getImageName(nil))
+}
+
+runAllTests()
diff --git a/test/Migrator/rdar31892850.swift b/test/Migrator/rdar31892850.swift
index f2675b9..883f16b 100644
--- a/test/Migrator/rdar31892850.swift
+++ b/test/Migrator/rdar31892850.swift
@@ -21,6 +21,6 @@
// CHECK: {
// CHECK: "file": "{{.*}}rdar31892850.swift",
// CHECK: "offset": 310,
-// CHECK: "text": ")!"
+// CHECK: "text": ")"
// CHECK: }
// CHECK:]
diff --git a/test/NameBinding/dynamic-member-lookup.swift b/test/NameBinding/dynamic-member-lookup.swift
index 49fc872..d89e097 100644
--- a/test/NameBinding/dynamic-member-lookup.swift
+++ b/test/NameBinding/dynamic-member-lookup.swift
@@ -150,7 +150,9 @@
let _ : Int = x.bar // Test implicitly forced optional
let b = x.bar // Should promote to 'Int?'
- let _ : Int = b // expected-error {{value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'}}
+ let _ : Int = b // expected-error {{value of optional type 'Int?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
}
diff --git a/test/Parse/optional_chain_lvalues.swift b/test/Parse/optional_chain_lvalues.swift
index ebf51c3..44845ee 100644
--- a/test/Parse/optional_chain_lvalues.swift
+++ b/test/Parse/optional_chain_lvalues.swift
@@ -36,7 +36,9 @@
mutT?.mutS = S()
mutT?.mutS? = S()
mutT?.mutS?.x += 0
-_ = mutT?.mutS?.x + 0 // expected-error{{value of optional type 'Int?' not unwrapped}} {{5-5=(}} {{18-18=)!}}
+_ = mutT?.mutS?.x + 0 // expected-error{{value of optional type 'Int?' must be unwrapped}}
+// expected-note@-1{{coalesce}}
+// expected-note@-2{{force-unwrap}}
mutT?.mutS?.y -= 0 // expected-error{{left side of mutating operator isn't mutable: 'y' is a 'let' constant}}
mutT?.immS = S() // expected-error{{cannot assign to property: 'immS' is a 'let' constant}}
mutT?.immS? = S() // expected-error{{cannot assign to value: 'immS' is a 'let' constant}}
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index cd2a7df..e048cd4 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -263,12 +263,16 @@
func optionality(_ op: UnsafeMutablePointer<Float>?) {
takesMutableVoidPointer(op)
% if not suffix:
- // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' not unwrapped}}
+ // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' must be unwrapped}}
+ // expected-note@-3{{coalesce}}
+ // expected-note@-4{{force-unwrap}}
% end
takesConstVoidPointer(op)
% if not suffix:
- // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' not unwrapped}}
+ // expected-error@-2 {{value of optional type 'UnsafeMutablePointer<Float>?' must be unwrapped}}
+ // expected-note@-3{{coalesce}}
+ // expected-note@-4{{force-unwrap}}
% end
}
diff --git a/test/SILGen/function_conversion.swift b/test/SILGen/function_conversion.swift
index 526a44f..4da77ae 100644
--- a/test/SILGen/function_conversion.swift
+++ b/test/SILGen/function_conversion.swift
@@ -665,3 +665,21 @@
return Foo<Klass>.enum1Func(SelfTy.bar)
}
}
+
+// CHECK: sil {{.*}} @$SS4SIgggoo_S2Ss11AnyHashableVyps5Error_pIegggrrzo_TR
+// CHECK: [[TUPLE:%.*]] = apply %4(%2, %3) : $@noescape @callee_guaranteed (@guaranteed String, @guaranteed String) -> (@owned String, @owned String)
+// CHECK: [[BORROW:%.*]] = begin_borrow [[TUPLE]] : $(String, String)
+// CHECK: [[FRST:%.*]] = tuple_extract [[BORROW]] : $(String, String), 0
+// CHECK: [[COPY1:%.*]] = copy_value [[FRST]] : $String
+// CHECK: [[SND:%.*]] = tuple_extract [[BORROW]] : $(String, String), 1
+// CHECK: [[COPY2:%.*]] = copy_value [[SND]] : $String
+// CHECK: end_borrow [[BORROW]] from [[TUPLE]] : $(String, String), $(String, String)
+// CHECK: destroy_value [[TUPLE]] : $(String, String)
+// CHECK: [[ADDR:%.*]] = alloc_stack $String
+// CHECK: store [[COPY1]] to [init] [[ADDR]] : $*String
+// CHECK: [[CVT:%.*]] = function_ref @$Ss21_convertToAnyHashableys0cD0VxSHRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : Hashable> (@in_guaranteed τ_0_0) -> @out AnyHashable
+// CHECK: apply [[CVT]]<String>(%0, [[ADDR]])
+func dontCrash() {
+ let userInfo = ["hello": "world"]
+ let d = [AnyHashable: Any](uniqueKeysWithValues: userInfo.map { ($0.key, $0.value) })
+}
diff --git a/test/decl/init/failable.swift b/test/decl/init/failable.swift
index 0571756..d93e439 100644
--- a/test/decl/init/failable.swift
+++ b/test/decl/init/failable.swift
@@ -32,7 +32,9 @@
func testConstruction(_ i: Int, s: String) {
let s0Opt = S0(string: s)
assert(s0Opt != nil)
- var _: S0 = s0Opt // expected-error{{value of optional type 'S0?' not unwrapped; did you mean to use '!' or '?'?}} {{20-20=!}}
+ var _: S0 = s0Opt // expected-error{{value of optional type 'S0?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
let s0IUO = S0(int: i)
assert(s0IUO != nil)
diff --git a/test/expr/cast/precedence.swift b/test/expr/cast/precedence.swift
index f45aed9..d80edaf 100644
--- a/test/expr/cast/precedence.swift
+++ b/test/expr/cast/precedence.swift
@@ -4,5 +4,7 @@
func testInIf(a: Any) {
if a as? Float {} // expected-error {{cannot be used as a boolean}} {{6-6=((}} {{17-17=) != nil)}}
- let _: Float = a as? Float // expected-error {{value of optional type 'Float?' not unwrapped; did you mean to use '!' or '?'?}} {{18-18=(}} {{29-29=)!}}
+ let _: Float = a as? Float // expected-error {{value of optional type 'Float?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
}
diff --git a/test/expr/postfix/dot/optional_context_member.swift b/test/expr/postfix/dot/optional_context_member.swift
index b2d79e3..fdb5307 100644
--- a/test/expr/postfix/dot/optional_context_member.swift
+++ b/test/expr/postfix/dot/optional_context_member.swift
@@ -13,14 +13,15 @@
case ():
return .someVar
case (): // expected-warning {{case is already handled by previous patterns; consider removing it}}
- return .someOptVar // expected-error 2 {{value of optional type 'Foo' not unwrapped; did you mean to use '!' or '?'?}} {{23-23=!}}
+ // FIXME: Customize this diagnostic for the optional case.
+ return .someOptVar // expected-error 1 {{member 'someOptVar' in 'Foo' produces result of type 'Foo?', but context expects 'Foo'}}
// TODO
//case ():
// return .someOptVar!
case (): // expected-warning {{case is already handled by previous patterns; consider removing it}}
return .someFunc()
case (): // expected-warning {{case is already handled by previous patterns; consider removing it}}
- return .someOptFunc() // expected-error{{}} {{26-26=!}}
+ return .someOptFunc() // expected-error{{member 'someOptFunc' in 'Foo' produces result of type 'Foo?', but context expects 'Foo'}}
// TODO
//case ():
// return .someOptFunc()!
diff --git a/test/stdlib/StringCompatibilityDiagnostics3.swift b/test/stdlib/StringCompatibilityDiagnostics3.swift
index a3edaa3..dc2b26a 100644
--- a/test/stdlib/StringCompatibilityDiagnostics3.swift
+++ b/test/stdlib/StringCompatibilityDiagnostics3.swift
@@ -22,6 +22,8 @@
var _ = String(str.utf8) ?? "" // expected-warning{{'init' is deprecated: Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)}}
var _ = String(str.utf8) // expected-warning{{'init' is deprecated: Failable initializer was removed in Swift 4. When upgrading to Swift 4, please use non-failable String.init(_:UTF8View)}}
- var _: String = String(str.utf8) // expected-error {{value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?}}
+ var _: String = String(str.utf8) // expected-error {{value of optional type 'String?' must be unwrapped to a value of type 'String'}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
}
diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift
index 3f97744..266d709 100644
--- a/test/stmt/foreach.swift
+++ b/test/stmt/foreach.swift
@@ -168,7 +168,9 @@
// <rdar://problem/21662365> QoI: diagnostic for for-each over an optional sequence isn't great
func testOptionalSequence() {
let array : [Int]?
- for x in array { // expected-error {{value of optional type '[Int]?' not unwrapped; did you mean to use '!' or '?'?}} {{17-17=!}}
+ for x in array { // expected-error {{value of optional type '[Int]?' must be unwrapped}}
+ // expected-note@-1{{coalesce}}
+ // expected-note@-2{{force-unwrap}}
}
}
diff --git a/validation-test/IDE/crashers_2_fixed/0020-rdar42056741.swift b/validation-test/IDE/crashers_2_fixed/0020-rdar42056741.swift
new file mode 100644
index 0000000..8c4ec32
--- /dev/null
+++ b/validation-test/IDE/crashers_2_fixed/0020-rdar42056741.swift
@@ -0,0 +1,23 @@
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -code-completion-token=COMPLETE -source-filename=%s
+// REQUIRES: objc_interop
+
+import Foundation
+
+class A {
+ static var `default` = A()
+
+ func foo(arg: String) -> Bool {
+ return false
+ }
+
+ func foo(arg: String, _ flag: UnsafeMutablePointer<ObjCBool>?) -> Bool {
+ return true
+ }
+}
+
+class B {
+ var bar: Bool = false
+ func baz() {
+ bar = A.default.foo(arg: self.#^COMPLETE^#)
+ }
+}