Skip to content

Commit

Permalink
Rollup merge of rust-lang#60938 - jonas-schievink:doc-include-paths, …
Browse files Browse the repository at this point in the history
…r=petrochenkov

rustdoc: make #[doc(include)] relative to the containing file

This matches the behavior of other in-source paths like `#[path]` and the `include_X!` macros.

Fixes rust-lang#58373 (comment)
Also addresses rust-lang#44732 (comment)

cc rust-lang#44732

This is still missing a stdsimd change (https://github.com/jonas-schievink/stdsimd/commit/42ed30e0b5fb5e2d11765b5d1e1f36234af85984), so CI will currently fail. I'll land that change once I get initial feedback for this PR.
  • Loading branch information
Centril authored Jul 24, 2019
2 parents 27a6a30 + 218ab4c commit 6a1ea97
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 61 deletions.
5 changes: 2 additions & 3 deletions src/doc/rustdoc/src/unstable-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,8 @@ Book][unstable-masked] and [its tracking issue][issue-masked].

As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This
is useful if certain documentation is so long that it would break the flow of reading the source.
Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` (where `sometype.md` is
a file adjacent to the `lib.rs` for the crate) will ask Rustdoc to instead read that file and use it
as if it were written inline.
Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to
instead read that file and use it as if it were written inline.

[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990

Expand Down
48 changes: 32 additions & 16 deletions src/libstd/os/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#![stable(feature = "raw_os", since = "1.1.0")]

#[doc(include = "os/raw/char.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
Expand All @@ -31,7 +32,8 @@
target_arch = "powerpc")),
all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[doc(include = "os/raw/char.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
Expand All @@ -54,37 +56,51 @@
target_arch = "powerpc")),
all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[doc(include = "os/raw/schar.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
#[doc(include = "os/raw/uchar.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
#[doc(include = "os/raw/short.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
#[doc(include = "os/raw/ushort.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
#[doc(include = "os/raw/int.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
#[doc(include = "os/raw/uint.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
#[doc(include = "os/raw/long.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[doc(include = "os/raw/ulong.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
#[doc(include = "os/raw/long.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
#[doc(include = "os/raw/ulong.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
#[doc(include = "os/raw/longlong.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
#[doc(include = "os/raw/ulonglong.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
#[doc(include = "os/raw/float.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
#[doc(include = "os/raw/double.md")]
#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
Expand Down
27 changes: 26 additions & 1 deletion src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ast::{self, Attribute, Name, PatKind};
use crate::attr::{HasAttrs, Stability, Deprecation};
use crate::source_map::{SourceMap, Spanned, respan};
use crate::source_map::{SourceMap, Spanned, FileName, respan};
use crate::edition::Edition;
use crate::ext::expand::{self, AstFragment, Invocation};
use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
Expand Down Expand Up @@ -889,6 +889,31 @@ impl<'a> ExtCtxt<'a> {
pub fn check_unused_macros(&self) {
self.resolver.check_unused_macros();
}

/// Resolve a path mentioned inside Rust code.
///
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
///
/// Returns an absolute path to the file that `path` refers to.
pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PathBuf {
let path = path.into();

// Relative paths are resolved relative to the file in which they are found
// after macro expansion (that is, they are unhygienic).
if !path.is_absolute() {
let callsite = span.source_callsite();
let mut result = match self.source_map().span_to_unmapped_path(callsite) {
FileName::Real(path) => path,
FileName::DocTest(path, _) => path,
other => panic!("cannot resolve relative path in non-file source `{}`", other),
};
result.pop();
result.push(path);
result
} else {
path
}
}
}

/// Extracts a string literal from the macro expanded version of `expr`,
Expand Down
6 changes: 1 addition & 5 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1253,7 +1253,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
return noop_visit_attribute(at, self);
}

let filename = self.cx.root_path.join(file.to_string());
let filename = self.cx.resolve_path(&*file.as_str(), it.span());
match fs::read_to_string(&filename) {
Ok(src) => {
let src_interned = Symbol::intern(&src);
Expand Down Expand Up @@ -1302,10 +1302,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
);
err.span_label(lit.span, "couldn't read file");

if e.kind() == ErrorKind::NotFound {
err.help("external doc paths are relative to the crate root");
}

err.emit();
}
}
Expand Down
32 changes: 5 additions & 27 deletions src/libsyntax/ext/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ use crate::symbol::Symbol;
use crate::tokenstream;

use smallvec::SmallVec;
use syntax_pos::{self, Pos, Span, FileName};
use syntax_pos::{self, Pos, Span};

use std::fs;
use std::io::ErrorKind;
use std::path::PathBuf;
use rustc_data_structures::sync::Lrc;

// These macros all relate to the file system; they either return
Expand Down Expand Up @@ -78,9 +77,9 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: &[tokenstrea
None => return DummyResult::any(sp),
};
// The file will be added to the code map by the parser
let path = res_rel_file(cx, sp, file);
let file = cx.resolve_path(file, sp);
let directory_ownership = DirectoryOwnership::Owned { relative: None };
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);

struct ExpandResult<'a> {
p: parse::parser::Parser<'a>,
Expand Down Expand Up @@ -115,7 +114,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To
Some(f) => f,
None => return DummyResult::expr(sp)
};
let file = res_rel_file(cx, sp, file);
let file = cx.resolve_path(file, sp);
match fs::read_to_string(&file) {
Ok(src) => {
let interned_src = Symbol::intern(&src);
Expand Down Expand Up @@ -143,7 +142,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
Some(f) => f,
None => return DummyResult::expr(sp)
};
let file = res_rel_file(cx, sp, file);
let file = cx.resolve_path(file, sp);
match fs::read(&file) {
Ok(bytes) => {
// Add the contents to the source map if it contains UTF-8.
Expand All @@ -164,24 +163,3 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
}
}
}

// resolve a file-system path to an absolute file-system path (if it
// isn't already)
fn res_rel_file(cx: &mut ExtCtxt<'_>, sp: syntax_pos::Span, arg: String) -> PathBuf {
let arg = PathBuf::from(arg);
// Relative paths are resolved relative to the file in which they are found
// after macro expansion (that is, they are unhygienic).
if !arg.is_absolute() {
let callsite = sp.source_callsite();
let mut path = match cx.source_map().span_to_unmapped_path(callsite) {
FileName::Real(path) => path,
FileName::DocTest(path, _) => path,
other => panic!("cannot resolve relative path in non-file source `{}`", other),
};
path.pop();
path.push(arg);
path
} else {
arg
}
}
2 changes: 1 addition & 1 deletion src/stdarch
1 change: 0 additions & 1 deletion src/test/ui/extern/external-doc-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#[doc(include = "not-a-file.md")]
pub struct SomeStruct; //~^ ERROR couldn't read
//~| HELP external doc paths are relative to the crate root

#[doc(include = "auxiliary/invalid-utf8.txt")]
pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
Expand Down
12 changes: 5 additions & 7 deletions src/test/ui/extern/external-doc-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,33 @@ error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
|
LL | #[doc(include = "not-a-file.md")]
| ^^^^^^^^^^^^^^^ couldn't read file
|
= help: external doc paths are relative to the crate root

error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
--> $DIR/external-doc-error.rs:9:17
--> $DIR/external-doc-error.rs:8:17
|
LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8

error: expected path to external documentation
--> $DIR/external-doc-error.rs:12:7
--> $DIR/external-doc-error.rs:11:7
|
LL | #[doc(include)]
| ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`

error: expected path to external documentation
--> $DIR/external-doc-error.rs:17:7
--> $DIR/external-doc-error.rs:16:7
|
LL | #[doc(include("../README.md"))]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`

error: expected path to external documentation
--> $DIR/external-doc-error.rs:22:7
--> $DIR/external-doc-error.rs:21:7
|
LL | #[doc(include = 123)]
| ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`

error: expected path to external documentation
--> $DIR/external-doc-error.rs:27:7
--> $DIR/external-doc-error.rs:26:7
|
LL | #[doc(include(123))]
| ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
Expand Down

0 comments on commit 6a1ea97

Please sign in to comment.