Skip to content

Error correction for missing idents #31065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 26, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -267,24 +267,28 @@ impl InlinedItem {

// FIXME: find a better place for this?
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let say = |s: &str| {
match (sp, sess) {
(_, None) => panic!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
let mut err_count = 0;
{
let mut say = |s: &str| {
match (sp, sess) {
(_, None) => panic!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
}
err_count += 1;
};
if s.is_empty() {
say("crate name must not be empty");
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' { continue }
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
}
};
if s.is_empty() {
say("crate name must not be empty");
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' { continue }
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
}
match sess {
Some(sess) => sess.abort_if_errors(),
None => {}

if err_count > 0 {
sess.unwrap().abort_if_errors();
}
}

1 change: 0 additions & 1 deletion src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
@@ -239,7 +239,6 @@ pub fn collect_language_items(session: &Session,
collector.collect(krate);
let LanguageItemCollector { mut items, .. } = collector;
weak_lang_items::check_crate(krate, session, &mut items);
session.abort_if_errors();
items
}

7 changes: 4 additions & 3 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
@@ -176,14 +176,15 @@ impl Session {
pub fn abort_if_errors(&self) {
self.diagnostic().abort_if_errors();
}
pub fn abort_if_new_errors<F>(&self, mut f: F)
where F: FnMut()
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the following suggestion belonged with PR #30320, but: Can you rename fn abort_if_new_errors to make it clearer what its relationship with the callback is?

In particular, when I see an invocation like sess.abort_if_new_errors(|| { stuff ... }), especially if my main experience is with the code base prior to PR #30320, my first thought is "this will somehow abort if we've seen new errors since the last time I invoked it, and it will also call this callback as part of the aborting process."

(That is of course not what is happening at all.)

The function you have here is more like a try_and_abort_on_new_errors(|| { stuff ... }), which I admit is verbose.

Anyway I won't r- the PR even if this suggestion is ignored, but I would appreciate if you consider the idea.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and the other problem with fn try_anything is that it may imply to some that try! or Result is somehow involved, which really isn't case here. I'd be okay with fn call_and_abort_on_new_errors or something along those lines.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have another PR which removes a bunch of abort_if_new_errors calls, and plan to do more there. So, I'll do a rename, but later, if that is OK.

where F: FnOnce() -> T
{
let count = self.err_count();
f();
let result = f();
if self.err_count() > count {
self.abort_if_errors();
}
result
}
pub fn span_warn(&self, sp: Span, msg: &str) {
self.diagnostic().span_warn(sp, msg)
97 changes: 55 additions & 42 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
@@ -69,8 +69,8 @@ pub fn compile_input(sess: Session,
let state = $make_state;
(control.$point.callback)(state);

$tsess.abort_if_errors();
if control.$point.stop == Compilation::Stop {
$tsess.abort_if_errors();
return;
}
})}
@@ -470,7 +470,11 @@ pub fn phase_2_configure_and_expand(sess: &Session,

let mut feature_gated_cfgs = vec![];
krate = time(time_passes, "configuration 1", || {
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs)
sess.abort_if_new_errors(|| {
syntax::config::strip_unconfigured_items(sess.diagnostic(),
krate,
&mut feature_gated_cfgs)
})
});

*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
@@ -481,13 +485,15 @@ pub fn phase_2_configure_and_expand(sess: &Session,
});

time(time_passes, "gated macro checking", || {
let features = syntax::feature_gate::check_crate_macros(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate);

// these need to be set "early" so that expansion sees `quote` if enabled.
*sess.features.borrow_mut() = features;
sess.abort_if_errors();
sess.abort_if_new_errors(|| {
let features =
syntax::feature_gate::check_crate_macros(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate);

// these need to be set "early" so that expansion sees `quote` if enabled.
*sess.features.borrow_mut() = features;
});
});


@@ -525,7 +531,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
llvm_passes, attributes, .. } = registry;

{
sess.abort_if_new_errors(|| {
let mut ls = sess.lint_store.borrow_mut();
for pass in early_lint_passes {
ls.register_early_pass(Some(sess), true, pass);
@@ -540,17 +546,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,

*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
*sess.plugin_attributes.borrow_mut() = attributes.clone();
}
});

// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
super::describe_lints(&*sess.lint_store.borrow(), true);
return None;
}
sess.lint_store.borrow_mut().process_command_line(sess);

// Abort if there are errors from lint processing or a plugin registrar.
sess.abort_if_errors();
sess.abort_if_new_errors(|| sess.lint_store.borrow_mut().process_command_line(sess));

krate = time(time_passes, "expansion", || {
// Windows dlls do not have rpaths, so they don't know how to find their
@@ -594,29 +597,36 @@ pub fn phase_2_configure_and_expand(sess: &Session,
// much as possible (e.g. help the programmer avoid platform
// specific differences)
time(time_passes, "complete gated feature checking 1", || {
let features = syntax::feature_gate::check_crate(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate,
&attributes,
sess.opts.unstable_features);
*sess.features.borrow_mut() = features;
sess.abort_if_errors();
sess.abort_if_new_errors(|| {
let features = syntax::feature_gate::check_crate(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate,
&attributes,
sess.opts.unstable_features);
*sess.features.borrow_mut() = features;
});
});

// JBC: make CFG processing part of expansion to avoid this problem:

// strip again, in case expansion added anything with a #[cfg].
krate = time(time_passes, "configuration 2", || {
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs)
});
krate = sess.abort_if_new_errors(|| {
let krate = time(time_passes, "configuration 2", || {
syntax::config::strip_unconfigured_items(sess.diagnostic(),
krate,
&mut feature_gated_cfgs)
});

time(time_passes, "gated configuration checking", || {
let features = sess.features.borrow();
feature_gated_cfgs.sort();
feature_gated_cfgs.dedup();
for cfg in &feature_gated_cfgs {
cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap());
}
time(time_passes, "gated configuration checking", || {
let features = sess.features.borrow();
feature_gated_cfgs.sort();
feature_gated_cfgs.dedup();
for cfg in &feature_gated_cfgs {
cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap());
}
});

krate
});

krate = time(time_passes, "maybe building test harness", || {
@@ -639,13 +649,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
// later, to make sure we've got everything (e.g. configuration
// can insert new attributes via `cfg_attr`)
time(time_passes, "complete gated feature checking 2", || {
let features = syntax::feature_gate::check_crate(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate,
&attributes,
sess.opts.unstable_features);
*sess.features.borrow_mut() = features;
sess.abort_if_errors();
sess.abort_if_new_errors(|| {
let features = syntax::feature_gate::check_crate(sess.codemap(),
&sess.parse_sess.span_diagnostic,
&krate,
&attributes,
sess.opts.unstable_features);
*sess.features.borrow_mut() = features;
});
});

time(time_passes,
@@ -711,9 +722,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
"external crate/lib resolution",
|| LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));

let lang_items = time(time_passes,
"language item collection",
|| middle::lang_items::collect_language_items(&sess, &hir_map));
let lang_items = time(time_passes, "language item collection", || {
sess.abort_if_new_errors(|| {
middle::lang_items::collect_language_items(&sess, &hir_map)
})
});

let resolve::CrateMap {
def_map,
19 changes: 8 additions & 11 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
@@ -258,15 +258,14 @@ impl<'a> CrateReader<'a> {
metadata: &MetadataBlob) {
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
if crate_rustc_version != Some(rustc_version()) {
span_err!(self.sess, span, E0514,
"the crate `{}` has been compiled with {}, which is \
incompatible with this version of rustc",
name,
crate_rustc_version
.as_ref().map(|s|&**s)
.unwrap_or("an old version of rustc")
span_fatal!(self.sess, span, E0514,
"the crate `{}` has been compiled with {}, which is \
incompatible with this version of rustc",
name,
crate_rustc_version
.as_ref().map(|s|&**s)
.unwrap_or("an old version of rustc")
);
self.sess.abort_if_errors();
}
}

@@ -511,7 +510,6 @@ impl<'a> CrateReader<'a> {
}
};
let span = mk_sp(lo, p.last_span.hi);
p.abort_if_errors();

// Mark the attrs as used
for attr in &attrs {
@@ -554,8 +552,7 @@ impl<'a> CrateReader<'a> {
name,
config::host_triple(),
self.sess.opts.target_triple);
span_err!(self.sess, span, E0456, "{}", &message[..]);
self.sess.abort_if_errors();
span_fatal!(self.sess, span, E0456, "{}", &message[..]);
}

let registrar =
5 changes: 3 additions & 2 deletions src/librustc_passes/const_fn.rs
Original file line number Diff line number Diff line change
@@ -18,8 +18,9 @@ use syntax::visit::{self, Visitor, FnKind};
use syntax::codemap::Span;

pub fn check_crate(sess: &Session, krate: &ast::Crate) {
visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate);
sess.abort_if_errors();
sess.abort_if_new_errors(|| {
visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate);
});
}

struct CheckConstFn<'a> {
6 changes: 4 additions & 2 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -3037,6 +3037,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
check_ribs: bool,
record_used: bool)
-> Option<LocalDef> {
if identifier.name == special_idents::invalid.name {
return Some(LocalDef::from_def(Def::Err));
}

// First, check to see whether the name is a primitive type.
if namespace == TypeNS {
if let Some(&prim_ty) = self.primitive_type_table
@@ -4019,10 +4023,8 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session,
resolver.callback = callback;

build_reduced_graph::build_reduced_graph(&mut resolver, krate);
session.abort_if_errors();

resolve_imports::resolve_imports(&mut resolver);
session.abort_if_errors();

resolver
}
31 changes: 18 additions & 13 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{self, Span, Spanned};
use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::{self, InternedString};
use syntax::parse::token::{self, InternedString, special_idents};
use syntax::ptr::P;
use syntax::util::lev_distance::find_best_match_for_name;

@@ -2839,8 +2839,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
method_ty
}
Err(error) => {
method::report_error(fcx, method_name.span, expr_t,
method_name.node, Some(rcvr), error);
if method_name.node != special_idents::invalid.name {
method::report_error(fcx, method_name.span, expr_t,
method_name.node, Some(rcvr), error);
}
fcx.write_error(expr.id);
fcx.tcx().types.err
}
@@ -2938,6 +2940,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
None => {}
}

if field.node == special_idents::invalid.name {
fcx.write_error(expr.id);
return;
}

if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
fcx.type_error_struct(field.span,
|actual| {
@@ -3788,8 +3795,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
Some((Some(ty), slice::ref_slice(item_segment), def))
}
Err(error) => {
method::report_error(fcx, span, ty,
item_name, None, error);
if item_name != special_idents::invalid.name {
method::report_error(fcx, span, ty, item_name, None, error);
}
fcx.write_error(node_id);
None
}
@@ -4221,7 +4229,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
// Check for unrepresentable discriminant values
match hint {
attr::ReprAny | attr::ReprExtern => (),
attr::ReprAny | attr::ReprExtern => {
disr_vals.push(current_disr_val);
}
attr::ReprInt(sp, ity) => {
if !disr_in_range(ccx, ity, current_disr_val) {
let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0082,
@@ -4231,14 +4241,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
err.emit();
}
}
attr::ReprSimd => {
ccx.tcx.sess.bug("range_to_inttype: found ReprSimd on an enum");
}
attr::ReprPacked => {
ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
}
// Error reported elsewhere.
attr::ReprSimd | attr::ReprPacked => {}
}
disr_vals.push(current_disr_val);
}
}

7 changes: 5 additions & 2 deletions src/libsyntax/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -555,6 +555,9 @@ impl Handler {
pub enum Level {
Bug,
Fatal,
// An error which while not immediately fatal, should stop the compiler
// progressing beyond the current phase.
PhaseFatal,
Error,
Warning,
Note,
@@ -573,7 +576,7 @@ impl fmt::Display for Level {
impl Level {
fn color(self) -> term::color::Color {
match self {
Bug | Fatal | Error => term::color::BRIGHT_RED,
Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED,
Warning => term::color::BRIGHT_YELLOW,
Note => term::color::BRIGHT_GREEN,
Help => term::color::BRIGHT_CYAN,
@@ -584,7 +587,7 @@ impl Level {
fn to_str(self) -> &'static str {
match self {
Bug => "error: internal compiler error",
Fatal | Error => "error",
Fatal | PhaseFatal | Error => "error",
Warning => "warning",
Note => "note",
Help => "help",
7 changes: 6 additions & 1 deletion src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
@@ -1304,9 +1304,14 @@ pub fn expand_crate(mut cx: ExtCtxt,
expander.cx.syntax_env.insert(name, extension);
}

let err_count = cx.parse_sess.span_diagnostic.err_count();
let mut ret = expander.fold_crate(c);
ret.exported_macros = expander.cx.exported_macros.clone();
cx.parse_sess.span_diagnostic.abort_if_errors();

if cx.parse_sess.span_diagnostic.err_count() > err_count {
cx.parse_sess.span_diagnostic.abort_if_errors();
}

ret
};
return (ret, cx.syntax_env.names);
20 changes: 7 additions & 13 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ pub fn parse_crate_from_source_str(name: String,
cfg,
name,
source);
maybe_aborted(panictry!(p.parse_crate_mod()),p)
panictry!(p.parse_crate_mod())
}

pub fn parse_crate_attrs_from_source_str(name: String,
@@ -110,7 +110,7 @@ pub fn parse_crate_attrs_from_source_str(name: String,
cfg,
name,
source);
maybe_aborted(panictry!(p.parse_inner_attributes()), p)
panictry!(p.parse_inner_attributes())
}

pub fn parse_expr_from_source_str(name: String,
@@ -119,7 +119,7 @@ pub fn parse_expr_from_source_str(name: String,
sess: &ParseSess)
-> P<ast::Expr> {
let mut p = new_parser_from_source_str(sess, cfg, name, source);
maybe_aborted(panictry!(p.parse_expr()), p)
panictry!(p.parse_expr())
}

pub fn parse_item_from_source_str(name: String,
@@ -128,7 +128,7 @@ pub fn parse_item_from_source_str(name: String,
sess: &ParseSess)
-> Option<P<ast::Item>> {
let mut p = new_parser_from_source_str(sess, cfg, name, source);
maybe_aborted(panictry!(p.parse_item()), p)
panictry!(p.parse_item())
}

pub fn parse_meta_from_source_str(name: String,
@@ -137,7 +137,7 @@ pub fn parse_meta_from_source_str(name: String,
sess: &ParseSess)
-> P<ast::MetaItem> {
let mut p = new_parser_from_source_str(sess, cfg, name, source);
maybe_aborted(panictry!(p.parse_meta_item()), p)
panictry!(p.parse_meta_item())
}

pub fn parse_stmt_from_source_str(name: String,
@@ -151,7 +151,7 @@ pub fn parse_stmt_from_source_str(name: String,
name,
source
);
maybe_aborted(panictry!(p.parse_stmt()), p)
panictry!(p.parse_stmt())
}

// Warning: This parses with quote_depth > 0, which is not the default.
@@ -168,7 +168,7 @@ pub fn parse_tts_from_source_str(name: String,
);
p.quote_depth += 1;
// right now this is re-creating the token trees from ... token trees.
maybe_aborted(panictry!(p.parse_all_token_trees()),p)
panictry!(p.parse_all_token_trees())
}

// Create a new parser from a source string
@@ -265,16 +265,10 @@ pub fn tts_to_parser<'a>(sess: &'a ParseSess,
p
}

/// Abort if necessary
pub fn maybe_aborted<T>(result: T, p: Parser) -> T {
p.abort_if_errors();
result
}

fn abort_if_errors<'a, T>(result: PResult<'a, T>, p: &Parser) -> T {
match result {
Ok(c) => {
p.abort_if_errors();
c
}
Err(mut e) => {
107 changes: 65 additions & 42 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -2355,6 +2355,59 @@ impl<'a> Parser<'a> {
)
}

// Assuming we have just parsed `.foo` (i.e., a dot and an ident), continue
// parsing into an expression.
fn parse_dot_suffix(&mut self,
ident: Ident,
ident_span: Span,
self_value: P<Expr>)
-> PResult<'a, P<Expr>> {
let (_, tys, bindings) = if self.eat(&token::ModSep) {
try!(self.expect_lt());
try!(self.parse_generic_values_after_lt())
} else {
(Vec::new(), Vec::new(), Vec::new())
};

if !bindings.is_empty() {
let last_span = self.last_span;
self.span_err(last_span, "type bindings are only permitted on trait paths");
}

let lo = self_value.span.lo;

Ok(match self.token {
// expr.f() method call.
token::OpenDelim(token::Paren) => {
let mut es = try!(self.parse_unspanned_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| Ok(try!(p.parse_expr()))
));
let hi = self.last_span.hi;

es.insert(0, self_value);
let id = spanned(ident_span.lo, ident_span.hi, ident);
let nd = self.mk_method_call(id, tys, es);
self.mk_expr(lo, hi, nd, None)
}
// Field access.
_ => {
if !tys.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
"field expressions may not \
have type parameters");
}

let id = spanned(ident_span.lo, ident_span.hi, ident);
let field = self.mk_field(self_value, id);
self.mk_expr(lo, ident_span.hi, field, None)
}
})
}

fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>) -> PResult<'a, P<Expr>> {
let mut e = e0;
let lo = e.span.lo;
@@ -2364,50 +2417,11 @@ impl<'a> Parser<'a> {
if self.eat(&token::Dot) {
match self.token {
token::Ident(i, _) => {
let dot = self.last_span.hi;
let dot_pos = self.last_span.hi;
hi = self.span.hi;
self.bump();
let (_, tys, bindings) = if self.eat(&token::ModSep) {
try!(self.expect_lt());
try!(self.parse_generic_values_after_lt())
} else {
(Vec::new(), Vec::new(), Vec::new())
};

if !bindings.is_empty() {
let last_span = self.last_span;
self.span_err(last_span, "type bindings are only permitted on trait paths");
}

// expr.f() method call
match self.token {
token::OpenDelim(token::Paren) => {
let mut es = try!(self.parse_unspanned_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| Ok(try!(p.parse_expr()))
));
hi = self.last_span.hi;

es.insert(0, e);
let id = spanned(dot, hi, i);
let nd = self.mk_method_call(id, tys, es);
e = self.mk_expr(lo, hi, nd, None);
}
_ => {
if !tys.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
"field expressions may not \
have type parameters");
}

let id = spanned(dot, hi, i);
let field = self.mk_field(e, id);
e = self.mk_expr(lo, hi, field, None);
}
}
e = try!(self.parse_dot_suffix(i, mk_sp(dot_pos, hi), e));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay refactoring

}
token::Literal(token::Integer(n), suf) => {
let sp = self.span;
@@ -2452,7 +2466,16 @@ impl<'a> Parser<'a> {
self.abort_if_errors();

}
_ => return self.unexpected()
_ => {
// FIXME Could factor this out into non_fatal_unexpected or something.
let actual = self.this_token_to_string();
self.span_err(self.span, &format!("unexpected token: `{}`", actual));

let dot_pos = self.last_span.hi;
e = try!(self.parse_dot_suffix(special_idents::invalid,
mk_sp(dot_pos, dot_pos),
e));
}
}
continue;
}
2 changes: 2 additions & 0 deletions src/test/compile-fail/cfg-non-opt-expr.rs
Original file line number Diff line number Diff line change
@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(stmt_expr_attributes)]

fn main() {
let _ = #[cfg(unset)] ();
//~^ ERROR removing an expression is not supported in this position
2 changes: 1 addition & 1 deletion src/test/compile-fail/double-type-import.rs
Original file line number Diff line number Diff line change
@@ -20,5 +20,5 @@ mod foo {
}

fn main() {
let _ = foo::X;
let _ = foo::X; //~ ERROR unresolved name `foo::X`
}
1 change: 1 addition & 0 deletions src/test/compile-fail/import-from-missing.rs
Original file line number Diff line number Diff line change
@@ -16,3 +16,4 @@ mod spam {
}

fn main() { ham(); eggs(); }
//~^ ERROR unresolved name `eggs`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I'm trying to decide if I'll be annoyed by this message ("what are you talking about, I clearly tried to import it above!"), or if I will be happy that it is there.

I guess our user base should know enough to read and address the compiler error messages in order from top down...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking the same thing. I think we do want to avoid this and I plan to file an issue once this PR lands

2 changes: 1 addition & 1 deletion src/test/compile-fail/import.rs
Original file line number Diff line number Diff line change
@@ -16,4 +16,4 @@ use zed::baz;
mod zed {
pub fn bar() { println!("bar"); }
}
fn main(args: Vec<String>) { bar(); }
fn main() { bar(); }
3 changes: 2 additions & 1 deletion src/test/compile-fail/import2.rs
Original file line number Diff line number Diff line change
@@ -16,4 +16,5 @@ mod baz {}
mod zed {
pub fn bar() { println!("bar3"); }
}
fn main(args: Vec<String>) { bar(); }
fn main() { bar(); }
//~^ ERROR unresolved name `bar`
3 changes: 1 addition & 2 deletions src/test/compile-fail/macro-reexport-malformed-1.rs
Original file line number Diff line number Diff line change
@@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]
#![feature(macro_reexport)]

#[macro_reexport] //~ ERROR bad macro reexport
extern crate std;

fn main() { }
3 changes: 1 addition & 2 deletions src/test/compile-fail/macro-reexport-malformed-2.rs
Original file line number Diff line number Diff line change
@@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]
#![feature(macro_reexport)]

#[macro_reexport="foo"] //~ ERROR bad macro reexport
extern crate std;

fn main() { }
3 changes: 1 addition & 2 deletions src/test/compile-fail/macro-reexport-malformed-3.rs
Original file line number Diff line number Diff line change
@@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]
#![feature(macro_reexport)]

#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport
extern crate std;

fn main() { }
2 changes: 2 additions & 0 deletions src/test/compile-fail/macro-reexport-undef.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,8 @@

// aux-build:two_macros.rs

#![feature(macro_reexport)]

#[macro_use(macro_two)]
#[macro_reexport(no_way)] //~ ERROR reexported macro not found
extern crate two_macros;
5 changes: 2 additions & 3 deletions src/test/compile-fail/macro-use-bad-args-1.rs
Original file line number Diff line number Diff line change
@@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]

#[macro_use(foo(bar))] //~ ERROR bad macro import
extern crate std;

fn main() {
}
5 changes: 2 additions & 3 deletions src/test/compile-fail/macro-use-bad-args-2.rs
Original file line number Diff line number Diff line change
@@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![no_std]

#[macro_use(foo="bar")] //~ ERROR bad macro import
extern crate std;

fn main() {
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/parse-error-correct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2016 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.

// Test that the parser is error correcting missing idents. Despite a parsing
// error (or two), we still run type checking (and don't get extra errors there).

fn main() {
let y = 42;
let x = y.; //~ ERROR unexpected token
let x = y.(); //~ ERROR unexpected token
let x = y.foo; //~ ERROR no field
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay this is impressive. :)

}
1 change: 1 addition & 0 deletions src/test/compile-fail/privacy3.rs
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ fn test1() {
use bar::gpriv;
//~^ ERROR unresolved import `bar::gpriv`. There is no `gpriv` in `bar`
gpriv();
//~^ ERROR unresolved name `gpriv`
}

#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
1 change: 1 addition & 0 deletions src/test/compile-fail/self_type_keyword.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ pub fn main() {
//~^ ERROR expected identifier, found keyword `Self`
Self!() => (),
//~^ ERROR expected identifier, found keyword `Self`
//~^^ ERROR macro undefined: 'Self!'
Foo { x: Self } => (),
//~^ ERROR expected identifier, found keyword `Self`
Foo { Self } => (),
1 change: 1 addition & 0 deletions src/test/compile-fail/use-mod.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ use foo::bar::{
Bar,
self
//~^ NOTE another `self` import appears here
//~^^ ERROR a module named `bar` has already been imported in this module
};

use {self};