//go:build go1.18 // +build go1.18 package hcl // This file contains additional diagnostics-related symbols that use the // Go 1.18 type parameters syntax and would therefore be incompatible with // Go 1.17 and earlier. // DiagnosticExtra attempts to retrieve an "extra value" of type T from the // given diagnostic, if either the diag.Extra field directly contains a value // of that type or the value implements DiagnosticExtraUnwrapper and directly // or indirectly returns a value of that type. // // Type T should typically be an interface type, so that code which generates // diagnostics can potentially return different implementations of the same // interface dynamically as needed. // // If a value of type T is found, returns that value and true to indicate // success. Otherwise, returns the zero value of T and false to indicate // failure. func DiagnosticExtra[T any](diag *Diagnostic) (T, bool) { extra := diag.Extra var zero T for { if ret, ok := extra.(T); ok { return ret, true } if unwrap, ok := extra.(DiagnosticExtraUnwrapper); ok { // If our "extra" implements DiagnosticExtraUnwrapper then we'll // unwrap one level and try this again. extra = unwrap.UnwrapDiagnosticExtra() } else { return zero, false } } }