mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
rustc: Remove support for hyphens in crate names
This commit removes parser support for `extern crate "foo" as bar` as the renamed crate is now required to be an identifier. Additionally this commit enables hard errors on crate names that contain hyphens in them, they must now solely contain alphanumeric characters or underscores. If the crate name is inferred from the file name, however, the file name `foo-bar.rs` will have the crate name inferred as `foo_bar`. If a binary is being emitted it will have the name `foo-bar` and a library will have the name `libfoo_bar.rlib`. This commit is a breaking change for a number of reasons: * Old syntax is being removed. This was previously only issuing warnings. * The output for the compiler when input is received on stdin is now `rust_out` instead of `rust-out`. * The crate name for a crate in the file `foo-bar.rs` is now `foo_bar` which can affect infrastructure such as logging. [breaking-change]
This commit is contained in:
parent
36ef29abf7
commit
b24a3b8201
@ -73,24 +73,20 @@ struct CrateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
|
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
|
||||||
let say = |s: &str, warn: bool| {
|
let say = |s: &str| {
|
||||||
match (sp, sess) {
|
match (sp, sess) {
|
||||||
(_, None) => panic!("{}", s),
|
(_, None) => panic!("{}", s),
|
||||||
(Some(sp), Some(sess)) if warn => sess.span_warn(sp, s),
|
|
||||||
(Some(sp), Some(sess)) => sess.span_err(sp, s),
|
(Some(sp), Some(sess)) => sess.span_err(sp, s),
|
||||||
(None, Some(sess)) if warn => sess.warn(s),
|
|
||||||
(None, Some(sess)) => sess.err(s),
|
(None, Some(sess)) => sess.err(s),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if s.len() == 0 {
|
if s.len() == 0 {
|
||||||
say("crate name must not be empty", false);
|
say("crate name must not be empty");
|
||||||
} else if s.contains("-") {
|
|
||||||
say(&format!("crate names soon cannot contain hyphens: {}", s), true);
|
|
||||||
}
|
}
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
if c.is_alphanumeric() { continue }
|
if c.is_alphanumeric() { continue }
|
||||||
if c == '_' || c == '-' { continue }
|
if c == '_' { continue }
|
||||||
say(&format!("invalid character `{}` in crate name: `{}`", c, s), false);
|
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
|
||||||
}
|
}
|
||||||
match sess {
|
match sess {
|
||||||
Some(sess) => sess.abort_if_errors(),
|
Some(sess) => sess.abort_if_errors(),
|
||||||
@ -306,13 +302,7 @@ impl<'a> CrateReader<'a> {
|
|||||||
-> Option<ast::CrateNum> {
|
-> Option<ast::CrateNum> {
|
||||||
let mut ret = None;
|
let mut ret = None;
|
||||||
self.sess.cstore.iter_crate_data(|cnum, data| {
|
self.sess.cstore.iter_crate_data(|cnum, data| {
|
||||||
// For now we do a "fuzzy match" on crate names by considering
|
if data.name != name { return }
|
||||||
// hyphens equal to underscores. This is purely meant to be a
|
|
||||||
// transitionary feature while we deprecate the quote syntax of
|
|
||||||
// `extern crate` statements.
|
|
||||||
if data.name != name.replace("-", "_") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
match hash {
|
match hash {
|
||||||
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
|
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
|
||||||
|
@ -159,11 +159,19 @@ pub fn find_crate_name(sess: Option<&Session>,
|
|||||||
}
|
}
|
||||||
if let Input::File(ref path) = *input {
|
if let Input::File(ref path) = *input {
|
||||||
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
||||||
return validate(s.to_string(), None);
|
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()
|
"rust_out".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_link_meta(sess: &Session, krate: &ast::Crate,
|
pub fn build_link_meta(sess: &Session, krate: &ast::Crate,
|
||||||
@ -455,7 +463,11 @@ pub fn filename_for_input(sess: &Session,
|
|||||||
}
|
}
|
||||||
config::CrateTypeExecutable => {
|
config::CrateTypeExecutable => {
|
||||||
let suffix = &sess.target.target.options.exe_suffix;
|
let suffix = &sess.target.target.options.exe_suffix;
|
||||||
out_filename.with_file_name(&format!("{}{}", libname, suffix))
|
if suffix.len() == 0 {
|
||||||
|
out_filename.to_path_buf()
|
||||||
|
} else {
|
||||||
|
out_filename.with_extension(&suffix[1..])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
|||||||
// environment to ensure that the target loads the right libraries at
|
// environment to ensure that the target loads the right libraries at
|
||||||
// runtime. It would be a sad day if the *host* libraries were loaded as a
|
// runtime. It would be a sad day if the *host* libraries were loaded as a
|
||||||
// mistake.
|
// mistake.
|
||||||
let mut cmd = Command::new(&outdir.path().join("rust-out"));
|
let mut cmd = Command::new(&outdir.path().join("rust_out"));
|
||||||
let var = DynamicLibrary::envvar();
|
let var = DynamicLibrary::envvar();
|
||||||
let newpath = {
|
let newpath = {
|
||||||
let path = env::var_os(var).unwrap_or(OsString::new());
|
let path = env::var_os(var).unwrap_or(OsString::new());
|
||||||
|
@ -4977,46 +4977,19 @@ impl<'a> Parser<'a> {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// extern crate url;
|
/// extern crate foo;
|
||||||
/// extern crate foo = "bar"; //deprecated
|
/// extern crate bar as foo;
|
||||||
/// extern crate "bar" as foo;
|
|
||||||
fn parse_item_extern_crate(&mut self,
|
fn parse_item_extern_crate(&mut self,
|
||||||
lo: BytePos,
|
lo: BytePos,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
attrs: Vec<Attribute>)
|
attrs: Vec<Attribute>)
|
||||||
-> P<Item> {
|
-> P<Item> {
|
||||||
|
|
||||||
let (maybe_path, ident) = match self.token {
|
let crate_name = self.parse_ident();
|
||||||
token::Ident(..) => {
|
let (maybe_path, ident) = if self.eat_keyword(keywords::As) {
|
||||||
let crate_name = self.parse_ident();
|
(Some(crate_name.name), self.parse_ident())
|
||||||
if self.eat_keyword(keywords::As) {
|
} else {
|
||||||
(Some(crate_name.name), self.parse_ident())
|
(None, crate_name)
|
||||||
} else {
|
|
||||||
(None, crate_name)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
token::Literal(token::Str_(..), suf) |
|
|
||||||
token::Literal(token::StrRaw(..), suf) => {
|
|
||||||
let sp = self.span;
|
|
||||||
self.expect_no_suffix(sp, "extern crate name", suf);
|
|
||||||
// forgo the internal suffix check of `parse_str` to
|
|
||||||
// avoid repeats (this unwrap will always succeed due
|
|
||||||
// to the restriction of the `match`)
|
|
||||||
let (s, _, _) = self.parse_optional_str().unwrap();
|
|
||||||
self.expect_keyword(keywords::As);
|
|
||||||
let the_ident = self.parse_ident();
|
|
||||||
self.obsolete(sp, ObsoleteSyntax::ExternCrateString);
|
|
||||||
let s = token::intern(&s);
|
|
||||||
(Some(s), the_ident)
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
let span = self.span;
|
|
||||||
let token_str = self.this_token_to_string();
|
|
||||||
self.span_fatal(span,
|
|
||||||
&format!("expected extern crate name but \
|
|
||||||
found `{}`",
|
|
||||||
token_str));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.expect(&token::Semi);
|
self.expect(&token::Semi);
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
extern crate "#a" as bar; //~ ERROR: invalid character `#` in crate name: `#a`
|
|
||||||
//~^ WARNING: obsolete syntax
|
|
||||||
|
|
||||||
fn main() {}
|
|
6
src/test/run-make/output-with-hyphens/Makefile
Normal file
6
src/test/run-make/output-with-hyphens/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
-include ../tools.mk
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(RUSTC) foo-bar.rs
|
||||||
|
[ -f $(TMPDIR)/$(call BIN,foo-bar) ]
|
||||||
|
[ -f $(TMPDIR)/libfoo_bar.rlib ]
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
@ -8,7 +8,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
extern crate "" as foo; //~ ERROR: crate name must not be empty
|
#![crate_type = "lib"]
|
||||||
//~^ WARNING: obsolete syntax
|
#![crate_type = "bin"]
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user