From 26c16174f811ed9339bd6939d9f45f88106cf93b Mon Sep 17 00:00:00 2001 From: Xi Ge Date: Mon, 27 Jan 2020 15:27:01 -0800 Subject: [PATCH 01/19] TBDGen: also using target variant to decide whether @_originallyDefinedIn is active This ensures we could emit linker directives for multiple platforms when building zippered libraries. --- lib/AST/Attr.cpp | 11 ++++++++++- test/TBD/linker-directives-ld-previous-macos.swift | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index bf2ec20779d8d..8a1f16b00d8ef 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -1360,10 +1360,19 @@ OriginallyDefinedInAttr::isActivePlatform(const ASTContext &ctx) const { Result.Platform = Platform; Result.Version = MovedVersion; Result.ModuleName = OriginalModuleName; - if (isPlatformActive(Platform, ctx.LangOpts)) { + if (isPlatformActive(Platform, ctx.LangOpts, /*TargetVariant*/false)) { Result.IsSimulator = ctx.LangOpts.Target.isSimulatorEnvironment(); return Result; } + + // Also check if the platform is active by using target variant. This ensures + // we emit linker directives for multiple platforms when building zippered + // libraries. + if (ctx.LangOpts.TargetVariant.hasValue() && + isPlatformActive(Platform, ctx.LangOpts, /*TargetVariant*/true)) { + Result.IsSimulator = ctx.LangOpts.TargetVariant->isSimulatorEnvironment(); + return Result; + } return None; } diff --git a/test/TBD/linker-directives-ld-previous-macos.swift b/test/TBD/linker-directives-ld-previous-macos.swift index 86ab5883ddb76..f678721facd96 100644 --- a/test/TBD/linker-directives-ld-previous-macos.swift +++ b/test/TBD/linker-directives-ld-previous-macos.swift @@ -7,8 +7,14 @@ // RUN: %target-swift-frontend -typecheck %S/Inputs/linker-directive.swift -emit-tbd -emit-tbd-path %t/linker_directives.tbd -previous-module-installname-map-file %S/Inputs/install-name-map-toasterkit.json // RUN: %FileCheck %s < %t/linker_directives.tbd +// RUN: %target-swift-frontend -target-variant x86_64-apple-ios13.0-macabi -typecheck %S/Inputs/linker-directive.swift -emit-tbd -emit-tbd-path %t/linker_directives.tbd -previous-module-installname-map-file %S/Inputs/install-name-map-toasterkit.json +// RUN: %FileCheck -check-prefix=CHECK-ZIPPERED %s < %t/linker_directives.tbd + // CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit5toastyyF$ // CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit7VehicleV4moveyyF$ // CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit7VehicleVMa$ // CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit7VehicleVMn$ -// CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit7VehicleVN$ \ No newline at end of file +// CHECK: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit7VehicleVN$ + +// CHECK-ZIPPERED: $ld$previous$/System/Previous/iOS/ToasterKit.dylib$$2$10.2$13.0$_$s10ToasterKit5toastyyF$ +// CHECK-ZIPPERED: $ld$previous$/System/Previous/macOS/ToasterKit.dylib$$1$10.8$10.15$_$s10ToasterKit5toastyyF$ From c7c95103663543081a1aafebc937dba766b5a59c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Fri, 24 Jan 2020 17:07:43 -0800 Subject: [PATCH 02/19] [ConstraintSystem] Don't re-attempt to bind type variable if it could be a hole If type variable is allowed to be a hole and it can't be bound to this particular (full resolved) type, just ignore this binding instead of re-trying it later. --- lib/Sema/CSSimplify.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 4568823340ff5..2794e9650a104 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2249,8 +2249,17 @@ ConstraintSystem::matchTypesBindTypeVar( // Simplify the right-hand type and perform the "occurs" check. typeVar = getRepresentative(typeVar); type = simplifyType(type, flags); - if (!isBindable(typeVar, type)) + if (!isBindable(typeVar, type)) { + if (shouldAttemptFixes()) { + // If type variable is allowed to be a hole and it can't be bound to + // a particular (full resolved) type, just ignore this binding + // instead of re-trying it and failing later. + if (typeVar->getImpl().canBindToHole() && !type->hasTypeVariable()) + return getTypeMatchSuccess(); + } + return formUnsolvedResult(); + } // Since member lookup doesn't check requirements // it might sometimes return types which are not From dea79e09c6d54a4e8a05fa92083538912a39ab08 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 27 Jan 2020 15:27:45 -0800 Subject: [PATCH 03/19] [ConstraintSystem] Detect that function type has failures before applying arguments If a type variable representing "function type" is a hole or it could be bound to some concrete type with a help of a fix, let's propagate holes to the "input" type. Doing so provides more information to upcoming argument and result matching. --- lib/Sema/CSSimplify.cpp | 31 ++++++++++++++++++++++--------- lib/Sema/ConstraintSystem.h | 1 + test/Constraints/bridging.swift | 2 +- test/expr/expressions.swift | 6 ++---- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 2794e9650a104..c89e42065b2f5 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7518,6 +7518,18 @@ ConstraintSystem::simplifyApplicableFnConstraint( // following: $T1 -> $T2. auto func1 = type1->castTo(); + // If a type variable representing "function type" is a hole + // or it could be bound to some concrete type with a help of + // a fix, let's propagate holes to the "input" type. Doing so + // provides more information to upcoming argument and result matching. + if (shouldAttemptFixes()) { + if (auto *typeVar = type2->getAs()) { + auto *locator = typeVar->getImpl().getLocator(); + if (typeVar->isHole() || hasFixFor(locator)) + recordPotentialHole(func1); + } + } + // Before stripping lvalue-ness and optional types, save the original second // type for handling `func callAsFunction` and `@dynamicCallable` // applications. This supports the following cases: @@ -7730,10 +7742,7 @@ ConstraintSystem::simplifyApplicableFnConstraint( // If there are any type variables associated with arguments/result // they have to be marked as "holes". - type1.visit([&](Type subType) { - if (auto *typeVar = subType->getAs()) - recordPotentialHole(typeVar); - }); + recordPotentialHole(func1); if (desugar2->isHole()) return SolutionKind::Solved; @@ -8007,11 +8016,7 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint( return SolutionKind::Error; recordPotentialHole(tv); - - Type(func1).visit([&](Type type) { - if (auto *typeVar = type->getAs()) - recordPotentialHole(typeVar); - }); + recordPotentialHole(func1); return SolutionKind::Solved; } @@ -8572,6 +8577,14 @@ void ConstraintSystem::recordPotentialHole(TypeVariableType *typeVar) { typeVar->getImpl().enableCanBindToHole(getSavedBindings()); } +void ConstraintSystem::recordPotentialHole(FunctionType *fnType) { + assert(fnType); + Type(fnType).visit([&](Type type) { + if (auto *typeVar = type->getAs()) + recordPotentialHole(typeVar); + }); +} + ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( ConstraintFix *fix, Type type1, Type type2, ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 1cd0c4724e7a4..028de0c16559c 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -2361,6 +2361,7 @@ class ConstraintSystem { bool recordFix(ConstraintFix *fix, unsigned impact = 1); void recordPotentialHole(TypeVariableType *typeVar); + void recordPotentialHole(FunctionType *fnType); /// Determine whether constraint system already has a fix recorded /// for a particular location. diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift index bafa1dab76723..4cdc52e3e2626 100644 --- a/test/Constraints/bridging.swift +++ b/test/Constraints/bridging.swift @@ -265,7 +265,7 @@ func rdar19831698() { var v71 = true + 1.0 // expected-error{{binary operator '+' cannot be applied to operands of type 'Bool' and 'Double'}} // expected-note@-1{{overloads for '+'}} var v72 = true + true // expected-error{{binary operator '+' cannot be applied to two 'Bool' operands}} - var v73 = true + [] // expected-error@:13 {{cannot convert value of type 'Bool' to expected argument type 'Array'}} + var v73 = true + [] // expected-error@:18 {{binary operator '+' cannot be applied to operands of type 'Bool' and '[Any]'}} var v75 = true + "str" // expected-error@:13 {{cannot convert value of type 'Bool' to expected argument type 'String'}} } diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 43af91bfcfebb..e63fe024f7fa4 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -748,10 +748,8 @@ func invalidDictionaryLiteral() { } -[4].joined(separator: [1]) // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}} -// expected-error@-1 {{cannot convert value of type '[Int]' to expected argument type 'String'}} -[4].joined(separator: [[[1]]]) // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}} -// expected-error@-1 {{cannot convert value of type '[[[Int]]]' to expected argument type 'String'}} +[4].joined(separator: [1]) // expected-error {{referencing instance method 'joined(separator:)' on 'Sequence' requires that 'Int' conform to 'Sequence'}} +[4].joined(separator: [[[1]]]) // expected-error {{referencing instance method 'joined(separator:)' on 'Sequence' requires that 'Int' conform to 'Sequence'}} //===----------------------------------------------------------------------===// // nil/metatype comparisons From e50756c10c51e539b8af1b08a51c62bf06608fe8 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 27 Jan 2020 17:17:27 -0800 Subject: [PATCH 04/19] [CSDiag] Obsolete function re-typecheck and diagnostics from `visitApplyExpr` --- lib/Sema/CSDiag.cpp | 93 ++-------------------------- test/Constraints/members.swift | 6 +- test/type/protocol_composition.swift | 4 +- 3 files changed, 11 insertions(+), 92 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 6860d71f77ef7..3558188f6e2dd 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1202,32 +1202,6 @@ static Expr *getFailedArgumentExpr(CalleeCandidateInfo CCI, Expr *argExpr) { bool FailureDiagnosis::diagnoseParameterErrors(CalleeCandidateInfo &CCI, Expr *fnExpr, Expr *argExpr, ArrayRef argLabels) { - if (auto *MTT = CS.getType(fnExpr)->getAs()) { - auto instTy = MTT->getInstanceType(); - auto &DE = CS.getASTContext().Diags; - if (instTy->getAnyNominal()) { - // If we are invoking a constructor on a nominal type and there are - // absolutely no candidates, then they must all be private. - if (CCI.empty() || (CCI.size() == 1 && CCI.candidates[0].getDecl() && - isa(CCI.candidates[0].getDecl()))) { - DE.diagnose(fnExpr->getLoc(), diag::no_accessible_initializers, - instTy); - return true; - } - // continue below - } else if (!instTy->is()) { - // If we are invoking a constructor on a non-nominal type, the expression - // is malformed. - SourceRange initExprRange(fnExpr->getSourceRange().Start, - argExpr->getSourceRange().End); - DE.diagnose(fnExpr->getLoc(), instTy->isExistentialType() ? - diag::construct_protocol_by_name : - diag::non_nominal_no_initializers, instTy) - .highlight(initExprRange); - return true; - } - } - // Try to diagnose errors related to the use of implicit self reference. if (diagnoseImplicitSelfErrors(fnExpr, argExpr, CCI, argLabels)) return true; @@ -1268,59 +1242,9 @@ bool FailureDiagnosis::diagnoseParameterErrors(CalleeCandidateInfo &CCI, return false; } -// Check if there is a structural problem in the function expression -// by performing type checking with the option to allow unresolved -// type variables. If that is going to produce a function type with -// unresolved result let's not re-typecheck the function expression, -// because it might produce unrelated diagnostics due to lack of -// contextual information. -static bool shouldTypeCheckFunctionExpr(FailureDiagnosis &FD, DeclContext *DC, - Expr *fnExpr) { - if (!isa(fnExpr)) - return true; - - SmallPtrSet fnTypes; - FD.getPossibleTypesOfExpressionWithoutApplying( - fnExpr, DC, fnTypes, FreeTypeVariableBinding::UnresolvedType); - - if (fnTypes.size() == 1) { - // Some member types depend on the arguments to produce a result type, - // type-checking such expressions without associated arguments is - // going to produce unrelated diagnostics. - if (auto fn = (*fnTypes.begin())->getAs()) { - auto resultType = fn->getResult(); - if (resultType->hasUnresolvedType() || resultType->hasTypeVariable()) - return false; - } - } - - // Might be a structural problem related to the member itself. - return true; -} - bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { auto *fnExpr = callExpr->getFn(); - - if (shouldTypeCheckFunctionExpr(*this, CS.DC, fnExpr)) { - // Type check the function subexpression to resolve a type for it if - // possible. - fnExpr = typeCheckChildIndependently(callExpr->getFn()); - if (!fnExpr) { - return CS.getASTContext().Diags.hadAnyError(); - } - } - - SWIFT_DEFER { - if (!fnExpr) return; - - // If it's a member operator reference, put the operator back. - if (auto operatorRef = fnExpr->getMemberOperatorRef()) - callExpr->setFn(operatorRef); - }; - - auto getFuncType = [](Type type) -> Type { return type->getRValueType(); }; - - auto fnType = getFuncType(CS.getType(fnExpr)); + auto fnType = CS.getType(fnExpr)->getRValueType(); bool hasTrailingClosure = callArgHasTrailingClosure(callExpr->getArg()); @@ -1489,17 +1413,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { if (CS.getType(argExpr)->hasUnresolvedType()) return false; - SmallVector params; - AnyFunctionType::decomposeInput(CS.getType(argExpr), params); - auto argString = AnyFunctionType::getParamListAsString(params); - - if (auto MTT = fnType->getAs()) { - if (MTT->getInstanceType()->isExistentialType()) { - diagnose(fnExpr->getLoc(), diag::construct_protocol_value, fnType); - return true; - } - } - bool isInitializer = isa(fnExpr); if (isa(argExpr) && cast(argExpr)->getNumElements() == 0) { @@ -1507,6 +1420,10 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { diagnose(fnExpr->getLoc(), diag::cannot_call_with_no_params, overloadName, isInitializer); } else { + SmallVector params; + AnyFunctionType::decomposeInput(CS.getType(argExpr), params); + auto argString = AnyFunctionType::getParamListAsString(params); + diagnose(fnExpr->getLoc(), diag::cannot_call_with_params, overloadName, argString, isInitializer); } diff --git a/test/Constraints/members.swift b/test/Constraints/members.swift index 7a39dd010c393..c2de930b8b443 100644 --- a/test/Constraints/members.swift +++ b/test/Constraints/members.swift @@ -405,17 +405,17 @@ func bar_32854314() -> Int { extension Array where Element == Int { func foo() { let _ = min(foo_32854314(), bar_32854314()) // expected-note {{use 'Swift.' to reference the global function in module 'Swift'}} {{13-13=Swift.}} - // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min()'}} + // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min(by:)'}} } func foo(_ x: Int, _ y: Double) { let _ = min(x, y) // expected-note {{use 'Swift.' to reference the global function in module 'Swift'}} {{13-13=Swift.}} - // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min()'}} + // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min(by:)'}} } func bar() { let _ = min(1.0, 2) // expected-note {{use 'Swift.' to reference the global function in module 'Swift'}} {{13-13=Swift.}} - // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min()'}} + // expected-error@-1 {{use of 'min' nearly matches global function 'min' in module 'Swift' rather than instance method 'min(by:)'}} } } diff --git a/test/type/protocol_composition.swift b/test/type/protocol_composition.swift index b78a9af3a5fd0..a75b0414b5aa5 100644 --- a/test/type/protocol_composition.swift +++ b/test/type/protocol_composition.swift @@ -173,7 +173,9 @@ takesP1AndP2([Swift.AnyObject & P1 & P2]()) takesP1AndP2([AnyObject & protocol_composition.P1 & P2]()) takesP1AndP2([AnyObject & P1 & protocol_composition.P2]()) takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{use of unresolved identifier 'DoesNotExist'}} -takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}} +// TODO(diagnostics): The problem here is that `&` is interpreted as a binary operator, we need to re-think +// how "missing member" fix is implemented because currently it finds N solutions with multiple fixes. +takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{cannot invoke '' with no arguments}} typealias T08 = P1 & inout P2 // expected-error {{'inout' may only be used on parameters}} typealias T09 = P1 & __shared P2 // expected-error {{'__shared' may only be used on parameters}} From c198c1a2aa0233fbafb66a67191924221a6cf35e Mon Sep 17 00:00:00 2001 From: Ravi Kandhadai Date: Mon, 27 Jan 2020 21:07:56 -0800 Subject: [PATCH 05/19] [Constant Evaluator] Add support for BinaryInteger.description which converts an integer to a string. This patch adds a @_semantics annotation to the BinaryInteger.description function. --- include/swift/AST/SemanticAttrs.def | 2 + lib/SILOptimizer/Utils/ConstExpr.cpp | 62 +++++++++++++++++++ stdlib/public/core/Integers.swift | 1 + .../constant_evaluable_subset_test.swift | 14 +++++ test/SILOptimizer/constant_evaluator_test.sil | 28 +++++++++ 5 files changed, 107 insertions(+) diff --git a/include/swift/AST/SemanticAttrs.def b/include/swift/AST/SemanticAttrs.def index 0069674b8a030..e810eb99c94e4 100644 --- a/include/swift/AST/SemanticAttrs.def +++ b/include/swift/AST/SemanticAttrs.def @@ -34,6 +34,8 @@ SEMANTICS_ATTR(STRING_PLUS_EQUALS, "string.plusequals") SEMANTICS_ATTR(FIND_STRING_SWITCH_CASE, "findStringSwitchCase") SEMANTICS_ATTR(FIND_STRING_SWITCH_CASE_WITH_CACHE, "findStringSwitchCaseWithCache") +SEMANTICS_ATTR(BINARY_INTEGER_DESCRIPTION, "binaryInteger.description") + SEMANTICS_ATTR(SWIFT_CONCURRENT_ASYNC, "swift.concurrent.async") SEMANTICS_ATTR(SWIFT_CONCURRENT_SAFE, "swift.concurrent.safe") SEMANTICS_ATTR(SWIFT_CONCURRENT, "swift.concurrent") diff --git a/lib/SILOptimizer/Utils/ConstExpr.cpp b/lib/SILOptimizer/Utils/ConstExpr.cpp index 8efe5fc27b65e..9bdea531f2418 100644 --- a/lib/SILOptimizer/Utils/ConstExpr.cpp +++ b/lib/SILOptimizer/Utils/ConstExpr.cpp @@ -56,6 +56,8 @@ enum class WellKnownFunction { StringEquals, // String.percentEscapedString.getter StringEscapePercent, + // BinaryInteger.description.getter + BinaryIntegerDescription, // _assertionFailure(_: StaticString, _: StaticString, file: StaticString,...) AssertionFailure, // A function taking one argument that prints the symbolic value of the @@ -83,6 +85,8 @@ static llvm::Optional classifyFunction(SILFunction *fn) { return WellKnownFunction::StringEquals; if (fn->hasSemanticsAttr(semantics::STRING_ESCAPE_PERCENT_GET)) return WellKnownFunction::StringEscapePercent; + if (fn->hasSemanticsAttr(semantics::BINARY_INTEGER_DESCRIPTION)) + return WellKnownFunction::BinaryIntegerDescription; if (fn->hasSemanticsAttrThatStartsWith("programtermination_point")) return WellKnownFunction::AssertionFailure; // A call to a function with the following semantics annotation will be @@ -789,6 +793,28 @@ static Type getArrayElementType(Type ty) { return Type(); } +/// Check if the given type \p ty is a stdlib integer type and if so return +/// whether the type is signed. Returns \c None if \p ty is not a stdlib integer +/// type, \c true if it is a signed integer type and \c false if it is an +/// unsigned integer type. +static Optional getSignIfStdlibIntegerType(Type ty) { + StructDecl *decl = ty->getStructOrBoundGenericStruct(); + if (!decl) + return None; + ASTContext &astCtx = ty->getASTContext(); + if (decl == astCtx.getIntDecl() || decl == astCtx.getInt8Decl() || + decl == astCtx.getInt16Decl() || decl == astCtx.getInt32Decl() || + decl == astCtx.getInt64Decl()) { + return true; + } + if (decl == astCtx.getUIntDecl() || decl == astCtx.getUInt8Decl() || + decl == astCtx.getUInt16Decl() || decl == astCtx.getUInt32Decl() || + decl == astCtx.getUInt64Decl()) { + return false; + } + return None; +} + /// Given a call to a well known function, collect its arguments as constants, /// fold it, and return None. If any of the arguments are not constants, marks /// the call's results as Unknown, and return an Unknown with information about @@ -1064,6 +1090,42 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, setValue(apply, resultVal); return None; } + case WellKnownFunction::BinaryIntegerDescription: { + // BinaryInteger.description.getter + assert(conventions.getNumDirectSILResults() == 1 && + conventions.getNumIndirectSILResults() == 0 && + conventions.getNumParameters() == 1 && apply->hasSubstitutions() && + "unexpected BinaryInteger.description.getter signature"); + // Get the type of the argument and check if it is a signed or + // unsigned integer. + SILValue integerArgument = apply->getOperand(1); + CanType argumentType = substituteGenericParamsAndSimpify( + integerArgument->getType().getASTType()); + Optional isSignedIntegerType = + getSignIfStdlibIntegerType(argumentType); + if (!isSignedIntegerType.hasValue()) { + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); + } + // Load the stdlib integer's value and convert it to a string. + SymbolicValue stdlibIntegerValue = + getConstAddrAndLoadResult(integerArgument); + if (!stdlibIntegerValue.isConstant()) { + return stdlibIntegerValue; + } + SymbolicValue builtinIntegerValue = + stdlibIntegerValue.lookThroughSingleElementAggregates(); + assert(builtinIntegerValue.getKind() == SymbolicValue::Integer && + "stdlib integer type must store only a builtin integer"); + APInt integer = builtinIntegerValue.getIntegerValue(); + SmallString<8> integerString; + isSignedIntegerType.getValue() ? integer.toStringSigned(integerString) + : integer.toStringUnsigned(integerString); + SymbolicValue resultVal = + SymbolicValue::getString(integerString.str(), evaluator.getAllocator()); + setValue(apply, resultVal); + return None; + } case WellKnownFunction::DebugPrint: { assert(apply->getNumArguments() == 1 && "debug_print function must take exactly one argument"); diff --git a/stdlib/public/core/Integers.swift b/stdlib/public/core/Integers.swift index 7a9ac0035e10e..56e85f0dfc57d 100644 --- a/stdlib/public/core/Integers.swift +++ b/stdlib/public/core/Integers.swift @@ -1557,6 +1557,7 @@ extension BinaryInteger { } /// A textual representation of this value. + @_semantics("binaryInteger.description") public var description: String { return _description(radix: 10, uppercase: false) } diff --git a/test/SILOptimizer/constant_evaluable_subset_test.swift b/test/SILOptimizer/constant_evaluable_subset_test.swift index b1603de445de7..4c77079039fbc 100644 --- a/test/SILOptimizer/constant_evaluable_subset_test.swift +++ b/test/SILOptimizer/constant_evaluable_subset_test.swift @@ -911,3 +911,17 @@ func interpretMetaTypeCast() -> Bool { func interpretMetaTypeCast2() -> Bool { return testMetaTypeCast(((Int) -> Int).self) } + +// CHECK-LABEL: @testBinaryIntegerDescription +// CHECK-NOT: error: +@_semantics("constant_evaluable") +func testBinaryIntegerDescription(_ x: T) -> String { + return x.description +} + +@_semantics("test_driver") +func interpretBinaryIntegerDescription() -> String { + var str = testBinaryIntegerDescription(-10) + str += testBinaryIntegerDescription(UInt(20)) + return str +} diff --git a/test/SILOptimizer/constant_evaluator_test.sil b/test/SILOptimizer/constant_evaluator_test.sil index b1a3a9a1123e2..fb555685f89a1 100644 --- a/test/SILOptimizer/constant_evaluator_test.sil +++ b/test/SILOptimizer/constant_evaluator_test.sil @@ -1503,3 +1503,31 @@ bb0: %3 = apply %2(%1) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Builtin.Int1 return %3 : $Builtin.Int1 } // CHECK: Returns int: -1 + +// CHECK-LABEL: @interpretBinaryIntegerDescription +sil [ossa] @interpretBinaryIntegerDescription : $@convention(thin) () -> @owned String { +bb0: + %0 = integer_literal $Builtin.Int64, -10 + %1 = struct $Int64 (%0 : $Builtin.Int64) + %2 = alloc_stack $Int64 + store %1 to [trivial] %2 : $*Int64 + %4 = function_ref @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String + %5 = apply %4(%2) : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String + dealloc_stack %2 : $*Int64 + return %5 : $String +} // CHECK: Returns string: "-10" + +sil [_semantics "binaryInteger.description"] @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String + +// CHECK-LABEL: @interpretUnsignedBinaryIntegerDescription +sil [ossa] @interpretUnsignedBinaryIntegerDescription : $@convention(thin) () -> @owned String { +bb0: + %0 = integer_literal $Builtin.Int64, 0xffffffffffffffff + %1 = struct $UInt64 (%0 : $Builtin.Int64) + %2 = alloc_stack $UInt64 + store %1 to [trivial] %2 : $*UInt64 + %4 = function_ref @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String + %5 = apply %4(%2) : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String + dealloc_stack %2 : $*UInt64 + return %5 : $String +} // CHECK: Returns string: "18446744073709551615" From a1c971907bef1f7d174da197e7f4f98ac2c3c9a8 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 27 Jan 2020 15:04:16 -0800 Subject: [PATCH 06/19] build: repair the Windows build This should repair the Windows build after #29451. The quoting behaviour was incorrect and was constructing an invalid compiler invocation. Solve the issue by using `target_include_directories` instead. However, since this needs the target, hoist the flag computation to the local sites. This replicates more logic because of the custom build trying to replicate the CMake build logic in CMake. --- cmake/modules/AddSwift.cmake | 59 ++++++++++++------- cmake/modules/SwiftWindowsSupport.cmake | 8 +-- .../cmake/modules/AddSwiftSourceKit.cmake | 6 ++ 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 56fa993418c07..409dca9ec0287 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -264,18 +264,6 @@ function(_add_variant_c_compile_flags) endif() if("${CFLAGS_SDK}" STREQUAL "WINDOWS") - # MSVC doesn't support -Xclang. We don't need to manually specify - # the dependent libraries as `cl` does so. - if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") - list(APPEND result -Xclang;--dependent-lib=oldnames) - # TODO(compnerd) handle /MT, /MTd - if("${CFLAGS_BUILD_TYPE}" STREQUAL "Debug") - list(APPEND result -Xclang;--dependent-lib=msvcrtd) - else() - list(APPEND result -Xclang;--dependent-lib=msvcrt) - endif() - endif() - # MSVC/clang-cl don't support -fno-pic or -fms-compatibility-version. if(NOT SWIFT_COMPILER_IS_MSVC_LIKE) list(APPEND result -fno-pic) @@ -366,11 +354,6 @@ function(_add_variant_c_compile_flags) list(APPEND result -isystem;${path}) endforeach() list(APPEND result "-D__ANDROID_API__=${SWIFT_ANDROID_API_LEVEL}") - elseif(CFLAGS_SDK STREQUAL WINDOWS) - swift_windows_include_for_arch(${CFLAGS_ARCH} ${CFLAGS_ARCH}_INCLUDE) - foreach(path ${${CFLAGS_ARCH}_INCLUDE}) - list(APPEND result "\"${CMAKE_INCLUDE_FLAG_C}${path}\"") - endforeach() endif() set("${CFLAGS_RESULT_VAR_NAME}" "${result}" PARENT_SCOPE) @@ -910,11 +893,9 @@ function(_add_swift_library_single target name) if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS") if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") - swift_windows_generate_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS) - foreach(flag ${SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS}) - list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;${flag}) - list(APPEND SWIFTLIB_SINGLE_C_COMPILE_FLAGS ${flag}) - endforeach() + swift_windows_get_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY) + list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS + -Xcc;-Xclang;-Xcc;-ivfsoverlay;-Xcc;-Xclang;-Xcc;${SWIFTLIB_SINGLE_VFS_OVERLAY}) endif() swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} SWIFTLIB_INCLUDE) foreach(directory ${SWIFTLIB_INCLUDE}) @@ -1390,6 +1371,25 @@ function(_add_swift_library_single target name) endif() # Set compilation and link flags. + if(SWIFTLIB_SINGLE_SDK STREQUAL WINDOWS) + swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} + ${SWIFTLIB_SINGLE_ARCHITECTURE}_INCLUDE) + target_include_directories(${target} SYSTEM PRIVATE + ${${SWIFTLIB_SINGLE_ARCHITECTURE}_INCLUDE}) + + if(NOT ${CMAKE_C_COMPILER_ID} STREQUAL MSVC) + swift_windows_get_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY) + target_compile_options(${target} PRIVATE + "SHELL:-Xclang -ivfsoverlay -Xclang ${SWIFTLIB_SINGLE_VFS_OVERLAY}") + + # MSVC doesn't support -Xclang. We don't need to manually specify + # the dependent libraries as `cl` does so. + target_compile_options(${target} PRIVATE + "SHELL:-Xclang --dependent-lib=oldnames" + # TODO(compnerd) handle /MT, /MTd + "SHELL:-Xclang --dependent-lib=msvcrt$<$:d>") + endif() + endif() target_include_directories(${target} SYSTEM PRIVATE ${SWIFT_${SWIFTLIB_SINGLE_SDK}_${SWIFTLIB_SINGLE_ARCHITECTURE}_ICU_UC_INCLUDE} ${SWIFT_${SWIFTLIB_SINGLE_SDK}_${SWIFTLIB_SINGLE_ARCHITECTURE}_ICU_I18N_INCLUDE}) @@ -2575,6 +2575,21 @@ function(_add_swift_executable_single name) ${SWIFTEXE_SINGLE_DEPENDS}) llvm_update_compile_flags("${name}") + if(SWIFTEXE_SINGLE_SDK STREQUAL WINDOWS) + swift_windows_include_for_arch(${SWIFTEXE_SINGLE_ARCHITECTURE} + ${SWIFTEXE_SINGLE_ARCHITECTURE}_INCLUDE) + target_include_directories(${name} SYSTEM PRIVATE + ${${SWIFTEXE_SINGLE_ARCHITECTURE}_INCLUDE}) + + if(NOT ${CMAKE_C_COMPILER_ID} STREQUAL MSVC) + # MSVC doesn't support -Xclang. We don't need to manually specify + # the dependent libraries as `cl` does so. + target_compile_options(${name} PRIVATE + "SHELL:-Xclang --dependent-lib=oldnames" + # TODO(compnerd) handle /MT, /MTd + "SHELL:-Xclang --dependent-lib=msvcrt$<$:d>") + endif() + endif() target_compile_options(${name} PRIVATE ${c_compile_flags}) target_link_directories(${name} PRIVATE diff --git a/cmake/modules/SwiftWindowsSupport.cmake b/cmake/modules/SwiftWindowsSupport.cmake index ffb6f7da6b70c..7d97cdbadcec7 100644 --- a/cmake/modules/SwiftWindowsSupport.cmake +++ b/cmake/modules/SwiftWindowsSupport.cmake @@ -49,7 +49,7 @@ function(swift_windows_lib_for_arch arch var) set(${var} ${paths} PARENT_SCOPE) endfunction() -function(swift_windows_generate_sdk_vfs_overlay flags) +function(swift_windows_get_sdk_vfs_overlay overlay) get_filename_component(VCToolsInstallDir ${VCToolsInstallDir} ABSOLUTE) get_filename_component(UniversalCRTSdkDir ${UniversalCRTSdkDir} ABSOLUTE) set(UCRTVersion ${UCRTVersion}) @@ -58,10 +58,8 @@ function(swift_windows_generate_sdk_vfs_overlay flags) configure_file("${SWIFT_SOURCE_DIR}/utils/WindowsSDKVFSOverlay.yaml.in" "${CMAKE_CURRENT_BINARY_DIR}/windows-sdk-vfs-overlay.yaml" @ONLY) - - set(${flags} - -Xclang;-ivfsoverlay;-Xclang;"${CMAKE_CURRENT_BINARY_DIR}/windows-sdk-vfs-overlay.yaml" - PARENT_SCOPE) + set(${overlay} ${CMAKE_CURRENT_BINARY_DIR}/windows-sdk-vfs-overlay.yaml + PARENT_SCOPE) endfunction() function(swift_verify_windows_VCVAR var) diff --git a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake index 4f88629516aa4..83b70845e0886 100644 --- a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake +++ b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake @@ -71,6 +71,12 @@ function(add_sourcekit_default_compiler_flags target) LIBRARY_SEARCH_DIRECTORIES_VAR_NAME library_search_directories) # Set compilation and link flags. + if(${SWIFT_HOST_VARIANT_SDK} STREQUAL WINDOWS) + swift_windows_include_for_arch(${SWIFT_HOST_VARIANT_ARCH} + ${SWIFT_HOST_VARIANT_ARCH}_INCLUDE) + target_include_directories(${target} SYSTEM PRIVATE + ${${SWIFT_HOST_VARIANT_ARCH}_INCLUDE}) + endif() target_compile_options(${target} PRIVATE -fblocks) target_link_options(${target} PRIVATE From 3e42a0f1cad0f022ef5ee94893bb02106d847668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodri=CC=81guez=20Troitin=CC=83o?= Date: Mon, 27 Jan 2020 22:51:25 -0800 Subject: [PATCH 07/19] [android] Escape include paths in Android. Before the result of `_add_variant_c_compile_flags` was a string, so appending several "-isystem" was not a problem. With #29451 the rules have changed since the list is now handled by CMake, and it deduplicates the repeated members in the list. Thanks, CMake. Should fix the Android CI builds that were failing since the merging of #29451. --- cmake/modules/AddSwift.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 56fa993418c07..efcdd40655eb3 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -363,7 +363,7 @@ function(_add_variant_c_compile_flags) swift_android_libcxx_include_paths(CFLAGS_CXX_INCLUDES) swift_android_include_for_arch("${CFLAGS_ARCH}" "${CFLAGS_ARCH}_INCLUDE") foreach(path IN LISTS CFLAGS_CXX_INCLUDES ${CFLAGS_ARCH}_INCLUDE) - list(APPEND result -isystem;${path}) + list(APPEND result "SHELL:${CMAKE_INCLUDE_SYSTEM_FLAG_C}${path}") endforeach() list(APPEND result "-D__ANDROID_API__=${SWIFT_ANDROID_API_LEVEL}") elseif(CFLAGS_SDK STREQUAL WINDOWS) From 38aded73b153a2fe1704d631d5e5d12e3c32b089 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 28 Jan 2020 00:35:48 -0800 Subject: [PATCH 08/19] [Diagnostics] Add a special case diagnostic for call to init on `Void` with arguments Expressions like `Void(...)` have a special locator which ends at `FunctionArgument` instead of `ApplyArgument` which makes it possible to type-check `Void()` call successfully. "extraneous arguments" diagnostic needs to handle such situations specifically e.g. `Void(0)`. --- lib/Sema/CSDiag.cpp | 15 --------------- lib/Sema/CSDiagnostics.cpp | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 3558188f6e2dd..1910e242ce091 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1296,21 +1296,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { } } - // Let's check whether this is a situation when callee expects - // no arguments but N are given. Otherwise, just below - // `typeCheckArgumentChild*` is going to use `()` is a contextual type which - // is incorrect. - if (argType && argType->isVoid()) { - auto *argExpr = callExpr->getArg(); - if (isa(argExpr) || - (isa(argExpr) && - cast(argExpr)->getNumElements() > 0)) { - diagnose(callExpr->getLoc(), diag::extra_argument_to_nullary_call) - .highlight(argExpr->getSourceRange()); - return true; - } - } - // Get the expression result of type checking the arguments to the call // independently, so we have some idea of what we're working with. // diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index df3bd12ac70d2..b8cf4a95a75bb 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -4561,7 +4561,21 @@ bool ExtraneousArgumentsFailure::diagnoseAsNote() { } bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const { - auto *arguments = getArgumentListExprFor(getLocator()); + auto *locator = getLocator(); + + // This specifically handles a case of `Void(...)` which generates + // constraints differently from other constructor invocations and + // wouldn't have `ApplyArgument` as a last element in the locator. + if (auto *call = dyn_cast(getRawAnchor())) { + auto *TE = dyn_cast(call->getFn()); + if (TE && getType(TE)->getMetatypeInstanceType()->isVoid()) { + emitDiagnostic(call->getLoc(), diag::extra_argument_to_nullary_call) + .highlight(call->getArg()->getSourceRange()); + return true; + } + } + + auto *arguments = getArgumentListExprFor(locator); if (!arguments) return false; From 18babf75746914ca140e9b964c4e6344680e9091 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 27 Jan 2020 15:36:04 -0800 Subject: [PATCH 09/19] SILGen: Lower the type of the return value merge phi in the context of the current function rdar://58929484 --- lib/SILGen/SILGenEpilog.cpp | 4 ++-- test/SILGen/opaque_result_type.swift | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/SILGen/SILGenEpilog.cpp b/lib/SILGen/SILGenEpilog.cpp index 414bfc6a27bd4..66f3302207a9a 100644 --- a/lib/SILGen/SILGenEpilog.cpp +++ b/lib/SILGen/SILGenEpilog.cpp @@ -30,8 +30,8 @@ void SILGenFunction::prepareEpilog(Type resultType, bool isThrowing, // emits unreachable if there is no source level return. NeedsReturn = (fnConv.funcTy->getNumResults() != 0); for (auto directResult : fnConv.getDirectSILResults()) { - SILType resultType = - F.mapTypeIntoContext(fnConv.getSILType(directResult)); + SILType resultType = F.getLoweredType( + F.mapTypeIntoContext(fnConv.getSILType(directResult))); epilogBB->createPhiArgument(resultType, ValueOwnershipKind::Owned); } } diff --git a/test/SILGen/opaque_result_type.swift b/test/SILGen/opaque_result_type.swift index eacbd6204ab5f..6980e773fc4c3 100644 --- a/test/SILGen/opaque_result_type.swift +++ b/test/SILGen/opaque_result_type.swift @@ -149,3 +149,19 @@ struct S2 : X { return foo } } + +class Base {} +class Sub1 : Base {} +class Sub2 : Base {} + +public class D { + var cond = true + // CHECK-LABEL: sil private [ossa] @$s18opaque_result_type1DC1c33_C2C55A4BAF30C3244D4A165D48A91142LLQrvg + // CHECK: bb3([[RET:%[0-9]+]] : @owned $Base): + // CHECH: return [[RET]] + // CHECK: } // end sil function '$s18opaque_result_type1DC1c33_C2C55A4BAF30C3244D4A165D48A91142LLQrvg' + private lazy var c: some Base = { + let d = cond ? Sub1() : Sub2() + return d + }() +} From 049e3844362e1082212c2126f6fa32ce0bf654d0 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 28 Jan 2020 09:21:05 -0800 Subject: [PATCH 10/19] build: move `compute_library_subdir` to where it is used This function is only used in SwiftSource.cmake. Locate the function there to make it easier to find. --- cmake/modules/AddSwift.cmake | 10 ---------- cmake/modules/SwiftSource.cmake | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 04fbab9045156..34a872f5f0856 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -28,16 +28,6 @@ function(add_dependencies_multiple_targets) endif() endfunction() -# Compute the library subdirectory to use for the given sdk and -# architecture, placing the result in 'result_var_name'. -function(compute_library_subdir result_var_name sdk arch) - if(sdk IN_LIST SWIFT_APPLE_PLATFORMS OR sdk STREQUAL "MACCATALYST") - set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}" PARENT_SCOPE) - else() - set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}" PARENT_SCOPE) - endif() -endfunction() - function(_compute_lto_flag option out_var) string(TOLOWER "${option}" lowercase_option) if (lowercase_option STREQUAL "full") diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake index 818a03c1e46cc..004d26b0fa8d3 100644 --- a/cmake/modules/SwiftSource.cmake +++ b/cmake/modules/SwiftSource.cmake @@ -1,6 +1,16 @@ include(macCatalystUtils) include(SwiftUtils) +# Compute the library subdirectory to use for the given sdk and +# architecture, placing the result in 'result_var_name'. +function(compute_library_subdir result_var_name sdk arch) + if(sdk IN_LIST SWIFT_APPLE_PLATFORMS OR sdk STREQUAL "MACCATALYST") + set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}" PARENT_SCOPE) + else() + set("${result_var_name}" "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}" PARENT_SCOPE) + endif() +endfunction() + # Process the sources within the given variable, pulling out any Swift # sources to be compiled with 'swift' directly. This updates # ${sourcesvar} in place with the resulting list and ${externalvar} with the From 5428060ca842a9fb4bf9236f1991a7e27cfe0f96 Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Tue, 28 Jan 2020 09:23:46 -0800 Subject: [PATCH 11/19] [build][gardening] adjust framework paths (#29507) Collate -F with the framework path to avoid unwanted deduplication of options by `target_compile_options` (which is the case after #29451) -- this way no undesired side effects are introduced should a new search path be added. Addresses rdar://problem/58934566 --- cmake/modules/AddSwift.cmake | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 04fbab9045156..ae92b3ec55bbd 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -163,9 +163,12 @@ function(_add_variant_c_compile_link_flags) endif() if(IS_DARWIN) + # We collate -F with the framework path to avoid unwanted deduplication + # of options by target_compile_options -- this way no undesired + # side effects are introduced should a new search path be added. list(APPEND result "-arch" "${CFLAGS_ARCH}" - "-F" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}/../../../Developer/Library/Frameworks") + "-F${SWIFT_SDK_${CFLAGS_SDK}_PATH}/../../../Developer/Library/Frameworks") set(add_explicit_version TRUE) @@ -405,8 +408,11 @@ function(_add_variant_swift_compile_flags endif() if(IS_DARWIN) + # We collate -F with the framework path to avoid unwanted deduplication + # of options by target_compile_options -- this way no undesired + # side effects are introduced should a new search path be added. list(APPEND result - "-F" "${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}/../../../Developer/Library/Frameworks") + "-F${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}/../../../Developer/Library/Frameworks") endif() is_build_type_optimized("${build_type}" optimized) From 88d655972289c31f1052fdf490b1eb570fa37350 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 27 Jan 2020 13:32:27 -0800 Subject: [PATCH 12/19] [GSB] Map invalid subject types in requirement constraints to ErrorType Resolves SR-12072 and rdar://58941114 --- lib/AST/GenericSignatureBuilder.cpp | 2 ++ .../compiler_crashers_2_fixed/rdar58941114.swift | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 validation-test/compiler_crashers_2_fixed/rdar58941114.swift diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index 488a44b6ff8a4..bb58412049496 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -4361,6 +4361,8 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement( if (subjectType->is()) { subjectType = resolveDependentMemberTypes(*this, subjectType); + } else { + subjectType = ErrorType::get(subjectType); } auto invalidConstraint = Constraint( diff --git a/validation-test/compiler_crashers_2_fixed/rdar58941114.swift b/validation-test/compiler_crashers_2_fixed/rdar58941114.swift new file mode 100644 index 0000000000000..50db463dda4dd --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/rdar58941114.swift @@ -0,0 +1,6 @@ +// RUN: not %target-swift-frontend %s -typecheck + +class C {} +protocol Foo { + associatedtype X where C: X +} From 255b2cf860a44512b4ba73ef6c0ad5809179ed46 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 28 Jan 2020 13:06:33 -0800 Subject: [PATCH 13/19] [NFC] Improve Nested Types Table Test To guard against the kind of complex failures seen in rdar://58690068, improve this regression test with a copy of a shrunken version of CocoaError.Code. In that radar, CocoaError.Code was defined in one overlay and extended in another translation unit. When deserialization encountered this, it failed to search the overlay's nested type tables and fell through to re-enter lookupDirect. --- .../Inputs/nested-type-with-overlay/overlay.swift | 10 ++++++++++ test/Serialization/nested-type-with-overlay.swift | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test/Serialization/Inputs/nested-type-with-overlay/overlay.swift b/test/Serialization/Inputs/nested-type-with-overlay/overlay.swift index 72f831e10f774..754423baa4235 100644 --- a/test/Serialization/Inputs/nested-type-with-overlay/overlay.swift +++ b/test/Serialization/Inputs/nested-type-with-overlay/overlay.swift @@ -8,3 +8,13 @@ extension Base { } public var shadowedFromSwift = Base.NestedAndShadowed(dummy: ()) + +public struct CustomError { + public struct Code : RawRepresentable { + public let rawValue: Int + + public init(rawValue: Int) { + self.rawValue = rawValue + } + } +} diff --git a/test/Serialization/nested-type-with-overlay.swift b/test/Serialization/nested-type-with-overlay.swift index e2c2f36cb0423..4b83de9c05b7b 100644 --- a/test/Serialization/nested-type-with-overlay.swift +++ b/test/Serialization/nested-type-with-overlay.swift @@ -8,8 +8,8 @@ // REQUIRES: asserts -// CHECK: 3 Serialization - # of nested types resolved without full lookup -// Unfortunately this isn't 4 because of the shadowed nested type from Clang. +// CHECK: 4 Serialization - # of nested types resolved without full lookup +// Unfortunately this isn't 5 because of the shadowed nested type from Clang. import HasOverlay @@ -20,3 +20,9 @@ public func resolveNestedTypes( public var shadowedFromClang = getShadowedFromClang() public var shadowedFromSwift = HasOverlay.shadowedFromSwift + +extension CustomError.Code { + public static var failedSuccessfully: CustomError.Code { + return CustomError.Code(rawValue: -9999) + } +} From 4a123f102e7c4d0a0d19b9eca1a2fb552362c4bf Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Mon, 27 Jan 2020 20:52:50 -0800 Subject: [PATCH 14/19] Fix the build-script --skip-build option. This option configures the build directories without building any targets. Splitting configuration from build allows for the decoupling of build products. This decoupling is essential for the enlightened way of developing Swift where the build-script is never actually used to build anything, and build products can be independently configured. When fully supported, this avoids many unnecessary full/clean rebuilds and enables debugging by mixing-and-matching configurations and rebuilding only select products after a change. Sadly, the option has degraded, and a recent commit rendered it fully broken: commit 34848e6026c9c43d45efe97a8849effdc1a1c97a Author: Alex Langford Date: Wed Jan 22 19:27:44 2020 [build] Unify logic to skip building projects in build-script-impl The breaking commit was itself a reasonable cleanup. The underlying problem was the original --skip-build was implemented using hacks that conflated configuration with build. This fix reinstates a reasonable situation: --skip-build has no effect on configuration, as documented. It merely skips building the targets. This is how it must behave to work as intended. --skip-build-{product} and its inverse --build-{product} controls which products will be configured. These options are in heavy use throughout the scripts, so changing the name (e.g. to --skip-config) would be disruptive and of questionable benefit. None of this changes the fact that any required build logic that people have dumped into build-script-impl still effectively breaks the enlightened way of building Swift, particularly when building toolchain components. --- utils/build-script | 4 +- utils/build-script-impl | 49 ++++++++++--------- .../build_swift/driver_arguments.py | 23 --------- .../build_swift/test_driver_arguments.py | 24 --------- 4 files changed, 28 insertions(+), 72 deletions(-) diff --git a/utils/build-script b/utils/build-script index 436fb357bac59..87065cd34f09e 100755 --- a/utils/build-script +++ b/utils/build-script @@ -464,9 +464,7 @@ class BuildScriptInvocation(object): ] if args.skip_build: - impl_args += ["--skip-build-cmark", - "--skip-build-llvm", - "--skip-build-swift"] + impl_args += ["--skip-build"] if not args.build_benchmarks: impl_args += ["--skip-build-benchmarks"] # Currently we do not build external benchmarks by default. diff --git a/utils/build-script-impl b/utils/build-script-impl index 49239434d12e0..b5b3264410f36 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -30,12 +30,13 @@ umask 0022 # A default value of "" indicates that the corresponding variable # will remain unset unless set explicitly. # -# skip-* parameters do not affect the configuration (CMake parameters). -# You can turn them on and off in different invocations of the script for the -# same build directory. +# The --skip-build parameter, with no product name, does not affect the +# configuration (CMake parameters). You can turn this option on and +# off in different invocations of the script for the same build +# directory without affecting configutation. # -# build-* parameters affect the CMake configuration (enable/disable those -# components). +# skip-build-* and build-* parameters affect the CMake configuration +# (enable/disable those components). # # Each variable name is re-exported into this script in uppercase, where dashes # are substituted by underscores. For example, `swift-install-components` is @@ -118,6 +119,7 @@ KNOWN_SETTINGS=( swift-stdlib-build-type "Debug" "the CMake build variant for Swift" ## Skip Build ... + skip-build "" "set to configure as usual while skipping the build step" skip-build-android "" "set to skip building Swift stdlibs for Android" skip-build-benchmarks "" "set to skip building Swift Benchmark Suite" skip-build-clang-tools-extra "" "set to skip building clang-tools-extra as part of llvm" @@ -1041,13 +1043,10 @@ if [[ ! "${SKIP_BUILD_PLAYGROUNDSUPPORT}" && ! -d ${PLAYGROUNDSUPPORT_SOURCE_DIR exit 1 fi -# We cannot currently apply the normal rules of skipping here for LLVM. Even if -# we are skipping building LLVM, we still need to at least build several tools -# that swift relies on for building and testing. See the LLVM configure rules. -PRODUCTS=(llvm) [[ "${SKIP_BUILD_CMARK}" ]] || PRODUCTS+=(cmark) [[ "${SKIP_BUILD_LIBCXX}" ]] || PRODUCTS+=(libcxx) [[ "${SKIP_BUILD_LIBICU}" ]] || PRODUCTS+=(libicu) +[[ "${SKIP_BUILD_LLVM}" ]] || PRODUCTS+=(llvm) [[ "${SKIP_BUILD_SWIFT}" ]] || PRODUCTS+=(swift) [[ "${SKIP_BUILD_LLDB}" ]] || PRODUCTS+=(lldb) [[ "${SKIP_BUILD_LIBDISPATCH}" ]] || PRODUCTS+=(libdispatch) @@ -1406,7 +1405,6 @@ for host in "${ALL_HOSTS[@]}"; do for product in "${PRODUCTS[@]}"; do [[ $(should_execute_action "${host}-${product/_static}-build") ]] || continue - unset skip_build source_dir_var="$(toupper ${product})_SOURCE_DIR" source_dir=${!source_dir_var} build_dir=$(build_directory ${host} ${product}) @@ -1436,7 +1434,7 @@ for host in "${ALL_HOSTS[@]}"; do if [ "${BUILD_LLVM}" == "0" ] ; then build_targets=(clean) fi - if [ "${SKIP_BUILD_LLVM}" ] ; then + if [ "${SKIP_BUILD}" ] ; then # We can't skip the build completely because the standalone # build of Swift depend on these for building and testing. build_targets=(llvm-tblgen clang-resource-headers intrinsics_gen clang-tablegen-targets) @@ -2207,18 +2205,25 @@ for host in "${ALL_HOSTS[@]}"; do fi # Build. - if [[ "${CMAKE_GENERATOR}" == "Xcode" ]] ; then - # Xcode generator uses "ALL_BUILD" instead of "all". - # Also, xcodebuild uses -target instead of bare names. - build_targets=("${build_targets[@]/all/ALL_BUILD}") - build_targets=("${build_targets[@]/#/${BUILD_TARGET_FLAG} }") - - # Xcode can't restart itself if it turns out we need to reconfigure. - # Do an advance build to handle that. - call "${CMAKE_BUILD[@]}" "${build_dir}" $(cmake_config_opt ${product}) - fi + # + # Even if builds are skipped, Swift configuration relies on + # some LLVM tools like TableGen. In the LLVM configure rules + # above, a small subset of LLVM build_targets are selected + # when SKIP_BUILD is set. + if [[ $(not ${SKIP_BUILD}) || "${product}" == "llvm" ]]; then + if [[ "${CMAKE_GENERATOR}" == "Xcode" ]] ; then + # Xcode generator uses "ALL_BUILD" instead of "all". + # Also, xcodebuild uses -target instead of bare names. + build_targets=("${build_targets[@]/all/ALL_BUILD}") + build_targets=("${build_targets[@]/#/${BUILD_TARGET_FLAG} }") + + # Xcode can't restart itself if it turns out we need to reconfigure. + # Do an advance build to handle that. + call "${CMAKE_BUILD[@]}" "${build_dir}" $(cmake_config_opt ${product}) + fi - call "${CMAKE_BUILD[@]}" "${build_dir}" $(cmake_config_opt ${product}) -- "${BUILD_ARGS[@]}" ${build_targets[@]} + call "${CMAKE_BUILD[@]}" "${build_dir}" $(cmake_config_opt ${product}) -- "${BUILD_ARGS[@]}" ${build_targets[@]} + fi # When we are building LLVM copy over the compiler-rt # builtins for iOS/tvOS/watchOS to ensure that Swift's diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index 3c607ee18efbb..ed569ad8a8473 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -131,29 +131,6 @@ def _apply_default_arguments(args): raise ValueError('error: --watchos-all is unavailable in open-source ' 'Swift.\nUse --watchos to skip watchOS device tests.') - # Propagate global --skip-build - if args.skip_build: - args.build_linux = False - args.build_freebsd = False - args.build_cygwin = False - args.build_osx = False - args.build_ios = False - args.build_tvos = False - args.build_watchos = False - args.build_android = False - args.build_benchmarks = False - args.build_external_benchmarks = False - args.build_lldb = False - args.build_llbuild = False - args.build_libcxx = False - args.build_swiftpm = False - args.build_xctest = False - args.build_foundation = False - args.build_libdispatch = False - args.build_libicu = False - args.build_playgroundsupport = False - args.build_pythonkit = False - # --skip-{ios,tvos,watchos} or --skip-build-{ios,tvos,watchos} are # merely shorthands for --skip-build-{**os}-{device,simulator} if not args.ios or not args.build_ios: diff --git a/utils/build_swift/tests/build_swift/test_driver_arguments.py b/utils/build_swift/tests/build_swift/test_driver_arguments.py index efbc469a28a3c..7811b6dd6d61e 100644 --- a/utils/build_swift/tests/build_swift/test_driver_arguments.py +++ b/utils/build_swift/tests/build_swift/test_driver_arguments.py @@ -540,30 +540,6 @@ def test_implied_defaults_build_variant(self): self.assertEqual(namespace.swift_build_variant, 'Debug') self.assertEqual(namespace.swift_stdlib_build_variant, 'Debug') - def test_implied_defaults_skip_build(self): - namespace = self.parse_default_args(['--skip-build']) - - self.assertFalse(namespace.build_benchmarks) - - self.assertFalse(namespace.build_linux) - self.assertFalse(namespace.build_android) - self.assertFalse(namespace.build_freebsd) - self.assertFalse(namespace.build_cygwin) - self.assertFalse(namespace.build_osx) - self.assertFalse(namespace.build_ios) - self.assertFalse(namespace.build_tvos) - self.assertFalse(namespace.build_watchos) - - self.assertFalse(namespace.build_foundation) - self.assertFalse(namespace.build_libdispatch) - self.assertFalse(namespace.build_libicu) - self.assertFalse(namespace.build_lldb) - self.assertFalse(namespace.build_llbuild) - self.assertFalse(namespace.build_libcxx) - self.assertFalse(namespace.build_playgroundsupport) - self.assertFalse(namespace.build_swiftpm) - self.assertFalse(namespace.build_xctest) - def test_implied_defaults_skip_build_ios(self): namespace = self.parse_default_args(['--skip-build-ios']) self.assertFalse(namespace.build_ios_device) From 608b1b4814333a348a232484546c395752ff6c60 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Tue, 28 Jan 2020 13:17:53 -0800 Subject: [PATCH 15/19] [ConstraintSystem] Allow solving same-type requirements for associated types where the base does not conform to the associated type's protocol. We can only reach this case when the solver has already applied a fix for the conformance failure. --- lib/Sema/CSSimplify.cpp | 25 +++++++++++++++---------- test/Constraints/same_types.swift | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 43a00626b0e8d..3d00cf3de5a07 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3331,10 +3331,13 @@ bool ConstraintSystem::repairFailures( if (lhs->hasHole() || rhs->hasHole()) return true; - // If dependent members are present here it's because - // base doesn't conform to associated type's protocol. - if (lhs->hasDependentMember() || rhs->hasDependentMember()) - break; + // If dependent members are present here it's because the base doesn't + // conform to the associated type's protocol. We can only get here if we + // already applied a fix for the conformance failure. + if (lhs->hasDependentMember() || rhs->hasDependentMember()) { + increaseScore(SK_Fix); + return true; + } // If requirement is something like `T == [Int]` let's let // type matcher a chance to match generic parameters before @@ -3949,12 +3952,14 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, llvm_unreachable("type variables should have already been handled by now"); case TypeKind::DependentMember: { - // If one of the dependent member types has no type variables, - // this comparison is effectively illformed, because dependent - // member couldn't be simplified down to the actual type, and - // we wouldn't be able to solve this constraint, so let's just fail. - if (!desugar1->hasTypeVariable() || !desugar2->hasTypeVariable()) - return getTypeMatchFailure(locator); + // If one of the dependent member types has no type variables, the + // dependent member can't be simplified because the base doesn't conform + // to the associated type's protocol. We can only get here if we already + // applied a fix for the conformance failure. + if (!desugar1->hasTypeVariable() || !desugar2->hasTypeVariable()) { + increaseScore(SK_Fix); + return getTypeMatchSuccess(); + } // Nothing we can solve yet, since we need to wait until // type variables will get resolved. diff --git a/test/Constraints/same_types.swift b/test/Constraints/same_types.swift index 2eda295170a75..6129d8046338b 100644 --- a/test/Constraints/same_types.swift +++ b/test/Constraints/same_types.swift @@ -333,3 +333,25 @@ class R: P7 where T: P7, T.A == T.Type { // expected-note {{'T' declared as p R.fn(args: R.self) // expected-error {{generic parameter 'T' could not be inferred}} // expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} + +// rdar://problem/58607155 +protocol AssocType1 { associatedtype A } +protocol AssocType2 { associatedtype A } + +func rdar58607155() { + func f(t1: T1, t2: T2) where T1.A == T2.A {} + // expected-note@-1 2 {{where 'T2' = 'MissingConformance'}} + // expected-note@-2 2 {{where 'T1' = 'MissingConformance'}} + + class Conformance: AssocType1, AssocType2 { typealias A = Int } + class MissingConformance {} + + // One generic argument has a conformance failure + f(t1: MissingConformance(), t2: Conformance()) // expected-error {{local function 'f(t1:t2:)' requires that 'MissingConformance' conform to 'AssocType1'}} + f(t1: Conformance(), t2: MissingConformance()) // expected-error {{local function 'f(t1:t2:)' requires that 'MissingConformance' conform to 'AssocType2'}} + + // Both generic arguments have a conformance failure + f(t1: MissingConformance(), t2: MissingConformance()) + // expected-error@-1 {{local function 'f(t1:t2:)' requires that 'MissingConformance' conform to 'AssocType1'}} + // expected-error@-2 {{local function 'f(t1:t2:)' requires that 'MissingConformance' conform to 'AssocType2'}} +} From bf41881bcd7e7b1b630ad3ca2457b0fd4fa9c59e Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Wed, 22 Jan 2020 20:07:14 +0100 Subject: [PATCH 16/19] Move swift runtime failure from linkage name to function name Signed-off-by: Med Ismail Bennani --- lib/IRGen/IRGenDebugInfo.cpp | 4 ++-- test/DebugInfo/linetable-codeview.swift | 2 +- test/IRGen/condfail_message.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 2a75f47fd89a1..8cbdd8095e06d 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -1847,7 +1847,7 @@ void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder, auto DL = llvm::DebugLoc::get(L.Line, L.Column, Scope, InlinedAt); Builder.SetCurrentDebugLocation(DL); } - + void IRGenDebugInfoImpl::addFailureMessageToCurrentLoc(IRBuilder &Builder, StringRef failureMsg) { auto TrapLoc = Builder.getCurrentDebugLocation(); @@ -1864,7 +1864,7 @@ void IRGenDebugInfoImpl::addFailureMessageToCurrentLoc(IRBuilder &Builder, FuncName += failureMsg; llvm::DISubprogram *TrapSP = DBuilder.createFunction( - MainModule, StringRef(), FuncName, TrapLoc->getFile(), 0, DIFnTy, 0, + MainModule, FuncName, StringRef(), TrapLoc->getFile(), 0, DIFnTy, 0, llvm::DINode::FlagArtificial, llvm::DISubprogram::SPFlagDefinition, nullptr, nullptr, nullptr); diff --git a/test/DebugInfo/linetable-codeview.swift b/test/DebugInfo/linetable-codeview.swift index 524d49c8561b9..77c7141e7a1ad 100644 --- a/test/DebugInfo/linetable-codeview.swift +++ b/test/DebugInfo/linetable-codeview.swift @@ -81,7 +81,7 @@ func foo() { // FIXME: The location of ``@llvm.trap`` should be in Integers.swift.gyb // instead of being artificial. // CHECK: ![[INLINEDADD]] = !DILocation(line: 0, scope: ![[FAILURE_FUNC:[0-9]+]], inlinedAt: ![[INLINELOC:[0-9]+]] -// CHECK-DAG: !{{.*}} = distinct !DISubprogram(linkageName: "Swift runtime failure: arithmetic overflow", scope: {{.*}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, {{.*}}) +// CHECK-DAG: !{{.*}} = distinct !DISubprogram(name: "Swift runtime failure: arithmetic overflow", scope: {{.*}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, {{.*}}) // CHECK-DAG: ![[INLINELOC]] = !DILocation(line: 0, scope: !{{[0-9]+}}, inlinedAt: ![[ADD]] // NOTE: These prologue instructions are given artificial line locations for diff --git a/test/IRGen/condfail_message.swift b/test/IRGen/condfail_message.swift index 8c3eabb2da652..5a5fc702cf465 100644 --- a/test/IRGen/condfail_message.swift +++ b/test/IRGen/condfail_message.swift @@ -11,6 +11,6 @@ func testit(_ a: Int8) -> Int8 { // CHECK: [[CALLER_LOC:![0-9]+]] = !DILocation(line: 9, column: 12, scope: !{{.*}}) // CHECK: [[LOC]] = !DILocation(line: 0, scope: [[FAILURE_FUNC:![0-9]+]], inlinedAt: [[CALLER_LOC]]) -// CHECK: [[FAILURE_FUNC]] = distinct !DISubprogram(linkageName: "Swift runtime failure: arithmetic overflow", scope: {{.*}}, file: {{.*}}, type: [[FUNC_TYPE:![0-9]+]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, {{.*}}) +// CHECK: [[FAILURE_FUNC]] = distinct !DISubprogram(name: "Swift runtime failure: arithmetic overflow", scope: {{.*}}, file: {{.*}}, type: [[FUNC_TYPE:![0-9]+]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, {{.*}}) // CHECK: [[FUNC_TYPE]] = !DISubroutineType(types: null) From 682bb316c026841b36d9c05c7f0d9c7d9072fe41 Mon Sep 17 00:00:00 2001 From: Ravi Kandhadai Date: Tue, 28 Jan 2020 14:17:10 -0800 Subject: [PATCH 17/19] [Constant Evaluator] Add support for displaying assertion/precondition failure messages and fatalError messages, when such errors happen during constant evaluation. --- lib/SILOptimizer/Utils/ConstExpr.cpp | 12 +++++-- .../constant_evaluable_subset_test.swift | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/SILOptimizer/Utils/ConstExpr.cpp b/lib/SILOptimizer/Utils/ConstExpr.cpp index 9bdea531f2418..402c2aadf27c0 100644 --- a/lib/SILOptimizer/Utils/ConstExpr.cpp +++ b/lib/SILOptimizer/Utils/ConstExpr.cpp @@ -784,6 +784,13 @@ extractStaticStringValue(SymbolicValue staticString) { return staticStringProps[0].getStringValue(); } +static Optional +extractStringOrStaticStringValue(SymbolicValue stringValue) { + if (stringValue.getKind() == SymbolicValue::String) + return stringValue.getStringValue(); + return extractStaticStringValue(stringValue); +} + /// If the specified type is a Swift.Array of some element type, then return the /// element type. Otherwise, return a null Type. static Type getArrayElementType(Type ty) { @@ -829,8 +836,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, for (unsigned i = 0; i < apply->getNumArguments(); i++) { SILValue argument = apply->getArgument(i); SymbolicValue argValue = getConstantValue(argument); - Optional stringOpt = extractStaticStringValue(argValue); - + Optional stringOpt = + extractStringOrStaticStringValue(argValue); // The first argument is a prefix that specifies the kind of failure // this is. if (i == 0) { @@ -842,7 +849,6 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, } continue; } - if (stringOpt) { message += ": "; message += stringOpt.getValue(); diff --git a/test/SILOptimizer/constant_evaluable_subset_test.swift b/test/SILOptimizer/constant_evaluable_subset_test.swift index 4c77079039fbc..49174d0db7c16 100644 --- a/test/SILOptimizer/constant_evaluable_subset_test.swift +++ b/test/SILOptimizer/constant_evaluable_subset_test.swift @@ -925,3 +925,35 @@ func interpretBinaryIntegerDescription() -> String { str += testBinaryIntegerDescription(UInt(20)) return str } + +// CHECK-LABEL: @testPreconditionFailure +// CHECK: error: not constant evaluable +@_semantics("constant_evaluable") +func testPreconditionFailure(_ x: Int) -> Int { + precondition(x > 0, "argument must be positive") + return x + 1 + // CHECK: note: operation traps + // Note that the message displayed depends on the assert configuration, + // therefore it is not checked here. For debug stdlib, the full message + // must be displayed. +} + +@_semantics("test_driver") +func interpretPreconditionFailure() -> Int { + return testPreconditionFailure(-10) +} + +// CHECK-LABEL: @testFatalError +// CHECK: error: not constant evaluable +@_semantics("constant_evaluable") +func testFatalError() -> Int { + fatalError("invoked an uncallable function") + return 0 + // CHECK: note: Fatal error: invoked an uncallable function + // CHECK: note: operation traps +} + +@_semantics("test_driver") +func interpretFatalError() -> Int { + return testFatalError() +} From 7392c8d01daa5a924eb22e9c68f2d9b4f5232000 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 29 Jan 2020 02:16:06 +0000 Subject: [PATCH 18/19] [WebAssembly] Add no-op MutexWASI.h implementation (#29459) * [WebAssembly] Add no-op MutexWASI.h implementation * Update wording of header comment in MutexWASI.h --- include/swift/Runtime/Mutex.h | 2 + include/swift/Runtime/MutexWASI.h | 69 +++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 include/swift/Runtime/MutexWASI.h diff --git a/include/swift/Runtime/Mutex.h b/include/swift/Runtime/Mutex.h index 1b320e9d22a6e..a24c555ccca03 100644 --- a/include/swift/Runtime/Mutex.h +++ b/include/swift/Runtime/Mutex.h @@ -24,6 +24,8 @@ #include "swift/Runtime/MutexPThread.h" #elif defined(_WIN32) #include "swift/Runtime/MutexWin32.h" +#elif defined(__wasi__) +#include "swift/Runtime/MutexWASI.h" #else #error "Implement equivalent of MutexPThread.h/cpp for your platform." #endif diff --git a/include/swift/Runtime/MutexWASI.h b/include/swift/Runtime/MutexWASI.h new file mode 100644 index 0000000000000..153a5f87b11dd --- /dev/null +++ b/include/swift/Runtime/MutexWASI.h @@ -0,0 +1,69 @@ +//===--- MutexWASI.h - -----------------------------------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// No-op implementation of locks for the WebAssembly System Interface. The +// implementation does not need to perform locking, because as of January 2020 +// WebAssembly does not support threads. +// See the current status at https://github.com/WebAssembly/proposals and +// https://github.com/webassembly/threads +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_RUNTIME_MUTEX_WASI_H +#define SWIFT_RUNTIME_MUTEX_WASI_H + +namespace swift { + +typedef void* ConditionHandle; +typedef void* MutexHandle; +typedef void* ReadWriteLockHandle; + +#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1 +#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1 +#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1 + +struct ConditionPlatformHelper { + static constexpr ConditionHandle staticInit() { + return nullptr; + }; + static void init(ConditionHandle &condition) {} + static void destroy(ConditionHandle &condition) {} + static void notifyOne(ConditionHandle &condition) {} + static void notifyAll(ConditionHandle &condition) {} + static void wait(ConditionHandle &condition, MutexHandle &mutex); +}; + +struct MutexPlatformHelper { + static constexpr MutexHandle staticInit() { return nullptr; } + static void init(MutexHandle &mutex, bool checked = false) {} + static void destroy(MutexHandle &mutex) {} + static void lock(MutexHandle &mutex) {} + static void unlock(MutexHandle &mutex) {} + static bool try_lock(MutexHandle &mutex) { return true; } + static void unsafeLock(MutexHandle &mutex) {} + static void unsafeUnlock(MutexHandle &mutex) {} +}; + +struct ReadWriteLockPlatformHelper { + static constexpr ReadWriteLockHandle staticInit() { return nullptr; } + static void init(ReadWriteLockHandle &rwlock) {} + static void destroy(ReadWriteLockHandle &rwlock) {} + static void readLock(ReadWriteLockHandle &rwlock) {} + static bool try_readLock(ReadWriteLockHandle &rwlock) { return true; } + static void readUnlock(ReadWriteLockHandle &rwlock) {} + static void writeLock(ReadWriteLockHandle &rwlock) {} + static bool try_writeLock(ReadWriteLockHandle &rwlock) { return true; } + static void writeUnlock(ReadWriteLockHandle &rwlock) {} +}; +} + +#endif From 44a64755666ed1272e0b0e949ac676ac92667bcd Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 29 Jan 2020 02:29:52 +0000 Subject: [PATCH 19/19] [WebAssembly] enable shims and stubs for WASI (#29505) * [WebAssembly] enable shims and stubs for WASI * Implement _swift_stdlib_getUnsafeArgvArgc for WASI * Make include unconditional, add JIRA links --- stdlib/public/SwiftShims/LibcShims.h | 4 +++- stdlib/public/stubs/CommandLine.cpp | 36 ++++++++++++++++++++++++++++ stdlib/public/stubs/LibcShims.cpp | 2 +- stdlib/public/stubs/Random.cpp | 4 +++- stdlib/public/stubs/Stubs.cpp | 8 +++++-- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/stdlib/public/SwiftShims/LibcShims.h b/stdlib/public/SwiftShims/LibcShims.h index 5725f294885f9..1c60a7561c5b8 100644 --- a/stdlib/public/SwiftShims/LibcShims.h +++ b/stdlib/public/SwiftShims/LibcShims.h @@ -43,6 +43,8 @@ typedef __swift_uint32_t __swift_mode_t; typedef __swift_uint16_t __swift_mode_t; #elif defined(_WIN32) typedef __swift_int32_t __swift_mode_t; +#elif defined(__wasi__) +typedef __swift_uint32_t __swift_mode_t; #else // just guessing typedef __swift_uint16_t __swift_mode_t; #endif @@ -105,7 +107,7 @@ static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) { return malloc_size(ptr); } #elif defined(__linux__) || defined(__CYGWIN__) || defined(__ANDROID__) \ - || defined(__HAIKU__) || defined(__FreeBSD__) + || defined(__HAIKU__) || defined(__FreeBSD__) || defined(__wasi__) static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) { #if defined(__ANDROID__) #if !defined(__ANDROID_API__) || __ANDROID_API__ >= 17 diff --git a/stdlib/public/stubs/CommandLine.cpp b/stdlib/public/stubs/CommandLine.cpp index 0b4506391beeb..cf371e5ababe4 100644 --- a/stdlib/public/stubs/CommandLine.cpp +++ b/stdlib/public/stubs/CommandLine.cpp @@ -206,6 +206,42 @@ char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) { return outBuf; } +#elif defined(__wasi__) +#include +#include +#include + +SWIFT_RUNTIME_STDLIB_API +char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) { + assert(outArgLen != nullptr); + + if (_swift_stdlib_ProcessOverrideUnsafeArgv) { + *outArgLen = _swift_stdlib_ProcessOverrideUnsafeArgc; + return _swift_stdlib_ProcessOverrideUnsafeArgv; + } + + __wasi_errno_t err; + + size_t argv_buf_size; + size_t argc; + err = __wasi_args_sizes_get(&argc, &argv_buf_size); + if (err != __WASI_ERRNO_SUCCESS) return nullptr; + + size_t num_ptrs = argc + 1; + char *argv_buf = (char *)malloc(argv_buf_size); + char **argv = (char **)calloc(num_ptrs, sizeof(char *)); + + err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf); + if (err != __WASI_ERRNO_SUCCESS) { + free(argv_buf); + free(argv); + return nullptr; + } + + *outArgLen = static_cast(argc); + + return argv; +} #else // Add your favorite OS's command line arg grabber here. SWIFT_RUNTIME_STDLIB_API char ** _swift_stdlib_getUnsafeArgvArgc(int *outArgLen) { diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp index 083deaa4747a1..b54ede8c61f66 100644 --- a/stdlib/public/stubs/LibcShims.cpp +++ b/stdlib/public/stubs/LibcShims.cpp @@ -23,7 +23,7 @@ #include #include -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__wasi__) #include #endif diff --git a/stdlib/public/stubs/Random.cpp b/stdlib/public/stubs/Random.cpp index bb69f7e7793d1..bc130b145015b 100644 --- a/stdlib/public/stubs/Random.cpp +++ b/stdlib/public/stubs/Random.cpp @@ -42,6 +42,8 @@ #include "swift/Runtime/Mutex.h" #include "../SwiftShims/Random.h" +#include // required for std::min + #if defined(__APPLE__) SWIFT_RUNTIME_STDLIB_API @@ -88,7 +90,7 @@ void swift::swift_stdlib_random(void *buf, __swift_size_t nbytes) { if (getrandom_available) { actual_nbytes = WHILE_EINTR(syscall(__NR_getrandom, buf, nbytes, 0)); } -#elif __has_include() && (defined(__CYGWIN__) || defined(__Fuchsia__)) +#elif __has_include() && (defined(__CYGWIN__) || defined(__Fuchsia__) || defined(__wasi__)) __swift_size_t getentropy_nbytes = std::min(nbytes, __swift_size_t{256}); if (0 == getentropy(buf, getentropy_nbytes)) { diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp index 55bada6a1db92..d5548c388df57 100644 --- a/stdlib/public/stubs/Stubs.cpp +++ b/stdlib/public/stubs/Stubs.cpp @@ -26,7 +26,7 @@ #define NOMINMAX #include #else -#if !defined(__HAIKU__) +#if !defined(__HAIKU__) && !defined(__wasi__) #include #else #include @@ -67,7 +67,7 @@ static float swift_strtof_l(const char *nptr, char **endptr, locale_t loc) { #define strtod_l swift_strtod_l #define strtof_l swift_strtof_l #endif -#elif defined(__linux__) +#elif defined(__linux__) || defined(__wasi__) #include #else #include @@ -503,6 +503,8 @@ const char *swift::_swift_stdlib_strtof_clocale( void swift::_swift_stdlib_flockfile_stdout() { #if defined(_WIN32) _lock_file(stdout); +#elif defined(__wasi__) + // WebAssembly/WASI doesn't support file locking yet https://bugs.swift.org/browse/SR-12097 #else flockfile(stdout); #endif @@ -511,6 +513,8 @@ void swift::_swift_stdlib_flockfile_stdout() { void swift::_swift_stdlib_funlockfile_stdout() { #if defined(_WIN32) _unlock_file(stdout); +#elif defined(__wasi__) + // WebAssembly/WASI doesn't support file locking yet https://bugs.swift.org/browse/SR-12097 #else funlockfile(stdout); #endif