Repository: SergioBenitez/Rocket
File: core/codegen/src/syn_ext.rs (Rust)

Code before:
    }
}

type MacTyMapFn = fn(&TokenStream) -> Option<syn::Type>;

impl IdentExt for syn::Ident {
    fn prepend(&self, string: &str) -> syn::Ident {
        syn::Ident::new(&format!("{}{}", string, self.unraw()), self.span())
    }

    fn append(&self, string: &str) -> syn::Ident {
        syn::Ident::new(&format!("{}{}", self, string), self.span())
    }

    fn with_span(mut self, span: Span) -> syn::Ident {
        self.set_span(span);
        self
    }

    fn rocketized(&self) -> syn::Ident {
        self.prepend(crate::ROCKET_IDENT_PREFIX)
    }

    fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, mut f: F) -> syn::Ident {
        // Use rustc_hash because it's deterministic, whereas the DefaultHasher
        // in std is nondeterministic. This prevents problems where compiling
        // rocket twice gives a different "Strict Version Hash" leading rustc
        // to conclude it's a different version of the crate.
        use rustc_hash::FxHasher;

        let mut hasher = FxHasher::default();
        let name = self.to_string();
        name.hash(&mut hasher);
        f(&mut hasher);

        self.append(&format!("_{}", hasher.finish()))
    }
}

impl ReturnTypeExt for syn::ReturnType {
    fn ty(&self) -> Option<&syn::Type> {
        match self {
            syn::ReturnType::Default => None,
            syn::ReturnType::Type(_, ty) => Some(ty),
        }
    }
}

impl FnArgExt for syn::FnArg {
    fn typed(&self) -> Option<(&Ident, &syn::Type)> {
        match self {

Review comment (suggestion):
I don't believe this is necessarily true. [`DefaultHasher::new()`](https://doc.rust-lang.org/stable/std/collections/hash_map/struct.DefaultHasher.html) always returns a `SipHasher` with keys of `0`, so it should always hash to the same values and should thus be deterministic.

Code after:
    }
}

type MacTyMapFn = fn(&TokenStream) -> Option<syn::Type>;

impl IdentExt for syn::Ident {
    fn prepend(&self, string: &str) -> syn::Ident {
        syn::Ident::new(&format!("{}{}", string, self.unraw()), self.span())
    }

    fn append(&self, string: &str) -> syn::Ident {
        syn::Ident::new(&format!("{}{}", self, string), self.span())
    }

    fn with_span(mut self, span: Span) -> syn::Ident {
        self.set_span(span);
        self
    }

    fn rocketized(&self) -> syn::Ident {
        self.prepend(crate::ROCKET_IDENT_PREFIX)
    }

    /// Create a unqiue version of the ident `self` based on the hash of `self`,
    /// its span, the current call site, and any additional information provided
    /// by the closure `f`.
    ///
    /// Span::source_file() / line / col are not stable, but the byte span and
    /// some kind of scope identifier do appear in the `Debug` representation
    /// for `Span`. And they seem to be consistent across compilations: "#57
    /// bytes(106..117)" at the time of writing. So we use that.
    fn uniqueify_with<F: FnMut(&mut dyn Hasher)>(&self, mut f: F) -> syn::Ident {
        use std::collections::hash_map::DefaultHasher;

        let mut hasher = DefaultHasher::new();
        self.hash(&mut hasher);
        format!("{:?}", self.span()).hash(&mut hasher);
        format!("{:?}", Span::call_site()).hash(&mut hasher);
        f(&mut hasher);

        self.append(&format!("_{}", hasher.finish()))
    }
}

impl ReturnTypeExt for syn::ReturnType {
    fn ty(&self) -> Option<&syn::Type> {
        match self {
            syn::ReturnType::Default => None,
            syn::ReturnType::Type(_, ty) => Some(ty),
        }
    }