[pull] main from llvm:main - #1661
Merged
Merged
Conversation
…ysis (#210278) Move the BoUpSLP-independent cost helpers out of SLPVectorizer.cpp into SLPVectorizer/SLPCostAnalysis.{h,cpp} (namespace llvm::slpvectorizer). Moved: * getShuffleCost * getGEPCosts RFC: https://discourse.llvm.org/t/modularizing-slpvectorizer-cpp/90922
) Adds export coverage for a retained local variable case where MLIR may contain separate `DILocalVariableAttr`s for the same source-level variable. A local variable can appear both in a `DISubprogram`'s `retainedNodes` and in a debug intrinsic such as `dbg.value` or `dbg.declare`. During import, the `retainedNodes` path may see the variable while the containing subprogram is represented by a self-recursive placeholder, while the debug intrinsic path later sees the finalized subprogram. This can produce two MLIR local variable attrs with different subprogram scopes. The exported LLVM IR debug metadata is still canonical for this case: both the debug intrinsic and the subprogram `retainedNodes` reference the same `DILocalVariable` metadata node. This patch adds regression coverage for that export behavior without extending the recursive debug-info machinery.
…ats (#210028) RISCVVLOptimizer runs before the machine SSA optimization passes. This includes EarlyMachineLICM, which causes previously loop invariant vmv.v.i/vmv.v.x/vfmv.v.f splats to use a loop variant VL defined by a PseudoVSETVLI. This prevents splats from being hoisted out: https://godbolt.org/z/Wf49roo7s This fixes it by adding another pass of EarlyMachineLICM before RISCVVLOptimizer. As measured on llvm-test-suite w/ `-march=rva23u64 -O3` this increases the number of vector splat instructions hoisted by MachineLICM by 4.4x, from 2140 to 9327. Compile time wise, the number of instructions executed increases geomean +0.2% on CTMark for -O3. -O0 builds are unaffected. Two other approaches were considered: - Use MachineLoopInfo in RISCVVLOptimizer to avoid changing the VL of any loop invariant pseudos. But that results in more vsetvli toggles, and still involves running the same analysis that EarlyMachineLICM depends on anyway - Hoist loop invariant pseudos ourselves in RISCVVLOptimizer. But in order to catch all cases that EarlyMachineLICM handles, we need to split critical edges and modify the CFG (which would invalidate the CFG analyses), and also hoist scalar non-pseudo instructions. In some cases it also led to more spilling due to increased register pressure, which EarlyMachineLICM has heuristics for avoiding.
…210878) Commit 2a33792 ("[clang][NFC] move traits to tablegen", #201491) deleted clang/include/clang/Basic/TransformTypeTraits.def in favor of a tablegen-generated clang/Basic/Traits.inc. The stale module map entry broke module builds. Renaming it to "clang/Basic/Traits.inc" doesn't seem to work, ('clang/Basic/Traits.inc' not found) but the build succeeds with the entry dropped entirely. Assisted-by: Claude Sonnet 5 rdar://182772346
haveFastClmul() called DL.getIndexType()/DL.getAllocaAddrSpace() directly, relying on the `using TargetTransformInfoImplBase::DL;` declaration in BasicTTIImplBase to bring the inherited DataLayout reference into scope. Because DL is reached through a two-level dependent base chain (BasicTTIImplBase<T> -> TargetTransformInfoImplCRTPBase<T>-> TargetTransformInfoImplBase), some compilers (observed with GCC 8.5.0) mis-resolve the member access and reject the code with a misleading diagnostic naming TargetTransformInfoImplBase rather than DataLayout. Access DL via thisT()->DL instead, matching the pattern already used elsewhere in this file (e.g. getABITypeAlign() call sites), which forces lookup to be deferred to instantiation time and avoids the compiler-version-dependent behavior.
…ons (#210653) getBlocksVector, mutable getBlocksSet, getSubLoopsVector, and getTopLevelLoopsVector expose LoopInfo's internal containers, so every caller open-codes loop-nest surgery, keeps the block vector and set in sync by hand, and freezes the representation. Replace them with two LoopInfoBase operations: * removeBlocksIf(LoopT &, Pred): drop matching blocks from a loop. * takeChildrenIf(LoopT *Parent, Pred): detach and return matching children, clearing their parent; a null Parent means the top level. Both preserve the relative order of what remains. Mutation inside LoopInfoBase also lets the analysis repair derived state once per edit and finish a multi-step edit before any query observes it, which an accessor returning a container cannot. For the same reason, move hasNoExitBlocks, getExitEdges, and getUniqueLatchExitBlock onto LoopInfoBase. Two behavior changes: SimpleLoopUnswitch's deleteDeadBlocksFromLoop runs its per-child deletion callbacks while the forest is still consistent, before detaching and destroying dead children; FixIrreducible's reconnectChildLoops keeps children in their original order rather than std::partition's. Aided by Claude Fable 5
…must be either disjoint or the same (#204329) So far, the LangRef hasn't been clear on the semantics of partially overlapping concurrent atomics in LLVM IR (specifically: a set of accesses marked as `atomic` that would be in a data race if they weren't `atomic` and not all of them access the exact same set of bytes). What loads read is defined in terms of individual bytes, but the memory ordering constraints are formulated closely to the C/C++ (and Java for `unordered`) memory model, where partially overlapping atomics are not possible. It's not obvious how concepts like C/C++'s per-location total modification order for `monotonic` accesses map to accesses that can partially overlap. While C/C++ relies on the modification order to ensure that atomics cannot tear (i.e., atomic reads return bytes from two or more atomic writes), our IR semantics (as written) currently does not guarantee this in the presence of partially overlapping accesses. This PR proposes a solution to this problem: It specifies that concurrent overlapping atomics must access the exact same set of bytes to act atomically. If they don't, they form a data race (i.e., participating loads read `undef` for affected bytes) and the atomic ordering constaints do not apply. This empowers the rest of the specification to imply that `monotonic` (or stronger) accesses do not tear. The PR also adds a constraint to ensure non-tearing for `unordered` atomic accesses. This solution implies that transformations that merge adjacent atomic loads/stores into wider atomic loads/stores are generally incorrect. Related RFC: https://discourse.llvm.org/t/rfc-semantics-of-partially-overlapping-atomic-accesses/91092
This patch implements Phase 1 of the [RFC](https://discourse.llvm.org/t/rfc-enforce-single-operand-format-for-all-enable-metadata-nodes/90571) "Enforce Single-Operand Format for All .enable Metadata Nodes". The two-operand boolean form !{!"llvm.loop.distribute.enable", i1 0/1} is replaced by a single-operand enable/disable pair: !{!"llvm.loop.distribute.enable"} ; force distribution !{!"llvm.loop.distribute.disable"} ; suppress distribution
PR #209999 (9e2e9b3) "broke" the GPU build by causing many/most tests to not run. The follow-up in #210715 (4bd1a44) broke it for real (https://lab.llvm.org/buildbot/#/builders/10/builds/32254) by causing too many tests to run. I think we just need to disable the extra tests, but I want to start out by reverting both patches so that it's easier to compare the before/after state in the next attempt.
…es (#209879) Followup to #207079. This replaces IR-level tests introduced in c311e7b that were using inline assembler hack with MIR-level tests, as suggested by @ganeshgit. Older test for bit counting instruction with more complex functions is kept alongside a new one that tests affected instructions in isolation.
In few places we are reinterpreting raw bytes as typed data. This works but is undefined behaviour if the address being used isn't at the same alignment as the target type. It likely has always been because we've got 4 and 8 byte types and 4 or 8 byte registers. However I prefer to use memcpy anyway to be safe. m_sve_state is a single byte but for consistency I'm using memcpy for it also.
qSymbol is sent to the debug server every time libraries are loaded. It can respond to this with symbols it wants to know the value for. It's rarely used so I expect that's why we had zero test coverage for it. In this commit I'm adding a test case, derived from the bug being reported in #200134. The mock debug server has a list of symbols to ask for and records the results. After LLDB has connected we check with the mock that it got all the answers it wanted. Right now, 2 of the symbols don't have values, but should according to the author of the bug report. One symbol is intentionally missing to check that LLDB handles that situation properly, even when the others have been fixed. While I was doing this I realised the documentaiton for an unknown symbol response was wrong. You can cross check this with GDB's: https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html#General-Query-Packets In theory we should test the MachO behaviour too. However I was not able to create a MachO example that did not end up using a host AArch64 Linux binary that it found via. PID, while also getting far enough to send qSymbol. Every workaround broke one of those 2 things. ELF testing is better than the nothing we currently have. Assisted by: ChatGPT 5.5
…mpound statement (#209229) <https://eel.is/c++draft/stmt.expand#nt:expansion-statement>: _expansion-statement_: template for ( _init-statement<sub>opt</sub>_ _for-range-declaration_ : _expansion-initializer_ ) _compound-statement_
A reducible loop has a single entry (header), which flatten() places at BlockLayout[IdxBegin], as its minimum-preorder block. A reducible loop then needs no storage at all. For the uncommon irreducible loop case, we append its full entry list (header first) after the Euler tour, referenced by [EntryBegin, EntryBegin+EntrySize), making `GenericCycleInfo::Cycle` (named only because "loop" is occupied by LoopInfo) trivially destructible.
This is redundant with using the standard -verify-machineinstrs. It's also confusing / worse, since the error is not produced to stderr.
…uring destruction (#210801) When a `lifetimebound` method is called during destruction the checker emits warnings which leads to false positives. To avoid this a dangling stack source is not reported if any frame on the current stack belongs to a destructor.
…#210683) This avoids adding a page-size-* lit feature when compiler-rt tests are configured to run through an emulator. Perviously this used to work because failure to detect the page size would fall back to 4096. Now after this change #209175, the code tries to execute config.python_executable through the emulator. For emulator-based test configurations, this is inappropriate. The function now returns None when an emulator is configured, and the lit feature is only added when a concrete page size is available.
This facilitates debugging with concepts, particularly when we need to check complex parameter mappings. Since this is mainly for debugging purpose, we don't promise any text stability and hence no tests provided.
The message was the opposite of the assert condition. In addition, when PatternSize == Size the caller wants to fill the region with exactly one copy of the pattern, which is a valid operation. The issue was found by AI. Also check `Size % PatternSize == 0` per L0 spec.
…#207976) Recently we found a compile time problem in the case that contains much high-cost live interval. And normal interference failures still set `Again=true` and can be retried (it cost N^2 complexity). We tracks when a join failed only because of the high-cost guard, so that avoids putting such copies back into the retry worklist. This reduce our huge function case from 14.6h to 12.8min in register coalescer pass.
… argument (#210718) `Sema::ActOnParamDefaultArgument` checked a default-argument expression for unexpanded parameter packs before checking whether the parameter itself is a pack. For a lambda parameter pack given a default argument that is a pack expansion referencing an enclosing function's parameter pack (e.g. `[](Types... = args...) {}`), the first check runs while still inside the lambda's scope and sets `LambdaScopeInfo::ContainsUnexpandedParameterPack` (a mechanism meant for legitimate outer-pack references). The subsequent `isParameterPack()` check then correctly diagnoses the real error and discards the default argument, but the stale flag survives into the built `LambdaExpr`'s dependence bits. A later unexpanded-pack check on that `LambdaExpr` finds nothing to report and hits `assert(!Unexpanded.empty() || LambdaReferencingOuterPacks)`, aborting instead of just diagnosing the error. Fix: check `Param->isParameterPack()` first and return immediately after discarding the default argument, before ever calling `DiagnoseUnexpandedParameterPack` on an expression that is about to be thrown away. [dcl.fct.default]p3 forbids a default argument on a pack parameter unconditionally, so this ordering is also semantically correct, not just a crash workaround. Fixes #210714
Adds a Rerun control value to ExecutionContext::Control that allows the re-execution of the current action immediately after it completes, without restarting the full compilation pipeline. This is analogous to GDB's ability to restart execution from a breakpoint. When the callback returns Rerun, the action is executed normally, then re-dispatched through the full ExecutionContext::operator() pipeline, including breakpoint matching, so the user gets a fresh opportunity to inspect or control the re-execution. As a practical usage example, a breakpoint + an observer can be added, to save and restore IR between runs to check if each run produces the same IR or something different each time. A depth-keyed structure is used, so rerun requests survive nested action dispatch and are consumed by the correct stack frame.
Deleting the temporary files produced by the DTLTO pipeline can be expensive on Windows hosts. For a Clang link (Debug build with sanitizers and instrumentation) using an optimized toolchain (PGO non-LTO, llvmorg-22.1.0) on a Windows 11 Pro (Build 26200), AMD Family 25 @ ~4.5 GHz, 16 cores/32 threads, 64 GB RAM machine, the mean duration of the "Remove DTLTO temporary files" time trace scope was 1267.789 ms (measured over 10 runs). This patch performs the deletions on a background thread, allowing them to overlap with the tail of the link to hide this cost. This is a re-implementation of the asynchronous cleanup idea from #186988, which had to be reverted in #189043 because cleanup was not guaranteed to complete before LLD invoked timeTraceProfilerCleanup(). In certain cases timeTraceProfilerCleanup() was called before temporary file deletion had completed in LLD, which caused memory leaks that were flagged by sanitizer builds. Note that the DTLTO implementation has been refactored heavily since #186988, so this is a re-implementation along the same lines. To solve the ordering issue, LLD now calls a hook that defaults to a no-op, and DTLTO overrides it to drain the background deletion work. LLD calls this hook before time-trace write/cleanup.
…207303) Perform the following fold given loadA and loadB can be proven consecutive: ``` concat(shuffle(loadA, loadB, mask0), shuffle(loadA, loadB, mask1)) -> shuffle(loadAB, poison, concat(mask0, mask1)) ```
This is a very delayed follow up to: https://discourse.llvm.org/t/rfc-surveying-lldbs-supported-platforms-and-architectures/83978 Where I realised that even for upstream supported targets, the level of testing and attention they get varies a lot. Which I think is not a bad thing, because LLDB would be much more chaotic if it were a bad thing. The problem I see is that no one really knows how to start writing proposals for new targets, and no one really knows how to properly assess one. Me included, but what I can do is write out some starting points for both parties. Hopefully this makes the process a bit more fair for those not used to writing RFCs. (and if we want to make the rules more strict, we will now have a place to document that) The document also includes some technical guidance, but I don't want to get stuck in the "How to Write an LLVM backend" type cycle. Where we write a thing and it becomes outdated instantly. So what's there is deliberately high level because Developers will have to learn the codebase anyway to have any chance of writing target support. A bit like adding a new language, which has unknown scope. But unlike a new language, there are plenty of targets to look at, so I think it's more justifiable here. In terms of the famous meme: This document isn't going to tell you how to "draw the rest of the owl", but it gives you the names of some key techniques in owl drawing and advice for how to best present your owl to the "drawings of owls" society when you're done. Please note that this new requirement of an RFC does not apply to targets that are in progress or in discussion right now.
…ter (#210920) For binary expression `1, 2`, StmtPrinter used to print it as `1 , 2` which doesn't look very pretty.
This adds the 'f' inline assembly constraint, as supported by GCC. An 'f'-constrained operand is passed in a floating point register.
…rpreter/* (#210289) `Stream::Printf` needs to call various other (variadic) functions, needs to parse the input string and potentially handle too-long format outputs. Calling in with a constant string is wasting a lot of instruction on doing nothing. assisted-by: claude
…210291) `Stream::Printf` needs to call various other (variadic) functions, needs to parse the input string and potentially handle too-long format outputs. Calling in with a constant string is wasting a lot of instruction on doing nothing. assisted-by: claude
…et/* (#210287) `Stream::Printf` needs to call various other (variadic) functions, needs to parse the input string and potentially handle too-long format outputs. Calling in with a constant string is wasting a lot of instruction on doing nothing. assisted-by: claude
…210926) A follow up PR of #198438 This is to address post commit test issues: https://lab.llvm.org/buildbot/#/builders/202/builds/726 Keep the normal combine and unknown-input baseline coverage enabled in all builds, and move the named rule-disable checks into an assertion-only test.
The C and C++ standards require both operands of pointer subtraction to refer to elements of the same array object. Clang/LLVM currently relies on this rule in several optimizations: - `inbounds` GEP introduces UB assumptions once the computed address escapes the originating object bounds. - `sdiv exact` assumes %op1 is divisable by %op2 otherwise it is a poison value. The first issue may be addressed with -fwrapv-pointer command line option, however there is no option in clang to mitigate the second issue. Patch adds a new -fdefined-pointer-subtraction to address this.
…tant splats" (#210937) Reverts #210028 I've bisected the hangs on rva20 to this commit: https://lab.llvm.org/buildbot/#/builders/210/builds/11806
…ilds (#194222) The next step is to setup the metadata for the wheel building process, and subsequently follow it up with workflow jobs that can automate this.
Following up to #209883, move transformations related to lowering/preparing for execution to VPlanLowering.cpp This moves materialize*, convertToConcreteRecipes, dissolveLoopRegions, expandBranchOnTwoConds, replaceWideCanonicalIVWithWideIV, expandSCEVsToVPInstructions, addBranchWeightToMiddleTerminator and the alias-mask materialization helpers. The createScalarIVSteps and scalarizeVPWidenPointerInduction are promoted to vputils. Depends on #209883
Use SCEV analysis on VPValue pointer operands to detect stride-1 memory
accesses in the outer loop vectorization path. When a load or store
address is an affine AddRec w.r.t. the vectorized outer loop with stride
equal to the element size, mark it as consecutive so it generates a wide
load/store instead of a gather/scatter.
For example, in the column-scaling pattern:
```
for (i = 0; i < N; i++) // outer: vectorized
for (j = 0; j < M; j++) // inner: uniform
A[i*M+j] *= scale[i];
```
The access scale[i] is now correctly identified as contiguous and
generates a vector load instead of a masked gather.
PR: #203790
Otherwise we'd have duplicate benchmark names.
…10724) The method was marked as noexcept in the synopsis, but it's neither marked noexcept in the spec nor in our implementation.
…allation substitutions (#209638) This patch restructures how libc++'s Lit site config is generated. Instead of relying on the user-selected configuration file to include the CMake bridge, it composes a site configuration from multiple independent bits. Importantly, it splits substitutions that pertain to the harness setup (e.g. where to find Python) and substitutions that pertain to libc++ itself (e.g. the path to libc++ headers). This split and the top-level composition of a site config file are incremental steps towards decoupling the test suite from libc++'s own build.
The immutable-set/map dataflow joins merged two containers by inserting
the
elements of one into the other one at a time, costing O(|B| * log|A|)
and
re-copying shared spine nodes on every insert.
Add a single-pass, structure-sharing tree merge on ImutAVLFactory
(mergeTrees), exposed as ImmutableSet::Factory::unionSets and
ImmutableMap::Factory::mergeWith. It recurses over the larger operand
and
splits the smaller at each key, returning non-overlapping subtrees
unchanged,
so each spine node is copied at most once: O(|B| * log(|A|/|B| + 1)).
Two flags tune it for the different joins:
* KeepUnmatched - keep keys unique to one side (set union / a lattice
join
with an identity) vs. pass them through the combiner (a symmetric join,
e.g. liveness Must->Maybe).
* SkipShared - return a pointer-identical subtree unchanged in O(1).
Valid
for an idempotent merge (Combine(a, a) == a), which holds for set union
and
every lattice join. Since dataflow states are path-copied from one
another,
a join's operands usually share most subtrees by pointer, so a join that
touches only a few keys becomes nearly O(diff).
Wire it into the Clang lifetime-safety analysis (set and map joins) and
the
LiveVariables merge, and add ImmutableMergeBM to track it.
Speedups on the lifetime-safety dataflow benchmark (LoanPropagation
phase):
pointer cycle in a loop ~2.6x (1.59 s -> 0.61 s)
CFG merges ~190x (1.83 s -> 9.5 ms)
switch fan-out ~1.9x (LiveOrigins; disjoint states, no skip)
LiveVariables is ~2-3x faster on liveness-heavy inputs and neutral on
typical
code (the join is a small fraction of real-code analysis time).
ImmutableMergeBM confirms the merge beats the add loop for small and
near-identical operands, except for independently-built sets differing
by
exactly one element; when one operand is derived from the other -- the
real
dataflow case -- the pointer-skip makes even that a large win. New
randomized
ADT stress tests check the merge against std::set/std::map oracles for
both
canonicalizing and non-canonicalizing factories.
Assisted by: Claude Opus 4.8
Co-authored-by: Gabor Horvath <gaborh@apple.com>
Closes #105418. Since gcc does not currently support `__atomic_fetch_min/max`, we use a CAS loop in `atomic_ref` and `support/gcc.h`. --------- Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
…rence (#207585) This PR adds a "one-liner" default implementation of parallel `std::adjacent_difference` on top of parallel binary `std::transform`. The implementation builds two iterator ranges out of the input one, so that a zip of these ranges yields adjacent pairs. Then performs a binary transform to calculate and output the adjacent differences. Part of #99938
Walking a StackFrame's parent chain was open-coded across the Analysis library and Static Analyzer as hand-rolled loops of the form `for (const StackFrame *SF = X; SF; SF = SF->getParent())`. Add range-based traversal helpers and convert the applicable loops: * StackFrame::parents() - strict ancestors (excludes *this) * StackFrame::parentsIncludingSelf() - *this then all ancestors Both are built on a small forward `parent_iterator` that dereferences to `const StackFrame &` and advances via getParent(), with a null past-the-end sentinel. For the common case of obtaining the current frame from an ExplodedNode or CheckerContext, add a self-inclusive `stackframes()` convenience on each that delegates to `getStackFrame()->parentsIncludingSelf()`. Converted call-sites additionally adopt llvm::any_of / llvm::enumerate / make_pointer_range where it makes the traversal more declarative. Loops that stop at a target frame or advance conditionally (i.e. not "walk until null") are intentionally left as-is.
Updates the error streaming string logic to handle the case where string interpolation used at the end of the description. Previously this could generate malformed code that would not compile e.g.: ``` "' failed to satisfy constraint: another attribute " << reformat(attr)"; ``` With this change the above example would now generate: ``` "' failed to satisfy constraint: another attribute " << reformat(attr) << ""; ```
…builtin (#210524) ## Summary Fix an assertion failure when Clang classifies a built-in call with type-dependent arguments before template instantiation, e.g., while deducing an `auto` non-type template parameter: For example: ```cpp template <auto> struct S {}; template <typename T> using Alias = S<__builtin_constant_p(T::x)>; ``` ``` Assertion failed: (isa<T>(CanonicalType)), function castAs, file TypeBase.h, line 9349. #9 clang::Type::castAs<clang::FunctionType>() const #10 clang::CallExpr::getCallReturnType(clang::ASTContext const&) const #11 ClassifyInternal(clang::ASTContext&, clang::Expr const*) #12 clang::Expr::ClassifyImpl(clang::ASTContext&, clang::SourceLocation*) const #13 clang::Sema::DeduceAutoType(...) #14 clang::Sema::CheckTemplateArgument(...) ``` ## Cause Built-in references initially have the BuiltinFn placeholder type. For a non-dependent call, `BuildResolvedCallExpr()` applies `CK_BuiltinFnToFnPtr`, converting the callee to its function-pointer type. When a call has type-dependent arguments, `BuildCallExpr()` postpones semantic analysis until instantiation. The callee, therefore, retains its BuiltinFn placeholder type. Deducing the auto non-type template parameter classifies the dependent call through `Expr::ClassifyImpl()`. This calls `CallExpr::getCallReturnType()`, which previously did not handle BuiltinFn and attempted to cast the placeholder to FunctionType, triggering an assertion. The issue also affects ordinary builtins such as `__builtin_ffs` and is not specific to` __builtin_constant_p`. ## Fix Handle `BuiltinFn` alongside the dependent and `Overload` callee cases in `CallExpr::getCallReturnType()` and return `DependentTy`. This matches the type `BuildCallExpr()` gives the `CallExpr` itself, so `getCallReturnType()` and `getType()` now agree on such calls. Built-in resolution and built-in-specific type checking still occur as usual during template instantiation. Added coverage for dependent calls and successful instantiation of `__builtin_constant_p` and `__builtin_ffs`, a non-dependent control case, and getCallReturnType() for a BuiltinFn callee.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )