Skip to content

Commit

Permalink
Fix the diagnostic issue and no_diff issue
Browse files Browse the repository at this point in the history
  • Loading branch information
kaizhangNV committed Oct 10, 2024
1 parent 1013d73 commit 406bc53
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 24 deletions.
73 changes: 49 additions & 24 deletions source/slang/slang-check-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace Slang
// We will defer the actual implementation of the constructor to the body visit, because
// we will have full information about each field in the struct during that stage.
void _synthesizeCtorSignature(StructDecl* structDecl);
void _searchMembersWithHigherVisibility(StructDecl* structDecl, const DeclVisibility ctorVisibility, List<VarDeclBase*>& resultMembers);
bool _searchMembersWithHigherVisibility(StructDecl* structDecl, const DeclVisibility ctorVisibility, List<VarDeclBase*>& resultMembers);
};

struct SemanticsDeclHeaderVisitor
Expand Down Expand Up @@ -170,8 +170,6 @@ namespace Slang

void cloneModifiers(Decl* dest, Decl* src);
void setFuncTypeIntoRequirementDecl(CallableDecl* decl, FuncType* funcType);

bool m_checkForSynthesizedCtor = false;
};

struct SemanticsDeclRedeclarationVisitor
Expand Down Expand Up @@ -2099,6 +2097,22 @@ namespace Slang
return ctorList;
}

template<typename VisitorType>
static void checkSynthesizedConstructorWithoutDiagnostic(VisitorType& subVisitor, Decl* decl)
{
subVisitor.dispatch(decl);
auto tempSink = subVisitor.getSink();
if (tempSink->getErrorCount() > 0)
{
auto structDecl = as<StructDecl>(decl->parentDecl);
structDecl->members.remove(decl);
structDecl->invalidateMemberDictionary();
structDecl->buildMemberDictionary();
structDecl->m_synthesizedCtorMap.remove((int)ConstructorDecl::ConstructorTags::MemberInitCtor);
}
return;
}

void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl)
{
// As described above in `SemanticsDeclHeaderVisitor::checkVarDeclCommon`,
Expand Down Expand Up @@ -7639,6 +7653,22 @@ namespace Slang

void SemanticsDeclBodyVisitor::visitFunctionDeclBase(FunctionDeclBase* decl)
{
if (auto constructorDecl = as<ConstructorDecl>(decl))
{
// When checking the synthesized constructor, it's possible to hit error, but we don't want to
// report this error, because this function is not created by user. Instead, when we detect this
// error, we will remove this synthesized constructor from the struct.
if (constructorDecl->containsTag(ConstructorDecl::ConstructorTags::MemberInitCtor) && !m_checkForSynthesizedCtor)
{
DiagnosticSink tempSink;
SemanticsContext subContext = withSink(&tempSink);
subContext.setCheckForSynthesizedCtor(true);
SemanticsDeclBodyVisitor subVisitor(subContext);
checkSynthesizedConstructorWithoutDiagnostic(subVisitor, decl);
return;
}
}

auto newContext = registerDifferentiableTypesForFunc(decl);
if (const auto body = decl->body)
{
Expand Down Expand Up @@ -8748,9 +8778,7 @@ namespace Slang
SLANG_ABORT_COMPILATION(msg.produceString().begin());
}
}

MemberExpr* memberExpr = createMemberExpr(thisExpr, ctor->ownedScope, member);

auto assign = m_astBuilder->create<AssignExpr>();
assign->left = memberExpr;
assign->right = initExpr;
Expand Down Expand Up @@ -9373,18 +9401,9 @@ namespace Slang
{
DiagnosticSink tempSink;
SemanticsContext subContext = withSink(&tempSink);
subContext.setCheckForSynthesizedCtor(true);
SemanticsDeclHeaderVisitor subVisitor(subContext);
subVisitor.m_checkForSynthesizedCtor = true;
subVisitor.dispatch(decl);

if (tempSink.getErrorCount() > 0)
{
auto structDecl = as<StructDecl>(decl->parentDecl);
structDecl->members.remove(decl);
structDecl->invalidateMemberDictionary();
structDecl->buildMemberDictionary();
structDecl->m_synthesizedCtorMap.remove((int)ConstructorDecl::ConstructorTags::MemberInitCtor);
}
checkSynthesizedConstructorWithoutDiagnostic(subVisitor, decl);
return;
}

Expand Down Expand Up @@ -11327,7 +11346,7 @@ namespace Slang
this, funcDecl, attr, DeclAssociationKind::PrimalSubstituteFunc);
}

void SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility(StructDecl* structDecl, const DeclVisibility ctorVisibility, List<VarDeclBase*>& resultMembers)
bool SemanticsDeclAttributesVisitor::_searchMembersWithHigherVisibility(StructDecl* structDecl, const DeclVisibility ctorVisibility, List<VarDeclBase*>& resultMembers)
{
auto findMembers = [&](StructDecl* structDecl)
{
Expand Down Expand Up @@ -11368,6 +11387,7 @@ namespace Slang

// Find the struct's members
findMembers(structDecl);
return (resultMembers.getCount() > 0);
}

// If a struct's member has:
Expand Down Expand Up @@ -11413,17 +11433,13 @@ namespace Slang
// Only the members whose visibility level is higher or equal than the
// constructor's visibility level will appear in the constructor's parameter list.
List<VarDeclBase*> resultMembers;
_searchMembersWithHigherVisibility(structDecl, ctorVisibility, resultMembers);

// If there is no members or none of members are visible, then don't bother to synthesize the member initialize constructor.
if (resultMembers.getCount() == 0)
if(!_searchMembersWithHigherVisibility(structDecl, ctorVisibility, resultMembers))
return;

// synthesize the constructor signature:
// 1. The constructor's name is always `$init`, we create one without parameters now.
ConstructorDecl* ctor = _createCtor(this, getASTBuilder(), structDecl);
ctor->addTag(ConstructorDecl::ConstructorTags::MemberInitCtor);
addVisibilityModifier(getASTBuilder(), ctor, ctorVisibility);
structDecl->m_synthesizedCtorMap.addIfNotExists((int)ConstructorDecl::ConstructorTags::MemberInitCtor, ctor);

ctor->members.reserve(resultMembers.getCount());
Expand All @@ -11446,11 +11462,20 @@ namespace Slang
ctorParam->nameAndLoc = NameLoc(member->getName(), ctor->loc);
ctorParam->loc = ctor->loc;
ctor->members.add(ctorParam);

// We need to ensure member is `no_diff` if it cannot be differentiated, `ctor` modifiers do not matter
// in this case since member-wise ctor is always differentiable or "treat as differentiable".
if (!isTypeDifferentiable(member->getType()) || member->hasModifier<NoDiffModifier>())
{
auto noDiffMod = m_astBuilder->create<NoDiffModifier>();
noDiffMod->loc = ctorParam->loc;
addModifier(ctorParam, noDiffMod);
}
}
ctor->members.reverse();

// 3. Add the modifiers, there is some special handling for the synthesized constructor that requires
// us to add some modifiers.
// 3. Add the necessary modifiers
addVisibilityModifier(getASTBuilder(), ctor, ctorVisibility);
}

void SemanticsDeclAttributesVisitor::visitStructDecl(StructDecl* structDecl)
Expand Down
7 changes: 7 additions & 0 deletions source/slang/slang-check-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,10 @@ namespace Slang

OrderedHashSet<Type*>* getCapturedTypePacks() { return m_capturedTypePacks; }

void setCheckForSynthesizedCtor(bool checkForSynthesizedCtor)
{
m_checkForSynthesizedCtor = checkForSynthesizedCtor;
}
private:
SharedSemanticsContext* m_shared = nullptr;

Expand Down Expand Up @@ -1107,6 +1111,9 @@ namespace Slang
ExpandExpr* m_parentExpandExpr = nullptr;

OrderedHashSet<Type*>* m_capturedTypePacks = nullptr;

// Flag to indicate whether this check is to check a synthesized constructor
bool m_checkForSynthesizedCtor = false;
};

struct OuterScopeContextRAII
Expand Down

0 comments on commit 406bc53

Please sign in to comment.