-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Sr 11159 space engine #26754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sr 11159 space engine #26754
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,8 +23,10 @@ | |
#include "swift/Basic/APIntMap.h" | ||
#include <llvm/ADT/APFloat.h> | ||
|
||
#include <numeric> | ||
#include <forward_list> | ||
#include <iterator> | ||
#include <numeric> | ||
#include <utility> | ||
|
||
using namespace swift; | ||
|
||
|
@@ -115,7 +117,7 @@ namespace { | |
|
||
// In type space, we reuse HEAD to help us print meaningful name, e.g., | ||
// tuple element name in fixits. | ||
Identifier Head; | ||
DeclName Head; | ||
std::forward_list<Space> Spaces; | ||
|
||
size_t computeSize(TypeChecker &TC, const DeclContext *DC, | ||
|
@@ -170,19 +172,18 @@ namespace { | |
llvm_unreachable("unhandled kind"); | ||
} | ||
|
||
explicit Space(Type T, Identifier NameForPrinting) | ||
: Kind(SpaceKind::Type), TypeAndVal(T), | ||
Head(NameForPrinting), Spaces({}){} | ||
explicit Space(Type T, DeclName NameForPrinting) | ||
: Kind(SpaceKind::Type), TypeAndVal(T), Head(NameForPrinting), | ||
Spaces({}) {} | ||
explicit Space(UnknownCase_t, bool allowedButNotRequired) | ||
: Kind(SpaceKind::UnknownCase), | ||
TypeAndVal(Type(), allowedButNotRequired), Head(Identifier()), | ||
Spaces({}) {} | ||
explicit Space(Type T, Identifier H, ArrayRef<Space> SP) | ||
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H), | ||
Spaces(SP.begin(), SP.end()) {} | ||
explicit Space(Type T, Identifier H, std::forward_list<Space> SP) | ||
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H), | ||
Spaces(SP) {} | ||
explicit Space(Type T, DeclName H, ArrayRef<Space> SP) | ||
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H), | ||
Spaces(SP.begin(), SP.end()) {} | ||
explicit Space(Type T, DeclName H, std::forward_list<Space> SP) | ||
: Kind(SpaceKind::Constructor), TypeAndVal(T), Head(H), Spaces(SP) {} | ||
explicit Space(ArrayRef<Space> SP) | ||
: Kind(SpaceKind::Disjunct), TypeAndVal(Type()), | ||
Head(Identifier()), Spaces(SP.begin(), SP.end()) {} | ||
|
@@ -194,23 +195,23 @@ namespace { | |
: Kind(SpaceKind::Empty), TypeAndVal(Type()), Head(Identifier()), | ||
Spaces({}) {} | ||
|
||
static Space forType(Type T, Identifier NameForPrinting) { | ||
static Space forType(Type T, DeclName NameForPrinting) { | ||
if (T->isStructurallyUninhabited()) | ||
return Space(); | ||
return Space(T, NameForPrinting); | ||
} | ||
static Space forUnknown(bool allowedButNotRequired) { | ||
return Space(UnknownCase, allowedButNotRequired); | ||
} | ||
static Space forConstructor(Type T, Identifier H, ArrayRef<Space> SP) { | ||
static Space forConstructor(Type T, DeclName H, ArrayRef<Space> SP) { | ||
if (llvm::any_of(SP, std::mem_fn(&Space::isEmpty))) { | ||
// A constructor with an unconstructible parameter can never actually | ||
// be used. | ||
return Space(); | ||
} | ||
return Space(T, H, SP); | ||
} | ||
static Space forConstructor(Type T, Identifier H, | ||
static Space forConstructor(Type T, DeclName H, | ||
std::forward_list<Space> SP) { | ||
// No need to filter SP here; this is only used to copy other | ||
// Constructor spaces. | ||
|
@@ -263,7 +264,7 @@ namespace { | |
return TypeAndVal.getPointer(); | ||
} | ||
|
||
Identifier getHead() const { | ||
DeclName getHead() const { | ||
assert(getKind() == SpaceKind::Constructor | ||
&& "Wrong kind of space tried to access head"); | ||
return Head; | ||
|
@@ -272,7 +273,7 @@ namespace { | |
Identifier getPrintingName() const { | ||
assert(getKind() == SpaceKind::Type | ||
&& "Wrong kind of space tried to access printing name"); | ||
return Head; | ||
return Head.getBaseIdentifier(); | ||
} | ||
|
||
const std::forward_list<Space> &getSpaces() const { | ||
|
@@ -333,7 +334,7 @@ namespace { | |
return this->isSubspace(or2Space, TC, DC); | ||
} | ||
|
||
return true; | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious if this affects any of our tests. I suspect it may close some SRs if this turns out to be salient. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ran the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, let's leave it in and run the broader test suite to see if this catches anything. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that the validation-test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's part of it, yes. |
||
} | ||
PAIRCASE (SpaceKind::Type, SpaceKind::Disjunct): { | ||
// (_ : Ty1) <= (S1 | ... | Sn) iff (S1 <= S) || ... || (Sn <= S) | ||
|
@@ -372,10 +373,11 @@ namespace { | |
PAIRCASE (SpaceKind::Constructor, SpaceKind::Constructor): { | ||
// Optimization: If the constructor heads don't match, subspace is | ||
// impossible. | ||
|
||
if (this->Head != other.Head) { | ||
return false; | ||
} | ||
|
||
// Special Case: Short-circuit comparisons with payload-less | ||
// constructors. | ||
if (other.getSpaces().empty()) { | ||
|
@@ -557,7 +559,8 @@ namespace { | |
PAIRCASE (SpaceKind::Constructor, SpaceKind::Constructor): { | ||
// Optimization: If the heads of the constructors don't match then | ||
// the two are disjoint and their difference is the first space. | ||
if (this->Head != other.Head) { | ||
if (this->Head.getBaseIdentifier() != | ||
other.Head.getBaseIdentifier()) { | ||
return *this; | ||
} | ||
|
||
|
@@ -696,19 +699,40 @@ namespace { | |
buffer << (getBoolValue() ? "true" : "false"); | ||
break; | ||
case SpaceKind::Constructor: { | ||
if (!Head.empty()) { | ||
if (!Head.getBaseIdentifier().empty()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're going to need to print the labels into the pattern as well. |
||
buffer << "."; | ||
buffer << Head.str(); | ||
buffer << Head.getBaseIdentifier().str(); | ||
} | ||
|
||
if (Spaces.empty()) { | ||
return; | ||
} | ||
|
||
auto args = Head.getArgumentNames().begin(); | ||
auto argEnd = Head.getArgumentNames().end(); | ||
|
||
// FIXME: Clean up code for performance | ||
buffer << "("; | ||
interleave(Spaces, [&](const Space ¶m) { | ||
param.show(buffer, forDisplay); | ||
}, [&buffer]() { buffer << ", "; }); | ||
llvm::SmallVector<std::pair<Identifier, Space>, 4> labelSpaces; | ||
for (auto param : Spaces) { | ||
if (args != argEnd) { | ||
labelSpaces.push_back( | ||
std::pair<Identifier, Space>(*args, param)); | ||
args++; | ||
} else | ||
labelSpaces.push_back( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you assert that you always have the same number of argument names in the base identifier as there are subspaces? If that much is true, then you can swap the interleave for the variant of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean a full assertion that stops compilation? Or just a check that runs a different path if that is the case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, just an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure just having an assertion allows all cases. For instance, if we check the number of argument names against spaces in the following example:
with the assertion, it fails where it should not. |
||
std::pair<Identifier, Space>(Identifier(), param)); | ||
} | ||
interleave( | ||
labelSpaces, | ||
[&](const std::pair<Identifier, Space> ¶m) { | ||
if (!param.first.empty()) { | ||
buffer << param.first; | ||
buffer << ": "; | ||
} | ||
param.second.show(buffer, forDisplay); | ||
}, | ||
[&buffer]() { buffer << ", "; }); | ||
buffer << ")"; | ||
} | ||
break; | ||
|
@@ -806,7 +830,7 @@ namespace { | |
Space::forType(TTy->getUnderlyingType(), Identifier())); | ||
} | ||
} | ||
return Space::forConstructor(tp, eed->getName(), | ||
return Space::forConstructor(tp, eed->getFullName(), | ||
constElemSpaces); | ||
}); | ||
|
||
|
@@ -967,7 +991,6 @@ namespace { | |
return; | ||
|
||
Space projection = projectPattern(TC, caseItem.getPattern()); | ||
|
||
bool isRedundant = !projection.isEmpty() && | ||
llvm::any_of(spaces, [&](const Space &handled) { | ||
return projection.isSubspace(handled, TC, DC); | ||
|
@@ -1420,8 +1443,8 @@ namespace { | |
auto subSpace = projectPattern(TC, OSP->getSubPattern()); | ||
// To match patterns like (_, _, ...)?, we must rewrite the underlying | ||
// tuple pattern to .some(_, _, ...) first. | ||
if (subSpace.getKind() == SpaceKind::Constructor | ||
&& subSpace.getHead().empty()) { | ||
if (subSpace.getKind() == SpaceKind::Constructor && | ||
subSpace.getHead().getBaseIdentifier().empty()) { | ||
return Space::forConstructor(item->getType(), name, | ||
std::move(subSpace.getSpaces())); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't your bug, but "Head" no longer makes sense under these changes. Perhaps
Name
orSpine
(definitely rooting more for the former than the latter).