Skip to content

Commit fff01cc

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

File tree

80 files changed

+538
-167
lines changed

Some content is hidden

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

80 files changed

+538
-167
lines changed

src/librustc_driver/driver.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,6 @@ where
987987
};
988988

989989
let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver);
990-
let err_count = ecx.parse_sess.span_diagnostic.err_count();
991990

992991
// Expand macros now!
993992
let krate = time(sess, "expand crate", || {
@@ -1013,9 +1012,6 @@ where
10131012
let msg = "missing fragment specifier";
10141013
sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
10151014
}
1016-
if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count {
1017-
ecx.parse_sess.span_diagnostic.abort_if_errors();
1018-
}
10191015
if cfg!(windows) {
10201016
env::set_var("PATH", &old_path);
10211017
}
@@ -1119,12 +1115,6 @@ where
11191115
})
11201116
})?;
11211117

1122-
// Unresolved macros might be due to mistyped `#[macro_use]`,
1123-
// so abort after checking for unknown attributes. (#49074)
1124-
if resolver.found_unresolved_macro {
1125-
sess.diagnostic().abort_if_errors();
1126-
}
1127-
11281118
// Lower ast -> hir.
11291119
// First, we need to collect the dep_graph.
11301120
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
@@ -278,25 +278,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
278278
visit::walk_ty(self, ty)
279279
}
280280

281-
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
282-
// Check if the path in this `use` is not generic, such as `use foo::bar<T>;` While this
283-
// can't happen normally thanks to the parser, a generic might sneak in if the `use` is
284-
// built using a macro.
285-
//
286-
// macro_use foo {
287-
// ($p:path) => { use $p; }
288-
// }
289-
// foo!(bar::baz<T>);
290-
use_tree.prefix.segments.iter().find(|segment| {
291-
segment.args.is_some()
292-
}).map(|segment| {
293-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
294-
"generic arguments in import path");
295-
});
296-
297-
visit::walk_use_tree(self, use_tree, id);
298-
}
299-
300281
fn visit_label(&mut self, label: &'a Label) {
301282
self.check_label(label.ident);
302283
visit::walk_label(self, label);
@@ -433,17 +414,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
433414
visit::walk_foreign_item(self, fi)
434415
}
435416

436-
fn visit_vis(&mut self, vis: &'a Visibility) {
437-
if let VisibilityKind::Restricted { ref path, .. } = vis.node {
438-
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
439-
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
440-
"generic arguments in visibility path");
441-
});
442-
}
443-
444-
visit::walk_vis(self, vis)
445-
}
446-
447417
fn visit_generics(&mut self, generics: &'a Generics) {
448418
let mut seen_non_lifetime_param = false;
449419
let mut seen_default = None;

src/librustc_resolve/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,6 @@ pub struct Resolver<'a> {
15761576
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
15771577
macro_defs: FxHashMap<Mark, DefId>,
15781578
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
1579-
pub found_unresolved_macro: bool,
15801579

15811580
/// List of crate local macros that we need to warn about as being unused.
15821581
/// Right now this only includes macro_rules! macros, and macros 2.0.
@@ -1911,7 +1910,6 @@ impl<'a> Resolver<'a> {
19111910
name_already_seen: FxHashMap::default(),
19121911
potentially_unused_imports: Vec::new(),
19131912
struct_constructors: Default::default(),
1914-
found_unresolved_macro: false,
19151913
unused_macros: FxHashSet::default(),
19161914
current_type_ascription: Vec::new(),
19171915
injected_crate: None,
@@ -2024,8 +2022,10 @@ impl<'a> Resolver<'a> {
20242022
record_used_id: Option<NodeId>,
20252023
path_span: Span)
20262024
-> Option<LexicalScopeBinding<'a>> {
2027-
let record_used = record_used_id.is_some();
20282025
assert!(ns == TypeNS || ns == ValueNS);
2026+
if ident.name == keywords::Invalid.name() {
2027+
return Some(LexicalScopeBinding::Def(Def::Err));
2028+
}
20292029
if ns == TypeNS {
20302030
ident.span = if ident.name == keywords::SelfUpper.name() {
20312031
// FIXME(jseyfried) improve `Self` hygiene
@@ -2038,6 +2038,7 @@ impl<'a> Resolver<'a> {
20382038
}
20392039

20402040
// Walk backwards up the ribs in scope.
2041+
let record_used = record_used_id.is_some();
20412042
let mut module = self.graph_root;
20422043
for i in (0 .. self.ribs[ns].len()).rev() {
20432044
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
@@ -182,7 +182,14 @@ impl<'a> base::Resolver for Resolver<'a> {
182182
};
183183

184184
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
185-
let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, true, force)?;
185+
let (def, ext) = match self.resolve_macro_to_def(path, kind, &parent_scope, true, force) {
186+
Ok((def, ext)) => (def, ext),
187+
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
188+
// Replace unresolved attributes with used inert attributes for better recovery.
189+
return Ok(Some(self.get_macro(Def::NonMacroAttr(NonMacroAttrKind::Tool))));
190+
}
191+
Err(determinacy) => return Err(determinacy),
192+
};
186193

187194
if let Def::Macro(def_id, _) = def {
188195
if after_derive {
@@ -337,7 +344,6 @@ impl<'a> Resolver<'a> {
337344
}
338345
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
339346
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
340-
self.found_unresolved_macro = true;
341347
Err(Determinacy::Determined)
342348
}
343349
PathResult::Module(..) => unreachable!(),
@@ -353,10 +359,8 @@ impl<'a> Resolver<'a> {
353359
let binding = self.early_resolve_ident_in_lexical_scope(
354360
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
355361
);
356-
match binding {
357-
Ok(..) => {}
358-
Err(Determinacy::Determined) => self.found_unresolved_macro = true,
359-
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
362+
if let Err(Determinacy::Undetermined) = binding {
363+
return Err(Determinacy::Undetermined);
360364
}
361365

362366
if trace {
@@ -858,14 +862,23 @@ impl<'a> Resolver<'a> {
858862
pub fn finalize_current_module_macro_resolutions(&mut self) {
859863
let module = self.current_module;
860864

861-
let check_consistency = |this: &mut Self, path: &[Segment], span,
862-
kind: MacroKind, initial_def, def| {
865+
let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
866+
initial_def: Option<Def>, def: Def| {
863867
if let Some(initial_def) = initial_def {
864868
if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() {
865869
// Make sure compilation does not succeed if preferred macro resolution
866870
// has changed after the macro had been expanded. In theory all such
867871
// situations should be reported as ambiguity errors, so this is a bug.
868-
span_bug!(span, "inconsistent resolution for a macro");
872+
if initial_def == Def::NonMacroAttr(NonMacroAttrKind::Custom) {
873+
// Yeah, legacy custom attributes are implemented using forced resolution
874+
// (which is a best effort error recovery tool, basically), so we can't
875+
// promise their resolution won't change later.
876+
let msg = format!("inconsistent resolution for a macro: first {}, then {}",
877+
initial_def.kind_name(), def.kind_name());
878+
this.session.span_err(span, &msg);
879+
} else {
880+
span_bug!(span, "inconsistent resolution for a macro");
881+
}
869882
}
870883
} else {
871884
// 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
@@ -2,7 +2,7 @@ pub use self::SyntaxExtension::*;
22

33
use ast::{self, Attribute, Name, PatKind, MetaItem};
44
use attr::HasAttrs;
5-
use source_map::{self, SourceMap, Spanned, respan};
5+
use source_map::{SourceMap, Spanned, respan};
66
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
77
use edition::Edition;
88
use errors::{DiagnosticBuilder, DiagnosticId};
@@ -481,7 +481,7 @@ impl DummyResult {
481481
pub fn raw_expr(sp: Span) -> P<ast::Expr> {
482482
P(ast::Expr {
483483
id: ast::DUMMY_NODE_ID,
484-
node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))),
484+
node: ast::ExprKind::Err,
485485
span: sp,
486486
attrs: ThinVec::new(),
487487
})
@@ -496,10 +496,11 @@ impl DummyResult {
496496
}
497497
}
498498

499+
/// A plain dummy type.
499500
pub fn raw_ty(sp: Span) -> P<ast::Ty> {
500501
P(ast::Ty {
501502
id: ast::DUMMY_NODE_ID,
502-
node: ast::TyKind::Infer,
503+
node: ast::TyKind::Err,
503504
span: sp
504505
})
505506
}
@@ -796,7 +797,6 @@ pub struct ExtCtxt<'a> {
796797
pub ecfg: expand::ExpansionConfig<'a>,
797798
pub root_path: PathBuf,
798799
pub resolver: &'a mut dyn Resolver,
799-
pub resolve_err_count: usize,
800800
pub current_expansion: ExpansionData,
801801
pub expansions: FxHashMap<Span, Vec<String>>,
802802
}
@@ -811,7 +811,6 @@ impl<'a> ExtCtxt<'a> {
811811
ecfg,
812812
root_path: PathBuf::new(),
813813
resolver,
814-
resolve_err_count: 0,
815814
current_expansion: ExpansionData {
816815
mark: Mark::root(),
817816
depth: 0,

src/libsyntax/ext/expand.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
344344
// FIXME(jseyfried): Refactor out the following logic
345345
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
346346
if let Some(ext) = ext {
347-
let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap();
348-
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy);
347+
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
348+
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
349+
invoc_fragment_kind.dummy(invoc_span).unwrap()
350+
});
349351
self.collect_invocations(fragment, &[])
350352
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
351353
if !item.derive_allowed() {
@@ -431,9 +433,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
431433

432434
fn resolve_imports(&mut self) {
433435
if self.monotonic {
434-
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
435436
self.cx.resolver.resolve_imports();
436-
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
437437
}
438438
}
439439

@@ -457,11 +457,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
457457
};
458458

459459
if self.monotonic {
460-
let err_count = self.cx.parse_sess.span_diagnostic.err_count();
461-
let mark = self.cx.current_expansion.mark;
462-
self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders,
463-
derives);
464-
self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
460+
self.cx.resolver.visit_ast_fragment_with_placeholders(
461+
self.cx.current_expansion.mark, &fragment_with_placeholders, derives
462+
);
465463
}
466464

467465
(fragment_with_placeholders, invocations)

src/libsyntax/feature_gate.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,16 +1272,15 @@ impl<'a> Context<'a> {
12721272
return;
12731273
}
12741274
}
1275-
if name.starts_with("rustc_") {
1276-
gate_feature!(self, rustc_attrs, attr.span,
1277-
"unless otherwise specified, attributes \
1278-
with the prefix `rustc_` \
1279-
are reserved for internal compiler diagnostics");
1280-
} else if !attr::is_known(attr) {
1281-
// Only run the custom attribute lint during regular feature gate
1282-
// checking. Macro gating runs before the plugin attributes are
1283-
// registered, so we skip this in that case.
1284-
if !is_macro {
1275+
if !attr::is_known(attr) {
1276+
if name.starts_with("rustc_") {
1277+
let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
1278+
are reserved for internal compiler diagnostics";
1279+
gate_feature!(self, rustc_attrs, attr.span, msg);
1280+
} else if !is_macro {
1281+
// Only run the custom attribute lint during regular feature gate
1282+
// checking. Macro gating runs before the plugin attributes are
1283+
// registered, so we skip this in that case.
12851284
let msg = format!("The attribute `{}` is currently unknown to the compiler and \
12861285
may have meaning added to it in the future", attr.path);
12871286
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
@@ -3,7 +3,7 @@ use deriving::generic::*;
33
use deriving::generic::ty::*;
44

55
use syntax::ast::{Expr, MetaItem};
6-
use syntax::ext::base::{Annotatable, ExtCtxt};
6+
use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt};
77
use syntax::ext::build::AstBuilder;
88
use syntax::ptr::P;
99
use syntax::symbol::Symbol;
@@ -69,7 +69,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
6969
span_err!(cx, trait_span, E0665,
7070
"`Default` cannot be derived for enums, only structs");
7171
// let compilation continue
72-
cx.expr_usize(trait_span, 0)
72+
DummyResult::raw_expr(trait_span)
7373
}
7474
_ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"),
7575
};

src/libsyntax_ext/format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,7 @@ impl<'a, 'b> Context<'a, 'b> {
666666
"X" => "UpperHex",
667667
_ => {
668668
ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname));
669-
"Dummy"
669+
return DummyResult::raw_expr(sp);
670670
}
671671
}
672672
}
@@ -713,7 +713,7 @@ pub fn expand_format_args_nl<'cx>(
713713
sp,
714714
feature_gate::GateIssue::Language,
715715
feature_gate::EXPLAIN_FORMAT_ARGS_NL);
716-
return base::DummyResult::expr(sp);
716+
return DummyResult::expr(sp);
717717
}
718718
sp = sp.apply_mark(ecx.current_expansion.mark);
719719
match parse_args(ecx, sp, tts) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
#[cfg(foo(bar))] //~ ERROR invalid predicate `foo`
2+
fn check() {}
3+
24
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
@@ -4,7 +4,7 @@ pub fn print(_args: std::fmt::Arguments) {}
44

55
#[macro_export]
66
macro_rules! myprint {
7-
($($arg:tt)*) => (print(format_args!($($arg)*)));
7+
($($arg:tt)*) => ($crate::print(format_args!($($arg)*)));
88
}
99

1010
#[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
@@ -4,6 +4,8 @@ trait Foo {
44
type Bar;
55
}
66

7+
struct Bar;
8+
79
impl Bar {
810
#[derive(Clone)]
911
//~^ 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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,3 @@ LL | #[derive(Clone)]
1111
| ^^^^^^^^^^^^^^^^
1212

1313
error: aborting due to 2 previous errors
14-
Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
fn foo() {
2-
println!("{:?}", (0..13).collect<Vec<i32>>()); //~ ERROR chained comparison
2+
(0..13).collect<Vec<i32>>();
3+
//~^ ERROR chained comparison
4+
//~| ERROR expected value, found struct `Vec`
5+
//~| ERROR expected value, found builtin type `i32`
6+
//~| ERROR attempted to take value of method `collect`
37
}
48

59
fn bar() {
6-
println!("{:?}", Vec<i32>::new()); //~ ERROR chained comparison
10+
Vec<i32>::new();
11+
//~^ ERROR chained comparison
12+
//~| ERROR expected value, found struct `Vec`
13+
//~| ERROR expected value, found builtin type `i32`
14+
//~| ERROR cannot find function `new` in the crate root
715
}
816

917
fn qux() {
10-
println!("{:?}", (0..13).collect<Vec<i32>()); //~ ERROR chained comparison
18+
(0..13).collect<Vec<i32>();
1119
//~^ ERROR chained comparison
20+
//~| ERROR chained comparison
21+
//~| ERROR expected value, found struct `Vec`
22+
//~| ERROR expected value, found builtin type `i32`
23+
//~| ERROR attempted to take value of method `collect`
24+
//~| ERROR mismatched types
1225
}
1326

1427
fn main() {}

0 commit comments

Comments
 (0)