Skip to content

Commit faf6d1e

Browse files
committed
Auto merge of #31065 - nrc:ident-correct, r=pnkfelix
This PR adds some minor error correction to the parser - if there is a missing ident, we recover and carry on. It also makes compilation more robust so that non-fatal errors (which is still most of them, unfortunately) in parsing do not cause us to abort compilation. The effect is that a program with a missing or incorrect ident can get all the way to type checking.
2 parents eceb96b + 43b3681 commit faf6d1e

27 files changed

+233
-163
lines changed

src/librustc/middle/cstore.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -267,24 +267,28 @@ impl InlinedItem {
267267

268268
// FIXME: find a better place for this?
269269
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
270-
let say = |s: &str| {
271-
match (sp, sess) {
272-
(_, None) => panic!("{}", s),
273-
(Some(sp), Some(sess)) => sess.span_err(sp, s),
274-
(None, Some(sess)) => sess.err(s),
270+
let mut err_count = 0;
271+
{
272+
let mut say = |s: &str| {
273+
match (sp, sess) {
274+
(_, None) => panic!("{}", s),
275+
(Some(sp), Some(sess)) => sess.span_err(sp, s),
276+
(None, Some(sess)) => sess.err(s),
277+
}
278+
err_count += 1;
279+
};
280+
if s.is_empty() {
281+
say("crate name must not be empty");
282+
}
283+
for c in s.chars() {
284+
if c.is_alphanumeric() { continue }
285+
if c == '_' { continue }
286+
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
275287
}
276-
};
277-
if s.is_empty() {
278-
say("crate name must not be empty");
279-
}
280-
for c in s.chars() {
281-
if c.is_alphanumeric() { continue }
282-
if c == '_' { continue }
283-
say(&format!("invalid character `{}` in crate name: `{}`", c, s));
284288
}
285-
match sess {
286-
Some(sess) => sess.abort_if_errors(),
287-
None => {}
289+
290+
if err_count > 0 {
291+
sess.unwrap().abort_if_errors();
288292
}
289293
}
290294

src/librustc/middle/lang_items.rs

-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ pub fn collect_language_items(session: &Session,
239239
collector.collect(krate);
240240
let LanguageItemCollector { mut items, .. } = collector;
241241
weak_lang_items::check_crate(krate, session, &mut items);
242-
session.abort_if_errors();
243242
items
244243
}
245244

src/librustc/session/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,15 @@ impl Session {
176176
pub fn abort_if_errors(&self) {
177177
self.diagnostic().abort_if_errors();
178178
}
179-
pub fn abort_if_new_errors<F>(&self, mut f: F)
180-
where F: FnMut()
179+
pub fn abort_if_new_errors<F, T>(&self, f: F) -> T
180+
where F: FnOnce() -> T
181181
{
182182
let count = self.err_count();
183-
f();
183+
let result = f();
184184
if self.err_count() > count {
185185
self.abort_if_errors();
186186
}
187+
result
187188
}
188189
pub fn span_warn(&self, sp: Span, msg: &str) {
189190
self.diagnostic().span_warn(sp, msg)

src/librustc_driver/driver.rs

+55-42
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ pub fn compile_input(sess: Session,
6969
let state = $make_state;
7070
(control.$point.callback)(state);
7171

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

471471
let mut feature_gated_cfgs = vec![];
472472
krate = time(time_passes, "configuration 1", || {
473-
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs)
473+
sess.abort_if_new_errors(|| {
474+
syntax::config::strip_unconfigured_items(sess.diagnostic(),
475+
krate,
476+
&mut feature_gated_cfgs)
477+
})
474478
});
475479

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

483487
time(time_passes, "gated macro checking", || {
484-
let features = syntax::feature_gate::check_crate_macros(sess.codemap(),
485-
&sess.parse_sess.span_diagnostic,
486-
&krate);
487-
488-
// these need to be set "early" so that expansion sees `quote` if enabled.
489-
*sess.features.borrow_mut() = features;
490-
sess.abort_if_errors();
488+
sess.abort_if_new_errors(|| {
489+
let features =
490+
syntax::feature_gate::check_crate_macros(sess.codemap(),
491+
&sess.parse_sess.span_diagnostic,
492+
&krate);
493+
494+
// these need to be set "early" so that expansion sees `quote` if enabled.
495+
*sess.features.borrow_mut() = features;
496+
});
491497
});
492498

493499

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

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

541547
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
542548
*sess.plugin_attributes.borrow_mut() = attributes.clone();
543-
}
549+
});
544550

545551
// Lint plugins are registered; now we can process command line flags.
546552
if sess.opts.describe_lints {
547553
super::describe_lints(&*sess.lint_store.borrow(), true);
548554
return None;
549555
}
550-
sess.lint_store.borrow_mut().process_command_line(sess);
551-
552-
// Abort if there are errors from lint processing or a plugin registrar.
553-
sess.abort_if_errors();
556+
sess.abort_if_new_errors(|| sess.lint_store.borrow_mut().process_command_line(sess));
554557

555558
krate = time(time_passes, "expansion", || {
556559
// 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,
594597
// much as possible (e.g. help the programmer avoid platform
595598
// specific differences)
596599
time(time_passes, "complete gated feature checking 1", || {
597-
let features = syntax::feature_gate::check_crate(sess.codemap(),
598-
&sess.parse_sess.span_diagnostic,
599-
&krate,
600-
&attributes,
601-
sess.opts.unstable_features);
602-
*sess.features.borrow_mut() = features;
603-
sess.abort_if_errors();
600+
sess.abort_if_new_errors(|| {
601+
let features = syntax::feature_gate::check_crate(sess.codemap(),
602+
&sess.parse_sess.span_diagnostic,
603+
&krate,
604+
&attributes,
605+
sess.opts.unstable_features);
606+
*sess.features.borrow_mut() = features;
607+
});
604608
});
605609

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

608612
// strip again, in case expansion added anything with a #[cfg].
609-
krate = time(time_passes, "configuration 2", || {
610-
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate, &mut feature_gated_cfgs)
611-
});
613+
krate = sess.abort_if_new_errors(|| {
614+
let krate = time(time_passes, "configuration 2", || {
615+
syntax::config::strip_unconfigured_items(sess.diagnostic(),
616+
krate,
617+
&mut feature_gated_cfgs)
618+
});
612619

613-
time(time_passes, "gated configuration checking", || {
614-
let features = sess.features.borrow();
615-
feature_gated_cfgs.sort();
616-
feature_gated_cfgs.dedup();
617-
for cfg in &feature_gated_cfgs {
618-
cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap());
619-
}
620+
time(time_passes, "gated configuration checking", || {
621+
let features = sess.features.borrow();
622+
feature_gated_cfgs.sort();
623+
feature_gated_cfgs.dedup();
624+
for cfg in &feature_gated_cfgs {
625+
cfg.check_and_emit(sess.diagnostic(), &features, sess.codemap());
626+
}
627+
});
628+
629+
krate
620630
});
621631

622632
krate = time(time_passes, "maybe building test harness", || {
@@ -639,13 +649,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
639649
// later, to make sure we've got everything (e.g. configuration
640650
// can insert new attributes via `cfg_attr`)
641651
time(time_passes, "complete gated feature checking 2", || {
642-
let features = syntax::feature_gate::check_crate(sess.codemap(),
643-
&sess.parse_sess.span_diagnostic,
644-
&krate,
645-
&attributes,
646-
sess.opts.unstable_features);
647-
*sess.features.borrow_mut() = features;
648-
sess.abort_if_errors();
652+
sess.abort_if_new_errors(|| {
653+
let features = syntax::feature_gate::check_crate(sess.codemap(),
654+
&sess.parse_sess.span_diagnostic,
655+
&krate,
656+
&attributes,
657+
sess.opts.unstable_features);
658+
*sess.features.borrow_mut() = features;
659+
});
649660
});
650661

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

714-
let lang_items = time(time_passes,
715-
"language item collection",
716-
|| middle::lang_items::collect_language_items(&sess, &hir_map));
725+
let lang_items = time(time_passes, "language item collection", || {
726+
sess.abort_if_new_errors(|| {
727+
middle::lang_items::collect_language_items(&sess, &hir_map)
728+
})
729+
});
717730

718731
let resolve::CrateMap {
719732
def_map,

src/librustc_metadata/creader.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,14 @@ impl<'a> CrateReader<'a> {
258258
metadata: &MetadataBlob) {
259259
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
260260
if crate_rustc_version != Some(rustc_version()) {
261-
span_err!(self.sess, span, E0514,
262-
"the crate `{}` has been compiled with {}, which is \
263-
incompatible with this version of rustc",
264-
name,
265-
crate_rustc_version
266-
.as_ref().map(|s|&**s)
267-
.unwrap_or("an old version of rustc")
261+
span_fatal!(self.sess, span, E0514,
262+
"the crate `{}` has been compiled with {}, which is \
263+
incompatible with this version of rustc",
264+
name,
265+
crate_rustc_version
266+
.as_ref().map(|s|&**s)
267+
.unwrap_or("an old version of rustc")
268268
);
269-
self.sess.abort_if_errors();
270269
}
271270
}
272271

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

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

561558
let registrar =

src/librustc_passes/const_fn.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ use syntax::visit::{self, Visitor, FnKind};
1818
use syntax::codemap::Span;
1919

2020
pub fn check_crate(sess: &Session, krate: &ast::Crate) {
21-
visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate);
22-
sess.abort_if_errors();
21+
sess.abort_if_new_errors(|| {
22+
visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate);
23+
});
2324
}
2425

2526
struct CheckConstFn<'a> {

src/librustc_resolve/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -3037,6 +3037,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30373037
check_ribs: bool,
30383038
record_used: bool)
30393039
-> Option<LocalDef> {
3040+
if identifier.name == special_idents::invalid.name {
3041+
return Some(LocalDef::from_def(Def::Err));
3042+
}
3043+
30403044
// First, check to see whether the name is a primitive type.
30413045
if namespace == TypeNS {
30423046
if let Some(&prim_ty) = self.primitive_type_table
@@ -4019,10 +4023,8 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session,
40194023
resolver.callback = callback;
40204024

40214025
build_reduced_graph::build_reduced_graph(&mut resolver, krate);
4022-
session.abort_if_errors();
40234026

40244027
resolve_imports::resolve_imports(&mut resolver);
4025-
session.abort_if_errors();
40264028

40274029
resolver
40284030
}

src/librustc_typeck/check/mod.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ use syntax::attr;
121121
use syntax::attr::AttrMetaMethods;
122122
use syntax::codemap::{self, Span, Spanned};
123123
use syntax::errors::DiagnosticBuilder;
124-
use syntax::parse::token::{self, InternedString};
124+
use syntax::parse::token::{self, InternedString, special_idents};
125125
use syntax::ptr::P;
126126
use syntax::util::lev_distance::find_best_match_for_name;
127127

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

2943+
if field.node == special_idents::invalid.name {
2944+
fcx.write_error(expr.id);
2945+
return;
2946+
}
2947+
29412948
if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
29422949
fcx.type_error_struct(field.span,
29432950
|actual| {
@@ -3788,8 +3795,9 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
37883795
Some((Some(ty), slice::ref_slice(item_segment), def))
37893796
}
37903797
Err(error) => {
3791-
method::report_error(fcx, span, ty,
3792-
item_name, None, error);
3798+
if item_name != special_idents::invalid.name {
3799+
method::report_error(fcx, span, ty, item_name, None, error);
3800+
}
37933801
fcx.write_error(node_id);
37943802
None
37953803
}
@@ -4221,7 +4229,9 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
42214229
}
42224230
// Check for unrepresentable discriminant values
42234231
match hint {
4224-
attr::ReprAny | attr::ReprExtern => (),
4232+
attr::ReprAny | attr::ReprExtern => {
4233+
disr_vals.push(current_disr_val);
4234+
}
42254235
attr::ReprInt(sp, ity) => {
42264236
if !disr_in_range(ccx, ity, current_disr_val) {
42274237
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>,
42314241
err.emit();
42324242
}
42334243
}
4234-
attr::ReprSimd => {
4235-
ccx.tcx.sess.bug("range_to_inttype: found ReprSimd on an enum");
4236-
}
4237-
attr::ReprPacked => {
4238-
ccx.tcx.sess.bug("range_to_inttype: found ReprPacked on an enum");
4239-
}
4244+
// Error reported elsewhere.
4245+
attr::ReprSimd | attr::ReprPacked => {}
42404246
}
4241-
disr_vals.push(current_disr_val);
42424247
}
42434248
}
42444249

0 commit comments

Comments
 (0)