@@ -1918,7 +1918,7 @@ class ExtensionRange {
19181918// / the initializer can be null if there is none.
19191919class PatternBindingEntry {
19201920 enum class Flags {
1921- Checked = 1 << 0 ,
1921+ // 1 << 0 is available
19221922 Removed = 1 << 1 ,
19231923 // / Whether the contents of this initializer were subsumed by
19241924 // / some other initialization, e.g., a lazy property's initializer
@@ -1927,6 +1927,15 @@ class PatternBindingEntry {
19271927 };
19281928 llvm::PointerIntPair<Pattern *, 3 , OptionSet<Flags>> PatternAndFlags;
19291929
1930+ enum class InitializerStatus {
1931+ // / The init expression has not been typechecked.
1932+ NotChecked = 0 ,
1933+ // / The init expression has been typechecked but not contextualized.
1934+ Checked,
1935+ // / The init expression has been typechecked and contextualized.
1936+ CheckedAndContextualized,
1937+ };
1938+
19301939 struct InitializerAndEqualLoc {
19311940 // When the initializer is removed we don't actually clear the pointers
19321941 // because we might need to get initializer's source range. Since the
@@ -1936,7 +1945,7 @@ class PatternBindingEntry {
19361945 Expr *originalInit;
19371946 // / Might be transformed, e.g. for a property wrapper. In the absence of
19381947 // / transformation or synthesis, holds the expr as parsed.
1939- Expr *initAfterSynthesis;
1948+ llvm::PointerIntPair< Expr *, 2 , InitializerStatus> initAfterSynthesis;
19401949 // / The location of the equal '=' token.
19411950 SourceLoc EqualLoc;
19421951 };
@@ -1974,6 +1983,7 @@ class PatternBindingEntry {
19741983 // typeCheckPatternBinding are requestified, merge this bit with
19751984 // Flags::Checked.
19761985 friend class PatternBindingEntryRequest ;
1986+ friend class PatternBindingCheckedAndContextualizedInitRequest ;
19771987
19781988 bool isFullyValidated () const {
19791989 return InitContextAndFlags.getInt ().contains (
@@ -1996,7 +2006,8 @@ class PatternBindingEntry {
19962006 // / \p E is the initializer as parsed.
19972007 PatternBindingEntry (Pattern *P, SourceLoc EqualLoc, Expr *E,
19982008 DeclContext *InitContext)
1999- : PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
2009+ : PatternAndFlags(P, {}),
2010+ InitExpr ({E, {E, InitializerStatus::NotChecked}, EqualLoc}),
20002011 InitContextAndFlags ({InitContext, llvm::None}) {}
20012012
20022013private:
@@ -2013,7 +2024,7 @@ class PatternBindingEntry {
20132024 if (PatternAndFlags.getInt ().contains (Flags::Removed) ||
20142025 InitContextAndFlags.getInt ().contains (PatternFlags::IsText))
20152026 return nullptr ;
2016- return InitExpr.initAfterSynthesis ;
2027+ return InitExpr.initAfterSynthesis . getPointer () ;
20172028 }
20182029 // / Retrieve the initializer if it should be executed to initialize this
20192030 // / particular pattern binding.
@@ -2060,11 +2071,26 @@ class PatternBindingEntry {
20602071 // / Set the initializer after the = as it was written in the source.
20612072 void setOriginalInit (Expr *);
20622073
2074+ InitializerStatus initializerStatus () const {
2075+ if (InitContextAndFlags.getInt ().contains (PatternFlags::IsText))
2076+ return InitializerStatus::NotChecked;
2077+ return InitExpr.initAfterSynthesis .getInt ();
2078+ }
20632079 bool isInitializerChecked () const {
2064- return PatternAndFlags. getInt (). contains (Flags::Checked) ;
2080+ return initializerStatus () != InitializerStatus::NotChecked ;
20652081 }
20662082 void setInitializerChecked () {
2067- PatternAndFlags.setInt (PatternAndFlags.getInt () | Flags::Checked);
2083+ assert (!InitContextAndFlags.getInt ().contains (PatternFlags::IsText));
2084+ InitExpr.initAfterSynthesis .setInt (InitializerStatus::Checked);
2085+ }
2086+
2087+ bool isInitializerCheckedAndContextualized () const {
2088+ return initializerStatus () == InitializerStatus::CheckedAndContextualized;
2089+ }
2090+ void setInitializerCheckedAndContextualized () {
2091+ assert (!InitContextAndFlags.getInt ().contains (PatternFlags::IsText));
2092+ InitExpr.initAfterSynthesis .setInt (
2093+ InitializerStatus::CheckedAndContextualized);
20682094 }
20692095
20702096 bool isInitializerSubsumed () const {
@@ -2128,6 +2154,7 @@ class PatternBindingDecl final : public Decl,
21282154 friend TrailingObjects;
21292155 friend class Decl ;
21302156 friend class PatternBindingEntryRequest ;
2157+ friend class PatternBindingCheckedAndContextualizedInitRequest ;
21312158
21322159 SourceLoc StaticLoc; // /< Location of the 'static/class' keyword, if present.
21332160 SourceLoc VarLoc; // /< Location of the 'var' keyword.
@@ -2276,9 +2303,13 @@ class PatternBindingDecl final : public Decl,
22762303 getMutablePatternList ()[i].setOriginalInit (E);
22772304 }
22782305
2279- // / Returns a fully typechecked executable init expression for the pattern at
2280- // / the given index.
2281- Expr *getCheckedExecutableInit (unsigned i) const ;
2306+ // / Returns a fully typechecked init expression for the pattern at the given
2307+ // / index.
2308+ Expr *getCheckedAndContextualizedInit (unsigned i) const ;
2309+
2310+ // / Returns the result of `getCheckedAndContextualizedInit()` if the init is
2311+ // / not subsumed. Otherwise, returns `nullptr`.
2312+ Expr *getCheckedAndContextualizedExecutableInit (unsigned i) const ;
22822313
22832314 Pattern *getPattern (unsigned i) const {
22842315 return getPatternList ()[i].getPattern ();
0 commit comments