From 4b284daeb0cc3f6df0835befad4326c81abeb374 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 9 Jan 2018 13:26:42 -0800 Subject: Support nested generics fixes #362 --- source/slang/check.cpp | 84 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 30 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index e7bd6d711..57ed71cb6 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -120,6 +120,15 @@ namespace Slang auto typeRepr = TranslateTypeNodeImpl(node); return ExtractTypeFromTypeRepr(typeRepr); } + TypeExp TranslateTypeNodeForced(TypeExp const& typeExp) + { + auto typeRepr = TranslateTypeNodeImpl(typeExp.exp); + + TypeExp result; + result.exp = typeRepr; + result.type = ExtractTypeFromTypeRepr(typeRepr); + return result; + } TypeExp TranslateTypeNode(TypeExp const& typeExp) { // HACK(tfoley): It seems that in some cases we end up re-checking @@ -130,14 +139,7 @@ namespace Slang { return typeExp; } - - - auto typeRepr = TranslateTypeNodeImpl(typeExp.exp); - - TypeExp result; - result.exp = typeRepr; - result.type = ExtractTypeFromTypeRepr(typeRepr); - return result; + return TranslateTypeNodeForced(typeExp); } RefPtr getExprDeclRefType(Expr * expr) @@ -1287,6 +1289,20 @@ namespace Slang varDecl->initExpr = initExpr; } + // Fill in default substitutions for the 'subtype' part of a type constraint decl + void CheckConstraintSubType(TypeExp & typeExp) + { + if (auto sharedTypeExpr = typeExp.exp.As()) + { + if (auto declRefType = sharedTypeExpr->base->AsDeclRefType()) + { + declRefType->declRef.substitutions = createDefaultSubstitutions(getSession(), declRefType->declRef.getDecl()); + if (auto typetype = typeExp.exp->type.type.As()) + typetype->type = declRefType; + } + } + } + void CheckGenericConstraintDecl(GenericTypeConstraintDecl* decl) { // TODO: are there any other validations we can do at this point? @@ -1294,9 +1310,13 @@ namespace Slang // There probably needs to be a kind of "occurs check" to make // sure that the constraint actually applies to at least one // of the parameters of the generic. - - decl->sub = TranslateTypeNode(decl->sub); - decl->sup = TranslateTypeNode(decl->sup); + if (decl->checkState == DeclCheckState::Unchecked) + { + decl->checkState = DeclCheckState::Checked; + CheckConstraintSubType(decl->sub); + decl->sub = TranslateTypeNodeForced(decl->sub); + decl->sup = TranslateTypeNodeForced(decl->sup); + } } void checkDecl(Decl* decl) @@ -1343,6 +1363,7 @@ namespace Slang { // check the type being inherited from auto base = inheritanceDecl->base; + CheckConstraintSubType(base); base = TranslateTypeNode(base); inheritanceDecl->base = base; @@ -1677,7 +1698,7 @@ namespace Slang // An associated type requirement should be allowed // to be satisfied by any type declaration: // a typedef, a `struct`, etc. - auto checkSubTypeMember = [&](DeclRef subStructTypeDeclRef) -> bool + auto checkSubTypeMember = [&](DeclRef subStructTypeDeclRef) -> bool { EnsureDecl(subStructTypeDeclRef.getDecl()); // this is a sub type (e.g. nested struct declaration) in an aggregate type @@ -1685,10 +1706,10 @@ namespace Slang if (auto requiredTypeDeclRef = requiredMemberDeclRef.As()) { bool conformance = true; - auto inheritanceReqDeclRefs = getMembersOfType(requiredTypeDeclRef); + auto inheritanceReqDeclRefs = getMembersOfType(requiredTypeDeclRef); for (auto inheritanceReqDeclRef : inheritanceReqDeclRefs) { - auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->base.type.As(); + auto interfaceDeclRefType = inheritanceReqDeclRef.getDecl()->getSup().type.As(); SLANG_ASSERT(interfaceDeclRefType); auto interfaceDeclRef = interfaceDeclRefType->declRef.As(); SLANG_ASSERT(interfaceDeclRef); @@ -1744,20 +1765,22 @@ namespace Slang // check if the specified type satisfies the constraints defined by the associated type if (auto requiredTypeDeclRef = requiredMemberDeclRef.As()) { - auto constraintList = getMembersOfType(requiredTypeDeclRef); - if (constraintList.Count()) + auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As(); + if (!declRefType) + return false; + + if (auto genTypeParamDeclRef = declRefType->declRef.As()) { - auto declRefType = GetType(typedefDeclRef)->GetCanonicalType()->As(); - if (!declRefType) - return false; + // TODO: check generic type parameter satisfies constraints + return true; + } + - auto structTypeDeclRef = declRefType->declRef.As(); - if (!structTypeDeclRef) - return false; + auto containerDeclRef = declRefType->declRef.As(); + if (!containerDeclRef) + return false; - return checkSubTypeMember(structTypeDeclRef); - } - return true; + return checkSubTypeMember(containerDeclRef); } } // Default: just assume that thing aren't being satisfied. @@ -2496,6 +2519,7 @@ namespace Slang // TODO: This needs to bottleneck through the common variable checks para->type = CheckUsableType(para->type); + if (para->type.Equals(getSession()->getVoidType())) { if (!isRewriteMode()) @@ -6154,7 +6178,6 @@ namespace Slang return expr; expr->type = QualType(getSession()->getErrorType()); - auto lookupResult = lookUp( getSession(), this, expr->name, expr->scope); @@ -6983,16 +7006,17 @@ namespace Slang subst->genericDecl = genericDecl; subst->outer = parentSubst.genericSubstitutions; resultSubst.genericSubstitutions = subst; - + SubstitutionSet outerSubst = resultSubst; + outerSubst.genericSubstitutions = outerSubst.genericSubstitutions?outerSubst.genericSubstitutions->outer:nullptr; for( auto mm : genericDecl->Members ) { if( auto genericTypeParamDecl = mm.As() ) { - subst->args.Add(DeclRefType::Create(session, makeDeclRef(genericTypeParamDecl.Ptr()))); + subst->args.Add(DeclRefType::Create(session, DeclRef(genericTypeParamDecl.Ptr(), outerSubst))); } else if( auto genericValueParamDecl = mm.As() ) { - subst->args.Add(new GenericParamIntVal(makeDeclRef(genericValueParamDecl.Ptr()))); + subst->args.Add(new GenericParamIntVal(DeclRef(genericValueParamDecl.Ptr(), outerSubst))); } } @@ -7002,7 +7026,7 @@ namespace Slang if (auto genericTypeConstraintDecl = mm.As()) { RefPtr witness = new DeclaredSubtypeWitness(); - witness->declRef = makeDeclRef(genericTypeConstraintDecl.Ptr()); + witness->declRef = DeclRef(genericTypeConstraintDecl.Ptr(), outerSubst); witness->sub = genericTypeConstraintDecl->sub.type; witness->sup = genericTypeConstraintDecl->sup.type; subst->args.Add(witness); -- cgit v1.2.3 From 4d2086f47e25aa4545df95ddfd260c8bc5aafdb2 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 13 Jan 2018 15:17:43 -0500 Subject: Fix creation of `ThisTypeSubstitution`. `createDefaultSubstitutions` now responsible for creating a `ThisTypeSubstitution` when `decl` is an `InterfaceDecl`. This is to ensure a reference to an associated type decl from the same interface that defines the assoctype decl will get a `ThisTypeSubstitution` so that the right hand side of it can be replaced by future substitutions. --- source/slang/check.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source/slang/check.cpp') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 57ed71cb6..6c484b493 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -155,8 +155,6 @@ namespace Slang RefPtr baseExpr, SourceLoc loc) { - if (declRef.As()) - getNewThisTypeSubst(declRef); if (baseExpr) { RefPtr expr; @@ -6993,15 +6991,19 @@ namespace Slang Decl* decl, SubstitutionSet parentSubst) { + SubstitutionSet resultSubst = parentSubst; + if (auto interfaceDecl = dynamic_cast(decl)) + { + resultSubst.thisTypeSubstitution = new ThisTypeSubstitution(); + } auto dd = decl->ParentDecl; if( auto genericDecl = dynamic_cast(dd) ) { // We don't want to specialize references to anything // other than the "inner" declaration itself. if(decl != genericDecl->inner) - return parentSubst; + return resultSubst; - SubstitutionSet resultSubst = parentSubst; RefPtr subst = new GenericSubstitution(); subst->genericDecl = genericDecl; subst->outer = parentSubst.genericSubstitutions; @@ -7032,9 +7034,8 @@ namespace Slang subst->args.Add(witness); } } - return resultSubst; } - return parentSubst; + return resultSubst; } SubstitutionSet createDefaultSubstitutions( -- cgit v1.2.3