I tried that first, actually, but it results in a panic+abort. Ugly diff:
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index 70f1c0e4e2d..98cb574bb88 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -89,6 +89,8 @@ pub fn inject(
struct TestHarnessGenerator<'a> {
cx: TestCtxt<'a>,
tests: Vec<Test>,
+ module_id: ast::NodeId,
+ parent_span: Span,
}
impl<'a> MutVisitor for TestHarnessGenerator<'a> {
@@ -108,36 +110,55 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
self.tests.push(test);
}
- // We don't want to recurse into anything other than mods, since
- // mods or tests inside of functions will break things
- if let ast::ItemKind::Mod(mut module) = item.kind {
- let tests = mem::take(&mut self.tests);
- noop_visit_mod(&mut module, self);
- let mut tests = mem::replace(&mut self.tests, tests);
-
- if !tests.is_empty() {
- let parent =
- if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
- // Create an identifier that will hygienically resolve the test
- // case name, even in another module.
- let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
- module.inner,
- AstPass::TestHarness,
- &[],
- Some(parent),
- );
- for test in &mut tests {
- // See the comment on `mk_main` for why we're using
- // `apply_mark` directly.
- test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
- }
- self.cx.test_cases.extend(tests);
+ let old_span = self.parent_span;
+ let old_module_id = self.module_id;
+
+ if let ast::ItemKind::Mod(ref module) = item.kind {
+ self.module_id =
+ if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
+ self.parent_span = module.inner;
+ }
+
+ let tests = mem::take(&mut self.tests);
+ noop_visit_item_kind(&mut item.kind, self);
+ let mut tests = mem::replace(&mut self.tests, tests);
+ if !tests.is_empty() {
+ // Create an identifier that will hygienically resolve the test
+ // case name, even in another module.
+ let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
+ self.parent_span,
+ AstPass::TestHarness,
+ &[],
+ Some(self.module_id),
+ );
+
+ for test in &mut tests {
+ // See the comment on `mk_main` for why we're using
+ // `apply_mark` directly.
+ test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
}
- item.kind = ast::ItemKind::Mod(module);
+ self.cx.test_cases.extend(tests);
}
+
+ self.parent_span = old_span;
+ self.module_id = old_module_id;
+
smallvec![P(item)]
}
+ fn visit_block(&mut self, b: &mut P<ast::Block>) {
+ let old_span = self.parent_span;
+ let old_module_id = self.module_id;
+
+ self.parent_span = b.span;
+ self.module_id =
+ if b.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { b.id };
+ noop_visit_block(b, self);
+
+ self.parent_span = old_span;
+ self.module_id = old_module_id;
+ }
+
fn visit_mac(&mut self, _mac: &mut ast::Mac) {
// Do nothing.
}
@@ -234,7 +255,13 @@ fn generate_test_harness(
test_runner,
};
- TestHarnessGenerator { cx, tests: Vec::new() }.visit_crate(krate);
+ TestHarnessGenerator {
+ cx,
Support #[test] on inner functions
+ tests: Vec::new(),
+ module_id: ast::CRATE_NODE_ID,
+ parent_span: krate.span,
+ }
+ .visit_crate(krate);
}
/// Creates a function item for use as the main function of a test build.
commit 8498c5f5b02dbb4ed58a1eb4901b0b733342c35f (origin/master, origin/HEAD, master)
Merge: a29424a2265 4b3c66d2c30
Author: bors <bors@rust-lang.org>
Date: Fri Feb 7 23:08:52 2020 +0000
Auto merge of #65232 - nikomatsakis:lazy-norm-anon-const-push-2, r=matthewjasper
replace the leak check with universes, take 2
This PR is an attempt to revive the "universe-based region check", which is an important step towards lazy normalization. Unlike before, we also modify the definition of
```
static ----------+-----...------+ (greatest)
~/P/r/src ❯❯❯ git add -u ✘ 141 alt_inner_test ✭ ◼
~/P/r/src ❯❯❯ git commit --amend alt_inner_test ✭ ✚ ◼
[alt_inner_test 7e088a8d74f] Support #[test] on inner functions
Date: Sat Feb 15 16:30:23 2020 -0800
1 file changed, 49 insertions(+), 20 deletions(-)
~/P/r/src ❯❯❯ git log -p alt_inner_test ✭ ◼
commit 7e088a8d74f768b69aff0f2d09281c376e67bc76 (HEAD -> alt_inner_test)
Author: Michael Bradshaw <mjbshaw@google.com>
Date: Sat Feb 15 16:30:23 2020 -0800
Support #[test] on inner functions
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index 70f1c0e4e2d..0021743b34a 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -22,6 +22,8 @@ use std::{iter, mem};
struct Test {
span: Span,
ident: Ident,
+ parent_span: Span,
+ module_id: ast::NodeId,
}
struct TestCtxt<'a> {
@@ -89,6 +91,8 @@ pub fn inject(
struct TestHarnessGenerator<'a> {
cx: TestCtxt<'a>,
tests: Vec<Test>,
+ module_id: ast::NodeId,
+ parent_span: Span,
}
impl<'a> MutVisitor for TestHarnessGenerator<'a> {
@@ -104,40 +108,59 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
if is_test_case(&item) {
debug!("this is a test item");
- let test = Test { span: item.span, ident: item.ident };
+ let test = Test { span: item.span, ident: item.ident, parent_span: self.parent_span, module_id: self.module_id };
self.tests.push(test);
}
- // We don't want to recurse into anything other than mods, since
- // mods or tests inside of functions will break things
- if let ast::ItemKind::Mod(mut module) = item.kind {
- let tests = mem::take(&mut self.tests);
- noop_visit_mod(&mut module, self);
- let mut tests = mem::replace(&mut self.tests, tests);
+ let old_span = self.parent_span;
+ let old_module_id = self.module_id;
- if !tests.is_empty() {
- let parent =
- if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id };
+ if let ast::ItemKind::Mod(ref module) = item.kind {
+ self.module_id =
+ if item.id == ast::DUMMY_NODE_ID { self.module_id } else { item.id };
+ self.parent_span = module.inner;
+ }
+
+ let tests = mem::take(&mut self.tests);
+ noop_visit_item_kind(&mut item.kind, self);
+ let mut tests = mem::replace(&mut self.tests, tests);
+ if !tests.is_empty() {
+ for test in &mut tests {
// Create an identifier that will hygienically resolve the test
// case name, even in another module.
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
- module.inner,
+ test.parent_span,
AstPass::TestHarness,
&[],
- Some(parent),
+ Some(test.module_id),
);
- for test in &mut tests {
- // See the comment on `mk_main` for why we're using
- // `apply_mark` directly.
- test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
- }
- self.cx.test_cases.extend(tests);
+
+ // See the comment on `mk_main` for why we're using
+ // `apply_mark` directly.
+ test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
}
- item.kind = ast::ItemKind::Mod(module);
+ self.cx.test_cases.extend(tests);
}
+
+ self.parent_span = old_span;
+ self.module_id = old_module_id;
+
smallvec![P(item)]
}
+ fn visit_block(&mut self, b: &mut P<ast::Block>) {
+ let old_span = self.parent_span;
+ let old_module_id = self.module_id;
+
+ self.parent_span = b.span;
+ self.module_id =
+ if b.id == ast::DUMMY_NODE_ID { self.module_id } else { b.id };
+ noop_visit_block(b, self);
+
+ self.parent_span = old_span;
+ self.module_id = old_module_id;
+ }
+
fn visit_mac(&mut self, _mac: &mut ast::Mac) {
// Do nothing.
}
@@ -234,7 +257,13 @@ fn generate_test_harness(
test_runner,
};
- TestHarnessGenerator { cx, tests: Vec::new() }.visit_crate(krate);
+ TestHarnessGenerator {
+ cx,
+ tests: Vec::new(),
+ module_id: ast::CRATE_NODE_ID,
+ parent_span: krate.span,
+ }
+ .visit_crate(krate);
}
/// Creates a function item for use as the main function of a test build.
Panic+abort:
thread 'rustc' panicked at 'called `Option::unwrap()` on a `None` value', /usr/local/google/home/mjbshaw/Projects/rust/src/librustc/hir/map/definitions.rs:347:9
stack backtrace:
0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
1: core::fmt::write
2: std::io::Write::write_fmt
3: std::panicking::default_hook::{{closure}}
4: std::panicking::default_hook
5: rustc_driver::report_ice
6: std::panicking::rust_panic_with_hook
7: rust_begin_unwind
8: core::panicking::panic_fmt
9: core::panicking::panic
10: rustc_resolve::macros::<impl rustc_expand::base::Resolver for rustc_resolve::Resolver>::expansion_for_ast_pass
11: <rustc_builtin_macros::test_harness::TestHarnessGenerator as syntax::mut_visit::MutVisitor>::flat_map_item
12: <alloc::vec::Vec<T> as syntax::util::map_in_place::MapInPlace<T>>::flat_map_in_place
13: syntax::mut_visit::noop_visit_item_kind
14: <rustc_builtin_macros::test_harness::TestHarnessGenerator as syntax::mut_visit::MutVisitor>::flat_map_item
15: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
16: std::panicking::try::do_call
17: __rust_maybe_catch_panic
18: syntax::mut_visit::noop_visit_crate
19: <rustc_builtin_macros::test_harness::TestHarnessGenerator as syntax::mut_visit::MutVisitor>::visit_crate
20: rustc_builtin_macros::test_harness::inject
21: rustc_session::utils::<impl rustc_session::session::Session>::time
22: rustc_interface::passes::configure_and_expand_inner
23: rustc_interface::passes::configure_and_expand::{{closure}}
24: rustc_data_structures::box_region::PinnedGenerator<I,A,R>::new
25: rustc_interface::passes::configure_and_expand
26: rustc_interface::queries::Queries::expansion
27: rustc_interface::queries::Queries::prepare_outputs
28: rustc_interface::queries::Queries::global_ctxt
29: rustc_interface::interface::run_compiler_in_existing_thread_pool
30: scoped_tls::ScopedKey<T>::set
31: syntax::attr::with_globals
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: internal compiler error: unexpected panic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.43.0-dev running on x86_64-unknown-linux-gnu
note: compiler flags: -Z unpretty=hir
query stack during panic:
end of query stack
[1] 144436 abort RUST_BACKTRACE=1 ./build/x86_64-unknown-linux-gnu/stage2/bin/rustc -O --tes