@@ -2283,6 +2283,22 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
22832283 }
22842284 }
22852285
2286+ bool checkBoundInOutVarDecl (PatternBindingDecl *pbd, unsigned patternIndex,
2287+ const Pattern *p, VarDecl *vd) {
2288+ // If our var decl doesn't have an initial value, error. We always want an
2289+ // inout var decl to have an lvalue initial value that it is binding to.
2290+ auto *expr = pbd->getInit (patternIndex);
2291+ assert (expr && " Code assumes that we checked for validity" );
2292+
2293+ // Next make sure that our initial value was an lvalue.
2294+ if (!isa<LoadExpr>(expr)) {
2295+ vd->diagnose (diag::referencebindings_binding_must_be_to_lvalue, " inout" );
2296+ return false ;
2297+ }
2298+
2299+ return true ;
2300+ }
2301+
22862302 void visitPatternBindingDecl (PatternBindingDecl *PBD) {
22872303 DeclContext *DC = PBD->getDeclContext ();
22882304
@@ -2308,6 +2324,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23082324 Pat->forEachVariable ([&](VarDecl *var) {
23092325 this ->visitBoundVariable (var);
23102326
2327+ auto markVarAndPBDInvalid = [PBD, var] {
2328+ PBD->setInvalid ();
2329+ var->setInvalid ();
2330+ };
2331+
23112332 if (PBD->isInitialized (i)) {
23122333 // Add the attribute that preserves the "has an initializer" value
23132334 // across module generation, as required for TBDGen.
@@ -2316,6 +2337,15 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23162337 var->getAttrs ().add (new (Ctx)
23172338 HasInitialValueAttr (/* IsImplicit=*/ true ));
23182339 }
2340+
2341+ // If we fail to check the bound inout introducer, mark the variable
2342+ // and pbd invalid().
2343+ if (var->getIntroducer () == VarDecl::Introducer::InOut) {
2344+ if (!checkBoundInOutVarDecl (PBD, i, Pat, var)) {
2345+ markVarAndPBDInvalid ();
2346+ }
2347+ }
2348+
23192349 return ;
23202350 }
23212351
@@ -2333,11 +2363,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23332363 if (var->isInvalid () || PBD->isInvalid ())
23342364 return ;
23352365
2336- auto markVarAndPBDInvalid = [PBD, var] {
2337- PBD->setInvalid ();
2338- var->setInvalid ();
2339- };
2340-
23412366 // Properties with an opaque return type need an initializer to
23422367 // determine their underlying type.
23432368 if (var->getOpaqueResultTypeDecl ()) {
@@ -2393,6 +2418,14 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23932418 markVarAndPBDInvalid ();
23942419 return ;
23952420 }
2421+
2422+ // Inout VarDecls need to have an initializer.
2423+ if (var->getIntroducer () == VarDecl::Introducer::InOut) {
2424+ var->diagnose (diag::referencebindings_binding_must_have_initial_value,
2425+ " inout" );
2426+ markVarAndPBDInvalid ();
2427+ return ;
2428+ }
23962429 });
23972430 }
23982431
0 commit comments