From e1c934972509f4bbd2c05affe565f91e7a1e6c16 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 13 Sep 2018 14:32:13 -0700 Subject: Add a better error message for common global generic failure (#634) A common mistake that seems to come up when using global generic type parameters: ```hlsl interface IHero { ... } type_param H : IHero; ParameterBlock gHero; ``` is to accidentally try to specialize the type parameter `H` using `H` itself as the argument (instead of some concrete type like `Batman`). The current front-end checks naively let this pass, because `H` satisfies all the requirements (it sure does declare that it implements `IHero`, which is the only requirement we have). This currently leads to downstream failure when we generate code with generic type parameters still left in the IR. This change implements a simple fix which is to: - Check when we are trying to specialize a global generic parameter using another global generic parameter, since this is currently always a mistake - Add a special-case diagnostic for the 99% case of this failure, which is specializing a type parameter to itself This fix is primarily motivated by the way generics support will initially be implemented in Falcor. --- source/slang/check.cpp | 36 ++++++++++++++++++++++++++++++++++++ source/slang/diagnostic-defs.h | 5 +++++ 2 files changed, 41 insertions(+) (limited to 'source') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 42bcfe4b5..7f91ac0c3 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -8635,6 +8635,42 @@ namespace Slang SLANG_ASSERT(argIndex < globalGenericArgs.Count()); auto globalGenericArg = globalGenericArgs[argIndex]; + // As a quick sanity check, see if the argument that is being supplied for a parameter + // is just the parameter itself, because this should always be an error: + // + if( auto argDeclRefType = globalGenericArg->As() ) + { + auto argDeclRef = argDeclRefType->declRef; + if(auto argGenericParamDeclRef = argDeclRef.As()) + { + if(argGenericParamDeclRef.getDecl() == globalGenericParam) + { + // We are trying to specialize a generic parameter using itself. + sink->diagnose(globalGenericParam, + Diagnostics::cannotSpecializeGlobalGenericToItself, + globalGenericParam->getName()); + sink->diagnose(entryPointFuncDecl, + Diagnostics::noteWhenCompilingEntryPoint, + entryPointFuncDecl->getName()); + continue; + } + else + { + // We are trying to specialize a generic parameter using a *different* + // global generic type parameter. + sink->diagnose(globalGenericParam, + Diagnostics::cannotSpecializeGlobalGenericToAnotherGenericParam, + globalGenericParam->getName(), + argGenericParamDeclRef.GetName()); + sink->diagnose(entryPointFuncDecl, + Diagnostics::noteWhenCompilingEntryPoint, + entryPointFuncDecl->getName()); + continue; + } + } + } + + // Create a substitution for this parameter/argument. RefPtr subst = new GlobalGenericParamSubstitution(); subst->paramDecl = globalGenericParam; diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h index c0c74c78e..83e82fc81 100644 --- a/source/slang/diagnostic-defs.h +++ b/source/slang/diagnostic-defs.h @@ -307,9 +307,14 @@ DIAGNOSTIC(38102, Error, accessorMustBeInsideSubscriptOrProperty, "an accessor d DIAGNOSTIC(38020, Error, mismatchEntryPointTypeArgument, "expecting $0 entry-point type arguments, provided $1.") DIAGNOSTIC(38021, Error, typeArgumentDoesNotConformToInterface, "type argument `$1` for generic parameter `$0` does not conform to interface `$1`.") +DIAGNOSTIC(38022, Error, cannotSpecializeGlobalGenericToItself, "the global type parameter '$0' cannot be specialized to itself") +DIAGNOSTIC(38023, Error, cannotSpecializeGlobalGenericToAnotherGenericParam, "the global type parameter '$0' cannot be specialized using another global type parameter ('$1')") +DIAGNOSTIC(-1, Note, noteWhenCompilingEntryPoint, "when compiling entry point '$0'") + DIAGNOSTIC(38200, Error, recursiveModuleImport, "module `$0` recursively imports itself") DIAGNOSTIC(39999, Fatal, errorInImportedModule, "error in imported module, compilation ceased.") + // 39xxx - Type layout and parameter binding. DIAGNOSTIC(39000, Error, conflictingExplicitBindingsForParameter, "conflicting explicit bindings for parameter '$0'") -- cgit v1.2.3