@@ -2246,74 +2246,64 @@ bool AvailabilityWalker::diagnoseIncDecRemoval(const ValueDecl *D,
22462246 return false ;
22472247}
22482248
2249- // / If this is a call to an unavailable sizeof family functions , diagnose it
2249+ // / If this is a call to an unavailable sizeof family function , diagnose it
22502250// / with a fixit hint and return true. If not, or if we fail, return false.
22512251bool AvailabilityWalker::diagnoseMemoryLayoutMigration (const ValueDecl *D,
2252- SourceRange R,
2253- const AvailableAttr *Attr,
2254- const ApplyExpr *call) {
2252+ SourceRange R,
2253+ const AvailableAttr *Attr,
2254+ const ApplyExpr *call) {
22552255
22562256 if (!D->getModuleContext ()->isStdlibModule ())
22572257 return false ;
22582258
2259- std::pair<StringRef, bool > KindValue
2260- = llvm::StringSwitch<std::pair<StringRef, bool >>(D->getNameStr ())
2261- .Case (" sizeof" , {" size" , false })
2262- .Case (" alignof" , {" alignment" , false })
2263- .Case (" strideof" , {" stride" , false })
2264- .Default ({});
2265-
2266- if (KindValue.first .empty ())
2259+ StringRef Property = llvm::StringSwitch<StringRef>(D->getNameStr ())
2260+ .Case (" sizeof" , " size" )
2261+ .Case (" alignof" , " alignment" )
2262+ .Case (" strideof" , " stride" )
2263+ .Default (StringRef ());
2264+ if (Property.empty ())
22672265 return false ;
22682266
2269- auto Kind = KindValue.first ;
2270- auto isValue = KindValue.second ;
2271-
22722267 auto args = dyn_cast<ParenExpr>(call->getArg ());
22732268 if (!args)
22742269 return false ;
22752270
2276- auto subject = args->getSubExpr ();
2277- if (!isValue) {
2278- // sizeof(type(of: x)) is equivalent to sizeofValue(x)
2279- if (auto DTE = dyn_cast<DynamicTypeExpr>(subject)) {
2280- subject = DTE->getBase ();
2281- isValue = true ;
2282- }
2283- }
2284-
22852271 EncodedDiagnosticMessage EncodedMessage (Attr->Message );
22862272 auto diag = TC.diagnose (R.Start , diag::availability_decl_unavailable_msg,
22872273 D->getFullName (), EncodedMessage.Message );
22882274 diag.highlight (R);
22892275
2276+ auto subject = args->getSubExpr ();
2277+
22902278 StringRef Prefix = " MemoryLayout<" ;
22912279 StringRef Suffix = " >." ;
2292- if (isValue) {
2293- auto valueType = subject->getType ()->getRValueType ();
2280+
2281+ if (auto DTE = dyn_cast<DynamicTypeExpr>(subject)) {
2282+ // Replace `sizeof(type(of: x))` with `MemoryLayout<X>.size`, where `X` is
2283+ // the static type of `x`. The previous spelling misleadingly hinted that
2284+ // `sizeof(_:)` might return the size of the *dynamic* type of `x`, when
2285+ // it is not the case.
2286+ auto valueType = DTE->getBase ()->getType ()->getRValueType ();
22942287 if (!valueType || valueType->hasError ()) {
2295- // If we don't have a suitable argument, we cannot emit a fix-it .
2288+ // If we don't have a suitable argument, we can't emit a fixit .
22962289 return true ;
22972290 }
2298-
2299- // NOTE: We are destructively replacing the source text here.
2300- // `sizeof(type(of: doSomething()))` => `MemoryLayout<T>.size`, where T is
2301- // the return type of `doSomething()`. If that function has any side
2302- // effects, this replacement will break the source.
2291+ // Note that in rare circumstances we may be destructively replacing the
2292+ // source text. For example, we'd replace `sizeof(type(of: doSomething()))`
2293+ // with `MemoryLayout<T>.size`, if T is the return type of `doSomething()`.
23032294 diag.fixItReplace (call->getSourceRange (),
2304- (Prefix + valueType->getString () + Suffix + Kind ).str ());
2295+ (Prefix + valueType->getString () + Suffix + Property ).str ());
23052296 } else {
23062297 SourceRange PrefixRange (call->getStartLoc (), args->getLParenLoc ());
23072298 SourceRange SuffixRange (args->getRParenLoc ());
23082299
2309- // We must truncate `.self`.
2310- // E.g. sizeof(T.self) => MemoryLayout<T>.size
2300+ // We must remove `.self`.
23112301 if (auto *DSE = dyn_cast<DotSelfExpr>(subject))
23122302 SuffixRange.Start = DSE->getDotLoc ();
23132303
23142304 diag
23152305 .fixItReplace (PrefixRange, Prefix)
2316- .fixItReplace (SuffixRange, (Suffix + Kind ).str ());
2306+ .fixItReplace (SuffixRange, (Suffix + Property ).str ());
23172307 }
23182308
23192309 return true ;
0 commit comments