@@ -3223,41 +3223,54 @@ static StorageRefResult findStorageReferenceExprForBorrow(Expr *e) {
32233223
32243224Expr *SILGenFunction::findStorageReferenceExprForMoveOnly (Expr *argExpr,
32253225 StorageReferenceOperationKind kind) {
3226+ ForceValueExpr *forceUnwrap = nullptr ;
3227+ // Check for a force unwrap. This might show up inside or outside of the
3228+ // load.
3229+ if (auto *fu = dyn_cast<ForceValueExpr>(argExpr)) {
3230+ forceUnwrap = fu;
3231+ argExpr = fu->getSubExpr ();
3232+ }
3233+
32263234 // If there's a load around the outer part of this arg expr, look past it.
32273235 bool sawLoad = false ;
32283236 if (auto *li = dyn_cast<LoadExpr>(argExpr)) {
32293237 argExpr = li->getSubExpr ();
32303238 sawLoad = true ;
32313239 }
32323240
3241+ // Check again for a force unwrap before the load.
3242+ if (auto *fu = dyn_cast<ForceValueExpr>(argExpr)) {
3243+ forceUnwrap = fu;
3244+ argExpr = fu->getSubExpr ();
3245+ }
3246+
32333247 // If we're consuming instead, then the load _must_ have been there.
32343248 if (kind == StorageReferenceOperationKind::Consume && !sawLoad)
32353249 return nullptr ;
32363250
3237- // If we did not see a load and our argExpr is a
3238- // declref_expr, return nullptr. We have an object not something that will be
3239- // in memory. This can happen with classes or with values captured by a
3240- // closure.
3241- //
3242- // NOTE: If we see a member_ref_expr from a decl_ref_expr, we still process it
3243- // since the declref_expr could be from a class.
3251+ // TODO: This section should be removed eventually. Decl refs should not be
3252+ // handled different from other storage. Removing it breaks some things
3253+ // currently.
32443254 if (!sawLoad) {
32453255 if (auto *declRef = dyn_cast<DeclRefExpr>(argExpr)) {
32463256 assert (!declRef->getType ()->is <LValueType>() &&
32473257 " Shouldn't ever have an lvalue type here!" );
3248-
3249- // Proceed if the storage references a global or static let.
3250- // TODO: We should treat any storage reference as a borrow, it seems, but
3251- // that currently disrupts what the move checker expects. It would also
3252- // be valuable to borrow copyable global lets, but this is a targeted
3253- // fix to allow noncopyable globals to work properly.
3254- bool isGlobal = false ;
3255- if (auto vd = dyn_cast<VarDecl>(declRef->getDecl ())) {
3256- isGlobal = vd->isGlobalStorage ();
3257- }
3258-
3259- if (!isGlobal) {
3260- return nullptr ;
3258+
3259+ // Proceed if the storage reference is a force unwrap.
3260+ if (!forceUnwrap) {
3261+ // Proceed if the storage references a global or static let.
3262+ // TODO: We should treat any storage reference as a borrow, it seems, but
3263+ // that currently disrupts what the move checker expects. It would also
3264+ // be valuable to borrow copyable global lets, but this is a targeted
3265+ // fix to allow noncopyable globals to work properly.
3266+ bool isGlobal = false ;
3267+ if (auto vd = dyn_cast<VarDecl>(declRef->getDecl ())) {
3268+ isGlobal = vd->isGlobalStorage ();
3269+ }
3270+
3271+ if (!isGlobal) {
3272+ return nullptr ;
3273+ }
32613274 }
32623275 }
32633276 }
@@ -3302,6 +3315,10 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
33023315 }
33033316 if (!isMoveOnly)
33043317 return nullptr ;
3318+
3319+ if (forceUnwrap) {
3320+ return forceUnwrap;
3321+ }
33053322
33063323 return result.getTransitiveRoot ();
33073324}
0 commit comments