Repository: twigphp/Twig (php)

Issue:
Wrong error location when failing to load a dynamic parent
When an included template has a dynamic parent and the computed parent name is invalid, the error gets reported with the location of the `include` tag rather than the location of the broken `extends` tag.

See these 2 fiddles to compare the reported location:

- an invalid static parent reports the error properly: https://twigfiddle.com/hmgy4z
- an invalid dynamic parent reports the error in the wrong location (`main.twig:3`): https://twigfiddle.com/tu86dd

The loading of the parent template in the compiled code already provides the appropriate location: https://github.com/twigphp/Twig/blob/19f98c7298359f62a65ccf670b123e8836582394/src/Node/ModuleNode.php#L118-L125

But `getParent` catches the exception and resets that info and runs the guessing (which then finds the wrong template apparently): https://github.com/twigphp/Twig/blob/19f98c7298359f62a65ccf670b123e8836582394/src/Template.php#L101-L105

This affects Twig 1.x, 2.x and 3.x in similar ways.

The reason things work fine for static parents is that the compile template bypasses `getParent()` in this case, and so bypasses the catch block.

Pull request:
Fix template name in error for an unknown dynamic extends called from an include
Closes #3265

The code was introduced in #1529, but removing it nowadays does not break any existing test.

Review ignoring whitespace.


Patch:
diff --git a/src/Template.php b/src/Template.php
index 7b3ce816..6add7bea 100644
--- a/src/Template.php
+++ b/src/Template.php
@@ -80,23 +80,16 @@ abstract class Template
             return $this->parent;
         }
 
-        try {
-            if (!$parent = $this->doGetParent($context)) {
-                return false;
-            }
-
-            if ($parent instanceof self || $parent instanceof TemplateWrapper) {
-                return $this->parents[$parent->getSourceContext()->getName()] = $parent;
-            }
+        if (!$parent = $this->doGetParent($context)) {
+            return false;
+        }
 
-            if (!isset($this->parents[$parent])) {
-                $this->parents[$parent] = $this->loadTemplate($parent);
-            }
-        } catch (LoaderError $e) {
-            $e->setSourceContext(null);
-            $e->guess();
+        if ($parent instanceof self || $parent instanceof TemplateWrapper) {
+            return $this->parents[$parent->getSourceContext()->getName()] = $parent;
+        }
 
-            throw $e;
+        if (!isset($this->parents[$parent])) {
+            $this->parents[$parent] = $this->loadTemplate($parent);
         }
 
         return $this->parents[$parent];


Test patch:
diff --git a/tests/Fixtures/tags/inheritance/dynamic_parent_from_include.test b/tests/Fixtures/tags/inheritance/dynamic_parent_from_include.test
new file mode 100644
index 00000000..42a3d60e
--- /dev/null
+++ b/tests/Fixtures/tags/inheritance/dynamic_parent_from_include.test
@@ -0,0 +1,14 @@
+--TEST--
+"extends" tag
+--TEMPLATE--
+{{ include('included.twig') }}
+
+--TEMPLATE(included.twig)--
+
+
+
+{% extends dynamic %}
+--DATA--
+return ['dynamic' => 'unknown.twig']
+--EXCEPTION--
+Twig\Error\LoaderError: Template "unknown.twig" is not defined in "included.twig" at line 5.