code: func validateConfigNulls(v cty.Value, path cty.Path) []*proto.Diagnostic {
  	var diags []*proto.Diagnostic
  	if v.IsNull() || !v.IsKnown() {
  		return diags
  	}
  
  	switch {
  	case v.Type().IsListType() || v.Type().IsSetType() || v.Type().IsTupleType():
  		it := v.ElementIterator()
  		for it.Next() {
  			kv, ev := it.Element()
  			if ev.IsNull() {
  				diags = append(diags, &proto.Diagnostic{
  					Severity:  proto.Diagnostic_ERROR,
  					Summary:   "Null value found in list",
  					Detail:    "Null values are not allowed for this attribute value.",
  					Attribute: convert.PathToAttributePath(append(path, cty.IndexStep{Key: kv})),
  				})
  				continue
  			}
  
  			d := validateConfigNulls(ev, append(path, cty.IndexStep{Key: kv}))
  			diags = convert.AppendProtoDiag(diags, d)
  		}
  
  	case v.Type().IsMapType() || v.Type().IsObjectType():
  		it := v.ElementIterator()
  		for it.Next() {
  			kv, ev := it.Element()
  			var step cty.PathStep
  			switch {
  			case v.Type().IsMapType():
  				step = cty.IndexStep{Key: kv}
  			case v.Type().IsObjectType():
  				step = cty.GetAttrStep{Name: kv.AsString()}
  			}
  			d := validateConfigNulls(ev, append(path, step))
  			diags = convert.AppendProtoDiag(diags, d)
  		}
  	}
  
  	return diags
  }
docs: // validateConfigNulls checks a config value for unsupported nulls before
  // attempting to shim the value. While null values can mostly be ignored in the
  // configuration, since they're not supported in HCL1, the case where a null
  // appears in a list-like attribute (list, set, tuple) will present a nil value
  // to helper/schema which can panic. Return an error to the user in this case,
  // indicating the attribute with the null value.