Skip to content

Commit 1433a4b

Browse files
authored
Rollup merge of rust-lang#60938 - jonas-schievink:doc-include-paths, 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.
2 parents 185b9ac + 218ab4c commit 1433a4b

File tree

8 files changed

+72
-61
lines changed

8 files changed

+72
-61
lines changed

src/doc/rustdoc/src/unstable-features.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,8 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
183183

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

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

src/libstd/os/raw/mod.rs

+32-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
99
#![stable(feature = "raw_os", since = "1.1.0")]
1010

11-
#[doc(include = "os/raw/char.md")]
11+
#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
12+
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
1213
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
1314
target_arch = "arm",
1415
target_arch = "hexagon",
@@ -32,7 +33,8 @@
3233
target_arch = "powerpc")),
3334
all(target_os = "fuchsia", target_arch = "aarch64")))]
3435
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
35-
#[doc(include = "os/raw/char.md")]
36+
#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
37+
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
3638
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
3739
target_arch = "arm",
3840
target_arch = "hexagon",
@@ -56,37 +58,51 @@
5658
target_arch = "powerpc")),
5759
all(target_os = "fuchsia", target_arch = "aarch64"))))]
5860
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
59-
#[doc(include = "os/raw/schar.md")]
61+
#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
62+
#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
6063
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
61-
#[doc(include = "os/raw/uchar.md")]
64+
#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
65+
#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
6266
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
63-
#[doc(include = "os/raw/short.md")]
67+
#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
68+
#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
6469
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
65-
#[doc(include = "os/raw/ushort.md")]
70+
#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
71+
#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
6672
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
67-
#[doc(include = "os/raw/int.md")]
73+
#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
74+
#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
6875
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
69-
#[doc(include = "os/raw/uint.md")]
76+
#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
77+
#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
7078
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
71-
#[doc(include = "os/raw/long.md")]
79+
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
80+
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
7281
#[cfg(any(target_pointer_width = "32", windows))]
7382
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
74-
#[doc(include = "os/raw/ulong.md")]
83+
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
84+
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
7585
#[cfg(any(target_pointer_width = "32", windows))]
7686
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
77-
#[doc(include = "os/raw/long.md")]
87+
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
88+
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
7889
#[cfg(all(target_pointer_width = "64", not(windows)))]
7990
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
80-
#[doc(include = "os/raw/ulong.md")]
91+
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
92+
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
8193
#[cfg(all(target_pointer_width = "64", not(windows)))]
8294
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
83-
#[doc(include = "os/raw/longlong.md")]
95+
#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
96+
#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
8497
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
85-
#[doc(include = "os/raw/ulonglong.md")]
98+
#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
99+
#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
86100
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
87-
#[doc(include = "os/raw/float.md")]
101+
#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
102+
#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
88103
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
89-
#[doc(include = "os/raw/double.md")]
104+
#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
105+
#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
90106
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;
91107

92108
#[stable(feature = "raw_os", since = "1.1.0")]

src/libsyntax/ext/base.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::ast::{self, Attribute, Name, PatKind};
22
use crate::attr::{HasAttrs, Stability, Deprecation};
3-
use crate::source_map::{SourceMap, Spanned, respan};
3+
use crate::source_map::{SourceMap, Spanned, FileName, respan};
44
use crate::edition::Edition;
55
use crate::ext::expand::{self, AstFragment, Invocation};
66
use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency};
@@ -889,6 +889,31 @@ impl<'a> ExtCtxt<'a> {
889889
pub fn check_unused_macros(&self) {
890890
self.resolver.check_unused_macros();
891891
}
892+
893+
/// Resolve a path mentioned inside Rust code.
894+
///
895+
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
896+
///
897+
/// Returns an absolute path to the file that `path` refers to.
898+
pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PathBuf {
899+
let path = path.into();
900+
901+
// Relative paths are resolved relative to the file in which they are found
902+
// after macro expansion (that is, they are unhygienic).
903+
if !path.is_absolute() {
904+
let callsite = span.source_callsite();
905+
let mut result = match self.source_map().span_to_unmapped_path(callsite) {
906+
FileName::Real(path) => path,
907+
FileName::DocTest(path, _) => path,
908+
other => panic!("cannot resolve relative path in non-file source `{}`", other),
909+
};
910+
result.pop();
911+
result.push(path);
912+
result
913+
} else {
914+
path
915+
}
916+
}
892917
}
893918

894919
/// Extracts a string literal from the macro expanded version of `expr`,

src/libsyntax/ext/expand.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12531253
return noop_visit_attribute(at, self);
12541254
}
12551255

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

1305-
if e.kind() == ErrorKind::NotFound {
1306-
err.help("external doc paths are relative to the crate root");
1307-
}
1308-
13091305
err.emit();
13101306
}
13111307
}

src/libsyntax/ext/source_util.rs

+5-27
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ use crate::symbol::Symbol;
88
use crate::tokenstream;
99

1010
use smallvec::SmallVec;
11-
use syntax_pos::{self, Pos, Span, FileName};
11+
use syntax_pos::{self, Pos, Span};
1212

1313
use std::fs;
1414
use std::io::ErrorKind;
15-
use std::path::PathBuf;
1615
use rustc_data_structures::sync::Lrc;
1716

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

8584
struct ExpandResult<'a> {
8685
p: parse::parser::Parser<'a>,
@@ -115,7 +114,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To
115114
Some(f) => f,
116115
None => return DummyResult::expr(sp)
117116
};
118-
let file = res_rel_file(cx, sp, file);
117+
let file = cx.resolve_path(file, sp);
119118
match fs::read_to_string(&file) {
120119
Ok(src) => {
121120
let interned_src = Symbol::intern(&src);
@@ -143,7 +142,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
143142
Some(f) => f,
144143
None => return DummyResult::expr(sp)
145144
};
146-
let file = res_rel_file(cx, sp, file);
145+
let file = cx.resolve_path(file, sp);
147146
match fs::read(&file) {
148147
Ok(bytes) => {
149148
// Add the contents to the source map if it contains UTF-8.
@@ -164,24 +163,3 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::
164163
}
165164
}
166165
}
167-
168-
// resolve a file-system path to an absolute file-system path (if it
169-
// isn't already)
170-
fn res_rel_file(cx: &mut ExtCtxt<'_>, sp: syntax_pos::Span, arg: String) -> PathBuf {
171-
let arg = PathBuf::from(arg);
172-
// Relative paths are resolved relative to the file in which they are found
173-
// after macro expansion (that is, they are unhygienic).
174-
if !arg.is_absolute() {
175-
let callsite = sp.source_callsite();
176-
let mut path = match cx.source_map().span_to_unmapped_path(callsite) {
177-
FileName::Real(path) => path,
178-
FileName::DocTest(path, _) => path,
179-
other => panic!("cannot resolve relative path in non-file source `{}`", other),
180-
};
181-
path.pop();
182-
path.push(arg);
183-
path
184-
} else {
185-
arg
186-
}
187-
}

src/test/ui/extern/external-doc-error.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

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

98
#[doc(include = "auxiliary/invalid-utf8.txt")]
109
pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file

src/test/ui/extern/external-doc-error.stderr

+5-7
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,33 @@ error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
33
|
44
LL | #[doc(include = "not-a-file.md")]
55
| ^^^^^^^^^^^^^^^ couldn't read file
6-
|
7-
= help: external doc paths are relative to the crate root
86

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

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

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

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

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

0 commit comments

Comments
 (0)