Skip to content

Commit 41a1b9c

Browse files
authored
Merge pull request #3500 from swiftwasm/main
[pull] swiftwasm from main
2 parents cd19d16 + 510afdf commit 41a1b9c

30 files changed

+661
-66
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ class ClangModuleLoader : public ModuleLoader {
238238
SubstitutionMap subst) = 0;
239239

240240
virtual bool isCXXMethodMutating(const clang::CXXMethodDecl *method) = 0;
241+
242+
virtual Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
243+
DeclContext *dc) = 0;
241244
};
242245

243246
/// Describes a C++ template instantiation error.

include/swift/ClangImporter/ClangImporter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ class ClangImporter final : public ClangModuleLoader {
458458
DeclName importName(const clang::NamedDecl *D,
459459
clang::DeclarationName givenName);
460460

461+
Type importFunctionReturnType(const clang::FunctionDecl *clangDecl,
462+
DeclContext *dc) override;
463+
461464
Optional<std::string>
462465
getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
463466
StringRef SwiftPCHHash);

include/swift/Option/Options.td

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,13 @@ def experimental_cxx_stdlib :
595595

596596
def experimental_emit_module_separately:
597597
Flag<["-"], "experimental-emit-module-separately">,
598-
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
599-
HelpText<"Schedule a swift module emission job instead of a merge-modules job (new Driver only)">;
598+
Flags<[NoInteractiveOption, HelpHidden]>,
599+
HelpText<"Emit module files as a distinct job (new Driver only)">;
600+
601+
def no_emit_module_separately:
602+
Flag<["-"], "no-emit-module-separately">,
603+
Flags<[NoInteractiveOption, HelpHidden]>,
604+
HelpText<"Force using merge-module as the incremental build mode (new Driver only)">;
600605

601606
def requirement_machine_EQ : Joined<["-"], "requirement-machine=">,
602607
Flags<[FrontendOption, ModuleInterfaceOption]>,

include/swift/SIL/MemoryLocations.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ void dumpBits(const SmallBitVector &bits);
4343
///
4444
/// Memory locations are limited to addresses which are guaranteed to
4545
/// be not aliased, like @in/inout parameters and alloc_stack.
46-
/// Currently only a certain set of address instructions are supported:
47-
/// Specifically those instructions which are going to be included when SIL
48-
/// supports opaque values.
46+
/// Currently only a certain set of address instructions are supported, for
47+
/// details see `MemoryLocations::analyzeLocationUsesRecursively` and
48+
/// `MemoryLocations::analyzeAddrProjection`.
4949
class MemoryLocations {
5050
public:
5151

@@ -288,7 +288,7 @@ class MemoryLocations {
288288
/// not covered by sub-fields.
289289
const Bits &getNonTrivialLocations();
290290

291-
/// Debug dump the MemoryLifetime internals.
291+
/// Debug dump the MemoryLocations internals.
292292
void dump() const;
293293

294294
private:

include/swift/SIL/SILType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ class SILType {
294294
/// even though they are technically trivial.
295295
bool isTrivial(const SILFunction &F) const;
296296

297+
/// True if the type is an empty tuple or an empty struct or a tuple or
298+
/// struct containing only empty types.
299+
bool isEmpty(const SILFunction &F) const;
300+
297301
/// True if the type, or the referenced type of an address type, is known to
298302
/// be a scalar reference-counted type such as a class, box, or thick function
299303
/// type. Returns false for non-trivial aggregates.

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7827,7 +7827,7 @@ FuncDecl *FuncDecl::createImported(ASTContext &Context, SourceLoc FuncLoc,
78277827
Type FnRetType,
78287828
GenericParamList *GenericParams,
78297829
DeclContext *Parent, ClangNode ClangN) {
7830-
assert(ClangN && FnRetType);
7830+
assert(ClangN);
78317831
auto *const FD = FuncDecl::createImpl(
78327832
Context, SourceLoc(), StaticSpellingKind::None, FuncLoc, Name, NameLoc,
78337833
Async, SourceLoc(), Throws, SourceLoc(), GenericParams, Parent, ClangN);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,6 +4277,19 @@ importName(const clang::NamedDecl *D,
42774277
getDeclName();
42784278
}
42794279

4280+
Type ClangImporter::importFunctionReturnType(
4281+
const clang::FunctionDecl *clangDecl, DeclContext *dc) {
4282+
bool isInSystemModule =
4283+
cast<ClangModuleUnit>(dc->getModuleScopeContext())->isSystemModule();
4284+
bool allowNSUIntegerAsInt =
4285+
Impl.shouldAllowNSUIntegerAsInt(isInSystemModule, clangDecl);
4286+
if (auto imported =
4287+
Impl.importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt)
4288+
.getType())
4289+
return imported;
4290+
return dc->getASTContext().getNeverType();
4291+
}
4292+
42804293
bool ClangImporter::isInOverlayModuleForImportedModule(
42814294
const DeclContext *overlayDC,
42824295
const DeclContext *importedDC) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4167,8 +4167,9 @@ namespace {
41674167
if (!bodyParams)
41684168
return nullptr;
41694169

4170-
importedType =
4171-
Impl.importFunctionReturnType(dc, decl, allowNSUIntegerAsInt);
4170+
if (decl->getReturnType()->isScalarType())
4171+
importedType =
4172+
Impl.importFunctionReturnType(dc, decl, allowNSUIntegerAsInt);
41724173
} else {
41734174
// Import the function type. If we have parameters, make sure their
41744175
// names get into the resulting function type.
@@ -4204,7 +4205,7 @@ namespace {
42044205
name = DeclName(Impl.SwiftContext, name.getBaseName(), bodyParams);
42054206
}
42064207

4207-
if (!importedType)
4208+
if (!bodyParams)
42084209
return nullptr;
42094210

42104211
auto loc = Impl.importSourceLoc(decl->getLocation());

lib/ClangImporter/ImportType.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1827,12 +1827,17 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
18271827
bool allowNSUIntegerAsInt =
18281828
shouldAllowNSUIntegerAsInt(isFromSystemModule, clangDecl);
18291829

1830+
// Only eagerly import the return type if it's not too expensive (the current
1831+
// huristic for that is if it's not a record type).
18301832
ImportedType importedType;
18311833
if (auto templateType =
18321834
dyn_cast<clang::TemplateTypeParmType>(clangDecl->getReturnType())) {
18331835
importedType = {findGenericTypeInGenericDecls(templateType, genericParams),
18341836
false};
1835-
} else {
1837+
} else if (!isa<clang::RecordType>(clangDecl->getReturnType()) ||
1838+
// TODO: we currently don't lazily load operator return types, but
1839+
// this should be trivial to add.
1840+
clangDecl->isOverloadedOperator()) {
18361841
importedType =
18371842
importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt);
18381843
if (!importedType)

lib/SIL/IR/SILType.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,30 @@ bool SILType::isTrivial(const SILFunction &F) const {
104104
return F.getTypeLowering(contextType).isTrivial();
105105
}
106106

107+
bool SILType::isEmpty(const SILFunction &F) const {
108+
if (auto tupleTy = getAs<TupleType>()) {
109+
// A tuple is empty if it either has no elements or if all elements are
110+
// empty.
111+
for (unsigned idx = 0, num = tupleTy->getNumElements(); idx < num; ++idx) {
112+
if (!getTupleElementType(idx).isEmpty(F))
113+
return false;
114+
}
115+
return true;
116+
}
117+
if (StructDecl *structDecl = getStructOrBoundGenericStruct()) {
118+
// Also, a struct is empty if it either has no fields or if all fields are
119+
// empty.
120+
SILModule &module = F.getModule();
121+
TypeExpansionContext typeEx = F.getTypeExpansionContext();
122+
for (VarDecl *field : structDecl->getStoredProperties()) {
123+
if (!getFieldType(field, module, typeEx).isEmpty(F))
124+
return false;
125+
}
126+
return true;
127+
}
128+
return false;
129+
}
130+
107131
bool SILType::isReferenceCounted(SILModule &M) const {
108132
return M.Types.getTypeLowering(*this,
109133
TypeExpansionContext::minimal())

lib/SIL/Utils/MemoryLocations.cpp

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -67,34 +67,6 @@ static bool allUsesInSameBlock(AllocStackInst *ASI) {
6767
return numDeallocStacks == 1;
6868
}
6969

70-
/// We don't handle empty tuples and empty structs.
71-
///
72-
/// Locations with empty types don't even need a store to count as
73-
/// "initialized". We don't handle such cases.
74-
static bool isEmptyType(SILType ty, SILFunction *function) {
75-
if (auto tupleTy = ty.getAs<TupleType>()) {
76-
// A tuple is empty if it either has no elements or if all elements are
77-
// empty.
78-
for (unsigned idx = 0, num = tupleTy->getNumElements(); idx < num; ++idx) {
79-
if (!isEmptyType(ty.getTupleElementType(idx), function))
80-
return false;
81-
}
82-
return true;
83-
}
84-
if (StructDecl *structDecl = ty.getStructOrBoundGenericStruct()) {
85-
// Also, a struct is empty if it either has no fields or if all fields are
86-
// empty.
87-
SILModule &module = function->getModule();
88-
TypeExpansionContext typeEx = function->getTypeExpansionContext();
89-
for (VarDecl *field : structDecl->getStoredProperties()) {
90-
if (!isEmptyType(ty.getFieldType(field, module, typeEx), function))
91-
return false;
92-
}
93-
return true;
94-
}
95-
return false;
96-
}
97-
9870
} // anonymous namespace
9971
} // namespace swift
10072

@@ -117,7 +89,7 @@ MemoryLocations::Location::Location(SILValue val, unsigned index, int parentIdx)
11789

11890
void MemoryLocations::Location::updateFieldCounters(SILType ty, int increment) {
11991
SILFunction *function = representativeValue->getFunction();
120-
if (!isEmptyType(ty, function)) {
92+
if (!ty.isEmpty(*function)) {
12193
numFieldsNotCoveredBySubfields += increment;
12294
if (!ty.isTrivial(*function))
12395
numNonTrivialFieldsNotCovered += increment;
@@ -215,7 +187,11 @@ void MemoryLocations::analyzeLocation(SILValue loc) {
215187
if (!handleTrivialLocations && loc->getType().isTrivial(*function))
216188
return;
217189

218-
if (isEmptyType(loc->getType(), function))
190+
/// We don't handle empty tuples and empty structs.
191+
///
192+
/// Locations with empty types don't even need a store to count as
193+
/// "initialized". We don't handle such cases.
194+
if (loc->getType().isEmpty(*function))
219195
return;
220196

221197
unsigned currentLocIdx = locations.size();
@@ -400,7 +376,7 @@ bool MemoryLocations::analyzeAddrProjection(
400376
SingleValueInstruction *projection, unsigned parentLocIdx,unsigned fieldNr,
401377
SmallVectorImpl<SILValue> &collectedVals, SubLocationMap &subLocationMap) {
402378

403-
if (isEmptyType(projection->getType(), projection->getFunction()))
379+
if (projection->getType().isEmpty(*projection->getFunction()))
404380
return false;
405381

406382
auto key = std::make_pair(parentLocIdx, fieldNr);

lib/SIL/Verifier/MemoryLifetimeVerifier.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,8 @@ namespace {
3131
/// A utility for verifying memory lifetime.
3232
///
3333
/// The MemoryLifetime utility checks the lifetime of memory locations.
34-
/// This is limited to memory locations which are guaranteed to be not aliased,
35-
/// like @in or @inout parameters. Also, alloc_stack locations are handled.
36-
///
37-
/// In addition to verification, the MemoryLifetime class can be used as utility
38-
/// (e.g. base class) for optimizations, which need to compute memory lifetime.
34+
/// This is limited to memory locations which can be handled by
35+
/// `MemoryLocations`.
3936
class MemoryLifetimeVerifier {
4037

4138
using Bits = MemoryLocations::Bits;
@@ -178,6 +175,16 @@ static bool isTrivialEnumElem(EnumElementDecl *elem, SILType enumType,
178175
enumType.getEnumElementType(elem, function).isTrivial(*function);
179176
}
180177

178+
static bool injectsNoPayloadCase(InjectEnumAddrInst *IEAI) {
179+
if (!IEAI->getElement()->hasAssociatedValues())
180+
return true;
181+
SILType enumType = IEAI->getOperand()->getType();
182+
SILFunction *function = IEAI->getFunction();
183+
SILType elemType = enumType.getEnumElementType(IEAI->getElement(), function);
184+
// Handle empty types (e.g. the empty tuple) as no-payload.
185+
return elemType.isEmpty(*function);
186+
}
187+
181188
static bool isOrHasEnum(SILType type) {
182189
return type.getASTType().findIf([](Type ty) {
183190
return ty->getEnumOrBoundGenericEnum() != nullptr;
@@ -349,7 +356,7 @@ void MemoryLifetimeVerifier::initDataflowInBlock(SILBasicBlock *block,
349356
case SILInstructionKind::InjectEnumAddrInst: {
350357
auto *IEAI = cast<InjectEnumAddrInst>(&I);
351358
int enumIdx = locations.getLocationIdx(IEAI->getOperand());
352-
if (enumIdx >= 0 && !IEAI->getElement()->hasAssociatedValues()) {
359+
if (enumIdx >= 0 && injectsNoPayloadCase(IEAI)) {
353360
// This is a bit tricky: an injected no-payload case means that the
354361
// "full" enum is initialized. So, for the purpose of dataflow, we
355362
// treat it like a full initialization of the payload data.
@@ -588,7 +595,7 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
588595
case SILInstructionKind::InjectEnumAddrInst: {
589596
auto *IEAI = cast<InjectEnumAddrInst>(&I);
590597
int enumIdx = locations.getLocationIdx(IEAI->getOperand());
591-
if (enumIdx >= 0 && !IEAI->getElement()->hasAssociatedValues()) {
598+
if (enumIdx >= 0 && injectsNoPayloadCase(IEAI)) {
592599
// Again, an injected no-payload case is treated like a "full"
593600
// initialization. See initDataflowInBlock().
594601
requireBitsClear(bits & nonTrivialLocations, IEAI->getOperand(), &I);

lib/Sema/ConstraintSystem.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3990,8 +3990,14 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
39903990

39913991
llvm::SmallSetVector<FixInContext, 4> fixes;
39923992
for (auto &solution : solutions) {
3993-
for (auto *fix : solution.Fixes)
3993+
for (auto *fix : solution.Fixes) {
3994+
// Ignore warnings in favor of actual error fixes,
3995+
// because they are not the source of ambiguity/failures.
3996+
if (fix->isWarning())
3997+
continue;
3998+
39943999
fixes.insert({&solution, fix});
4000+
}
39954001
}
39964002

39974003
llvm::MapVector<ConstraintLocator *, SmallVector<FixInContext, 4>>

lib/Sema/TypeCheckDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,6 +1989,13 @@ ResultTypeRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
19891989
resultTyRepr = cast<SubscriptDecl>(decl)->getElementTypeRepr();
19901990
}
19911991

1992+
if (!resultTyRepr && decl->getClangDecl() &&
1993+
isa<clang::FunctionDecl>(decl->getClangDecl())) {
1994+
auto clangFn = cast<clang::FunctionDecl>(decl->getClangDecl());
1995+
return ctx.getClangModuleLoader()->importFunctionReturnType(
1996+
clangFn, decl->getDeclContext());
1997+
}
1998+
19921999
// Nothing to do if there's no result type.
19932000
if (resultTyRepr == nullptr)
19942001
return TupleType::getEmpty(ctx);

stdlib/public/core/Codable.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,8 +3308,8 @@ public enum DecodingError: Error {
33083308
/// for debugging.
33093309
case valueNotFound(Any.Type, Context)
33103310

3311-
/// An indication that a keyed decoding container was asked for an entry for
3312-
/// the given key, but did not contain one.
3311+
/// An indication that a keyed decoding container was asked for an entry for
3312+
/// the given key, but did not contain one.
33133313
///
33143314
/// As associated values, this case contains the attempted key and context
33153315
/// for debugging.

test/Constraints/closures.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,3 +1163,13 @@ func rdar78917861() {
11631163
}()
11641164
}
11651165
}
1166+
1167+
// rdar://81228501 - type-checker crash due to applied invalid solution
1168+
func test(arr: [[Int]]) {
1169+
struct A {
1170+
init(arg: [Int]) {}
1171+
}
1172+
1173+
arr.map { ($0 as? [Int]).map { A($0) } } // expected-error {{missing argument label 'arg:' in call}} {{36-36=arg: }}
1174+
// expected-warning@-1 {{conditional cast from '[Int]' to '[Int]' always succeeds}}
1175+
}

test/Driver/Dependencies/one-way-merge-module-fine.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: cp -r %S/Inputs/one-way-fine/* %t
55
// RUN: touch -t 201401240005 %t/*
66

7-
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s
7+
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-FIRST %s
88

99
// CHECK-FIRST-NOT: warning
1010
// CHECK-FIRST: Handled main.swift
@@ -14,7 +14,7 @@
1414
// swift-driver checks existence of all outputs
1515
// RUN: touch -t 201401240006 %t/{main,other,master}.swift{module,doc,sourceinfo}
1616

17-
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s
17+
// RUN: cd %t && %swiftc_driver -driver-use-frontend-path "%{python.unquoted};%S/Inputs/update-dependencies.py;%swift-dependency-tool" -output-file-map %t/output.json -incremental -driver-always-rebuild-dependents ./main.swift ./other.swift -emit-module-path %t/master.swiftmodule -module-name main -j1 -v -no-emit-module-separately 2>&1 | %FileCheck -check-prefix=CHECK-SECOND %s
1818

1919
// CHECK-SECOND-NOT: warning
2020
// CHECK-SECOND-NOT: Handled

test/SIL/memory_lifetime.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,3 +650,35 @@ bb0(%0 : $Int, %1 : @guaranteed $@callee_guaranteed (@in_guaranteed (Int, ((), (
650650
dealloc_stack %2 : $*(Int, ((), ()))
651651
return %5 : $Int
652652
}
653+
654+
enum Result<T1, T2>{
655+
case success(T1)
656+
case failure(T2)
657+
}
658+
659+
sil @try_get_error : $@convention(thin) () -> @error Error
660+
661+
sil [ossa] @test_init_enum_empty_case : $@convention(thin) () -> @error Error {
662+
bb0:
663+
%0 = alloc_stack $Result<(), Error>
664+
%1 = function_ref @try_get_error : $@convention(thin) () -> @error Error
665+
try_apply %1() : $@convention(thin) () -> @error Error, normal bb1, error bb2
666+
667+
bb1(%3 : $()):
668+
inject_enum_addr %0 : $*Result<(), Error>, #Result.success!enumelt
669+
br bb3
670+
671+
bb2(%6 : @owned $Error):
672+
%7 = init_enum_data_addr %0 : $*Result<(), Error>, #Result.failure!enumelt
673+
store %6 to [init] %7 : $*Error
674+
inject_enum_addr %0 : $*Result<(), Error>, #Result.failure!enumelt
675+
br bb3
676+
677+
bb3:
678+
%11 = load [take] %0 : $*Result<(), Error>
679+
destroy_value %11 : $Result<(), Error>
680+
dealloc_stack %0 : $*Result<(), Error>
681+
%14 = tuple ()
682+
return %14 : $()
683+
}
684+

0 commit comments

Comments
 (0)