pub fn find_crate_name(sess: Option<&Session>,
                       attrs: &[ast::Attribute],
                       input: &Input) -> String {
    let validate = |s: String, span: Option<Span>| {
        creader::validate_crate_name(sess, &s[..], span);
        s
    };

    // Look in attributes 100% of the time to make sure the attribute is marked
    // as used. After doing this, however, we still prioritize a crate name from
    // the command line over one found in the #[crate_name] attribute. If we
    // find both we ensure that they're the same later on as well.
    let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
                               .and_then(|at| at.value_str().map(|s| (at, s)));

    if let Some(sess) = sess {
        if let Some(ref s) = sess.opts.crate_name {
            if let Some((attr, ref name)) = attr_crate_name {
                if *s != &name[..] {
                    let msg = format!("--crate-name and #[crate_name] are \
                                       required to match, but `{}` != `{}`",
                                      s, name);
                    sess.span_err(attr.span, &msg[..]);
                }
            }
            return validate(s.clone(), None);
        }
    }

    if let Some((attr, s)) = attr_crate_name {
        return validate(s.to_string(), Some(attr.span));
    }
    if let Input::File(ref path) = *input {
        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
            if s.starts_with("-") {
                let msg = format!("crate names cannot start with a `-`, but \
                                   `{}` has a leading hyphen", s);
                if let Some(sess) = sess {
                    sess.err(&msg);
                }
            } else {
                return validate(s.replace("-", "_"), None);
            }
        }
    }

    "rust_out".to_string()
}
/*
 * Name mangling and its relationship to metadata. This is complex. Read
 * carefully.
 *
 * The semantic model of Rust linkage is, broadly, that "there's no global
 * namespace" between crates. Our aim is to preserve the illusion of this
 * model despite the fact that it's not *quite* possible to implement on
 * modern linkers. We initially didn't use system linkers at all, but have
 * been convinced of their utility.
 *
 * There are a few issues to handle:
 *
 *  - Linkers operate on a flat namespace, so we have to flatten names.
 *    We do this using the C++ namespace-mangling technique. Foo::bar
 *    symbols and such.
 *
 *  - Symbols with the same name but different types need to get different
 *    linkage-names. We do this by hashing a string-encoding of the type into
 *    a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
 *    we use SHA256) to "prevent collisions". This is not airtight but 16 hex
 *    digits on uniform probability means you're going to need 2**32 same-name
 *    symbols in the same process before you're even hitting birthday-paradox
 *    collision probability.
 *
 *  - Symbols in different crates but with same names "within" the crate need
 *    to get different linkage-names.
 *
 *  - The hash shown in the filename needs to be predictable and stable for
 *    build tooling integration. It also needs to be using a hash function
 *    which is easy to use from Python, make, etc.
 *
 * So here is what we do:
 *
 *  - Consider the package id; every crate has one (specified with crate_id
 *    attribute).  If a package id isn't provided explicitly, we infer a
 *    versionless one from the output name. The version will end up being 0.0
 *    in this case. CNAME and CVERS are taken from this package id. For
 *    example, github.com/mozilla/CNAME#CVERS.
 *
 *  - Define CMH as SHA256(crateid).
 *
 *  - Define CMH8 as the first 8 characters of CMH.
 *
 *  - Compile our crate to lib CNAME-CMH8-CVERS.so
 *
 *  - Define STH(sym) as SHA256(CMH, type_str(sym))
 *
 *  - Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
 *    name, non-name metadata, and type sense, and versioned in the way
 *    system linkers understand.
 */
Name mangling and its relationship to metadata. This is complex. Read
carefully.

The semantic model of Rust linkage is, broadly, that "there's no global
namespace" between crates. Our aim is to preserve the illusion of this
model despite the fact that it's not *quite* possible to implement on
modern linkers. We initially didn't use system linkers at all, but have
been convinced of their utility.

There are a few issues to handle.

- Linkers operate on a flat namespace, so we have to flatten names.
We do this using the C++ namespace-mangling technique. Foo::bar
symbols and such.

- Symbols with the same name but different types need to get different
linkage-names. We do this by hashing a string-encoding of the type into
a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
we use SHA256) to "prevent collisions". This is not airtight but 16 hex
digits on uniform probability means you're going to need 2**32 same-name
symbols in the same process before you're even hitting birthday-paradox
collision probability.

- Symbols in different crates but with same names "within" the crate need
to get different linkage-names.

- The hash shown in the filename needs to be predictable and stable for
build tooling integration. It also needs to be using a hash function
which is easy to use from Python, make, etc.

So here is what we do.

- Consider the package id; every crate has one (specified with crate_id
attribute).  If a package id isn't provided explicitly, we infer a
versionless one from the output name. The version will end up being 0.0
in this case. CNAME and CVERS are taken from this package id.

- Define CMH as SHA256(crateid).

- Define CMH8 as the first 8 characters of CMH.

- Compile our crate to lib CNAME-CMH8-CVERS.so



- Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
name, non-name metadata, and type sense, and versioned in the way
system linkers understand.
Name mangling and its relationship to metadata . This is complex . Read carefully . The semantic model of Rust linkage is broadly that " there ' s no global namespace " between crates . Our aim is to preserve the illusion of this model despite the fact that it ' s not * quite * possible to implement on modern linkers . We initially didn ' t use system linkers at all but have been convinced of their utility . There are a few issues to handle . - Linkers operate on a flat namespace so we have to flatten names . We do this using the C ++ namespace - mangling technique . Foo :: bar symbols and such . - Symbols with the same name but different types need to get different linkage - names . We do this by hashing a string - encoding of the type into a fixed - size ( currently 16 - byte hex ) cryptographic hash function ( CHF : we use SHA256 ) to " prevent collisions " . This is not airtight but 16 hex digits on uniform probability means you ' re going to need 2 ** 32 same - name symbols in the same process before you ' re even hitting birthday - paradox collision probability . - Symbols in different crates but with same names " within " the crate need to get different linkage - names . - The hash shown in the filename needs to be predictable and stable for build tooling integration . It also needs to be using a hash function which is easy to use from Python make etc . So here is what we do . - Consider the package id ; every crate has one ( specified with crate_id attribute ) . If a package id isn ' t provided explicitly we infer a versionless one from the output name . The version will end up being 0 . 0 in this case . CNAME and CVERS are taken from this package id . - Define CMH as SHA256 ( crateid ) . - Define CMH8 as the first 8 characters of CMH . - Compile our crate to lib CNAME - CMH8 - CVERS . so - Suffix a mangled sym with :: STH@CVERS so that it is unique in the name non - name metadata and type sense and versioned in the way system linkers understand .
pub fn find_crate_name(sess: Option<&Session>,
                       attrs: &[ast::Attribute],
                       input: &Input) -> String {
    let validate = |s: String, span: Option<Span>| {
        creader::validate_crate_name(sess, &s[..], span);
        s
    };
    // Look in attributes 100% of the time to make sure the attribute is marked
    // as used. After doing this, however, we still prioritize a crate name from
    // the command line over one found in the #[crate_name] attribute. If we
    // find both we ensure that they're the same later on as well.
    let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
                               .and_then(|at| at.value_str().map(|s| (at, s)));
    if let Some(sess) = sess {
        if let Some(ref s) = sess.opts.crate_name {
            if let Some((attr, ref name)) = attr_crate_name {
                if *s != &name[..] {
                    let msg = format!("--crate-name and #[crate_name] are \
                                       required to match, but `{}` != `{}`",
                                      s, name);
                    sess.span_err(attr.span, &msg[..]);
                }
            }
            return validate(s.clone(), None);
        }
    }
    if let Some((attr, s)) = attr_crate_name {
        return validate(s.to_string(), Some(attr.span));
    }
    if let Input::File(ref path) = *input {
        if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
            if s.starts_with("-") {
                let msg = format!("crate names cannot start with a `-`, but \
                                   `{}` has a leading hyphen", s);
                if let Some(sess) = sess {
                    sess.err(&msg);
                }
            } else {
                return validate(s.replace("-", "_"), None);
            }
        }
    }
    "rust_out".to_string()
}
pub fn find_crate_name ( sess : Option < & Session > , attrs : & [ ast :: Attribute ] , input : & Input ) -> String { let validate = | s : String , span : Option < Span > | { creader :: validate_crate_name ( sess , & s [ .. ] , span ) ; s } ; // Look in attributes 100% of the time to make sure the attribute is marked // as used. After doing this, however, we still prioritize a crate name from // the command line over one found in the #[crate_name] attribute. If we // find both we ensure that they're the same later on as well. let attr_crate_name = attrs . iter ( ) . find ( | at | at . check_name ( " " ) ) . and_then ( | at | at . value_str ( ) . map ( | s | ( at , s ) ) ) ; if let Some ( sess ) = sess { if let Some ( ref s ) = sess . opts . crate_name { if let Some ( ( attr , ref name ) ) = attr_crate_name { if * s != & name [ .. ] { let msg = format ! ( " \
 " s name ) ; sess . span_err ( attr . span , & msg [ .. ] ) ; } } return validate ( s . clone ( ) , None ) ; } } if let Some ( ( attr , s ) ) = attr_crate_name { return validate ( s . to_string ( ) , Some ( attr . span ) ) ; } if let Input :: File ( ref path ) = * input { if let Some ( s ) = path . file_stem ( ) . and_then ( | s | s . to_str ( ) ) { if s . starts_with ( " " ) { let msg = format ! ( " \
 " s ) ; if let Some ( sess ) = sess { sess . err ( & msg ) ; } } else { return validate ( s . replace ( " " , " " ) , None ) ; } } } " " . to_string ( ) }
Name mangling and its relationship to metadata.
Name mangling and its relationship to metadata .
sess
Option<&Session>
attrs
&[ast::Attribute]
input
&Input
sess
Option<&Session>
attrs
&[ast::Attribute]
input
&Input