func AbsTraversalForExpr(expr Expression) (Traversal, Diagnostics) {
	type asTraversal interface {
		AsTraversal() Traversal
	}
	physExpr := UnwrapExpressionUntil(expr, func(expr Expression) bool {
		_, supported := expr.(asTraversal)
		return supported
	})
	if asT, supported := physExpr.(asTraversal); supported {
		if traversal := asT.AsTraversal(); traversal != nil {
			return traversal, nil
		}
	}
	return nil, Diagnostics{
		&Diagnostic{
			Severity: DiagError,
			Summary:  "Invalid expression",
			Detail:   "A static variable reference is required.",
			Subject:  expr.Range().Ptr(),
		},
	}
}
AbsTraversalForExpr attempts to interpret the given expression as
an absolute traversal, or returns error diagnostic(s) if that is
not possible for the given expression.

A particular Expression implementation can support this function by
offering a method called AsTraversal that takes no arguments and
returns either a valid absolute traversal or nil to indicate that
no traversal is possible. Alternatively, an implementation can support
UnwrapExpression to delegate handling of this function to a wrapped
Expression object.

In most cases the calling application is interested in the value
that results from an expression, but in rarer cases the application
needs to see the the name of the variable and subsequent
attributes/indexes itself, for example to allow users to give references
to the variables themselves rather than to their values. An implementer
of this function should at least support attribute and index steps.
package hcl