Skip to content

Commit f16993d

Browse files
committed
resolve/expand: resolve_macro_invocation no longer returns determinate errors
It either returns the indeterminacy error, or valid (but perhaps dummy) `SyntaxExtension`. With this change enum `Determinacy` is no longer used in libsyntax and can be moved to resolve. The regressions in diagnosics are fixed in the next commits.
1 parent cd0fd63 commit f16993d

File tree

10 files changed

+108
-123
lines changed

10 files changed

+108
-123
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleIm
99
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
1010
use crate::{ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
1111
use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
12-
use crate::{resolve_error, resolve_struct_error, ResolutionError};
12+
use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
1313

1414
use rustc::bug;
1515
use rustc::hir::def::{self, *};
@@ -30,7 +30,6 @@ use syntax::attr;
3030
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
3131
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
3232
use syntax::ext::base::SyntaxExtension;
33-
use syntax::ext::base::Determinacy::Undetermined;
3433
use syntax::ext::hygiene::Mark;
3534
use syntax::ext::tt::macro_rules;
3635
use syntax::feature_gate::is_builtin_attr;
@@ -231,9 +230,9 @@ impl<'a> Resolver<'a> {
231230
source: source.ident,
232231
target: ident,
233232
source_bindings: PerNS {
234-
type_ns: Cell::new(Err(Undetermined)),
235-
value_ns: Cell::new(Err(Undetermined)),
236-
macro_ns: Cell::new(Err(Undetermined)),
233+
type_ns: Cell::new(Err(Determinacy::Undetermined)),
234+
value_ns: Cell::new(Err(Determinacy::Undetermined)),
235+
macro_ns: Cell::new(Err(Determinacy::Undetermined)),
237236
},
238237
target_bindings: PerNS {
239238
type_ns: Cell::new(None),

src/librustc_resolve/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
pub use rustc::hir::def::{Namespace, PerNS};
1717

18+
use Determinacy::*;
1819
use GenericParameters::*;
1920
use RibKind::*;
2021
use smallvec::smallvec;
@@ -41,7 +42,6 @@ use syntax::source_map::SourceMap;
4142
use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
4243
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
4344
use syntax::ext::base::SyntaxExtension;
44-
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
4545
use syntax::ext::base::MacroKind;
4646
use syntax::symbol::{Symbol, kw, sym};
4747
use syntax::util::lev_distance::find_best_match_for_name;
@@ -93,6 +93,18 @@ enum Weak {
9393
No,
9494
}
9595

96+
#[derive(Copy, Clone, PartialEq, Debug)]
97+
pub enum Determinacy {
98+
Determined,
99+
Undetermined,
100+
}
101+
102+
impl Determinacy {
103+
fn determined(determined: bool) -> Determinacy {
104+
if determined { Determinacy::Determined } else { Determinacy::Undetermined }
105+
}
106+
}
107+
96108
enum ScopeSet {
97109
Import(Namespace),
98110
AbsolutePath(Namespace),

src/librustc_resolve/macros.rs

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
1+
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
22
use crate::{CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
33
use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
44
use crate::{is_known_tool, resolve_error};
@@ -14,7 +14,7 @@ use rustc::{ty, lint, span_bug};
1414
use syntax::ast::{self, Ident, ItemKind};
1515
use syntax::attr::{self, StabilityLevel};
1616
use syntax::errors::DiagnosticBuilder;
17-
use syntax::ext::base::{self, Determinacy};
17+
use syntax::ext::base::{self, Indeterminate};
1818
use syntax::ext::base::{MacroKind, SyntaxExtension};
1919
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
2020
use syntax::ext::hygiene::{self, Mark};
@@ -216,7 +216,7 @@ impl<'a> base::Resolver for Resolver<'a> {
216216
}
217217

218218
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
219-
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
219+
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
220220
let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
221221
InvocationKind::Attr { attr: None, .. } =>
222222
return Ok(None),
@@ -229,12 +229,7 @@ impl<'a> base::Resolver for Resolver<'a> {
229229
};
230230

231231
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
232-
let (res, ext) = match self.resolve_macro_to_res(path, kind, &parent_scope, true, force) {
233-
Ok((res, ext)) => (res, ext),
234-
// Return dummy syntax extensions for unresolved macros for better recovery.
235-
Err(Determinacy::Determined) => (Res::Err, self.dummy_ext(kind)),
236-
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
237-
};
232+
let (res, ext) = self.resolve_macro_to_res(path, kind, &parent_scope, true, force)?;
238233

239234
let span = invoc.span();
240235
let descr = fast_print_path(path);
@@ -287,7 +282,7 @@ impl<'a> Resolver<'a> {
287282
parent_scope: &ParentScope<'a>,
288283
trace: bool,
289284
force: bool,
290-
) -> Result<(Res, Lrc<SyntaxExtension>), Determinacy> {
285+
) -> Result<(Res, Lrc<SyntaxExtension>), Indeterminate> {
291286
let res = self.resolve_macro_to_res_inner(path, kind, parent_scope, trace, force);
292287

293288
// Report errors and enforce feature gates for the resolved macro.
@@ -313,7 +308,14 @@ impl<'a> Resolver<'a> {
313308
}
314309
}
315310

316-
let res = res?;
311+
let res = match res {
312+
Err(Determinacy::Undetermined) => return Err(Indeterminate),
313+
Ok(Res::Err) | Err(Determinacy::Determined) => {
314+
// Return dummy syntax extensions for unresolved macros for better recovery.
315+
return Ok((Res::Err, self.dummy_ext(kind)));
316+
}
317+
Ok(res) => res,
318+
};
317319

318320
match res {
319321
Res::Def(DefKind::Macro(_), def_id) => {
@@ -328,35 +330,23 @@ impl<'a> Resolver<'a> {
328330
}
329331
}
330332
Res::NonMacroAttr(attr_kind) => {
331-
if kind == MacroKind::Attr {
332-
if attr_kind == NonMacroAttrKind::Custom {
333-
assert!(path.segments.len() == 1);
334-
if !features.custom_attribute {
335-
let msg = format!("The attribute `{}` is currently unknown to the \
336-
compiler and may have meaning added to it in the \
337-
future", path);
338-
self.report_unknown_attribute(
339-
path.span,
340-
&path.segments[0].ident.as_str(),
341-
&msg,
342-
sym::custom_attribute,
343-
);
344-
}
333+
if attr_kind == NonMacroAttrKind::Custom {
334+
assert!(path.segments.len() == 1);
335+
if !features.custom_attribute {
336+
let msg = format!("The attribute `{}` is currently unknown to the \
337+
compiler and may have meaning added to it in the \
338+
future", path);
339+
self.report_unknown_attribute(
340+
path.span,
341+
&path.segments[0].ident.as_str(),
342+
&msg,
343+
sym::custom_attribute,
344+
);
345345
}
346-
} else {
347-
// Not only attributes, but anything in macro namespace can result in
348-
// `Res::NonMacroAttr` definition (e.g., `inline!()`), so we must report
349-
// an error for those cases.
350-
let msg = format!("expected a macro, found {}", res.descr());
351-
self.session.span_err(path.span, &msg);
352-
return Err(Determinacy::Determined);
353346
}
354347
}
355-
Res::Err => {
356-
return Err(Determinacy::Determined);
357-
}
358348
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
359-
}
349+
};
360350

361351
Ok((res, self.get_macro(res)))
362352
}
@@ -608,9 +598,7 @@ impl<'a> Resolver<'a> {
608598
result = Ok((binding, Flags::empty()));
609599
break;
610600
}
611-
Err(Determinacy::Determined) => {}
612-
Err(Determinacy::Undetermined) =>
613-
result = Err(Determinacy::Undetermined),
601+
Err(Indeterminate) => result = Err(Determinacy::Undetermined),
614602
}
615603
}
616604
result

src/librustc_resolve/resolve_imports.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use ImportDirectiveSubclass::*;
22

33
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
44
use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
5+
use crate::Determinacy::{self, *};
56
use crate::Namespace::{self, TypeNS, MacroNS};
67
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
78
use crate::{Resolver, Segment};
@@ -27,7 +28,6 @@ use rustc::util::nodemap::FxHashSet;
2728
use rustc::{bug, span_bug};
2829

2930
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
30-
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
3131
use syntax::ext::hygiene::Mark;
3232
use syntax::symbol::kw;
3333
use syntax::util::lev_distance::find_best_match_for_name;

src/libsyntax/ext/base.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,9 @@ impl SyntaxExtension {
676676

677677
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
678678

679+
/// Error type that denotes indeterminacy.
680+
pub struct Indeterminate;
681+
679682
pub trait Resolver {
680683
fn next_node_id(&mut self) -> ast::NodeId;
681684

@@ -689,23 +692,11 @@ pub trait Resolver {
689692
fn resolve_imports(&mut self);
690693

691694
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
692-
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
695+
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
693696

694697
fn check_unused_macros(&self);
695698
}
696699

697-
#[derive(Copy, Clone, PartialEq, Debug)]
698-
pub enum Determinacy {
699-
Determined,
700-
Undetermined,
701-
}
702-
703-
impl Determinacy {
704-
pub fn determined(determined: bool) -> Determinacy {
705-
if determined { Determinacy::Determined } else { Determinacy::Undetermined }
706-
}
707-
}
708-
709700
#[derive(Clone)]
710701
pub struct ModuleData {
711702
pub mod_path: Vec<ast::Ident>,

src/libsyntax/ext/expand.rs

Lines changed: 53 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
313313
let scope =
314314
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
315315
let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
316-
Ok(ext) => Some(ext),
317-
Err(Determinacy::Determined) => None,
318-
Err(Determinacy::Undetermined) => {
316+
Ok(ext) => ext,
317+
Err(Indeterminate) => {
319318
undetermined_invocations.push(invoc);
320319
continue
321320
}
@@ -328,65 +327,61 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
328327
self.cx.current_expansion.mark = scope;
329328
// FIXME(jseyfried): Refactor out the following logic
330329
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
331-
if let Some(ext) = ext {
332-
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
333-
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
334-
invoc_fragment_kind.dummy(invoc_span).unwrap()
335-
});
336-
self.collect_invocations(fragment, &[])
337-
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
338-
if !item.derive_allowed() {
339-
let attr = attr::find_by_name(item.attrs(), sym::derive)
340-
.expect("`derive` attribute should exist");
341-
let span = attr.span;
342-
let mut err = self.cx.mut_span_err(span,
343-
"`derive` may only be applied to \
344-
structs, enums and unions");
345-
if let ast::AttrStyle::Inner = attr.style {
346-
let trait_list = traits.iter()
347-
.map(|t| t.to_string()).collect::<Vec<_>>();
348-
let suggestion = format!("#[derive({})]", trait_list.join(", "));
349-
err.span_suggestion(
350-
span, "try an outer attribute", suggestion,
351-
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
352-
Applicability::MaybeIncorrect
353-
);
354-
}
355-
err.emit();
330+
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
331+
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
332+
invoc_fragment_kind.dummy(invoc_span).unwrap()
333+
});
334+
self.collect_invocations(fragment, &[])
335+
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
336+
if !item.derive_allowed() {
337+
let attr = attr::find_by_name(item.attrs(), sym::derive)
338+
.expect("`derive` attribute should exist");
339+
let span = attr.span;
340+
let mut err = self.cx.mut_span_err(span,
341+
"`derive` may only be applied to \
342+
structs, enums and unions");
343+
if let ast::AttrStyle::Inner = attr.style {
344+
let trait_list = traits.iter()
345+
.map(|t| t.to_string()).collect::<Vec<_>>();
346+
let suggestion = format!("#[derive({})]", trait_list.join(", "));
347+
err.span_suggestion(
348+
span, "try an outer attribute", suggestion,
349+
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
350+
Applicability::MaybeIncorrect
351+
);
356352
}
353+
err.emit();
354+
}
357355

358-
let mut item = self.fully_configure(item);
359-
item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
360-
let mut item_with_markers = item.clone();
361-
add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
362-
let derives = derives.entry(invoc.expansion_data.mark).or_default();
363-
364-
derives.reserve(traits.len());
365-
invocations.reserve(traits.len());
366-
for path in traits {
367-
let mark = Mark::fresh(self.cx.current_expansion.mark);
368-
derives.push(mark);
369-
invocations.push(Invocation {
370-
kind: InvocationKind::Derive {
371-
path,
372-
item: item.clone(),
373-
item_with_markers: item_with_markers.clone(),
374-
},
375-
fragment_kind: invoc.fragment_kind,
376-
expansion_data: ExpansionData {
377-
mark,
378-
..invoc.expansion_data.clone()
379-
},
380-
});
381-
}
382-
let fragment = invoc.fragment_kind
383-
.expect_from_annotatables(::std::iter::once(item_with_markers));
384-
self.collect_invocations(fragment, derives)
385-
} else {
386-
unreachable!()
356+
let mut item = self.fully_configure(item);
357+
item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
358+
let mut item_with_markers = item.clone();
359+
add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
360+
let derives = derives.entry(invoc.expansion_data.mark).or_default();
361+
362+
derives.reserve(traits.len());
363+
invocations.reserve(traits.len());
364+
for path in traits {
365+
let mark = Mark::fresh(self.cx.current_expansion.mark);
366+
derives.push(mark);
367+
invocations.push(Invocation {
368+
kind: InvocationKind::Derive {
369+
path,
370+
item: item.clone(),
371+
item_with_markers: item_with_markers.clone(),
372+
},
373+
fragment_kind: invoc.fragment_kind,
374+
expansion_data: ExpansionData {
375+
mark,
376+
..invoc.expansion_data.clone()
377+
},
378+
});
387379
}
380+
let fragment = invoc.fragment_kind
381+
.expect_from_annotatables(::std::iter::once(item_with_markers));
382+
self.collect_invocations(fragment, derives)
388383
} else {
389-
self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
384+
unreachable!()
390385
};
391386

392387
if expanded_fragments.len() < depth {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
1+
#[derive(inline)] //~ ERROR macro `inline` may not be used for derive attributes
22
struct S;
33

44
fn main() {}

src/test/ui/macros/macro-path-prelude-fail-4.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: expected a macro, found built-in attribute
1+
error: macro `inline` may not be used for derive attributes
22
--> $DIR/macro-path-prelude-fail-4.rs:1:10
33
|
44
LL | #[derive(inline)]
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
1+
#[derive(rustfmt::skip)] //~ ERROR macro `rustfmt::skip` may not be used for derive attributes
22
struct S;
33

44
fn main() {
5-
rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
5+
rustfmt::skip!(); //~ ERROR `rustfmt::skip` can only be used in attributes
66
}

0 commit comments

Comments
 (0)