You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: error_tracker.rs
    path of file: ./repos/rerun/crates/re_renderer/src/error_handling
    
    the code of the file until where you have to start completion: use ahash::HashMap;
use parking_lot::Mutex;

use crate::config::WgpuBackendType;

use super::handle_async_error;

#[cfg(not(webgpu))]
use super::wgpu_core_error::WrappedContextError;

#[cfg(webgpu)]
#[derive(Hash, PartialEq, Eq, Debug)]
pub struct WrappedContextError(pub String);

pub struct ErrorEntry {
    /// Frame index for frame on which this error was last logged.
    last_occurred_frame_index: u64,

    /// Description of the error.
    // TODO(#4507): Expecting to need this once we use this in space views. Also very useful for debugging.
    #[allow(dead_code)]
    description: String,
}

/// Keeps track of wgpu errors and de-duplicates messages across frames.
///
/// On native & webgl, what accounts for as an error duplicate is a heuristic based on wgpu-core error type.
///
/// Used to avoid spamming the user with repeating errors.
/// [`crate::RenderContext`] maintains a "top level" error tracker for all otherwise unhandled errors.
///
/// TODO(#4507): Users should be able to create their own scopes feeding into separate trackers.
#[derive(Default)]
pub struct ErrorTracker {
    pub errors: Mutex<HashMap<WrappedContextError, ErrorEntry>>,
}

impl ErrorTracker {
    /// Called by the renderer context when the last
    
    pub fn handle_error(&self, error: wgpu::Error, frame_index: u64) {
        match error {
            wgpu::Error::OutOfMemory { source: _ } => {
                re_log::error!("A wgpu operation caused out-of-memory: {error}");
            }
            wgpu::Error::Validation {
                source: _source,
                description,
            } => {
                let entry = ErrorEntry {
                    last_occurred_frame_index: frame_index,
                    description: description.clone(),
                };

                cfg_if::cfg_if! {
                    if #[cfg(webgpu)] {
                        if self.errors.lock().insert(
                            WrappedContextError(description.clone()),
                            entry
                        ).is_none() {
                            re_log::error!(
                                "WGPU error in frame {}: {}", frame_index, description
                            );
                        }
                    } else {
                        match _source.downcast::<wgpu_core::error::ContextError>() {
                            Ok(ctx_err) => {
                                if ctx_err
                                    .cause
                                    .downcast_ref::<wgpu_core::command::CommandEncoderError>()
                                    .is_some()
                                {
                                    // Actual command encoder errors never carry any meaningful
                                    // information: ignore them.
                                    return;
                                }

                                let ctx_err = WrappedContextError(ctx_err);
                                if self.errors.lock().insert(ctx_err, entry).is_none() {
                                    re_log::error!(
                                        "WGPU error in frame {}: {}", frame_index, description
                                    );
                                }
                            }
                            Err(err) => re_log::error!("Wgpu operation failed: {err}"),
                        }
                    }
                }
            }
        }
    }