diff options
| author | Yong He <yonghe@outlook.com> | 2025-10-06 17:21:37 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-07 00:21:37 +0000 |
| commit | 6af3381f47e3c22e1657c0e0064fa466e8bde0f6 (patch) | |
| tree | be187939b58bd6196fb0b2e5824d5d60f312b6b3 /source/slang/slang-check-decl.cpp | |
| parent | f4449d9376f0a5c32274fd812d135f3595159bae (diff) | |
Use symbol alias instead of wrapper synthesis to implement link-time types. (#8603)
This change achieves link-time type resolution with a different
mechanism.
For `extern struct Foo : IFoo = FooImpl;`,
instead of synthesizing a wrapper type `Foo` that has a `FooImpl inner`
field and dispatches all interface method calls to `inner.method()`,
this PR completely removes this synthesis step, and instead just lower
such `extern`/`export` types as `IRSymbolAlias` instructions that is
just a reference to the type being wrapped.
Then we extend the linker logic to clone the referenced symbol instead
of the SymbolAlias insts itself during linking.
By doing so, we greatly simply the logic need to support link-time
types, and achieves higher robustness by not having to deal with many
AST synthesis scenarios.
Closes #8554.
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 586 |
1 files changed, 86 insertions, 500 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 6a4e3668f..fa31c54bd 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -2553,24 +2553,17 @@ void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl) structDecl->addTag(TypeTag::Incomplete); } - // Slang supports a convenient syntax to create a wrapper type from + // Slang supports a convenient syntax to create a link-time aliased type from // an existing type that implements a given interface. For example, // the user can write: struct FooWrapper:IFoo = Foo; - // In this case we will synthesize the FooWrapper type with an inner - // member of type `Foo`, and use it to implement all requirements of - // IFoo. - // If this is a wrapper struct, synthesize the inner member now. - if (structDecl->wrappedType.exp) - { - structDecl->wrappedType = CheckProperType(structDecl->wrappedType); - auto member = m_astBuilder->create<VarDecl>(); - member->type = structDecl->wrappedType; - member->nameAndLoc.name = getName("inner"); - member->nameAndLoc.loc = structDecl->wrappedType.exp->loc; - member->loc = member->nameAndLoc.loc; - addModifier(member, m_astBuilder->create<SynthesizedModifier>()); - structDecl->addMember(member); + // In this case we need to check the aliasedType expr. + if (structDecl->aliasedType.exp) + { + SemanticsVisitor visitor(withDeclToExcludeFromLookup(structDecl)); + structDecl->aliasedType = visitor.CheckProperType(structDecl->aliasedType); + structDecl->addTag(getTypeTags(structDecl->aliasedType)); } + checkVisibility(structDecl); } @@ -5348,16 +5341,6 @@ void SemanticsVisitor::_addMethodWitness( witnessTable->add(requiredMemberDeclRef.getDecl(), RequirementWitness(satisfyingMemberDeclRef)); } -static bool isWrapperTypeDecl(Decl* decl) -{ - if (auto aggTypeDecl = as<AggTypeDecl>(decl)) - { - if (aggTypeDecl->wrappedType) - return true; - } - return false; -} - // Is it allowed to have an interface method parameter whose direction is `reqDir`, and an // implementing method parameter whose direction is `implDir`? // @@ -5487,16 +5470,14 @@ bool SemanticsVisitor::trySynthesizeMethodRequirementWitness( // With the big picture spelled out, we can settle into // the work of constructing our synthesized method. // - bool isInWrapperType = isWrapperTypeDecl(context->parentDecl); - // First, we check that the differentiabliity of the method matches the requirement, // and we don't attempt to synthesize a method if they don't match. if (lookupResult.isValid()) { - if (!isInWrapperType && getShared()->getFuncDifferentiableLevel( - as<FunctionDeclBase>(lookupResult.item.declRef.getDecl())) < - getShared()->getFuncDifferentiableLevel( - as<FunctionDeclBase>(requiredMemberDeclRef.getDecl()))) + if (getShared()->getFuncDifferentiableLevel( + as<FunctionDeclBase>(lookupResult.item.declRef.getDecl())) < + getShared()->getFuncDifferentiableLevel( + as<FunctionDeclBase>(requiredMemberDeclRef.getDecl()))) { return false; } @@ -5524,25 +5505,7 @@ bool SemanticsVisitor::trySynthesizeMethodRequirementWitness( auto baseOverloadedExpr = m_astBuilder->create<OverloadedExpr>(); baseOverloadedExpr->name = requiredMemberDeclRef.getDecl()->getName(); - if (isInWrapperType) - { - auto aggTypeDecl = as<AggTypeDecl>(context->parentDecl); - baseOverloadedExpr->lookupResult2 = lookUpMember( - m_astBuilder, - this, - baseOverloadedExpr->name, - aggTypeDecl->wrappedType.type, - aggTypeDecl->ownedScope, - LookupMask::Default, - LookupOptions::IgnoreBaseInterfaces); - addModifier(synFuncDecl, m_astBuilder->create<ForceInlineAttribute>()); - - synFuncDecl->parentDecl = aggTypeDecl; - } - else - { - baseOverloadedExpr->lookupResult2 = lookupResult; - } + baseOverloadedExpr->lookupResult2 = lookupResult; // Non-static methods cannot implement static methods, remove them. if (requiredMemberDeclRef.getDecl()->hasModifier<HLSLStaticModifier>()) @@ -5557,24 +5520,7 @@ bool SemanticsVisitor::trySynthesizeMethodRequirementWitness( // if (synThis) { - if (isInWrapperType) - { - // If this is a wrapper type, then use the inner - // object as the actual this parameter for the redirected - // call. - auto innerExpr = m_astBuilder->create<VarExpr>(); - innerExpr->scope = synThis->scope; - innerExpr->name = getName("inner"); - baseOverloadedExpr->base = CheckExpr(innerExpr); - SemanticsDeclBodyVisitor bodyVisitor(withParentFunc(synFuncDecl)); - bodyVisitor.maybeRegisterDifferentiableType( - m_astBuilder, - baseOverloadedExpr->base->type); - } - else - { - baseOverloadedExpr->base = synThis; - } + baseOverloadedExpr->base = synThis; } @@ -5823,8 +5769,7 @@ bool SemanticsVisitor::trySynthesizeConstructorRequirementWitness( bool isDefaultInitializableType = requiredMemberDeclRef.getParent() == getASTBuilder()->getDefaultInitializableTypeInterfaceDecl(); - bool isInWrapperType = isWrapperTypeDecl(context->parentDecl); - if (!isInWrapperType && !isDefaultInitializableType && !satisfyingMemberLookupResult.isValid()) + if (!isDefaultInitializableType && !satisfyingMemberLookupResult.isValid()) { return false; } @@ -5846,53 +5791,7 @@ bool SemanticsVisitor::trySynthesizeConstructorRequirementWitness( auto seqStmt = m_astBuilder->create<SeqStmt>(); ctorDecl->body = seqStmt; - - if (isInWrapperType) - { - SemanticsDeclBodyVisitor bodyVisitor(withParentFunc(ctorDecl)); - bodyVisitor.maybeRegisterDifferentiableType(m_astBuilder, context->conformingType); - - if (auto varDecl = context->parentDecl->findFirstDirectMemberDeclOfType<VarDeclBase>()) - { - auto varExpr = m_astBuilder->create<VarExpr>(); - varExpr->scope = ctorDecl->ownedScope; - varExpr->name = varDecl->getName(); - auto checkedVarExpr = CheckTerm(varExpr); - if (!checkedVarExpr) - return false; - if (as<ErrorType>(checkedVarExpr->type.type)) - return false; - auto assign = m_astBuilder->create<AssignExpr>(); - assign->left = checkedVarExpr; - auto temp = m_astBuilder->create<InvokeExpr>(); - auto lookupResult = lookUpMember( - m_astBuilder, - this, - ctorName, - varDecl->type.type, - ctorDecl->ownedScope, - LookupMask::Function, - LookupOptions::IgnoreBaseInterfaces); - temp->functionExpr = createLookupResultExpr( - ctorName, - lookupResult, - nullptr, - context->parentDecl->loc, - nullptr); - temp->arguments.addRange(synArgs); - auto resolvedVar = ResolveInvoke(temp); - if (!resolvedVar) - return false; - assign->right = resolvedVar; - assign->type = m_astBuilder->getVoidType(); - bodyVisitor.maybeRegisterDifferentiableType(m_astBuilder, varDecl->type.type); - - auto stmt = m_astBuilder->create<ExpressionStmt>(); - stmt->expression = assign; - seqStmt->stmts.add(stmt); - } - } - else if (synArgs.getCount()) + if (synArgs.getCount()) { // The body of our synthesized method is going to try to // make a ctor call with the specified arguments (e.g., @@ -5965,12 +5864,6 @@ bool SemanticsVisitor::trySynthesizePropertyRequirementWitness( DeclRef<PropertyDecl> requiredMemberDeclRef, RefPtr<WitnessTable> witnessTable) { - if (isWrapperTypeDecl(context->parentDecl)) - return trySynthesizeWrapperTypePropertyRequirementWitness( - context, - requiredMemberDeclRef, - witnessTable); - // The situation here is that the context of an inheritance // declaration didn't provide an exact match for a required // property. E.g.: @@ -6130,244 +6023,6 @@ bool SemanticsVisitor::trySynthesizePropertyRequirementWitness( return true; } -bool SemanticsVisitor::trySynthesizeWrapperTypePropertyRequirementWitness( - ConformanceCheckingContext* context, - DeclRef<PropertyDecl> requiredMemberDeclRef, - RefPtr<WitnessTable> witnessTable) -{ - // We are synthesizing a property requirement for a wrapper type: - // - // interface IFoo { property value : int { get; set; } } - // struct Foo : IFoo = FooImpl; - // - // We need to synthesize Foo to: - // - // struct Foo : IFoo - // { - // FooImpl inner; - // property value : int { get { return inner.value; } - // set { inner.value = newValue; } - // } - // } - // - // To do so, we need to grab the witness table of FooImpl:IFoo, and create - // wrapper property in Foo that forwards the accessors to the inner object. - // - // We get started by constructing a synthesized `PropertyDecl`. - // - auto synPropertyDecl = m_astBuilder->create<PropertyDecl>(); - synPropertyDecl->parentDecl = context->parentDecl; - - // Synthesize the property name with a prefix to avoid name clashing. - // - synPropertyDecl->nameAndLoc = requiredMemberDeclRef.getDecl()->nameAndLoc; - synPropertyDecl->nameAndLoc.name = - getName(String("$syn_property_") + getText(requiredMemberDeclRef.getName())); - - // Find the witness that FooImpl : IFoo. - auto aggTypeDecl = as<AggTypeDecl>(context->parentDecl); - auto innerType = aggTypeDecl->wrappedType.type; - DeclRef<Decl> innerProperty; - auto innerWitness = tryGetSubtypeWitness(innerType, witnessTable->baseType); - if (!innerWitness) - return false; - - for (auto requiredAccessorDeclRef : - getMembersOfType<AccessorDecl>(m_astBuilder, requiredMemberDeclRef)) - { - auto innerEntry = tryLookUpRequirementWitness( - m_astBuilder, - innerWitness, - requiredAccessorDeclRef.getDecl()); - if (innerEntry.getFlavor() != RequirementWitness::Flavor::declRef) - return false; - auto innerAccessorDeclRef = as<AccessorDecl>(innerEntry.getDeclRef()); - if (!innerAccessorDeclRef) - return false; - - // The synthesized accessor will be an AST node of the same class as - // the required accessor. - // - auto synAccessorDecl = (AccessorDecl*)m_astBuilder->createByNodeType( - requiredAccessorDeclRef.getDecl()->astNodeType); - synAccessorDecl->ownedScope = m_astBuilder->create<Scope>(); - synAccessorDecl->ownedScope->containerDecl = synAccessorDecl; - synAccessorDecl->ownedScope->parent = getScope(context->parentDecl); - - // The return type should be the same as the inner object's accessor return type. - // - synAccessorDecl->returnType.type = getResultType(m_astBuilder, innerAccessorDeclRef); - - // Similarly, our synthesized accessor will have parameters matching those of the inner - // accessor. - // - List<Expr*> synArgs; - for (auto innerParamDeclRef : getParameters(m_astBuilder, innerAccessorDeclRef)) - { - auto paramType = getType(m_astBuilder, innerParamDeclRef); - - // The synthesized parameter will ahve the same name and - // type as the parameter of the requirement. - // - auto synParamDecl = m_astBuilder->create<ParamDecl>(); - synParamDecl->nameAndLoc = innerParamDeclRef.getDecl()->nameAndLoc; - synParamDecl->type.type = paramType; - - // We need to add the parameter as a child declaration of - // the accessor we are building. - // - synAccessorDecl->addMember(synParamDecl); - - // For each paramter, we will create an argument expression - // to represent it in the body of the accessor. - // - auto synArg = m_astBuilder->create<VarExpr>(); - synArg->declRef = makeDeclRef(synParamDecl); - synArg->type = paramType; - synArgs.add(synArg); - } - - // Now synthesize the body of the property accessor. - // The body of the accessor will depend on the class of the accessor - // we are synthesizing (e.g., `get` vs. `set`). - // - Stmt* synBodyStmt = nullptr; - auto propertyRef = m_astBuilder->create<MemberExpr>(); - propertyRef->scope = synAccessorDecl->ownedScope; - auto base = m_astBuilder->create<VarExpr>(); - base->scope = propertyRef->scope; - base->name = getName("inner"); - propertyRef->baseExpression = base; - innerProperty = innerAccessorDeclRef.getParent(); - propertyRef->name = requiredMemberDeclRef.getName(); - auto checkedPropertyRefExpr = CheckExpr(propertyRef); - - if (as<GetterDecl>(requiredAccessorDeclRef)) - { - auto synReturn = m_astBuilder->create<ReturnStmt>(); - synReturn->expression = checkedPropertyRefExpr; - - synBodyStmt = synReturn; - } - else if (as<SetterDecl>(requiredAccessorDeclRef)) - { - auto synAssign = m_astBuilder->create<AssignExpr>(); - synAssign->left = checkedPropertyRefExpr; - synAssign->right = synArgs[0]; - - auto synCheckedAssign = checkAssignWithCheckedOperands(synAssign); - - auto synExprStmt = m_astBuilder->create<ExpressionStmt>(); - synExprStmt->expression = synCheckedAssign; - - synBodyStmt = synExprStmt; - } - else - { - // While there are other kinds of accessors than `get` and `set`, - // those are currently only reserved for the internal use in the core module. - // We will not bother with synthesis for those cases. - // - return false; - } - - addModifier(synAccessorDecl, m_astBuilder->create<ForceInlineAttribute>()); - synAccessorDecl->body = synBodyStmt; - - synPropertyDecl->addMember(synAccessorDecl); - - // Register the synthesized accessor. - // - witnessTable->add( - requiredAccessorDeclRef.getDecl(), - RequirementWitness(makeDeclRef(synAccessorDecl))); - } - - // The type of our synthesized property will be the same as the inner property. - // - auto propertyType = getType(m_astBuilder, as<PropertyDecl>(innerProperty)); - synPropertyDecl->type.type = propertyType; - - // The visibility of synthesized decl should be the same as the inner requirement - if (innerProperty.getDecl()->findModifier<VisibilityModifier>()) - { - auto vis = getDeclVisibility(innerProperty.getDecl()); - addVisibilityModifier(synPropertyDecl, vis); - } - - context->parentDecl->addMember(synPropertyDecl); - witnessTable->add( - requiredMemberDeclRef.getDecl(), - RequirementWitness(makeDeclRef(synPropertyDecl))); - return true; -} - -bool SemanticsVisitor::trySynthesizeAssociatedTypeRequirementWitness( - ConformanceCheckingContext* context, - LookupResult const& inLookupResult, - DeclRef<AssocTypeDecl> requiredMemberDeclRef, - RefPtr<WitnessTable> witnessTable) -{ - SLANG_UNUSED(inLookupResult); - - // The only case we can synthesize for now is when the conformant type - // is a wrapper type. - if (!isWrapperTypeDecl(context->parentDecl)) - return false; - auto aggTypeDecl = as<AggTypeDecl>(context->parentDecl); - auto lookupResult = lookUpMember( - m_astBuilder, - this, - requiredMemberDeclRef.getName(), - aggTypeDecl->wrappedType.type, - aggTypeDecl->ownedScope, - LookupMask::Default, - LookupOptions::IgnoreBaseInterfaces); - if (!lookupResult.isValid() || lookupResult.isOverloaded()) - return false; - auto assocType = DeclRefType::create(m_astBuilder, lookupResult.item.declRef); - witnessTable->add(requiredMemberDeclRef.getDecl(), assocType); - for (auto typeConstraintDecl : - getMembersOfType<TypeConstraintDecl>(m_astBuilder, requiredMemberDeclRef)) - { - auto witness = tryGetSubtypeWitness(assocType, getSup(m_astBuilder, typeConstraintDecl)); - if (!witness) - return false; - witnessTable->add(typeConstraintDecl.getDecl(), witness); - } - return true; -} - -bool SemanticsVisitor::trySynthesizeAssociatedConstantRequirementWitness( - ConformanceCheckingContext* context, - LookupResult const& inLookupResult, - DeclRef<VarDeclBase> requiredMemberDeclRef, - RefPtr<WitnessTable> witnessTable) -{ - SLANG_UNUSED(inLookupResult); - - // The only case we can synthesize for now is when the conformant type - // is a wrapper type, i.e. - // struct Foo:IFoo = FooImpl; - if (!isWrapperTypeDecl(context->parentDecl)) - return false; - - // Find the witness that FooImpl : IFoo. - auto aggTypeDecl = as<AggTypeDecl>(context->parentDecl); - auto innerType = aggTypeDecl->wrappedType.type; - DeclRef<Decl> innerProperty; - auto innerWitness = tryGetSubtypeWitness(innerType, witnessTable->baseType); - if (!innerWitness) - return false; - - auto witness = - tryLookUpRequirementWitness(m_astBuilder, innerWitness, requiredMemberDeclRef.getDecl()); - if (witness.getFlavor() != RequirementWitness::Flavor::val) - return false; - witnessTable->add(requiredMemberDeclRef.getDecl(), witness.getVal()); - return true; -} - bool SemanticsVisitor::synthesizeAccessorRequirements( ConformanceCheckingContext* context, DeclRef<ContainerDecl> requiredMemberDeclRef, @@ -6609,92 +6264,12 @@ bool SemanticsVisitor::synthesizeAccessorRequirements( return true; } -bool SemanticsVisitor::trySynthesizeWrapperTypeSubscriptRequirementWitness( - ConformanceCheckingContext* context, - DeclRef<SubscriptDecl> requiredMemberDeclRef, - RefPtr<WitnessTable> witnessTable) -{ - // We are synthesizing the subscript requirement for a wrapper type: - // struct Wrapper - // { - // Inner inner; - // subscript(int index)->int { get { return inner[index]; } - // set { inner[index] = newValue; } - // } - // } - // - // // Find the witness that FooImpl : IFoo. - auto aggTypeDecl = as<AggTypeDecl>(context->parentDecl); - auto innerType = aggTypeDecl->wrappedType.type; - DeclRef<Decl> innerProperty; - auto innerWitness = tryGetSubtypeWitness(innerType, witnessTable->baseType); - if (!innerWitness) - return false; - // - List<Expr*> synArgs; - ThisExpr* synThis; - auto synSubscriptDecl = synthesizeMethodSignatureForRequirementWitness( - context, - requiredMemberDeclRef, - synArgs, - synThis); - auto declType = getType(m_astBuilder, getDefaultDeclRef(synSubscriptDecl).as<SubscriptDecl>()); - synThis->checked = true; - - // Form a `this[args...]` expression that we will use to coerce from - // in the synthesized subscript accessors. - // - DiagnosticSink tempSink(getSourceManager(), nullptr); - SemanticsVisitor subVisitor(withSink(&tempSink)); - auto base = m_astBuilder->create<VarExpr>(); - base->scope = synThis->scope; - base->name = getName("inner"); - - IndexExpr* indexExpr = m_astBuilder->create<IndexExpr>(); - indexExpr->baseExpression = base; - indexExpr->indexExprs = _Move(synArgs); - auto synBaseStorageExpr = subVisitor.CheckTerm(indexExpr); - - if (tempSink.getErrorCount() != 0) - return false; - - // Our synthesized subscript will have an accessor declaration for - // each accessor of the requirement. - // - bool canSynAccessors = synthesizeAccessorRequirements( - context, - requiredMemberDeclRef, - declType, - synBaseStorageExpr, - synSubscriptDecl, - witnessTable); - if (!canSynAccessors) - return false; - - // The visibility of synthesized decl should be the min of the parent decl and the requirement. - if (requiredMemberDeclRef.getDecl()->findModifier<VisibilityModifier>()) - { - auto requirementVisibility = getDeclVisibility(requiredMemberDeclRef.getDecl()); - auto thisVisibility = getDeclVisibility(context->parentDecl); - auto visibility = Math::Min(thisVisibility, requirementVisibility); - addVisibilityModifier(synSubscriptDecl, visibility); - } - - return true; -} - bool SemanticsVisitor::trySynthesizeSubscriptRequirementWitness( ConformanceCheckingContext* context, const LookupResult& lookupResult, DeclRef<SubscriptDecl> requiredMemberDeclRef, RefPtr<WitnessTable> witnessTable) { - if (isWrapperTypeDecl(context->parentDecl)) - return trySynthesizeWrapperTypeSubscriptRequirementWitness( - context, - requiredMemberDeclRef, - witnessTable); - // The situation here is that the context of an inheritance // declaration didn't provide an exact match for a required // subscript. E.g.: @@ -6926,21 +6501,13 @@ bool SemanticsVisitor::trySynthesizeRequirementWitness( } else { - return trySynthesizeAssociatedTypeRequirementWitness( - context, - lookupResult, - requiredAssocTypeDeclRef, - witnessTable); + return false; } } if (auto requiredConstantDeclRef = requiredMemberDeclRef.as<VarDeclBase>()) { - return trySynthesizeAssociatedConstantRequirementWitness( - context, - lookupResult, - requiredConstantDeclRef, - witnessTable); + return false; } if (auto requiredCtor = requiredMemberDeclRef.as<ConstructorDecl>()) @@ -7543,54 +7110,51 @@ bool SemanticsVisitor::findWitnessForInterfaceRequirement( // lookup results that might be usable, but not as-is. // LookupResult lookupResult; - if (!isWrapperTypeDecl(context->parentDecl)) + lookupResult = lookUpMember( + m_astBuilder, + this, + name, + subType, + nullptr, + LookupMask::Default, + LookupOptions::IgnoreBaseInterfaces); + + if (!lookupResult.isValid()) { - lookupResult = lookUpMember( - m_astBuilder, - this, - name, - subType, - nullptr, - LookupMask::Default, - LookupOptions::IgnoreBaseInterfaces); + // If we failed to look up a member with the name of the + // requirement, it may be possible that we can still synthesis the + // implementation if this is one of the known builtin requirements, + // or if the interface method contains a default impl. + // Otherwise, report diagnostic now. - if (!lookupResult.isValid()) + if (requiredMemberDeclRef.getDecl()->hasModifier<BuiltinRequirementModifier>() || + (requiredMemberDeclRef.as<GenericDecl>() && + getInner(requiredMemberDeclRef.as<GenericDecl>()) + ->hasModifier<BuiltinRequirementModifier>())) + { + } + else if ( + requiredMemberDeclRef.as<SubscriptDecl>() && + (as<ArrayExpressionType>(context->conformingType) || + as<VectorExpressionType>(context->conformingType) || + as<MatrixExpressionType>(context->conformingType))) { - // If we failed to look up a member with the name of the - // requirement, it may be possible that we can still synthesis the - // implementation if this is one of the known builtin requirements, - // or if the interface method contains a default impl. - // Otherwise, report diagnostic now. - - if (requiredMemberDeclRef.getDecl()->hasModifier<BuiltinRequirementModifier>() || - (requiredMemberDeclRef.as<GenericDecl>() && - getInner(requiredMemberDeclRef.as<GenericDecl>()) - ->hasModifier<BuiltinRequirementModifier>())) - { - } - else if ( - requiredMemberDeclRef.as<SubscriptDecl>() && - (as<ArrayExpressionType>(context->conformingType) || - as<VectorExpressionType>(context->conformingType) || - as<MatrixExpressionType>(context->conformingType))) - { - } - else if (hasDefaultImpl(requiredMemberDeclRef)) - { - } - else - { - getSink()->diagnose( - inheritanceDecl, - Diagnostics::typeDoesntImplementInterfaceRequirement, - subType, - requiredMemberDeclRef); - getSink()->diagnose( - requiredMemberDeclRef, - Diagnostics::seeDeclarationOf, - requiredMemberDeclRef); - return false; - } + } + else if (hasDefaultImpl(requiredMemberDeclRef)) + { + } + else + { + getSink()->diagnose( + inheritanceDecl, + Diagnostics::typeDoesntImplementInterfaceRequirement, + subType, + requiredMemberDeclRef); + getSink()->diagnose( + requiredMemberDeclRef, + Diagnostics::seeDeclarationOf, + requiredMemberDeclRef); + return false; } } if (lookupResult.isOverloaded()) @@ -7649,10 +7213,6 @@ bool SemanticsVisitor::findWitnessForInterfaceRequirement( // code required to handle all the conversions that might be // required on `this`. // - // Another situation that will get us here is that we are dealing with - // a wrapper type (struct Foo:IFoo=FooImpl), and we will synthesize - // wrappers that redirects the call into the inner element. - // MethodWitnessSynthesisFailureDetails failureDetails = {}; if (trySynthesizeRequirementWitness( context, @@ -8056,6 +7616,32 @@ bool SemanticsVisitor::checkConformance( // code to work. return true; } + + // If sub type is a link-time-resolved wrapper type (e.g. `extern struct Foo : IFoo = + // FooImpl;`), fill in `inheritanceDecl->witnessVal` with a Witness val that shows `FooImpl + // : IFoo`. + auto aggTypeDecl = as<AggTypeDecl>(declRef.getDecl()); + + if (aggTypeDecl && aggTypeDecl->aliasedType) + { + auto witness = tryGetSubtypeWitness(aggTypeDecl->aliasedType, superType); + if (witness) + { + inheritanceDecl->witnessVal = witness; + } + else + { + if (!as<ErrorType>(aggTypeDecl->aliasedType)) + { + getSink()->diagnose( + inheritanceDecl, + Diagnostics::typeArgumentDoesNotConformToInterface, + aggTypeDecl->aliasedType, + superType); + } + } + return witness != nullptr; + } } // Look at the type being inherited from, and validate |
