-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Revert "[HLSL] Add implicit resource element type concepts to AST" #116305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
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
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-clang Author: Joshua Batista (bob80905) ChangesReverts llvm/llvm-project#112600 Full diff: https://github.com/llvm/llvm-project/pull/116305.diff 6 Files Affected:
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index d90a7d3c697a04..cac15b974a276e 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -289,9 +289,8 @@ struct BuiltinTypeDeclBuilder {
}
TemplateParameterListBuilder addTemplateArgumentList(Sema &S);
- BuiltinTypeDeclBuilder &
- addSimpleTemplateParams(Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD);
- BuiltinTypeDeclBuilder &addConceptSpecializationExpr(Sema &S);
+ BuiltinTypeDeclBuilder &addSimpleTemplateParams(Sema &S,
+ ArrayRef<StringRef> Names);
};
struct TemplateParameterListBuilder {
@@ -313,129 +312,30 @@ struct TemplateParameterListBuilder {
S.Context, Builder.Record->getDeclContext(), SourceLocation(),
SourceLocation(), /* TemplateDepth */ 0, Position,
&S.Context.Idents.get(Name, tok::TokenKind::identifier),
- /* Typename */ true,
- /* ParameterPack */ false,
- /* HasTypeConstraint*/ false);
+ /* Typename */ false,
+ /* ParameterPack */ false);
if (!DefaultValue.isNull())
Decl->setDefaultArgument(
S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(),
SourceLocation()));
+
Params.emplace_back(Decl);
return *this;
}
- /*
- The concept specialization expression (CSE) constructed in
- constructConceptSpecializationExpr is constructed so that it
- matches the CSE that is constructed when parsing the below C++ code:
-
- template<typename T>
- concept is_typed_resource_element_compatible = sizeof(T) <= 16;
-
- template<typename element_type> requires
- is_typed_resource_element_compatible<element_type>
- struct RWBuffer {
- element_type Val;
- };
-
- int fn() {
- RWBuffer<int> Buf;
- }
-
- When dumping the AST and filtering for "RWBuffer", the resulting AST
- structure is what we're trying to construct below, specifically the
- CSE portion.
- */
- ConceptSpecializationExpr *
- constructConceptSpecializationExpr(Sema &S, ConceptDecl *CD) {
- ASTContext &Context = S.getASTContext();
- SourceLocation Loc = Builder.Record->getBeginLoc();
- DeclarationNameInfo DNI(CD->getDeclName(), Loc);
- NestedNameSpecifierLoc NNSLoc;
- DeclContext *DC = Builder.Record->getDeclContext();
- TemplateArgumentListInfo TALI(Loc, Loc);
-
- // Assume that the concept decl has just one template parameter
- // This parameter should have been added when CD was constructed
- // in getTypedBufferConceptDecl
- assert(CD->getTemplateParameters()->size() == 1 &&
- "unexpected concept decl parameter count");
- TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>(
- CD->getTemplateParameters()->getParam(0));
-
- // this TemplateTypeParmDecl is the template for the resource, and is
- // used to construct a template argumentthat will be used
- // to construct the ImplicitConceptSpecializationDecl
- TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
- Context, // AST context
- Builder.Record->getDeclContext(), // DeclContext
- SourceLocation(), SourceLocation(),
- /*depth=*/0, // Depth in the template parameter list
- /*position=*/0, // Position in the template parameter list
- /*id=*/nullptr, // Identifier for 'T'
- /*Typename=*/true, // Indicates this is a 'typename' or 'class'
- /*ParameterPack=*/false, // Not a parameter pack
- /*HasTypeConstraint=*/false // Has no type constraint
- );
-
- T->setDeclContext(DC);
-
- QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
-
- // this is the 2nd template argument node, on which
- // the concept constraint is actually being applied: 'element_type'
- TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
-
- QualType CSETType = Context.getTypeDeclType(T);
-
- // this is the 1st template argument node, which represents
- // the abstract type that a concept would refer to: 'T'
- TemplateArgument CSETA = TemplateArgument(CSETType);
-
- ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
- ImplicitConceptSpecializationDecl::Create(
- Context, Builder.Record->getDeclContext(), Loc, {CSETA});
-
- // Constraint satisfaction is used to construct the
- // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
- // located at the bottom of the sample AST above.
- const ConstraintSatisfaction CS(CD, {ConceptTA});
- TemplateArgumentLoc TAL = S.getTrivialTemplateArgumentLoc(
- ConceptTA, QualType(), SourceLocation());
-
- TALI.addArgument(TAL);
- const ASTTemplateArgumentListInfo *ATALI =
- ASTTemplateArgumentListInfo::Create(Context, TALI);
-
- // In the concept reference, ATALI is what adds the extra
- // TemplateArgument node underneath CSE
- ConceptReference *CR =
- ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
-
- ConceptSpecializationExpr *CSE =
- ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
-
- return CSE;
- }
-
- BuiltinTypeDeclBuilder &finalizeTemplateArgs(ConceptDecl *CD = nullptr) {
+ BuiltinTypeDeclBuilder &finalizeTemplateArgs() {
if (Params.empty())
return Builder;
- ConceptSpecializationExpr *CSE =
- CD ? constructConceptSpecializationExpr(S, CD) : nullptr;
-
auto *ParamList = TemplateParameterList::Create(S.Context, SourceLocation(),
SourceLocation(), Params,
- SourceLocation(), CSE);
+ SourceLocation(), nullptr);
Builder.Template = ClassTemplateDecl::Create(
S.Context, Builder.Record->getDeclContext(), SourceLocation(),
DeclarationName(Builder.Record->getIdentifier()), ParamList,
Builder.Record);
-
Builder.Record->setDescribedClassTemplate(Builder.Template);
Builder.Template->setImplicit(true);
Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
-
// NOTE: setPreviousDecl before addDecl so new decl replace old decl when
// make visible.
Builder.Template->setPreviousDecl(Builder.PrevTemplate);
@@ -455,13 +355,13 @@ BuiltinTypeDeclBuilder::addTemplateArgumentList(Sema &S) {
return TemplateParameterListBuilder(S, *this);
}
-BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addSimpleTemplateParams(
- Sema &S, ArrayRef<StringRef> Names, ConceptDecl *CD = nullptr) {
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addSimpleTemplateParams(Sema &S,
+ ArrayRef<StringRef> Names) {
TemplateParameterListBuilder Builder = this->addTemplateArgumentList(S);
for (StringRef Name : Names)
Builder.addTypeParameter(Name);
-
- return Builder.finalizeTemplateArgs(CD);
+ return Builder.finalizeTemplateArgs();
}
HLSLExternalSemaSource::~HLSLExternalSemaSource() {}
@@ -572,103 +472,10 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
.addDefaultHandleConstructor(S);
}
-BinaryOperator *constructSizeOfLEQ16Expr(ASTContext &Context,
- SourceLocation NameLoc,
- TemplateTypeParmDecl *T) {
- // Obtain the QualType for 'unsigned long'
- QualType UnsignedLongType = Context.UnsignedLongTy;
-
- // Create a QualType that points to this TemplateTypeParmDecl
- QualType TType = Context.getTypeDeclType(T);
-
- // Create a TypeSourceInfo for the template type parameter 'T'
- TypeSourceInfo *TTypeSourceInfo =
- Context.getTrivialTypeSourceInfo(TType, NameLoc);
-
- UnaryExprOrTypeTraitExpr *sizeOfExpr = new (Context) UnaryExprOrTypeTraitExpr(
- UETT_SizeOf, TTypeSourceInfo, UnsignedLongType, NameLoc, NameLoc);
-
- // Create an IntegerLiteral for the value '16' with size type
- QualType SizeType = Context.getSizeType();
- llvm::APInt SizeValue = llvm::APInt(Context.getTypeSize(SizeType), 16);
- IntegerLiteral *SizeLiteral =
- new (Context) IntegerLiteral(Context, SizeValue, SizeType, NameLoc);
-
- QualType BoolTy = Context.BoolTy;
-
- BinaryOperator *binaryOperator =
- BinaryOperator::Create(Context, sizeOfExpr, // Left-hand side expression
- SizeLiteral, // Right-hand side expression
- BO_LE, // Binary operator kind (<=)
- BoolTy, // Result type (bool)
- VK_LValue, // Value kind
- OK_Ordinary, // Object kind
- NameLoc, // Source location of operator
- FPOptionsOverride());
-
- return binaryOperator;
-}
-
-Expr *constructTypedBufferConstraintExpr(Sema &S, SourceLocation NameLoc,
- TemplateTypeParmDecl *T) {
- ASTContext &Context = S.getASTContext();
-
- // first get the "sizeof(T) <= 16" expression, as a binary operator
- BinaryOperator *SizeOfLEQ16 = constructSizeOfLEQ16Expr(Context, NameLoc, T);
- // TODO: add the 'builtin_hlsl_is_typed_resource_element_compatible' builtin
- // and return a binary operator that evaluates the builtin on the given
- // template type parameter 'T'.
- // Defined in issue https://github.com/llvm/llvm-project/issues/113223
- return SizeOfLEQ16;
-}
-
-ConceptDecl *constructTypedBufferConceptDecl(Sema &S, NamespaceDecl *NSD) {
- ASTContext &Context = S.getASTContext();
- DeclContext *DC = NSD->getDeclContext();
- SourceLocation DeclLoc = SourceLocation();
-
- IdentifierInfo &ElementTypeII = Context.Idents.get("element_type");
- TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create(
- Context, NSD->getDeclContext(), DeclLoc, DeclLoc,
- /*depth=*/0,
- /*position=*/0,
- /*id=*/&ElementTypeII,
- /*Typename=*/true,
- /*ParameterPack=*/false);
-
- T->setDeclContext(DC);
- T->setReferenced();
-
- // Create and Attach Template Parameter List to ConceptDecl
- TemplateParameterList *ConceptParams = TemplateParameterList::Create(
- Context, DeclLoc, DeclLoc, {T}, DeclLoc, nullptr);
-
- DeclarationName DeclName = DeclarationName(
- &Context.Idents.get("__is_typed_resource_element_compatible"));
- Expr *ConstraintExpr = constructTypedBufferConstraintExpr(S, DeclLoc, T);
-
- // Create a ConceptDecl
- ConceptDecl *CD =
- ConceptDecl::Create(Context, NSD->getDeclContext(), DeclLoc, DeclName,
- ConceptParams, ConstraintExpr);
-
- // Attach the template parameter list to the ConceptDecl
- CD->setTemplateParameters(ConceptParams);
-
- // Add the concept declaration to the Translation Unit Decl
- NSD->getDeclContext()->addDecl(CD);
-
- return CD;
-}
-
void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
CXXRecordDecl *Decl;
- ConceptDecl *TypedBufferConcept =
- constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace);
-
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
- .addSimpleTemplateParams(*SemaPtr, {"element_type"},
- TypedBufferConcept)
+ .addSimpleTemplateParams(*SemaPtr, {"element_type"})
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
index e3060a2dfa9677..ebddd72ddb1e0e 100644
--- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl
+++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
@@ -11,15 +11,7 @@
// instantiated specialization.
// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
-// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
-// EMPTY-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_typed_resource_element_compatible'
-// EMPTY-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
-// EMPTY-NEXT: TemplateArgument type 'type-parameter-0-0'
-// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
-// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
-// EMPTY-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
-// EMPTY-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
-// EMPTY-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
+// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class RWBuffer
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
@@ -33,15 +25,7 @@ RWBuffer<float> Buffer;
#endif
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit RWBuffer
-// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
-// CHECK-NEXT: ConceptSpecializationExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'bool' Concept 0x{{[0-9A-Fa-f]+}} '__is_typed_resource_element_compatible'
-// CHECK-NEXT: ImplicitConceptSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>
-// CHECK-NEXT: TemplateArgument type 'type-parameter-0-0'
-// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-0' dependent depth 0 index 0
-// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
-// CHECK-NEXT: TemplateArgument type 'element_type':'type-parameter-0-0'
-// CHECK-NEXT: TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'element_type' dependent depth 0 index 0
-// CHECK-NEXT: TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'element_type'
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
diff --git a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
index 081ab1355caaac..521c3d45b20225 100644
--- a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl
@@ -12,7 +12,7 @@
// instantiated specialization.
// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
-// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
+// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class StructuredBuffer
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
@@ -26,7 +26,7 @@ StructuredBuffer<float> Buffer;
#endif
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
-// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> typename depth 0 index 0 element_type
+// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class StructuredBuffer definition
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
diff --git a/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl b/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl
deleted file mode 100644
index 414ed6eb821246..00000000000000
--- a/clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -ast-dump-filter=__is_typed_resource_element_compatible %s | FileCheck %s
-
-// CHECK: ConceptDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> __is_typed_resource_element_compatible
-// CHECK: |-TemplateTypeParmDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> referenced typename depth 0 index 0 element_type
-// CHECK: `-BinaryOperator 0x{{[0-9a-f]+}} <<invalid sloc>> 'bool' lvalue '<='
-// CHECK: |-UnaryExprOrTypeTraitExpr 0x{{[0-9a-f]+}} <<invalid sloc>> 'unsigned long' sizeof 'element_type'
-// CHECK: `-IntegerLiteral 0x{{[0-9a-f]+}} <<invalid sloc>> 'unsigned long' 16
-
-
-RWBuffer<float> Buffer;
diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
index a170cef6e5da11..76b5d01b8036eb 100644
--- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
@@ -5,24 +5,13 @@ typedef vector<float, 3> float3;
RWBuffer<float3> Buffer;
// expected-error@+2 {{class template 'RWBuffer' requires template arguments}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
+// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
RWBuffer BufferErr1;
// expected-error@+2 {{too few template arguments for class template 'RWBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer {}}}
+// expected-note@*:* {{template declaration from hidden source: template <class element_type> class RWBuffer}}
RWBuffer<> BufferErr2;
-struct threeDoubles {
- double a;
- double b;
- double c;
-};
-
-// expected-error@+3 {{constraints not satisfied for class template 'RWBuffer'}}
-// expected-note@*:* {{because 'threeDoubles' does not satisfy '__is_typed_resource_element_compatible'}}
-// expected-note@*:* {{because 'sizeof(threeDoubles) <= 16UL' (24 <= 16) evaluated to false}}
-RWBuffer<threeDoubles> BufferErr3;
-
[numthreads(1,1,1)]
void main() {
(void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer<vector<float, 3>>'}}
diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
index 552624f13ee5f8..a472d5519dc51f 100644
--- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
@@ -5,11 +5,11 @@ typedef vector<float, 3> float3;
StructuredBuffer<float3> Buffer;
// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
+// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
StructuredBuffer BufferErr1;
// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> class StructuredBuffer {}}}
+// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
StructuredBuffer<> BufferErr2;
[numthreads(1,1,1)]
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
clang:frontend
Language frontend issues, e.g. anything involving "Sema"
clang
Clang issues not falling into any other category
HLSL
HLSL Language Support
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.
Reverts #112600