diff options
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 |
