Set the value of .Self in a where to that of the outer .Self. (#2344)

Prior to this change, declarations like `let N:! X(.Self) where .(X(.Self).Y) == 5;` have the surprising behavior of the two `.Self` expressions resolving to two different symbolic values. Fix this by forcing the inner one to have the same symbolic value as the outer one, albeit with a different type.
This commit is contained in:
Richard Smith
2022-10-25 11:59:42 -07:00
committed by GitHub
parent c68cced1fb
commit bc7bf325d6
8 changed files with 69 additions and 44 deletions
+12
View File
@@ -914,6 +914,17 @@ class WhereExpression : public RewritableMixin<Expression> {
auto self_binding() const -> const GenericBinding& { return *self_binding_; }
auto self_binding() -> GenericBinding& { return *self_binding_; }
auto enclosing_dot_self() const
-> std::optional<Nonnull<const GenericBinding*>> {
return enclosing_dot_self_;
}
// Sets the enclosing value of `.Self`. Can only be called during name
// resolution.
void set_enclosing_dot_self(Nonnull<const GenericBinding*> dot_self) {
CARBON_CHECK(!enclosing_dot_self_ || enclosing_dot_self_ == dot_self);
enclosing_dot_self_ = dot_self;
}
auto clauses() const -> llvm::ArrayRef<Nonnull<const WhereClause*>> {
return clauses_;
}
@@ -922,6 +933,7 @@ class WhereExpression : public RewritableMixin<Expression> {
private:
Nonnull<GenericBinding*> self_binding_;
std::vector<Nonnull<WhereClause*>> clauses_;
std::optional<Nonnull<const GenericBinding*>> enclosing_dot_self_;
};
// An expression whose semantics have not been implemented. This can be used