Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage of extern crate fails doc tests #33731

Closed
Osspial opened this issue May 19, 2016 · 6 comments
Closed

Usage of extern crate fails doc tests #33731

Osspial opened this issue May 19, 2016 · 6 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@Osspial
Copy link

Osspial commented May 19, 2016

If a doc test attempts to import any types declared in it's own crate, including the phrase extern crate anywhere in the code will cause the test to not compile, throwing a "unresolved import" error at the attempted import. For example, if we have struct Foo in crate bar, with the crate baz declared under dev_dependencies, these tests will all fail to compile when there's no reason for them not to:

/// ```
/// extern crate baz;
/// use bar::Foo;
/// ```
pub struct Foo{}
/// ```
/// // The phrase "extern crate" breaks this!
/// use bar::Foo;
/// ```
pub struct Foo{}
/// ```
/// use bar::Foo;
/// let string = "extern crate";
/// ```
pub struct Foo{}

The following error log is given by cargo test:

running 1 test
test Foo_0 ... FAILED

failures:

---- Foo_0 stdout ----
        <anon>:2:9: 2:12 error: unresolved import `bar::Foo`. Maybe a missing `extern crate bar`? [E0432]
<anon>:2     use bar::Foo;
                 ^~~
error: aborting due to previous error(s)
thread 'Foo_0' panicked at 'Box<Any>', ../src/librustc\session/mod.rs:153
stack backtrace:
   0:         0x61cc34dc - strncmp
   1:         0x61cc2b5c - strncmp
   2:         0x61c84d6f - strncmp
   3:         0x67f193ba - strncmp
   4:         0x67f96c9b - strncmp
   5:         0x6ca6943d - strncmp
   6:         0x6ca6e301 - strncmp
   7:         0x661e3803 - strncmp
   8:         0x61caf9ba - strncmp
   9:         0x661e3bba - strncmp
  10:         0x61cc1209 - strncmp
  11:     0x7fff457f8101 - strncmp


failures:
    Foo_0

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured

Rust version:

rustc 1.8.0 (db2939409 2016-04-11)
binary: rustc
commit-hash: db2939409db26ab4904372c82492cd3488e4c44e
commit-date: 2016-04-11
host: x86_64-pc-windows-gnu
release: 1.8.0
@alexcrichton alexcrichton added the T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. label May 19, 2016
@durka
Copy link
Contributor

durka commented May 19, 2016

This is by design. It's a confusing design. The code in doc tests is (1) wrapped in fn main (unless main is already in there), and (2) the extern crate is put outside that fn (unless it's already in there). So putting in extern crate but not fn main causes it to skip step 2 but not step 1, making the imports unresolvable. The rules are described in the book.

@Osspial
Copy link
Author

Osspial commented May 19, 2016

OK, I can see why it would be done that way. However, there are still two issues:

  1. The error message doesn't indicate the actual problem
  2. Examples 2/3 should still compile, as extern crate isn't an actual bit of code

It looks like rustdoc is just doing a blind search for the phrase extern crate in the code, which is causing some issues that shouldn't be present.

EDIT:
Additionally, the phrase "remainder of the text" in rule 4 seems to imply that everything after extern crate is supposed to be implicitly wrapped by an automatically generated fn main.

@durka
Copy link
Contributor

durka commented May 19, 2016

Yeah, it just does a blind substring search. Possibly rustdoc could look
for the "unresolved import" error and give an extra hint?

On Thu, May 19, 2016 at 12:02 PM, Osspial notifications@github.com wrote:

OK, I can see why it would be done that way. However, there are still two
issues:

  1. The error message doesn't indicate the actual problem
  2. Examples 2/3 should still compile, as extern crate isn't an actual
    bit of code

It looks like rustdoc is just doing a blind search for the phrase extern
crate in the code, which is causing some issues that shouldn't be present.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub
#33731 (comment)

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label Sep 16, 2016
@steveklabnik steveklabnik added T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. and removed T-tools labels May 18, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 25, 2017
@QuietMisdreavus
Copy link
Member

Update: Still an issue. The offending code still does a naive string search before inserting extern crate my_crate; into the doctest:

rust/src/librustdoc/test.rs

Lines 403 to 410 in ae2f299

if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") {
if let Some(cratename) = cratename {
if s.contains(cratename) {
prog.push_str(&format!("extern crate {};\n", cratename));
line_offset += 1;
}
}
}

A proper fix should scan the lines of the original string much like the way it checks for fn main:

rust/src/librustdoc/test.rs

Lines 414 to 423 in ae2f299

let already_has_main = s.lines()
.map(|line| {
let comment = line.find("//");
if let Some(comment_begins) = comment {
&line[0..comment_begins]
} else {
line
}
})
.any(|code| code.contains("fn main"));

Or even better, actually parse the code and look for the import that way. It would also fully fix #21299, since it has the same problem: the last example will fail if you replace "extern crate" with "fn main".

@Enet4
Copy link
Contributor

Enet4 commented Jul 19, 2018

Is this issue still reproducible? I stumbled upon a similar situation, but the doctest below seems to compile just fine since 1.26.0 (it fails in 1.25.0 and older).

//! # Examples
//!
//! ```
//! extern crate byteorder;
//! use byteorder::ReadBytesExt;
//! ```

@QuietMisdreavus
Copy link
Member

That doctest doesn't exercise the issue. The problem is that you can't use any types from your own crate in there, right. (Unless your crate is byteorder, but then you're doing everything correctly.) Rustdoc still won't add extern crate my_crate; to the doctest.

bors added a commit that referenced this issue Nov 4, 2018
rustdoc: Replaces fn main search and extern crate search with proper parsing during doctests.

Fixes #21299.
Fixes #33731.

Let me know if there's any additional changes you'd like made!
tormol pushed a commit to tormol/map_in_place that referenced this issue Feb 9, 2020
Test that this is compatible back to Rust 1.26.0.

Rust 1.24.0 and earlier fail in the doctest due to
rust-lang/rust#33731
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. T-dev-tools Relevant to the dev-tools subteam, which will review and decide on the PR/issue. T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants