Skip to content

Commit

Permalink
Auto merge of #23546 - alexcrichton:hyphens, r=brson
Browse files Browse the repository at this point in the history
The compiler will now issue a warning for crates that have syntax of the form
`extern crate "foo" as bar`, but it will still continue to accept this syntax.
Additionally, the string `foo-bar` will match the crate name `foo_bar` to assist
in the transition period as well.

This patch will land hopefully in tandem with a Cargo patch that will start
translating all crate names to have underscores instead of hyphens.

cc #23533
  • Loading branch information
bors committed Mar 24, 2015
2 parents ed81038 + eb2f1d9 commit 123a754
Show file tree
Hide file tree
Showing 67 changed files with 144 additions and 145 deletions.
32 changes: 20 additions & 12 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,24 @@ struct CrateInfo {
}

pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let err = |s: &str| {
let say = |s: &str, warn: bool| {
match (sp, sess) {
(_, None) => panic!("{}", s),
(Some(sp), Some(sess)) if warn => sess.span_warn(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),
}
};
if s.len() == 0 {
err("crate name must not be empty");
} else if s.char_at(0) == '-' {
err(&format!("crate name cannot start with a hyphen: {}", s));
say("crate name must not be empty", false);
} else if s.contains("-") {
say(&format!("crate names soon cannot contain hyphens: {}", s), true);
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' || c == '-' { continue }
err(&format!("invalid character `{}` in crate name: `{}`", c, s));
say(&format!("invalid character `{}` in crate name: `{}`", c, s), false);
}
match sess {
Some(sess) => sess.abort_if_errors(),
Expand Down Expand Up @@ -153,8 +155,9 @@ impl<'a> CrateReader<'a> {
}
}

// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
// Traverses an AST, reading all the information about use'd crates and
// extern libraries necessary for later resolving, typechecking, linking,
// etc.
pub fn read_crates(&mut self, krate: &ast::Crate) {
self.process_crate(krate);
visit::walk_crate(self, krate);
Expand Down Expand Up @@ -184,11 +187,10 @@ impl<'a> CrateReader<'a> {
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
ident, path_opt);
let name = match *path_opt {
Some((ref path_str, _)) => {
let name = path_str.to_string();
validate_crate_name(Some(self.sess), &name[..],
Some(name) => {
validate_crate_name(Some(self.sess), name.as_str(),
Some(i.span));
name
name.as_str().to_string()
}
None => ident.to_string(),
};
Expand Down Expand Up @@ -304,7 +306,13 @@ impl<'a> CrateReader<'a> {
-> Option<ast::CrateNum> {
let mut ret = None;
self.sess.cstore.iter_crate_data(|cnum, data| {
if data.name != name { return }
// For now we do a "fuzzy match" on crate names by considering
// 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 {
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/save/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
let name = get_ident(item.ident);
let name = &name;
let location = match *s {
Some((ref s, _)) => s.to_string(),
Some(s) => s.to_string(),
None => name.to_string(),
};
let alias_span = self.span.span_for_last_ident(item.span);
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
ast::ItemExternCrate(ref p) => {
let path = match *p {
None => None,
Some((ref x, _)) => Some(x.to_string()),
Some(x) => Some(x.to_string()),
};
om.extern_crates.push(ExternCrate {
name: name,
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1771,8 +1771,8 @@ pub struct Item {
pub enum Item_ {
/// An`extern crate` item, with optional original crate name,
///
/// e.g. `extern crate foo` or `extern crate "foo-bar" as foo`
ItemExternCrate(Option<(InternedString, StrStyle)>),
/// e.g. `extern crate foo` or `extern crate foo_bar as foo`
ItemExternCrate(Option<Name>),
/// A `use` or `pub use` item
ItemUse(P<ViewPath>),

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ mod test {
let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[..], ex_s);

let ex_s = "extern crate \"foo\" as bar;";
let ex_s = "extern crate foo as bar;";
let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[..], ex_s);
Expand Down
6 changes: 6 additions & 0 deletions src/libsyntax/parse/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use ptr::P;
pub enum ObsoleteSyntax {
ClosureKind,
EmptyIndex,
ExternCrateString,
}

pub trait ParserObsoleteMethods {
Expand Down Expand Up @@ -56,6 +57,11 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
"write `[..]` instead",
false, // warning for now
),
ObsoleteSyntax::ExternCrateString => (
"\"crate-name\"",
"use an identifier not in quotes instead",
false, // warning for now
),
};

self.report(sp, kind, kind_str, desc, error);
Expand Down
32 changes: 12 additions & 20 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4986,37 +4986,28 @@ impl<'a> Parser<'a> {
attrs: Vec<Attribute>)
-> P<Item> {

let span = self.span;
let (maybe_path, ident) = match self.token {
token::Ident(..) => {
let the_ident = self.parse_ident();
let path = if self.eat_keyword_noexpect(keywords::As) {
// skip the ident if there is one
if self.token.is_ident() { self.bump(); }

self.span_err(span, "expected `;`, found `as`");
self.fileline_help(span,
&format!("perhaps you meant to enclose the crate name `{}` in \
a string?",
the_ident.as_str()));
None
let crate_name = self.parse_ident();
if self.eat_keyword(keywords::As) {
(Some(crate_name.name), self.parse_ident())
} else {
None
};
self.expect(&token::Semi);
(path, the_ident)
(None, crate_name)
}
},
token::Literal(token::Str_(..), suf) | token::Literal(token::StrRaw(..), suf) => {
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, style, _) = self.parse_optional_str().unwrap();
let (s, _, _) = self.parse_optional_str().unwrap();
self.expect_keyword(keywords::As);
let the_ident = self.parse_ident();
self.expect(&token::Semi);
(Some((s, style)), the_ident)
self.obsolete(sp, ObsoleteSyntax::ExternCrateString);
let s = token::intern(&s);
(Some(s), the_ident)
},
_ => {
let span = self.span;
Expand All @@ -5027,6 +5018,7 @@ impl<'a> Parser<'a> {
token_str));
}
};
self.expect(&token::Semi);

let last_span = self.last_span;
self.mk_item(lo,
Expand Down
9 changes: 7 additions & 2 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,13 @@ impl<'a> State<'a> {
ast::ItemExternCrate(ref optional_path) => {
try!(self.head(&visibility_qualified(item.vis,
"extern crate")));
if let Some((ref p, style)) = *optional_path {
try!(self.print_string(p, style));
if let Some(p) = *optional_path {
let val = token::get_name(p);
if val.contains("-") {
try!(self.print_string(&val, ast::CookedStr));
} else {
try!(self.print_name(p));
}
try!(space(&mut self.s));
try!(word(&mut self.s, "as"));
try!(space(&mut self.s));
Expand Down
6 changes: 3 additions & 3 deletions src/libsyntax/std_inject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ impl fold::Folder for StandardLibraryInjector {

// The name to use in `extern crate "name" as std;`
let actual_crate_name = match self.alt_std_name {
Some(ref s) => token::intern_and_get_ident(&s[..]),
None => token::intern_and_get_ident("std"),
Some(ref s) => token::intern(&s),
None => token::intern("std"),
};

krate.module.items.insert(0, P(ast::Item {
Expand All @@ -64,7 +64,7 @@ impl fold::Folder for StandardLibraryInjector {
attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
InternedString::new("macro_use")))),
node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))),
node: ast::ItemExternCrate(Some(actual_crate_name)),
vis: ast::Inherited,
span: DUMMY_SP
}));
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions src/test/compile-fail/bad-crate-id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
// except according to those terms.

extern crate "" as foo; //~ ERROR: crate name must not be empty
//~^ WARNING: obsolete syntax

fn main() {}
1 change: 1 addition & 0 deletions src/test/compile-fail/bad-crate-id2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
// except according to those terms.

extern crate "#a" as bar; //~ ERROR: invalid character `#` in crate name: `#a`
//~^ WARNING: obsolete syntax

fn main() {}
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-all-remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::Remote1;

impl<T> Remote1<T> for isize { }
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-bigint-param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::Remote1;

pub struct BigInt;
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-cow-no-cover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

// Test that it's not ok for U to appear uncovered

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::{Remote,Pair};

pub struct Cover<T>(T);
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-lone-type-parameter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::Remote;

impl<T> Remote for T { }
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
// except according to those terms.

// ignore-tidy-linelength
// aux-build:coherence-orphan-lib.rs
// aux-build:coherence_orphan_lib.rs

#![feature(optin_builtin_traits)]

extern crate "coherence-orphan-lib" as lib;
extern crate coherence_orphan_lib as lib;

use lib::TheTrait;

Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-overlapping-pairs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::Remote;

struct Foo;
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-pair-covered-uncovered-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
// Test that the same coverage rules apply even if the local type appears in the
// list of type parameters, not the self type.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::{Remote1, Pair};

pub struct Local<T>(T);
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/coherence-pair-covered-uncovered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:coherence-lib.rs
// aux-build:coherence_lib.rs

extern crate "coherence-lib" as lib;
extern crate coherence_lib as lib;
use lib::{Remote, Pair};

struct Local<T>(T);
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/derive-no-std-not-supported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

extern crate core;
extern crate rand;
extern crate "serialize" as rustc_serialize;
extern crate serialize as rustc_serialize;

#[derive(Rand)] //~ ERROR this trait cannot be derived
//~^ WARNING `#[derive(Rand)]` is deprecated
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-11680.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:issue-11680.rs
// aux-build:issue_11680.rs

extern crate "issue-11680" as other;
extern crate issue_11680 as other;

fn main() {
let _b = other::Foo::Bar(1);
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-12612.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:issue-12612-1.rs
// aux-build:issue_12612_1.rs

extern crate "issue-12612-1" as foo;
extern crate issue_12612_1 as foo;

use foo::bar;

Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-16725.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:issue-16725.rs
// aux-build:issue_16725.rs

extern crate "issue-16725" as foo;
extern crate issue_16725 as foo;

fn main() {
unsafe { foo::bar(); }
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-17718-const-privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:issue-17718-const-privacy.rs
// aux-build:issue_17718_const_privacy.rs

extern crate "issue-17718-const-privacy" as other;
extern crate issue_17718_const_privacy as other;

use a::B; //~ ERROR: const `B` is private
use other::{
Expand Down
Loading

0 comments on commit 123a754

Please sign in to comment.