Skip to content

Commit cc2b08d

Browse files
committed
Do not abort compilation if expansion produces errors
Fix a number of uncovered deficiencies in diagnostics
1 parent 49f5106 commit cc2b08d

File tree

83 files changed

+598
-223
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+598
-223
lines changed

src/librustc_driver/driver.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,6 @@ where
997997
};
998998

999999
let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
1000-
let err_count = ecx.parse_sess.span_diagnostic.err_count();
10011000

10021001
// Expand macros now!
10031002
let krate = time(sess, "expand crate", || {
@@ -1023,9 +1022,6 @@ where
10231022
let msg = "missing fragment specifier";
10241023
sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
10251024
}
1026-
if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
1027-
ecx.parse_sess.span_diagnostic.abort_if_errors();
1028-
}
10291025
if cfg!(windows) {
10301026
env::set_var("PATH", &old_path);
10311027
}
@@ -1129,12 +1125,6 @@ where
11291125
})
11301126
})?;
11311127

1132-
// Unresolved macros might be due to mistyped `#[macro_use]`,
1133-
// so abort after checking for unknown attributes. (#49074)
1134-
if resolver.found_unresolved_macro {
1135-
sess.diagnostic().abort_if_errors();
1136-
}
1137-
11381128
// Lower ast -> hir.
11391129
// First, we need to collect the dep_graph.
11401130
let dep_graph = match future_dep_graph {

src/librustc_passes/ast_validation.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -288,25 +288,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
288288
visit::walk_ty(self, ty)
289289
}
290290

291-
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
292-
// Check if the path in this `use` is not generic, such as `use foo::bar<T>;` While this
293-
// can't happen normally thanks to the parser, a generic might sneak in if the `use` is
294-
// built using a macro.
295-
//
296-
// macro_use foo {
297-
// ($p:path) => { use $p; }
298-
// }
299-
// foo!(bar::baz<T>);
300-
use_tree.prefix.segments.iter().find(|segment| {
301-
segment.args.is_some()
302-
}).map(|segment| {
303-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
304-
"generic arguments in import path");
305-
});
306-
307-
visit::walk_use_tree(self, use_tree, id);
308-
}
309-
310291
fn visit_label(&mut self, label: &'a Label) {
311292
self.check_label(label.ident);
312293
visit::walk_label(self, label);
@@ -443,17 +424,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
443424
visit::walk_foreign_item(self, fi)
444425
}
445426

446-
fn visit_vis(&mut self, vis: &'a Visibility) {
447-
if let VisibilityKind::Restricted { ref path, .. } = vis.node {
448-
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
449-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
450-
"generic arguments in visibility path");
451-
});
452-
}
453-
454-
visit::walk_vis(self, vis)
455-
}
456-
457427
fn visit_generics(&mut self, generics: &'a Generics) {
458428
let mut seen_non_lifetime_param = false;
459429
let mut seen_default = None;

src/librustc_resolve/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,6 @@ pub struct Resolver<'a> {
15841584
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
15851585
macro_defs: FxHashMap<Mark, DefId>,
15861586
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
1587-
pub found_unresolved_macro: bool,
15881587

15891588
/// List of crate local macros that we need to warn about as being unused.
15901589
/// Right now this only includes macro_rules! macros, and macros 2.0.
@@ -1919,7 +1918,6 @@ impl<'a> Resolver<'a> {
19191918
name_already_seen: FxHashMap::default(),
19201919
potentially_unused_imports: Vec::new(),
19211920
struct_constructors: Default::default(),
1922-
found_unresolved_macro: false,
19231921
unused_macros: FxHashSet::default(),
19241922
current_type_ascription: Vec::new(),
19251923
injected_crate: None,
@@ -2032,8 +2030,10 @@ impl<'a> Resolver<'a> {
20322030
record_used_id: Option<NodeId>,
20332031
path_span: Span)
20342032
-> Option<LexicalScopeBinding<'a>> {
2035-
let record_used = record_used_id.is_some();
20362033
assert!(ns == TypeNS || ns == ValueNS);
2034+
if ident.name == keywords::Invalid.name() {
2035+
return Some(LexicalScopeBinding::Def(Def::Err));
2036+
}
20372037
if ns == TypeNS {
20382038
ident.span = if ident.name == keywords::SelfUpper.name() {
20392039
// FIXME(jseyfried) improve `Self` hygiene
@@ -2046,6 +2046,7 @@ impl<'a> Resolver<'a> {
20462046
}
20472047

20482048
// Walk backwards up the ribs in scope.
2049+
let record_used = record_used_id.is_some();
20492050
let mut module = self.graph_root;
20502051
for i in (0 .. self.ribs[ns].len()).rev() {
20512052
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {

src/librustc_resolve/macros.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,14 @@ impl<'a> base::Resolver for Resolver<'a> {
192192
};
193193

194194
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
195-
let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, true, force)?;
195+
let (def, ext) = match self.resolve_macro_to_def(path, kind, &parent_scope, true, force) {
196+
Ok((def, ext)) => (def, ext),
197+
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
198+
// Replace unresolved attributes with used inert attributes for better recovery.
199+
return Ok(Some(self.get_macro(Def::NonMacroAttr(NonMacroAttrKind::Tool))));
200+
}
201+
Err(determinacy) => return Err(determinacy),
202+
};
196203

197204
if let Def::Macro(def_id, _) = def {
198205
if after_derive {
@@ -347,7 +354,6 @@ impl<'a> Resolver<'a> {
347354
}
348355
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
349356
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
350-
self.found_unresolved_macro = true;
351357
Err(Determinacy::Determined)
352358
}
353359
PathResult::Module(..) => unreachable!(),
@@ -363,10 +369,8 @@ impl<'a> Resolver<'a> {
363369
let binding = self.early_resolve_ident_in_lexical_scope(
364370
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
365371
);
366-
match binding {
367-
Ok(..) => {}
368-
Err(Determinacy::Determined) => self.found_unresolved_macro = true,
369-
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
372+
if let Err(Determinacy::Undetermined) = binding {
373+
return Err(Determinacy::Undetermined);
370374
}
371375

372376
if trace {
@@ -868,14 +872,23 @@ impl<'a> Resolver<'a> {
868872
pub fn finalize_current_module_macro_resolutions(&mut self) {
869873
let module = self.current_module;
870874

871-
let check_consistency = |this: &mut Self, path: &[Segment], span,
872-
kind: MacroKind, initial_def, def| {
875+
let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
876+
initial_def: Option<Def>, def: Def| {
873877
if let Some(initial_def) = initial_def {
874878
if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() {
875879
// Make sure compilation does not succeed if preferred macro resolution
876880
// has changed after the macro had been expanded. In theory all such
877881
// situations should be reported as ambiguity errors, so this is a bug.
878-
span_bug!(span, "inconsistent resolution for a macro");
882+
if initial_def == Def::NonMacroAttr(NonMacroAttrKind::Custom) {
883+
// Yeah, legacy custom attributes are implemented using forced resolution
884+
// (which is a best effort error recovery tool, basically), so we can't
885+
// promise their resolution won't change later.
886+
let msg = format!("inconsistent resolution for a macro: first {}, then {}",
887+
initial_def.kind_name(), def.kind_name());
888+
this.session.span_err(span, &msg);
889+
} else {
890+
span_bug!(span, "inconsistent resolution for a macro");
891+
}
879892
}
880893
} else {
881894
// It's possible that the macro was unresolved (indeterminate) and silently

src/libsyntax/ext/base.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub use self::SyntaxExtension::*;
1212

1313
use ast::{self, Attribute, Name, PatKind, MetaItem};
1414
use attr::HasAttrs;
15-
use source_map::{self, SourceMap, Spanned, respan};
15+
use source_map::{SourceMap, Spanned, respan};
1616
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
1717
use edition::Edition;
1818
use errors::{DiagnosticBuilder, DiagnosticId};
@@ -491,7 +491,7 @@ impl DummyResult {
491491
pub fn raw_expr(sp: Span) -> P<ast::Expr> {
492492
P(ast::Expr {
493493
id: ast::DUMMY_NODE_ID,
494-
node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))),
494+
node: ast::ExprKind::Err,
495495
span: sp,
496496
attrs: ThinVec::new(),
497497
})
@@ -506,10 +506,11 @@ impl DummyResult {
506506
}
507507
}
508508

509+
/// A plain dummy type.
509510
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
510511
P(ast::Ty {
511512
id: ast::DUMMY_NODE_ID,
512-
node: ast::TyKind::Infer,
513+
node: ast::TyKind::Err,
513514
span: sp
514515
})
515516
}
@@ -806,7 +807,6 @@ pub struct ExtCtxt<'a> {
806807
pub ecfg: expand::ExpansionConfig<'a>,
807808
pub root_path: PathBuf,
808809
pub resolver: &'a mut dyn Resolver,
809-
pub resolve_err_count: usize,
810810
pub current_expansion: ExpansionData,
811811
pub expansions: FxHashMap<Span, Vec<String>>,
812812
}
@@ -821,7 +821,6 @@ impl<'a> ExtCtxt<'a> {
821821
ecfg,
822822
root_path: PathBuf::new(),
823823
resolver,
824-
resolve_err_count: 0,
825824
current_expansion: ExpansionData {
826825
mark: Mark::root(),
827826
depth: 0,

src/libsyntax/ext/expand.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
354354
// FIXME(jseyfried): Refactor out the following logic
355355
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
356356
if let Some(ext) = ext {
357-
let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
358-
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
357+
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
358+
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
359+
invoc_fragment_kind.dummy(invoc_span).unwrap()
360+
});
359361
self.collect_invocations(fragment, &[])
360362
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
361363
if !item.derive_allowed() {
@@ -441,9 +443,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
441443

442444
fn resolve_imports(&mut self) {
443445
if self.monotonic {
444-
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
445446
self.cx.resolver.resolve_imports();
446-
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
447447
}
448448
}
449449

@@ -467,11 +467,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
467467
};
468468

469469
if self.monotonic {
470-
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
471-
let mark = self.cx.current_expansion.mark;
472-
self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
473-
derives);
474-
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
470+
self.cx.resolver.visit_ast_fragment_with_placeholders(
471+
self.cx.current_expansion.mark, &fragment_with_placeholders, derives
472+
);
475473
}
476474

477475
(fragment_with_placeholders, invocations)

src/libsyntax/feature_gate.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,16 +1284,15 @@ impl<'a> Context<'a> {
12841284
return;
12851285
}
12861286
}
1287-
if name.starts_with("rustc_") {
1288-
gate_feature!(self, rustc_attrs, attr.span,
1289-
"unless otherwise specified, attributes \
1290-
with the prefix `rustc_` \
1291-
are reserved for internal compiler diagnostics");
1292-
} else if !attr::is_known(attr) {
1293-
// Only run the custom attribute lint during regular feature gate
1294-
// checking. Macro gating runs before the plugin attributes are
1295-
// registered, so we skip this in that case.
1296-
if !is_macro {
1287+
if !attr::is_known(attr) {
1288+
if name.starts_with("rustc_") {
1289+
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
1290+
are reserved for internal compiler diagnostics";
1291+
gate_feature!(self, rustc_attrs, attr.span, msg);
1292+
} else if !is_macro {
1293+
// Only run the custom attribute lint during regular feature gate
1294+
// checking. Macro gating runs before the plugin attributes are
1295+
// registered, so we skip this in that case.
12971296
let msg = format!("The attribute `{}` is currently unknown to the compiler and \
12981297
may have meaning added to it in the future", attr.path);
12991298
gate_feature!(self, custom_attribute, attr.span, &msg);

src/libsyntax_ext/deriving/default.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use deriving::generic::*;
1313
use deriving::generic::ty::*;
1414

1515
use syntax::ast::{Expr, MetaItem};
16-
use syntax::ext::base::{Annotatable, ExtCtxt};
16+
use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt};
1717
use syntax::ext::build::AstBuilder;
1818
use syntax::ptr::P;
1919
use syntax::symbol::Symbol;
@@ -79,7 +79,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
7979
span_err!(cx, trait_span, E0665,
8080
"`Default` cannot be derived for enums, only structs");
8181
// let compilation continue
82-
cx.expr_usize(trait_span, 0)
82+
DummyResult::raw_expr(trait_span)
8383
}
8484
_ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"),
8585
};

src/libsyntax_ext/format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> {
676676
"X" => "UpperHex",
677677
_ => {
678678
ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname));
679-
"Dummy"
679+
return DummyResult::raw_expr(sp);
680680
}
681681
}
682682
}
@@ -723,7 +723,7 @@ pub fn expand_format_args_nl<'cx>(
723723
sp,
724724
feature_gate::GateIssue::Language,
725725
feature_gate::EXPLAIN_FORMAT_ARGS_NL);
726-
return base::DummyResult::expr(sp);
726+
return DummyResult::expr(sp);
727727
}
728728
sp = sp.apply_mark(ecx.current_expansion.mark);
729729
match parse_args(ecx, sp, tts) {

src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@
99
// except according to those terms.
1010

1111
#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
12+
fn check() {}
13+
1214
fn main() {}

src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ macro_rules! generate_s10 {
3333
}
3434

3535
generate_s10!(concat!("nonexistent"));
36+
37+
fn main() {}

src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn print(_args: std::fmt::Arguments) {}
1414

1515
#[macro_export]
1616
macro_rules! myprint {
17-
($($arg:tt)*) => (print(format_args!($($arg)*)));
17+
($($arg:tt)*) => ($crate::print(format_args!($($arg)*)));
1818
}
1919

2020
#[macro_export]

src/test/ui/derives/derive-on-trait-item-or-impl-item.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ trait Foo {
1414
type Bar;
1515
}
1616

17+
struct Bar;
18+
1719
impl Bar {
1820
#[derive(Clone)]
1921
//~^ ERROR `derive` may only be applied to structs, enums and unions

src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | #[derive(Clone)]
55
| ^^^^^^^^^^^^^^^^
66

77
error: `derive` may only be applied to structs, enums and unions
8-
--> $DIR/derive-on-trait-item-or-impl-item.rs:18:5
8+
--> $DIR/derive-on-trait-item-or-impl-item.rs:20:5
99
|
1010
LL | #[derive(Clone)]
1111
| ^^^^^^^^^^^^^^^^

src/test/ui/did_you_mean/issue-40396.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,29 @@
99
// except according to those terms.
1010

1111
fn foo() {
12-
println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
12+
(0..13).collect<Vec<i32>>();
13+
//~^ ERROR chained comparison
14+
//~| ERROR expected value, found struct `Vec`
15+
//~| ERROR expected value, found builtin type `i32`
16+
//~| ERROR attempted to take value of method `collect`
1317
}
1418

1519
fn bar() {
16-
println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
20+
Vec<i32>::new();
21+
//~^ ERROR chained comparison
22+
//~| ERROR expected value, found struct `Vec`
23+
//~| ERROR expected value, found builtin type `i32`
24+
//~| ERROR cannot find function `new` in the crate root
1725
}
1826

1927
fn qux() {
20-
println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
28+
(0..13).collect<Vec<i32>();
2129
//~^ ERROR chained comparison
30+
//~| ERROR chained comparison
31+
//~| ERROR expected value, found struct `Vec`
32+
//~| ERROR expected value, found builtin type `i32`
33+
//~| ERROR attempted to take value of method `collect`
34+
//~| ERROR mismatched types
2235
}
2336

2437
fn main() {}

0 commit comments

Comments
 (0)