diff --git a/Cargo.lock b/Cargo.lock index 18dfe890a0c1e..ce1f705bdffad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2131,6 +2131,7 @@ dependencies = [ "rustc-workspace-hack", "rustc_version", "shell-escape", + "smallvec 1.4.2", ] [[package]] diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 896af8a9191c2..d1bbf74307c6b 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -94,7 +94,14 @@ pub fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, true, output, visited); if cpp_like_names { - output.push('*'); + // Slices and `&str` are treated like C++ pointers when computing debug + // info for MSVC debugger. However, adding '*' at the end of these types' names + // causes the .natvis engine for WinDbg to fail to display their data, so we opt these + // types out to aid debugging in MSVC. + match *inner_type.kind() { + ty::Slice(_) | ty::Str => {} + _ => output.push('*'), + } } } ty::Array(inner_type, len) => { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index af9926400ca44..aec0fc253ca5e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -366,11 +366,25 @@ impl LintBuffer { /// ``` /// /// The `{{produces}}` tag will be automatically replaced with the output from -/// the example by the build system. You can build and view the rustc book -/// with `x.py doc --stage=1 src/doc/rustc --open`. If the lint example is too -/// complex to run as a simple example (for example, it needs an extern -/// crate), mark it with `ignore` and manually paste the expected output below -/// the example. +/// the example by the build system. If the lint example is too complex to run +/// as a simple example (for example, it needs an extern crate), mark the code +/// block with `ignore` and manually replace the `{{produces}}` line with the +/// expected output in a `text` code block. +/// +/// If this is a rustdoc-only lint, then only include a brief introduction +/// with a link with the text `[rustdoc book]` so that the validator knows +/// that this is for rustdoc only (see BROKEN_INTRA_DOC_LINKS as an example). +/// +/// Commands to view and test the documentation: +/// +/// * `./x.py doc --stage=1 src/doc/rustc --open`: Builds the rustc book and opens it. +/// * `./x.py test src/tools/lint-docs`: Validates that the lint docs have the +/// correct style, and that the code example actually emits the expected +/// lint. +/// +/// If you have already built the compiler, and you want to make changes to +/// just the doc comments, then use the `--keep-stage=0` flag with the above +/// commands to avoid rebuilding the compiler. #[macro_export] macro_rules! declare_lint { ($(#[$attr:meta])* $vis: vis $NAME: ident, $Level: ident, $desc: expr) => ( diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b438be0696ac1..66c709b408098 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -996,6 +996,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"), no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED], "prevent automatic injection of the profiler_builtins crate"), + normalize_docs: bool = (false, parse_bool, [TRACKED], + "normalize associated items in rustdoc when generating documentation"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], "pass `-install_name @rpath/...` to the macOS linker (default: no)"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 834dd4656ff76..b13019146568c 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; use std::cmp::Ordering::{Equal, Greater, Less}; -use std::str::from_utf8; +use std::str::{from_utf8, from_utf8_unchecked}; #[test] fn test_le() { @@ -1971,3 +1971,97 @@ fn test_str_escapes() { "; assert_eq!(x, r"\\"); // extraneous whitespace stripped } + +#[test] +fn const_str_ptr() { + const A: [u8; 2] = ['h' as u8, 'i' as u8]; + const B: &'static [u8; 2] = &A; + const C: *const u8 = B as *const u8; + + unsafe { + let foo = &A as *const u8; + assert_eq!(foo, C); + assert_eq!(from_utf8_unchecked(&A), "hi"); + assert_eq!(*C, A[0]); + assert_eq!(*(&B[0] as *const u8), A[0]); + } +} + +#[test] +fn utf8() { + let yen: char = '¥'; // 0xa5 + let c_cedilla: char = 'ç'; // 0xe7 + let thorn: char = 'þ'; // 0xfe + let y_diaeresis: char = 'ÿ'; // 0xff + let pi: char = 'Π'; // 0x3a0 + + assert_eq!(yen as isize, 0xa5); + assert_eq!(c_cedilla as isize, 0xe7); + assert_eq!(thorn as isize, 0xfe); + assert_eq!(y_diaeresis as isize, 0xff); + assert_eq!(pi as isize, 0x3a0); + + assert_eq!(pi as isize, '\u{3a0}' as isize); + assert_eq!('\x0a' as isize, '\n' as isize); + + let bhutan: String = "འབྲུག་ཡུལ།".to_string(); + let japan: String = "日本".to_string(); + let uzbekistan: String = "Ўзбекистон".to_string(); + let austria: String = "Österreich".to_string(); + + let bhutan_e: String = + "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); + let japan_e: String = "\u{65e5}\u{672c}".to_string(); + let uzbekistan_e: String = + "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); + let austria_e: String = "\u{d6}sterreich".to_string(); + + let oo: char = 'Ö'; + assert_eq!(oo as isize, 0xd6); + + fn check_str_eq(a: String, b: String) { + let mut i: isize = 0; + for ab in a.bytes() { + println!("{}", i); + println!("{}", ab); + let bb: u8 = b.as_bytes()[i as usize]; + println!("{}", bb); + assert_eq!(ab, bb); + i += 1; + } + } + + check_str_eq(bhutan, bhutan_e); + check_str_eq(japan, japan_e); + check_str_eq(uzbekistan, uzbekistan_e); + check_str_eq(austria, austria_e); +} + +#[test] +fn utf8_chars() { + // Chars of 1, 2, 3, and 4 bytes + let chs: Vec = vec!['e', 'é', '€', '\u{10000}']; + let s: String = chs.iter().cloned().collect(); + let schs: Vec = s.chars().collect(); + + assert_eq!(s.len(), 10); + assert_eq!(s.chars().count(), 4); + assert_eq!(schs.len(), 4); + assert_eq!(schs.iter().cloned().collect::(), s); + + assert!((from_utf8(s.as_bytes()).is_ok())); + // invalid prefix + assert!((!from_utf8(&[0x80]).is_ok())); + // invalid 2 byte prefix + assert!((!from_utf8(&[0xc0]).is_ok())); + assert!((!from_utf8(&[0xc0, 0x10]).is_ok())); + // invalid 3 byte prefix + assert!((!from_utf8(&[0xe0]).is_ok())); + assert!((!from_utf8(&[0xe0, 0x10]).is_ok())); + assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok())); + // invalid 4 byte prefix + assert!((!from_utf8(&[0xf0]).is_ok())); + assert!((!from_utf8(&[0xf0, 0x10]).is_ok())); + assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok())); + assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok())); +} diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index 3244bbc2d670d..66c25e449df2b 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -408,3 +408,56 @@ fn ascii_const() { const BYTE_IS_ASCII: bool = 97u8.is_ascii(); assert!(BYTE_IS_ASCII); } + +#[test] +fn ascii_ctype_const() { + macro_rules! suite { + ( $( $fn:ident => [$a:ident, $A:ident, $nine:ident, $dot:ident, $space:ident]; )* ) => { + $( + mod $fn { + const CHAR_A_LOWER: bool = 'a'.$fn(); + const CHAR_A_UPPER: bool = 'A'.$fn(); + const CHAR_NINE: bool = '9'.$fn(); + const CHAR_DOT: bool = '.'.$fn(); + const CHAR_SPACE: bool = ' '.$fn(); + + const U8_A_LOWER: bool = b'a'.$fn(); + const U8_A_UPPER: bool = b'A'.$fn(); + const U8_NINE: bool = b'9'.$fn(); + const U8_DOT: bool = b'.'.$fn(); + const U8_SPACE: bool = b' '.$fn(); + + pub fn run() { + assert_eq!(CHAR_A_LOWER, $a); + assert_eq!(CHAR_A_UPPER, $A); + assert_eq!(CHAR_NINE, $nine); + assert_eq!(CHAR_DOT, $dot); + assert_eq!(CHAR_SPACE, $space); + + assert_eq!(U8_A_LOWER, $a); + assert_eq!(U8_A_UPPER, $A); + assert_eq!(U8_NINE, $nine); + assert_eq!(U8_DOT, $dot); + assert_eq!(U8_SPACE, $space); + } + } + )* + + $( $fn::run(); )* + } + } + + suite! { + // 'a' 'A' '9' '.' ' ' + is_ascii_alphabetic => [true, true, false, false, false]; + is_ascii_uppercase => [false, true, false, false, false]; + is_ascii_lowercase => [true, false, false, false, false]; + is_ascii_alphanumeric => [true, true, true, false, false]; + is_ascii_digit => [false, false, true, false, false]; + is_ascii_hexdigit => [true, true, true, false, false]; + is_ascii_punctuation => [false, false, false, true, false]; + is_ascii_graphic => [true, true, true, true, false]; + is_ascii_whitespace => [false, false, false, false, true]; + is_ascii_control => [false, false, false, false, false]; + } +} diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index acbd913982c1f..75528ebb54eaf 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -101,3 +101,82 @@ fn static_init() { assert!(S_INT.fetch_add(1, SeqCst) == 0); assert!(S_UINT.fetch_add(1, SeqCst) == 0); } + +#[test] +fn atomic_access_bool() { + static mut ATOMIC: AtomicBool = AtomicBool::new(false); + + unsafe { + assert_eq!(*ATOMIC.get_mut(), false); + ATOMIC.store(true, SeqCst); + assert_eq!(*ATOMIC.get_mut(), true); + ATOMIC.fetch_or(false, SeqCst); + assert_eq!(*ATOMIC.get_mut(), true); + ATOMIC.fetch_and(false, SeqCst); + assert_eq!(*ATOMIC.get_mut(), false); + ATOMIC.fetch_nand(true, SeqCst); + assert_eq!(*ATOMIC.get_mut(), true); + ATOMIC.fetch_xor(true, SeqCst); + assert_eq!(*ATOMIC.get_mut(), false); + } +} + +#[test] +fn atomic_alignment() { + use std::mem::{align_of, size_of}; + + #[cfg(target_has_atomic = "8")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "ptr")] + assert_eq!(align_of::>(), size_of::>()); + #[cfg(target_has_atomic = "8")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "8")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "16")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "16")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "32")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "32")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "64")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "64")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "128")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "128")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "ptr")] + assert_eq!(align_of::(), size_of::()); + #[cfg(target_has_atomic = "ptr")] + assert_eq!(align_of::(), size_of::()); +} + +#[test] +fn atomic_compare_exchange() { + use Ordering::*; + + static ATOMIC: AtomicIsize = AtomicIsize::new(0); + + ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok(); + ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok(); + ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok(); + ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok(); + ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok(); + ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok(); + ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok(); + ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok(); + ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok(); + ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok(); + ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok(); + ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok(); + ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok(); + ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok(); + ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok(); + ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok(); + ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok(); + ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); +} diff --git a/library/core/tests/bool.rs b/library/core/tests/bool.rs index e89eb2c7f94d5..e40f0482aee3e 100644 --- a/library/core/tests/bool.rs +++ b/library/core/tests/bool.rs @@ -1,3 +1,87 @@ +use core::cmp::Ordering::{Equal, Greater, Less}; +use core::ops::{BitAnd, BitOr, BitXor}; + +#[test] +fn test_bool() { + assert_eq!(false.eq(&true), false); + assert_eq!(false == false, true); + assert_eq!(false != true, true); + assert_eq!(false.ne(&false), false); + + assert_eq!(false.bitand(false), false); + assert_eq!(true.bitand(false), false); + assert_eq!(false.bitand(true), false); + assert_eq!(true.bitand(true), true); + + assert_eq!(false & false, false); + assert_eq!(true & false, false); + assert_eq!(false & true, false); + assert_eq!(true & true, true); + + assert_eq!(false.bitor(false), false); + assert_eq!(true.bitor(false), true); + assert_eq!(false.bitor(true), true); + assert_eq!(true.bitor(true), true); + + assert_eq!(false | false, false); + assert_eq!(true | false, true); + assert_eq!(false | true, true); + assert_eq!(true | true, true); + + assert_eq!(false.bitxor(false), false); + assert_eq!(true.bitxor(false), true); + assert_eq!(false.bitxor(true), true); + assert_eq!(true.bitxor(true), false); + + assert_eq!(false ^ false, false); + assert_eq!(true ^ false, true); + assert_eq!(false ^ true, true); + assert_eq!(true ^ true, false); + + assert_eq!(!true, false); + assert_eq!(!false, true); + + let s = false.to_string(); + assert_eq!(s, "false"); + let s = true.to_string(); + assert_eq!(s, "true"); + + assert!(true > false); + assert!(!(false > true)); + + assert!(false < true); + assert!(!(true < false)); + + assert!(false <= false); + assert!(false >= false); + assert!(true <= true); + assert!(true >= true); + + assert!(false <= true); + assert!(!(false >= true)); + assert!(true >= false); + assert!(!(true <= false)); + + assert_eq!(true.cmp(&true), Equal); + assert_eq!(false.cmp(&false), Equal); + assert_eq!(true.cmp(&false), Greater); + assert_eq!(false.cmp(&true), Less); +} + +#[test] +pub fn test_bool_not() { + if !false { + assert!((true)); + } else { + assert!((false)); + } + if !true { + assert!((false)); + } else { + assert!((true)); + } +} + #[test] fn test_bool_to_option() { assert_eq!(false.then_some(0), None); diff --git a/library/core/tests/cmp.rs b/library/core/tests/cmp.rs index 835289daf715a..11cf7add07ada 100644 --- a/library/core/tests/cmp.rs +++ b/library/core/tests/cmp.rs @@ -132,3 +132,74 @@ fn ordering_const() { const THEN: Ordering = Equal.then(ORDERING); assert_eq!(THEN, Greater); } + +#[test] +fn cmp_default() { + // Test default methods in PartialOrd and PartialEq + + #[derive(Debug)] + struct Fool(bool); + + impl PartialEq for Fool { + fn eq(&self, other: &Fool) -> bool { + let Fool(this) = *self; + let Fool(other) = *other; + this != other + } + } + + struct Int(isize); + + impl PartialEq for Int { + fn eq(&self, other: &Int) -> bool { + let Int(this) = *self; + let Int(other) = *other; + this == other + } + } + + impl PartialOrd for Int { + fn partial_cmp(&self, other: &Int) -> Option { + let Int(this) = *self; + let Int(other) = *other; + this.partial_cmp(&other) + } + } + + struct RevInt(isize); + + impl PartialEq for RevInt { + fn eq(&self, other: &RevInt) -> bool { + let RevInt(this) = *self; + let RevInt(other) = *other; + this == other + } + } + + impl PartialOrd for RevInt { + fn partial_cmp(&self, other: &RevInt) -> Option { + let RevInt(this) = *self; + let RevInt(other) = *other; + other.partial_cmp(&this) + } + } + + assert!(Int(2) > Int(1)); + assert!(Int(2) >= Int(1)); + assert!(Int(1) >= Int(1)); + assert!(Int(1) < Int(2)); + assert!(Int(1) <= Int(2)); + assert!(Int(1) <= Int(1)); + + assert!(RevInt(2) < RevInt(1)); + assert!(RevInt(2) <= RevInt(1)); + assert!(RevInt(1) <= RevInt(1)); + assert!(RevInt(1) > RevInt(2)); + assert!(RevInt(1) >= RevInt(2)); + assert!(RevInt(1) >= RevInt(1)); + + assert_eq!(Fool(true), Fool(false)); + assert!(Fool(true) != Fool(true)); + assert!(Fool(false) != Fool(false)); + assert_eq!(Fool(false), Fool(true)); +} diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs index 6b8a989fa426f..ec4b49da384c3 100644 --- a/library/core/tests/iter.rs +++ b/library/core/tests/iter.rs @@ -3493,3 +3493,15 @@ fn test_flatten_non_fused_inner() { assert_eq!(iter.next(), Some(1)); assert_eq!(iter.next(), None); } + +#[test] +pub fn extend_for_unit() { + let mut x = 0; + { + let iter = (0..5).map(|_| { + x += 1; + }); + ().extend(iter); + } + assert_eq!(x, 5); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 1efb3b7411898..106c9fe5da3e6 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -8,6 +8,7 @@ #![feature(bound_cloned)] #![feature(box_syntax)] #![feature(cell_update)] +#![feature(cfg_target_has_atomic)] #![feature(const_assume)] #![feature(const_cell_into_inner)] #![feature(core_intrinsics)] @@ -63,6 +64,7 @@ #![feature(int_bits_const)] #![feature(nonzero_leading_trailing_zeros)] #![feature(const_option)] +#![feature(integer_atomics)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; @@ -82,6 +84,7 @@ mod hash; mod intrinsics; mod iter; mod lazy; +mod macros; mod manually_drop; mod mem; mod nonzero; @@ -98,3 +101,4 @@ mod str_lossy; mod task; mod time; mod tuple; +mod unicode; diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs new file mode 100644 index 0000000000000..482f3c1c99840 --- /dev/null +++ b/library/core/tests/macros.rs @@ -0,0 +1,14 @@ +#[test] +fn assert_eq_trailing_comma() { + assert_eq!(1, 1,); +} + +#[test] +fn assert_escape() { + assert!(r#"☃\backslash"#.contains("\\")); +} + +#[test] +fn assert_ne_trailing_comma() { + assert_ne!(1, 2,); +} diff --git a/library/core/tests/num/wrapping.rs b/library/core/tests/num/wrapping.rs index 5d4ecb2669a96..01defab2b38f0 100644 --- a/library/core/tests/num/wrapping.rs +++ b/library/core/tests/num/wrapping.rs @@ -74,3 +74,236 @@ wrapping_test!(u64, u64::MIN, u64::MAX); #[cfg(not(target_os = "emscripten"))] wrapping_test!(u128, u128::MIN, u128::MAX); wrapping_test!(usize, usize::MIN, usize::MAX); + +// Don't warn about overflowing ops on 32-bit platforms +#[cfg_attr(target_pointer_width = "32", allow(const_err))] +fn wrapping_int_api() { + assert_eq!(i8::MAX.wrapping_add(1), i8::MIN); + assert_eq!(i16::MAX.wrapping_add(1), i16::MIN); + assert_eq!(i32::MAX.wrapping_add(1), i32::MIN); + assert_eq!(i64::MAX.wrapping_add(1), i64::MIN); + assert_eq!(isize::MAX.wrapping_add(1), isize::MIN); + + assert_eq!(i8::MIN.wrapping_sub(1), i8::MAX); + assert_eq!(i16::MIN.wrapping_sub(1), i16::MAX); + assert_eq!(i32::MIN.wrapping_sub(1), i32::MAX); + assert_eq!(i64::MIN.wrapping_sub(1), i64::MAX); + assert_eq!(isize::MIN.wrapping_sub(1), isize::MAX); + + assert_eq!(u8::MAX.wrapping_add(1), u8::MIN); + assert_eq!(u16::MAX.wrapping_add(1), u16::MIN); + assert_eq!(u32::MAX.wrapping_add(1), u32::MIN); + assert_eq!(u64::MAX.wrapping_add(1), u64::MIN); + assert_eq!(usize::MAX.wrapping_add(1), usize::MIN); + + assert_eq!(u8::MIN.wrapping_sub(1), u8::MAX); + assert_eq!(u16::MIN.wrapping_sub(1), u16::MAX); + assert_eq!(u32::MIN.wrapping_sub(1), u32::MAX); + assert_eq!(u64::MIN.wrapping_sub(1), u64::MAX); + assert_eq!(usize::MIN.wrapping_sub(1), usize::MAX); + + assert_eq!((0xfe_u8 as i8).wrapping_mul(16), (0xe0_u8 as i8)); + assert_eq!((0xfedc_u16 as i16).wrapping_mul(16), (0xedc0_u16 as i16)); + assert_eq!((0xfedc_ba98_u32 as i32).wrapping_mul(16), (0xedcb_a980_u32 as i32)); + assert_eq!( + (0xfedc_ba98_7654_3217_u64 as i64).wrapping_mul(16), + (0xedcb_a987_6543_2170_u64 as i64) + ); + + match () { + #[cfg(target_pointer_width = "32")] + () => { + assert_eq!((0xfedc_ba98_u32 as isize).wrapping_mul(16), (0xedcb_a980_u32 as isize)); + } + #[cfg(target_pointer_width = "64")] + () => { + assert_eq!( + (0xfedc_ba98_7654_3217_u64 as isize).wrapping_mul(16), + (0xedcb_a987_6543_2170_u64 as isize) + ); + } + } + + assert_eq!((0xfe as u8).wrapping_mul(16), (0xe0 as u8)); + assert_eq!((0xfedc as u16).wrapping_mul(16), (0xedc0 as u16)); + assert_eq!((0xfedc_ba98 as u32).wrapping_mul(16), (0xedcb_a980 as u32)); + assert_eq!((0xfedc_ba98_7654_3217 as u64).wrapping_mul(16), (0xedcb_a987_6543_2170 as u64)); + + match () { + #[cfg(target_pointer_width = "32")] + () => { + assert_eq!((0xfedc_ba98 as usize).wrapping_mul(16), (0xedcb_a980 as usize)); + } + #[cfg(target_pointer_width = "64")] + () => { + assert_eq!( + (0xfedc_ba98_7654_3217 as usize).wrapping_mul(16), + (0xedcb_a987_6543_2170 as usize) + ); + } + } + + macro_rules! check_mul_no_wrap { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_mul($f), ($e) * $f); + }; + } + macro_rules! check_mul_wraps { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_mul($f), $e); + }; + } + + check_mul_no_wrap!(0xfe_u8 as i8, -1); + check_mul_no_wrap!(0xfedc_u16 as i16, -1); + check_mul_no_wrap!(0xfedc_ba98_u32 as i32, -1); + check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); + check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); + + check_mul_no_wrap!(0xfe_u8 as i8, -2); + check_mul_no_wrap!(0xfedc_u16 as i16, -2); + check_mul_no_wrap!(0xfedc_ba98_u32 as i32, -2); + check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); + check_mul_no_wrap!(0xfedc_ba98_fedc_ba98_u64 as u64 as isize, -2); + + check_mul_no_wrap!(0xfe_u8 as i8, 2); + check_mul_no_wrap!(0xfedc_u16 as i16, 2); + check_mul_no_wrap!(0xfedc_ba98_u32 as i32, 2); + check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); + check_mul_no_wrap!(0xfedc_ba98_fedc_ba98_u64 as u64 as isize, 2); + + check_mul_wraps!(0x80_u8 as i8, -1); + check_mul_wraps!(0x8000_u16 as i16, -1); + check_mul_wraps!(0x8000_0000_u32 as i32, -1); + check_mul_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); + match () { + #[cfg(target_pointer_width = "32")] + () => { + check_mul_wraps!(0x8000_0000_u32 as isize, -1); + } + #[cfg(target_pointer_width = "64")] + () => { + check_mul_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); + } + } + + macro_rules! check_div_no_wrap { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_div($f), ($e) / $f); + }; + } + macro_rules! check_div_wraps { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_div($f), $e); + }; + } + + check_div_no_wrap!(0xfe_u8 as i8, -1); + check_div_no_wrap!(0xfedc_u16 as i16, -1); + check_div_no_wrap!(0xfedc_ba98_u32 as i32, -1); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); + + check_div_no_wrap!(0xfe_u8 as i8, -2); + check_div_no_wrap!(0xfedc_u16 as i16, -2); + check_div_no_wrap!(0xfedc_ba98_u32 as i32, -2); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -2); + + check_div_no_wrap!(0xfe_u8 as i8, 2); + check_div_no_wrap!(0xfedc_u16 as i16, 2); + check_div_no_wrap!(0xfedc_ba98_u32 as i32, 2); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); + check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, 2); + + check_div_wraps!(-128 as i8, -1); + check_div_wraps!(0x8000_u16 as i16, -1); + check_div_wraps!(0x8000_0000_u32 as i32, -1); + check_div_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); + match () { + #[cfg(target_pointer_width = "32")] + () => { + check_div_wraps!(0x8000_0000_u32 as isize, -1); + } + #[cfg(target_pointer_width = "64")] + () => { + check_div_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); + } + } + + macro_rules! check_rem_no_wrap { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_rem($f), ($e) % $f); + }; + } + macro_rules! check_rem_wraps { + ($e:expr, $f:expr) => { + assert_eq!(($e).wrapping_rem($f), 0); + }; + } + + check_rem_no_wrap!(0xfe_u8 as i8, -1); + check_rem_no_wrap!(0xfedc_u16 as i16, -1); + check_rem_no_wrap!(0xfedc_ba98_u32 as i32, -1); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); + + check_rem_no_wrap!(0xfe_u8 as i8, -2); + check_rem_no_wrap!(0xfedc_u16 as i16, -2); + check_rem_no_wrap!(0xfedc_ba98_u32 as i32, -2); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -2); + + check_rem_no_wrap!(0xfe_u8 as i8, 2); + check_rem_no_wrap!(0xfedc_u16 as i16, 2); + check_rem_no_wrap!(0xfedc_ba98_u32 as i32, 2); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); + check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, 2); + + check_rem_wraps!(0x80_u8 as i8, -1); + check_rem_wraps!(0x8000_u16 as i16, -1); + check_rem_wraps!(0x8000_0000_u32 as i32, -1); + check_rem_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); + match () { + #[cfg(target_pointer_width = "32")] + () => { + check_rem_wraps!(0x8000_0000_u32 as isize, -1); + } + #[cfg(target_pointer_width = "64")] + () => { + check_rem_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); + } + } + + macro_rules! check_neg_no_wrap { + ($e:expr) => { + assert_eq!(($e).wrapping_neg(), -($e)); + }; + } + macro_rules! check_neg_wraps { + ($e:expr) => { + assert_eq!(($e).wrapping_neg(), ($e)); + }; + } + + check_neg_no_wrap!(0xfe_u8 as i8); + check_neg_no_wrap!(0xfedc_u16 as i16); + check_neg_no_wrap!(0xfedc_ba98_u32 as i32); + check_neg_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64); + check_neg_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize); + + check_neg_wraps!(0x80_u8 as i8); + check_neg_wraps!(0x8000_u16 as i16); + check_neg_wraps!(0x8000_0000_u32 as i32); + check_neg_wraps!(0x8000_0000_0000_0000_u64 as i64); + match () { + #[cfg(target_pointer_width = "32")] + () => { + check_neg_wraps!(0x8000_0000_u32 as isize); + } + #[cfg(target_pointer_width = "64")] + () => { + check_neg_wraps!(0x8000_0000_0000_0000_u64 as isize); + } + } +} diff --git a/library/core/tests/ops.rs b/library/core/tests/ops.rs index e9d595e65e2b2..53e5539fad91c 100644 --- a/library/core/tests/ops.rs +++ b/library/core/tests/ops.rs @@ -1,4 +1,5 @@ use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; +use core::ops::{Deref, DerefMut}; // Test the Range structs and syntax. @@ -197,3 +198,35 @@ fn range_structural_match() { _ => unreachable!(), } } + +// Test Deref implementations + +#[test] +fn deref_mut_on_ref() { + // Test that `&mut T` implements `DerefMut` + + fn inc + DerefMut>(mut t: T) { + *t += 1; + } + + let mut x: isize = 5; + inc(&mut x); + assert_eq!(x, 6); +} + +#[test] +fn deref_on_ref() { + // Test that `&T` and `&mut T` implement `Deref` + + fn deref>(t: T) -> U { + *t + } + + let x: isize = 3; + let y = deref(&x); + assert_eq!(y, 3); + + let mut x: isize = 4; + let y = deref(&mut x); + assert_eq!(y, 4); +} diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index ae814efec2086..5388b4756245a 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -402,3 +402,13 @@ fn test_unwrap_drop() { assert_eq!(x.get(), 0); } + +#[test] +pub fn option_ext() { + let thing = "{{ f }}"; + let f = thing.find("{{"); + + if f.is_none() { + println!("None!"); + } +} diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 1970b17e26721..57c2fb06c16dd 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -400,3 +400,16 @@ fn align_offset_weird_strides() { } assert!(!x); } + +#[test] +fn offset_from() { + let mut a = [0; 5]; + let ptr1: *mut i32 = &mut a[1]; + let ptr2: *mut i32 = &mut a[3]; + unsafe { + assert_eq!(ptr2.offset_from(ptr1), 2); + assert_eq!(ptr1.offset_from(ptr2), -2); + assert_eq!(ptr1.offset(2), ptr2); + assert_eq!(ptr2.offset(-2), ptr1); + } +} diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs index 39ea4831b9b86..81660870e95e4 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -320,3 +320,41 @@ fn result_const() { const IS_ERR: bool = RESULT.is_err(); assert!(!IS_ERR) } + +#[test] +fn result_opt_conversions() { + #[derive(Copy, Clone, Debug, PartialEq)] + struct BadNumErr; + + fn try_num(x: i32) -> Result { + if x <= 5 { Ok(x + 1) } else { Err(BadNumErr) } + } + + type ResOpt = Result, BadNumErr>; + type OptRes = Option>; + + let mut x: ResOpt = Ok(Some(5)); + let mut y: OptRes = Some(Ok(5)); + assert_eq!(x, y.transpose()); + assert_eq!(x.transpose(), y); + + x = Ok(None); + y = None; + assert_eq!(x, y.transpose()); + assert_eq!(x.transpose(), y); + + x = Err(BadNumErr); + y = Some(Err(BadNumErr)); + assert_eq!(x, y.transpose()); + assert_eq!(x.transpose(), y); + + let res: Result, BadNumErr> = (0..10) + .map(|x| { + let y = try_num(x)?; + Ok(if y % 2 == 0 { Some(y - 1) } else { None }) + }) + .filter_map(Result::transpose) + .collect(); + + assert_eq!(res, Err(BadNumErr)) +} diff --git a/library/core/tests/unicode.rs b/library/core/tests/unicode.rs new file mode 100644 index 0000000000000..c28ea859115e1 --- /dev/null +++ b/library/core/tests/unicode.rs @@ -0,0 +1,5 @@ +#[test] +pub fn version() { + let (major, _minor, _update) = core::unicode::UNICODE_VERSION; + assert!(major >= 10); +} diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index d9fbdd1b5e794..44fb3adf07023 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -936,4 +936,10 @@ fn ip_const() { const IS_MULTICAST: bool = IP_ADDRESS.is_multicast(); assert!(!IS_MULTICAST); + + const IS_IP_V4: bool = IP_ADDRESS.is_ipv4(); + assert!(IS_IP_V4); + + const IS_IP_V6: bool = IP_ADDRESS.is_ipv6(); + assert!(!IS_IP_V6); } diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index c94fc41178dfe..0e55ec648c9c5 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -1,5 +1,6 @@ use std::env::*; use std::ffi::{OsStr, OsString}; +use std::path::PathBuf; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; @@ -76,3 +77,63 @@ fn test_env_set_var() { assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" })); } + +#[test] +#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] +#[allow(deprecated)] +fn env_home_dir() { + fn var_to_os_string(var: Result) -> Option { + match var { + Ok(var) => Some(OsString::from(var)), + Err(VarError::NotUnicode(var)) => Some(var), + _ => None, + } + } + + cfg_if::cfg_if! { + if #[cfg(unix)] { + let oldhome = var_to_os_string(var("HOME")); + + set_var("HOME", "/home/MountainView"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + remove_var("HOME"); + if cfg!(target_os = "android") { + assert!(home_dir().is_none()); + } else { + // When HOME is not set, some platforms return `None`, + // but others return `Some` with a default. + // Just check that it is not "/home/MountainView". + assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + } + + if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } + } else if #[cfg(windows)] { + let oldhome = var_to_os_string(var("HOME")); + let olduserprofile = var_to_os_string(var("USERPROFILE")); + + remove_var("HOME"); + remove_var("USERPROFILE"); + + assert!(home_dir().is_some()); + + set_var("HOME", "/home/MountainView"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + remove_var("HOME"); + + set_var("USERPROFILE", "/home/MountainView"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + set_var("HOME", "/home/MountainView"); + set_var("USERPROFILE", "/home/PaloAlto"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + remove_var("HOME"); + remove_var("USERPROFILE"); + + if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } + if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); } + } + } +} diff --git a/src/test/ui/sleep.rs b/library/std/tests/thread.rs similarity index 60% rename from src/test/ui/sleep.rs rename to library/std/tests/thread.rs index f3f8d7259c44e..754b264c6ad93 100644 --- a/src/test/ui/sleep.rs +++ b/library/std/tests/thread.rs @@ -1,17 +1,16 @@ -// run-pass -// ignore-emscripten no threads support - -use std::thread::{self, sleep}; -use std::time::Duration; use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; -fn main() { +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn sleep() { let finished = Arc::new(Mutex::new(false)); let t_finished = finished.clone(); thread::spawn(move || { - sleep(Duration::new(u64::MAX, 0)); + thread::sleep(Duration::new(u64::MAX, 0)); *t_finished.lock().unwrap() = true; }); - sleep(Duration::from_millis(100)); + thread::sleep(Duration::from_millis(100)); assert_eq!(*finished.lock().unwrap(), false); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 508d785834fce..b5bbb6372ee6c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -413,6 +413,7 @@ impl<'a> Builder<'a> { test::TheBook, test::UnstableBook, test::RustcBook, + test::LintDocs, test::RustcGuide, test::EmbeddedBook, test::EditionGuide, @@ -730,6 +731,7 @@ impl<'a> Builder<'a> { .env("CFG_RELEASE_CHANNEL", &self.config.channel) .env("RUSTDOC_REAL", self.rustdoc(compiler)) .env("RUSTC_BOOTSTRAP", "1") + .arg("-Znormalize_docs") .arg("-Winvalid_codeblock_attributes"); if self.config.deny_warnings { cmd.arg("-Dwarnings"); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index af7f7eff89418..a296a1fe3f4fe 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -527,6 +527,7 @@ impl Step for Rustc { cargo.rustdocflag("--document-private-items"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("-Zunstable-options"); + cargo.rustdocflag("-Znormalize-docs"); compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. @@ -726,6 +727,7 @@ fn symlink_dir_force(config: &Config, src: &Path, dst: &Path) -> io::Result<()> pub struct RustcBook { pub compiler: Compiler, pub target: TargetSelection, + pub validate: bool, } impl Step for RustcBook { @@ -742,6 +744,7 @@ impl Step for RustcBook { run.builder.ensure(RustcBook { compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), target: run.target, + validate: false, }); } @@ -772,6 +775,9 @@ impl Step for RustcBook { if builder.config.verbose() { cmd.arg("--verbose"); } + if self.validate { + cmd.arg("--validate"); + } // If the lib directories are in an unusual location (changed in // config.toml), then this needs to explicitly update the dylib search // path. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e087e2b8ff153..1df50322a0732 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -688,38 +688,6 @@ impl Step for RustdocJSNotStd { } } -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustdocUi { - pub target: TargetSelection, - pub compiler: Compiler, -} - -impl Step for RustdocUi { - type Output = (); - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/test/rustdoc-ui") - } - - fn make_run(run: RunConfig<'_>) { - let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); - run.builder.ensure(RustdocUi { target: run.target, compiler }); - } - - fn run(self, builder: &Builder<'_>) { - builder.ensure(Compiletest { - compiler: self.compiler, - target: self.target, - mode: "ui", - suite: "rustdoc-ui", - path: "src/test/rustdoc-ui", - compare_mode: None, - }) - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Tidy; @@ -934,6 +902,7 @@ default_test!(Debuginfo { path: "src/test/debuginfo", mode: "debuginfo", suite: host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" }); host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" }); +host_test!(RustdocUi { path: "src/test/rustdoc-ui", mode: "ui", suite: "rustdoc-ui" }); host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" }); @@ -2115,3 +2084,36 @@ impl Step for TierCheck { try_run(builder, &mut cargo.into()); } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct LintDocs { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Step for LintDocs { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/lint-docs") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(LintDocs { + compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), + target: run.target, + }); + } + + /// Tests that the lint examples in the rustc book generate the correct + /// lints and have the expected format. + fn run(self, builder: &Builder<'_>) { + builder.ensure(crate::doc::RustcBook { + compiler: self.compiler, + target: self.target, + validate: true, + }); + } +} diff --git a/src/doc/book b/src/doc/book index 13e1c05420bca..a190438d77d28 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 13e1c05420bca86ecc79e4ba5b6d02de9bd53c62 +Subproject commit a190438d77d28041f24da4f6592e287fab073a61 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index ca8169e69b479..ba34b8a968f95 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit ca8169e69b479f615855d0eece7e318138fcfc00 +Subproject commit ba34b8a968f9531d38c4dc4411d5568b7c076bfe diff --git a/src/doc/nomicon b/src/doc/nomicon index 23c49f1d5ce47..d8383b65f7948 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 23c49f1d5ce4720bc5b7e3a920f47eccc8da6b63 +Subproject commit d8383b65f7948c2ca19191b3b4bd709b403aaf45 diff --git a/src/doc/reference b/src/doc/reference index a7de763c21329..a8afdca5d0715 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit a7de763c213292f5b44bf10acb87ffa38724814d +Subproject commit a8afdca5d0715b2257b6f8b9a032fd4dd7dae855 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 1886fda6981b7..236c734a2cb32 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 1886fda6981b723e4de637074455558f8bc1e83c +Subproject commit 236c734a2cb323541b3394f98682cb981b9ec086 diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 52cfb08cdc9a4..ce8caae375e98 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -156,7 +156,7 @@ target | std | host | notes `aarch64-apple-tvos` | * | | ARM64 tvOS `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ? | | -`aarch64-unknown-netbsd` | ? | | +`aarch64-unknown-netbsd` | ✓ | ✓ | `aarch64-unknown-openbsd` | ✓ | ✓ | ARM64 OpenBSD `aarch64-unknown-redox` | ? | | ARM64 Redox OS `aarch64-uwp-windows-msvc` | ? | | @@ -167,7 +167,7 @@ target | std | host | notes `armv6-unknown-netbsd-eabihf` | ? | | `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD -`armv7-unknown-netbsd-eabihf` | ? | | +`armv7-unknown-netbsd-eabihf` | ✓ | ✓ | `armv7-wrs-vxworks-eabihf` | ? | | `armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat `armv7s-apple-ios` | ✓ | | @@ -178,7 +178,7 @@ target | std | host | notes `i686-pc-windows-msvc` | ✓ | | 32-bit Windows XP support `i686-unknown-uefi` | ? | | 32-bit UEFI `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku -`i686-unknown-netbsd` | ✓ | | NetBSD/i386 with SSE2 +`i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 `i686-unknown-openbsd` | ✓ | ✓ | 32-bit OpenBSD `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | @@ -194,7 +194,7 @@ target | std | host | notes `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | -`powerpc-unknown-netbsd` | ? | | +`powerpc-unknown-netbsd` | ✓ | ✓ | `powerpc-wrs-vxworks` | ? | | `powerpc-wrs-vxworks-spe` | ? | | `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index ff996b2a9254e..8feef9c259c13 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -124,6 +124,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), stability: None, + const_stability: None, deprecation: None, kind: ImplItem(Impl { unsafety: hir::Unsafety::Normal, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 5721927d0ec8d..33b5e84c5e074 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -113,6 +113,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), stability: None, + const_stability: None, deprecation: None, kind: ImplItem(Impl { unsafety: hir::Unsafety::Normal, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 61121c776f491..f3067360f0680 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -483,6 +483,7 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) def_id: DefId::local(CRATE_DEF_INDEX), visibility: clean::Public, stability: None, + const_stability: None, deprecation: None, kind: clean::ImportItem(clean::Import::new_simple( item.ident.to_string(), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9e8ce45292417..d294d8f02a80f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1515,9 +1515,12 @@ impl Clean for hir::Ty<'_> { } /// Returns `None` if the type could not be normalized -#[allow(unreachable_code, unused_variables)] fn normalize(cx: &DocContext<'tcx>, ty: Ty<'_>) -> Option> { - return None; // HACK: low-churn fix for #79459 while we wait for a trait normalization fix + // HACK: low-churn fix for #79459 while we wait for a trait normalization fix + if !cx.tcx.sess.opts.debugging_opts.normalize_docs { + return None; + } + use crate::rustc_trait_selection::infer::TyCtxtInferExt; use crate::rustc_trait_selection::traits::query::normalize::AtExt; use rustc_middle::traits::ObligationCause; @@ -2189,6 +2192,7 @@ fn clean_extern_crate( def_id: crate_def_id, visibility: krate.vis.clean(cx), stability: None, + const_stability: None, deprecation: None, kind: ExternCrateItem(name.clean(cx), path), }] @@ -2259,6 +2263,7 @@ impl Clean> for doctree::Import<'_> { def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), stability: None, + const_stability: None, deprecation: None, kind: ImportItem(Import::new_simple( self.name.clean(cx), @@ -2279,6 +2284,7 @@ impl Clean> for doctree::Import<'_> { def_id: DefId::local(CRATE_DEF_INDEX), visibility: self.vis.clean(cx), stability: None, + const_stability: None, deprecation: None, kind: ImportItem(inner), }] diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2283b71a94fef..38d25d8d98e85 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -12,7 +12,7 @@ use rustc_ast::attr; use rustc_ast::util::comments::beautify_doc_string; use rustc_ast::{self as ast, AttrStyle}; use rustc_ast::{FloatTy, IntTy, UintTy}; -use rustc_attr::{Stability, StabilityLevel}; +use rustc_attr::{ConstStability, Stability, StabilityLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_feature::UnstableFeatures; use rustc_hir as hir; @@ -87,6 +87,7 @@ crate struct Item { crate def_id: DefId, crate stability: Option, crate deprecation: Option, + crate const_stability: Option, } impl fmt::Debug for Item { @@ -155,6 +156,7 @@ impl Item { visibility: cx.tcx.visibility(def_id).clean(cx), stability: cx.tcx.lookup_stability(def_id).cloned(), deprecation: cx.tcx.lookup_deprecation(def_id).clean(cx), + const_stability: cx.tcx.lookup_const_stability(def_id).cloned(), } } @@ -262,6 +264,13 @@ impl Item { } } + crate fn const_stable_since(&self) -> Option { + match self.const_stability?.level { + StabilityLevel::Stable { since, .. } => Some(since.as_str()), + StabilityLevel::Unstable { .. } => None, + } + } + crate fn is_non_exhaustive(&self) -> bool { self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index bbd4be88e6a8b..de620a35c80d7 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1692,13 +1692,13 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top write!(buf, "

"); - if let Some(version) = item.stable_since() { - write!( - buf, - "{0}", - version - ); - } + render_stability_since_raw( + buf, + item.stable_since().as_deref(), + item.const_stable_since().as_deref(), + None, + None, + ); write!( buf, "\ @@ -2476,6 +2476,7 @@ fn render_implementor( AssocItemLink::Anchor(None), RenderMode::Normal, implementor.impl_item.stable_since().as_deref(), + implementor.impl_item.const_stable_since().as_deref(), false, Some(use_absolute), false, @@ -2506,6 +2507,7 @@ fn render_impls( assoc_link, RenderMode::Normal, containing_item.stable_since().as_deref(), + containing_item.const_stable_since().as_deref(), true, None, false, @@ -2756,6 +2758,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, assoc_link, RenderMode::Normal, implementor.impl_item.stable_since().as_deref(), + implementor.impl_item.const_stable_since().as_deref(), false, None, true, @@ -2898,10 +2901,40 @@ fn assoc_type( } } -fn render_stability_since_raw(w: &mut Buffer, ver: Option<&str>, containing_ver: Option<&str>) { +fn render_stability_since_raw( + w: &mut Buffer, + ver: Option<&str>, + const_ver: Option<&str>, + containing_ver: Option<&str>, + containing_const_ver: Option<&str>, +) { + let ver = ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None }); + + let const_ver = const_ver.and_then(|inner| if !inner.is_empty() { Some(inner) } else { None }); + if let Some(v) = ver { - if containing_ver != ver && !v.is_empty() { - write!(w, "{0}", v) + if let Some(cv) = const_ver { + if const_ver != containing_const_ver { + write!( + w, + "{0} (const: {1})", + v, cv + ); + } else if ver != containing_ver { + write!( + w, + "{0}", + v + ); + } + } else { + if ver != containing_ver { + write!( + w, + "{0}", + v + ); + } } } } @@ -2910,7 +2943,9 @@ fn render_stability_since(w: &mut Buffer, item: &clean::Item, containing_item: & render_stability_since_raw( w, item.stable_since().as_deref(), + item.const_stable_since().as_deref(), containing_item.stable_since().as_deref(), + containing_item.const_stable_since().as_deref(), ) } @@ -3462,6 +3497,7 @@ fn render_assoc_items( AssocItemLink::Anchor(None), render_mode, containing_item.stable_since().as_deref(), + containing_item.const_stable_since().as_deref(), true, None, false, @@ -3654,6 +3690,7 @@ fn render_impl( link: AssocItemLink<'_>, render_mode: RenderMode, outer_version: Option<&str>, + outer_const_version: Option<&str>, show_def_docs: bool, use_absolute: Option, is_on_foreign_type: bool, @@ -3705,11 +3742,13 @@ fn render_impl( ); } write!(w, "", id); - let since = i.impl_item.stability.as_ref().and_then(|s| match s.level { - StabilityLevel::Stable { since } => Some(since.as_str()), - StabilityLevel::Unstable { .. } => None, - }); - render_stability_since_raw(w, since.as_deref(), outer_version); + render_stability_since_raw( + w, + i.impl_item.stable_since().as_deref(), + i.impl_item.const_stable_since().as_deref(), + outer_version, + outer_const_version, + ); write_srclink(cx, &i.impl_item, w, cache); write!(w, "

"); @@ -3746,6 +3785,7 @@ fn render_impl( render_mode: RenderMode, is_default_item: bool, outer_version: Option<&str>, + outer_const_version: Option<&str>, trait_: Option<&clean::Trait>, show_def_docs: bool, cache: &Cache, @@ -3775,7 +3815,13 @@ fn render_impl( write!(w, ""); render_assoc_item(w, item, link.anchor(&id), ItemType::Impl); write!(w, ""); - render_stability_since_raw(w, item.stable_since().as_deref(), outer_version); + render_stability_since_raw( + w, + item.stable_since().as_deref(), + item.const_stable_since().as_deref(), + outer_version, + outer_const_version, + ); write_srclink(cx, item, w, cache); write!(w, ""); } @@ -3791,7 +3837,13 @@ fn render_impl( write!(w, "

", id, item_type, extra_class); assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), ""); write!(w, ""); - render_stability_since_raw(w, item.stable_since().as_deref(), outer_version); + render_stability_since_raw( + w, + item.stable_since().as_deref(), + item.const_stable_since().as_deref(), + outer_version, + outer_const_version, + ); write_srclink(cx, item, w, cache); write!(w, "

"); } @@ -3854,6 +3906,7 @@ fn render_impl( render_mode, false, outer_version, + outer_const_version, trait_, show_def_docs, cache, @@ -3868,6 +3921,7 @@ fn render_impl( parent: &clean::Item, render_mode: RenderMode, outer_version: Option<&str>, + outer_const_version: Option<&str>, show_def_docs: bool, cache: &Cache, ) { @@ -3888,6 +3942,7 @@ fn render_impl( render_mode, true, outer_version, + outer_const_version, None, show_def_docs, cache, @@ -3909,6 +3964,7 @@ fn render_impl( &i.impl_item, render_mode, outer_version, + outer_const_version, show_def_docs, cache, ); diff --git a/src/test/rustdoc-ui/.gitattributes b/src/test/rustdoc-ui/.gitattributes deleted file mode 100644 index 2bcabdffb3d93..0000000000000 --- a/src/test/rustdoc-ui/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -intra-links-warning-crlf.rs eol=crlf diff --git a/src/test/rustdoc-ui/intra-doc/.gitattributes b/src/test/rustdoc-ui/intra-doc/.gitattributes new file mode 100644 index 0000000000000..6c125fac52f5e --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/.gitattributes @@ -0,0 +1 @@ +warning-crlf.rs eol=crlf diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc/alias-ice.rs similarity index 100% rename from src/test/rustdoc-ui/intra-doc-alias-ice.rs rename to src/test/rustdoc-ui/intra-doc/alias-ice.rs diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc/alias-ice.stderr similarity index 82% rename from src/test/rustdoc-ui/intra-doc-alias-ice.stderr rename to src/test/rustdoc-ui/intra-doc/alias-ice.stderr index 771fc2204f5f8..3db5fad4cfbdc 100644 --- a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr +++ b/src/test/rustdoc-ui/intra-doc/alias-ice.stderr @@ -1,11 +1,11 @@ error: unresolved link to `TypeAlias::hoge` - --> $DIR/intra-doc-alias-ice.rs:5:30 + --> $DIR/alias-ice.rs:5:30 | LL | /// [broken cross-reference](TypeAlias::hoge) | ^^^^^^^^^^^^^^^ the type alias `TypeAlias` has no associated item named `hoge` | note: the lint level is defined here - --> $DIR/intra-doc-alias-ice.rs:1:9 + --> $DIR/alias-ice.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.rs b/src/test/rustdoc-ui/intra-doc/ambiguity.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-ambiguity.rs rename to src/test/rustdoc-ui/intra-doc/ambiguity.rs diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.stderr b/src/test/rustdoc-ui/intra-doc/ambiguity.stderr similarity index 90% rename from src/test/rustdoc-ui/intra-links-ambiguity.stderr rename to src/test/rustdoc-ui/intra-doc/ambiguity.stderr index 936055da01cf7..7e967dc88bcdd 100644 --- a/src/test/rustdoc-ui/intra-links-ambiguity.stderr +++ b/src/test/rustdoc-ui/intra-doc/ambiguity.stderr @@ -1,11 +1,11 @@ error: `true` is both a module and a builtin type - --> $DIR/intra-links-ambiguity.rs:38:6 + --> $DIR/ambiguity.rs:38:6 | LL | /// [true] | ^^^^ ambiguous link | note: the lint level is defined here - --> $DIR/intra-links-ambiguity.rs:1:9 + --> $DIR/ambiguity.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | /// [prim@true] | ^^^^^^^^^ error: `ambiguous` is both a struct and a function - --> $DIR/intra-links-ambiguity.rs:27:6 + --> $DIR/ambiguity.rs:27:6 | LL | /// [`ambiguous`] is ambiguous. | ^^^^^^^^^^^ ambiguous link @@ -34,7 +34,7 @@ LL | /// [`ambiguous()`] is ambiguous. | ^^^^^^^^^^^^^ error: `ambiguous` is both a struct and a function - --> $DIR/intra-links-ambiguity.rs:29:6 + --> $DIR/ambiguity.rs:29:6 | LL | /// [ambiguous] is ambiguous. | ^^^^^^^^^ ambiguous link @@ -49,7 +49,7 @@ LL | /// [ambiguous()] is ambiguous. | ^^^^^^^^^^^ error: `multi_conflict` is a struct, a function, and a macro - --> $DIR/intra-links-ambiguity.rs:31:6 + --> $DIR/ambiguity.rs:31:6 | LL | /// [`multi_conflict`] is a three-way conflict. | ^^^^^^^^^^^^^^^^ ambiguous link @@ -68,7 +68,7 @@ LL | /// [`multi_conflict!`] is a three-way conflict. | ^^^^^^^^^^^^^^^^^ error: `type_and_value` is both a module and a constant - --> $DIR/intra-links-ambiguity.rs:33:16 + --> $DIR/ambiguity.rs:33:16 | LL | /// Ambiguous [type_and_value]. | ^^^^^^^^^^^^^^ ambiguous link @@ -83,7 +83,7 @@ LL | /// Ambiguous [const@type_and_value]. | ^^^^^^^^^^^^^^^^^^^^ error: `foo::bar` is both an enum and a function - --> $DIR/intra-links-ambiguity.rs:35:42 + --> $DIR/ambiguity.rs:35:42 | LL | /// Ambiguous non-implied shortcut link [`foo::bar`]. | ^^^^^^^^^^ ambiguous link diff --git a/src/test/rustdoc-ui/intra-links-anchors.rs b/src/test/rustdoc-ui/intra-doc/anchors.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-anchors.rs rename to src/test/rustdoc-ui/intra-doc/anchors.rs diff --git a/src/test/rustdoc-ui/intra-links-anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr similarity index 81% rename from src/test/rustdoc-ui/intra-links-anchors.stderr rename to src/test/rustdoc-ui/intra-doc/anchors.stderr index 1825a4ad1fa6b..5b272d960d50f 100644 --- a/src/test/rustdoc-ui/intra-links-anchors.stderr +++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr @@ -1,29 +1,29 @@ error: `Foo::f#hola` contains an anchor, but links to fields are already anchored - --> $DIR/intra-links-anchors.rs:25:15 + --> $DIR/anchors.rs:25:15 | LL | /// Or maybe [Foo::f#hola]. | ^^^^^^^^^^^ contains invalid anchor | note: the lint level is defined here - --> $DIR/intra-links-anchors.rs:1:9 + --> $DIR/anchors.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ error: `hello#people#!` contains multiple anchors - --> $DIR/intra-links-anchors.rs:31:28 + --> $DIR/anchors.rs:31:28 | LL | /// Another anchor error: [hello#people#!]. | ^^^^^^^^^^^^^^ contains invalid anchor error: `Enum::A#whatever` contains an anchor, but links to variants are already anchored - --> $DIR/intra-links-anchors.rs:37:28 + --> $DIR/anchors.rs:37:28 | LL | /// Damn enum's variants: [Enum::A#whatever]. | ^^^^^^^^^^^^^^^^ contains invalid anchor error: `u32#hello` contains an anchor, but links to builtin types are already anchored - --> $DIR/intra-links-anchors.rs:43:6 + --> $DIR/anchors.rs:43:6 | LL | /// [u32#hello] | ^^^^^^^^^ contains invalid anchor diff --git a/src/test/rustdoc-ui/auxiliary/intra-doc-broken.rs b/src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs similarity index 100% rename from src/test/rustdoc-ui/auxiliary/intra-doc-broken.rs rename to src/test/rustdoc-ui/intra-doc/auxiliary/intra-doc-broken.rs diff --git a/src/test/rustdoc-ui/intra-doc-broken-reexport.rs b/src/test/rustdoc-ui/intra-doc/broken-reexport.rs similarity index 100% rename from src/test/rustdoc-ui/intra-doc-broken-reexport.rs rename to src/test/rustdoc-ui/intra-doc/broken-reexport.rs diff --git a/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-disambiguator-mismatch.rs rename to src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.rs diff --git a/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr similarity index 80% rename from src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr rename to src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr index 2e732baf6e01e..2f5f3daa29785 100644 --- a/src/test/rustdoc-ui/intra-links-disambiguator-mismatch.stderr +++ b/src/test/rustdoc-ui/intra-doc/disambiguator-mismatch.stderr @@ -1,18 +1,18 @@ error: incompatible link kind for `S` - --> $DIR/intra-links-disambiguator-mismatch.rs:14:14 + --> $DIR/disambiguator-mismatch.rs:14:14 | LL | /// Link to [struct@S] | ^^^^^^^^ help: to link to the enum, prefix with `enum@`: `enum@S` | note: the lint level is defined here - --> $DIR/intra-links-disambiguator-mismatch.rs:1:9 + --> $DIR/disambiguator-mismatch.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ = note: this link resolved to an enum, which is not a struct error: incompatible link kind for `S` - --> $DIR/intra-links-disambiguator-mismatch.rs:19:14 + --> $DIR/disambiguator-mismatch.rs:19:14 | LL | /// Link to [mod@S] | ^^^^^ help: to link to the enum, prefix with `enum@`: `enum@S` @@ -20,7 +20,7 @@ LL | /// Link to [mod@S] = note: this link resolved to an enum, which is not a module error: incompatible link kind for `S` - --> $DIR/intra-links-disambiguator-mismatch.rs:24:14 + --> $DIR/disambiguator-mismatch.rs:24:14 | LL | /// Link to [union@S] | ^^^^^^^ help: to link to the enum, prefix with `enum@`: `enum@S` @@ -28,7 +28,7 @@ LL | /// Link to [union@S] = note: this link resolved to an enum, which is not a union error: incompatible link kind for `S` - --> $DIR/intra-links-disambiguator-mismatch.rs:29:14 + --> $DIR/disambiguator-mismatch.rs:29:14 | LL | /// Link to [trait@S] | ^^^^^^^ help: to link to the enum, prefix with `enum@`: `enum@S` @@ -36,7 +36,7 @@ LL | /// Link to [trait@S] = note: this link resolved to an enum, which is not a trait error: incompatible link kind for `T` - --> $DIR/intra-links-disambiguator-mismatch.rs:34:14 + --> $DIR/disambiguator-mismatch.rs:34:14 | LL | /// Link to [struct@T] | ^^^^^^^^ help: to link to the trait, prefix with `trait@`: `trait@T` @@ -44,7 +44,7 @@ LL | /// Link to [struct@T] = note: this link resolved to a trait, which is not a struct error: incompatible link kind for `m` - --> $DIR/intra-links-disambiguator-mismatch.rs:39:14 + --> $DIR/disambiguator-mismatch.rs:39:14 | LL | /// Link to [derive@m] | ^^^^^^^^ help: to link to the macro, add an exclamation mark: `m!` @@ -52,7 +52,7 @@ LL | /// Link to [derive@m] = note: this link resolved to a macro, which is not a derive macro error: incompatible link kind for `s` - --> $DIR/intra-links-disambiguator-mismatch.rs:44:14 + --> $DIR/disambiguator-mismatch.rs:44:14 | LL | /// Link to [const@s] | ^^^^^^^ help: to link to the static, prefix with `static@`: `static@s` @@ -60,7 +60,7 @@ LL | /// Link to [const@s] = note: this link resolved to a static, which is not a constant error: incompatible link kind for `c` - --> $DIR/intra-links-disambiguator-mismatch.rs:49:14 + --> $DIR/disambiguator-mismatch.rs:49:14 | LL | /// Link to [static@c] | ^^^^^^^^ help: to link to the constant, prefix with `const@`: `const@c` @@ -68,7 +68,7 @@ LL | /// Link to [static@c] = note: this link resolved to a constant, which is not a static error: incompatible link kind for `c` - --> $DIR/intra-links-disambiguator-mismatch.rs:54:14 + --> $DIR/disambiguator-mismatch.rs:54:14 | LL | /// Link to [fn@c] | ^^^^ help: to link to the constant, prefix with `const@`: `const@c` @@ -76,7 +76,7 @@ LL | /// Link to [fn@c] = note: this link resolved to a constant, which is not a function error: incompatible link kind for `c` - --> $DIR/intra-links-disambiguator-mismatch.rs:59:14 + --> $DIR/disambiguator-mismatch.rs:59:14 | LL | /// Link to [c()] | ^^^ help: to link to the constant, prefix with `const@`: `const@c` @@ -84,7 +84,7 @@ LL | /// Link to [c()] = note: this link resolved to a constant, which is not a function error: incompatible link kind for `f` - --> $DIR/intra-links-disambiguator-mismatch.rs:64:14 + --> $DIR/disambiguator-mismatch.rs:64:14 | LL | /// Link to [const@f] | ^^^^^^^ help: to link to the function, add parentheses: `f()` diff --git a/src/test/rustdoc-ui/intra-link-double-anchor.rs b/src/test/rustdoc-ui/intra-doc/double-anchor.rs similarity index 100% rename from src/test/rustdoc-ui/intra-link-double-anchor.rs rename to src/test/rustdoc-ui/intra-doc/double-anchor.rs diff --git a/src/test/rustdoc-ui/intra-link-double-anchor.stderr b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr similarity index 85% rename from src/test/rustdoc-ui/intra-link-double-anchor.stderr rename to src/test/rustdoc-ui/intra-doc/double-anchor.stderr index 3282ec8b79379..1cd9231eded4d 100644 --- a/src/test/rustdoc-ui/intra-link-double-anchor.stderr +++ b/src/test/rustdoc-ui/intra-doc/double-anchor.stderr @@ -1,5 +1,5 @@ warning: `with#anchor#error` contains multiple anchors - --> $DIR/intra-link-double-anchor.rs:5:18 + --> $DIR/double-anchor.rs:5:18 | LL | /// docs [label][with#anchor#error] | ^^^^^^^^^^^^^^^^^ contains invalid anchor diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-doc/errors.rs similarity index 100% rename from src/test/rustdoc-ui/intra-link-errors.rs rename to src/test/rustdoc-ui/intra-doc/errors.rs diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-doc/errors.stderr similarity index 83% rename from src/test/rustdoc-ui/intra-link-errors.stderr rename to src/test/rustdoc-ui/intra-doc/errors.stderr index be98cac94ece7..21c806108e3af 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-doc/errors.stderr @@ -1,95 +1,95 @@ error: unresolved link to `path::to::nonexistent::module` - --> $DIR/intra-link-errors.rs:7:6 + --> $DIR/errors.rs:7:6 | LL | /// [path::to::nonexistent::module] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope | note: the lint level is defined here - --> $DIR/intra-link-errors.rs:1:9 + --> $DIR/errors.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ error: unresolved link to `path::to::nonexistent::macro` - --> $DIR/intra-link-errors.rs:11:6 + --> $DIR/errors.rs:11:6 | LL | /// [path::to::nonexistent::macro!] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope error: unresolved link to `path::to::nonexistent::type` - --> $DIR/intra-link-errors.rs:15:6 + --> $DIR/errors.rs:15:6 | LL | /// [type@path::to::nonexistent::type] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:19:6 + --> $DIR/errors.rs:19:6 | LL | /// [std::io::not::here] | ^^^^^^^^^^^^^^^^^^ no item named `not` in module `io` error: unresolved link to `std::io::not::here` - --> $DIR/intra-link-errors.rs:23:6 + --> $DIR/errors.rs:23:6 | LL | /// [type@std::io::not::here] | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `not` in module `io` error: unresolved link to `std::io::Error::x` - --> $DIR/intra-link-errors.rs:27:6 + --> $DIR/errors.rs:27:6 | LL | /// [std::io::Error::x] | ^^^^^^^^^^^^^^^^^ the struct `Error` has no field or associated item named `x` error: unresolved link to `std::io::ErrorKind::x` - --> $DIR/intra-link-errors.rs:31:6 + --> $DIR/errors.rs:31:6 | LL | /// [std::io::ErrorKind::x] | ^^^^^^^^^^^^^^^^^^^^^ the enum `ErrorKind` has no variant or associated item named `x` error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:35:6 + --> $DIR/errors.rs:35:6 | LL | /// [f::A] | ^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `f::A` - --> $DIR/intra-link-errors.rs:39:6 + --> $DIR/errors.rs:39:6 | LL | /// [f::A!] | ^^^^^ `f` is a function, not a module or type, and cannot have associated items error: unresolved link to `S::A` - --> $DIR/intra-link-errors.rs:43:6 + --> $DIR/errors.rs:43:6 | LL | /// [S::A] | ^^^^ the struct `S` has no field or associated item named `A` error: unresolved link to `S::fmt` - --> $DIR/intra-link-errors.rs:47:6 + --> $DIR/errors.rs:47:6 | LL | /// [S::fmt] | ^^^^^^ the struct `S` has no field or associated item named `fmt` error: unresolved link to `E::D` - --> $DIR/intra-link-errors.rs:51:6 + --> $DIR/errors.rs:51:6 | LL | /// [E::D] | ^^^^ the enum `E` has no variant or associated item named `D` error: unresolved link to `u8::not_found` - --> $DIR/intra-link-errors.rs:55:6 + --> $DIR/errors.rs:55:6 | LL | /// [u8::not_found] | ^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `std::primitive::u8::not_found` - --> $DIR/intra-link-errors.rs:59:6 + --> $DIR/errors.rs:59:6 | LL | /// [std::primitive::u8::not_found] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the builtin type `u8` has no associated item named `not_found` error: unresolved link to `Vec::into_iter` - --> $DIR/intra-link-errors.rs:63:6 + --> $DIR/errors.rs:63:6 | LL | /// [type@Vec::into_iter] | ^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL | /// [type@Vec::into_iter] | help: to link to the associated function, add parentheses: `Vec::into_iter()` error: unresolved link to `S` - --> $DIR/intra-link-errors.rs:68:6 + --> $DIR/errors.rs:68:6 | LL | /// [S!] | ^^ @@ -107,7 +107,7 @@ LL | /// [S!] | help: to link to the struct, prefix with `struct@`: `struct@S` error: unresolved link to `S::h` - --> $DIR/intra-link-errors.rs:78:6 + --> $DIR/errors.rs:78:6 | LL | /// [type@S::h] | ^^^^^^^^^ @@ -116,7 +116,7 @@ LL | /// [type@S::h] | help: to link to the associated function, add parentheses: `S::h()` error: unresolved link to `T::g` - --> $DIR/intra-link-errors.rs:86:6 + --> $DIR/errors.rs:86:6 | LL | /// [type@T::g] | ^^^^^^^^^ @@ -125,13 +125,13 @@ LL | /// [type@T::g] | help: to link to the associated function, add parentheses: `T::g()` error: unresolved link to `T::h` - --> $DIR/intra-link-errors.rs:91:6 + --> $DIR/errors.rs:91:6 | LL | /// [T::h!] | ^^^^^ the trait `T` has no macro named `h` error: unresolved link to `m` - --> $DIR/intra-link-errors.rs:98:6 + --> $DIR/errors.rs:98:6 | LL | /// [m()] | ^^^ diff --git a/src/test/rustdoc-ui/intra-link-malformed-generics.rs b/src/test/rustdoc-ui/intra-doc/malformed-generics.rs similarity index 100% rename from src/test/rustdoc-ui/intra-link-malformed-generics.rs rename to src/test/rustdoc-ui/intra-doc/malformed-generics.rs diff --git a/src/test/rustdoc-ui/intra-link-malformed-generics.stderr b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr similarity index 73% rename from src/test/rustdoc-ui/intra-link-malformed-generics.stderr rename to src/test/rustdoc-ui/intra-doc/malformed-generics.stderr index fe5d4cd1bbffa..2e1b22807bc39 100644 --- a/src/test/rustdoc-ui/intra-link-malformed-generics.stderr +++ b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr @@ -1,89 +1,89 @@ error: unresolved link to `Vec<` - --> $DIR/intra-link-malformed-generics.rs:3:6 + --> $DIR/malformed-generics.rs:3:6 | LL | //! [Vec<] | ^^^^ unbalanced angle brackets | note: the lint level is defined here - --> $DIR/intra-link-malformed-generics.rs:1:9 + --> $DIR/malformed-generics.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ error: unresolved link to `Vec $DIR/intra-link-malformed-generics.rs:4:6 + --> $DIR/malformed-generics.rs:4:6 | LL | //! [Vec` - --> $DIR/intra-link-malformed-generics.rs:5:6 + --> $DIR/malformed-generics.rs:5:6 | LL | //! [Vec] | ^^^^^^^^^^ unbalanced angle brackets error: unresolved link to `Vec>>` - --> $DIR/intra-link-malformed-generics.rs:6:6 + --> $DIR/malformed-generics.rs:6:6 | LL | //! [Vec>>] | ^^^^^^^^^^^^ unbalanced angle brackets error: unresolved link to `Vec>>` - --> $DIR/intra-link-malformed-generics.rs:7:6 + --> $DIR/malformed-generics.rs:7:6 | LL | //! [Vec>>] | ^^^^^^^^ unbalanced angle brackets error: unresolved link to ` $DIR/intra-link-malformed-generics.rs:8:6 + --> $DIR/malformed-generics.rs:8:6 | LL | //! [ $DIR/intra-link-malformed-generics.rs:9:6 + --> $DIR/malformed-generics.rs:9:6 | LL | //! [Vec::<] | ^^^^^^ unbalanced angle brackets error: unresolved link to `` - --> $DIR/intra-link-malformed-generics.rs:10:6 + --> $DIR/malformed-generics.rs:10:6 | LL | //! [] | ^^^ missing type for generic parameters error: unresolved link to `` - --> $DIR/intra-link-malformed-generics.rs:11:6 + --> $DIR/malformed-generics.rs:11:6 | LL | //! [] | ^^^^^^^^^^^^^^^^ missing type for generic parameters error: unresolved link to `Vec::new` - --> $DIR/intra-link-malformed-generics.rs:12:6 + --> $DIR/malformed-generics.rs:12:6 | LL | //! [Vec::new()] | ^^^^^^^^^^^^^ has invalid path separator error: unresolved link to `Vec<>` - --> $DIR/intra-link-malformed-generics.rs:13:6 + --> $DIR/malformed-generics.rs:13:6 | LL | //! [Vec<>] | ^^^^^^^^ too many angle brackets error: unresolved link to `Vec<>` - --> $DIR/intra-link-malformed-generics.rs:14:6 + --> $DIR/malformed-generics.rs:14:6 | LL | //! [Vec<>] | ^^^^^ empty angle brackets error: unresolved link to `Vec<<>>` - --> $DIR/intra-link-malformed-generics.rs:15:6 + --> $DIR/malformed-generics.rs:15:6 | LL | //! [Vec<<>>] | ^^^^^^^ too many angle brackets error: unresolved link to `::into_iter` - --> $DIR/intra-link-malformed-generics.rs:18:6 + --> $DIR/malformed-generics.rs:18:6 | LL | //! [::into_iter] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported @@ -91,7 +91,7 @@ LL | //! [::into_iter] = note: see https://github.com/rust-lang/rust/issues/74563 for more information error: unresolved link to ` as IntoIterator>::iter` - --> $DIR/intra-link-malformed-generics.rs:19:6 + --> $DIR/malformed-generics.rs:19:6 | LL | //! [ as IntoIterator>::iter] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.rs b/src/test/rustdoc-ui/intra-doc/prim-conflict.rs similarity index 100% rename from src/test/rustdoc-ui/intra-link-prim-conflict.rs rename to src/test/rustdoc-ui/intra-doc/prim-conflict.rs diff --git a/src/test/rustdoc-ui/intra-link-prim-conflict.stderr b/src/test/rustdoc-ui/intra-doc/prim-conflict.stderr similarity index 84% rename from src/test/rustdoc-ui/intra-link-prim-conflict.stderr rename to src/test/rustdoc-ui/intra-doc/prim-conflict.stderr index 43587a80021af..01275f8d9afb0 100644 --- a/src/test/rustdoc-ui/intra-link-prim-conflict.stderr +++ b/src/test/rustdoc-ui/intra-doc/prim-conflict.stderr @@ -1,11 +1,11 @@ error: `char` is both a module and a builtin type - --> $DIR/intra-link-prim-conflict.rs:4:6 + --> $DIR/prim-conflict.rs:4:6 | LL | /// [char] | ^^^^ ambiguous link | note: the lint level is defined here - --> $DIR/intra-link-prim-conflict.rs:1:9 + --> $DIR/prim-conflict.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | /// [prim@char] | ^^^^^^^^^ error: `char` is both a module and a builtin type - --> $DIR/intra-link-prim-conflict.rs:10:6 + --> $DIR/prim-conflict.rs:10:6 | LL | /// [type@char] | ^^^^^^^^^ ambiguous link @@ -34,7 +34,7 @@ LL | /// [prim@char] | ^^^^^^^^^ error: incompatible link kind for `char` - --> $DIR/intra-link-prim-conflict.rs:19:6 + --> $DIR/prim-conflict.rs:19:6 | LL | /// [struct@char] | ^^^^^^^^^^^ help: to link to the module, prefix with `mod@`: `mod@char` @@ -42,7 +42,7 @@ LL | /// [struct@char] = note: this link resolved to a module, which is not a struct error: incompatible link kind for `char` - --> $DIR/intra-link-prim-conflict.rs:26:10 + --> $DIR/prim-conflict.rs:26:10 | LL | //! [struct@char] | ^^^^^^^^^^^ help: to link to the builtin type, prefix with `prim@`: `prim@char` diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-doc/private.private.stderr similarity index 90% rename from src/test/rustdoc-ui/intra-links-private.private.stderr rename to src/test/rustdoc-ui/intra-doc/private.private.stderr index eeef24b479747..6e11ec3e87bf9 100644 --- a/src/test/rustdoc-ui/intra-links-private.private.stderr +++ b/src/test/rustdoc-ui/intra-doc/private.private.stderr @@ -1,5 +1,5 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` - --> $DIR/intra-links-private.rs:5:11 + --> $DIR/private.rs:5:11 | LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private diff --git a/src/test/rustdoc-ui/intra-links-private.public.stderr b/src/test/rustdoc-ui/intra-doc/private.public.stderr similarity index 89% rename from src/test/rustdoc-ui/intra-links-private.public.stderr rename to src/test/rustdoc-ui/intra-doc/private.public.stderr index 3f7b17586f19e..3a6a4b664522a 100644 --- a/src/test/rustdoc-ui/intra-links-private.public.stderr +++ b/src/test/rustdoc-ui/intra-doc/private.public.stderr @@ -1,5 +1,5 @@ warning: public documentation for `DocMe` links to private item `DontDocMe` - --> $DIR/intra-links-private.rs:5:11 + --> $DIR/private.rs:5:11 | LL | /// docs [DontDocMe] | ^^^^^^^^^ this item is private diff --git a/src/test/rustdoc-ui/intra-links-private.rs b/src/test/rustdoc-ui/intra-doc/private.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-private.rs rename to src/test/rustdoc-ui/intra-doc/private.rs diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs b/src/test/rustdoc-ui/intra-doc/span-ice-55723.rs similarity index 100% rename from src/test/rustdoc-ui/intra-link-span-ice-55723.rs rename to src/test/rustdoc-ui/intra-doc/span-ice-55723.rs diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr similarity index 79% rename from src/test/rustdoc-ui/intra-link-span-ice-55723.stderr rename to src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr index d8afa9e7efd59..10ca14e850fd7 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr @@ -1,11 +1,11 @@ error: unresolved link to `i` - --> $DIR/intra-link-span-ice-55723.rs:9:10 + --> $DIR/span-ice-55723.rs:9:10 | LL | /// (arr[i]) | ^ no item named `i` in scope | note: the lint level is defined here - --> $DIR/intra-link-span-ice-55723.rs:1:9 + --> $DIR/span-ice-55723.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.rs b/src/test/rustdoc-ui/intra-doc/warning-crlf.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-warning-crlf.rs rename to src/test/rustdoc-ui/intra-doc/warning-crlf.rs diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr similarity index 83% rename from src/test/rustdoc-ui/intra-links-warning-crlf.stderr rename to src/test/rustdoc-ui/intra-doc/warning-crlf.stderr index 67c48378fd2f4..01e4282003766 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr @@ -1,5 +1,5 @@ warning: unresolved link to `error` - --> $DIR/intra-links-warning-crlf.rs:7:6 + --> $DIR/warning-crlf.rs:7:6 | LL | /// [error] | ^^^^^ no item named `error` in scope @@ -8,7 +8,7 @@ LL | /// [error] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` - --> $DIR/intra-links-warning-crlf.rs:12:11 + --> $DIR/warning-crlf.rs:12:11 | LL | /// docs [error1] | ^^^^^^ no item named `error1` in scope @@ -16,7 +16,7 @@ LL | /// docs [error1] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` - --> $DIR/intra-links-warning-crlf.rs:15:11 + --> $DIR/warning-crlf.rs:15:11 | LL | /// docs [error2] | ^^^^^^ no item named `error2` in scope @@ -24,7 +24,7 @@ LL | /// docs [error2] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` - --> $DIR/intra-links-warning-crlf.rs:23:20 + --> $DIR/warning-crlf.rs:23:20 | LL | * It also has an [error]. | ^^^^^ no item named `error` in scope diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-doc/warning.rs similarity index 100% rename from src/test/rustdoc-ui/intra-links-warning.rs rename to src/test/rustdoc-ui/intra-doc/warning.rs diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-doc/warning.stderr similarity index 86% rename from src/test/rustdoc-ui/intra-links-warning.stderr rename to src/test/rustdoc-ui/intra-doc/warning.stderr index 0b074e9d53e3d..430d18165a005 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-doc/warning.stderr @@ -1,5 +1,5 @@ warning: unresolved link to `Foo::baz` - --> $DIR/intra-links-warning.rs:3:23 + --> $DIR/warning.rs:3:23 | LL | //! Test with [Foo::baz], [Bar::foo], ... | ^^^^^^^^ the struct `Foo` has no field or associated item named `baz` @@ -7,37 +7,37 @@ LL | //! Test with [Foo::baz], [Bar::foo], ... = note: `#[warn(broken_intra_doc_links)]` on by default warning: unresolved link to `Bar::foo` - --> $DIR/intra-links-warning.rs:3:35 + --> $DIR/warning.rs:3:35 | LL | //! Test with [Foo::baz], [Bar::foo], ... | ^^^^^^^^ no item named `Bar` in scope warning: unresolved link to `Uniooon::X` - --> $DIR/intra-links-warning.rs:6:13 + --> $DIR/warning.rs:6:13 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ no item named `Uniooon` in scope warning: unresolved link to `Qux::Z` - --> $DIR/intra-links-warning.rs:6:30 + --> $DIR/warning.rs:6:30 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ no item named `Qux` in scope warning: unresolved link to `Uniooon::X` - --> $DIR/intra-links-warning.rs:10:14 + --> $DIR/warning.rs:10:14 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ no item named `Uniooon` in scope warning: unresolved link to `Qux::Z` - --> $DIR/intra-links-warning.rs:10:31 + --> $DIR/warning.rs:10:31 | LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ no item named `Qux` in scope warning: unresolved link to `Qux:Y` - --> $DIR/intra-links-warning.rs:14:13 + --> $DIR/warning.rs:14:13 | LL | /// [Qux:Y] | ^^^^^ no item named `Qux:Y` in scope @@ -45,7 +45,7 @@ LL | /// [Qux:Y] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarA` - --> $DIR/intra-links-warning.rs:21:10 + --> $DIR/warning.rs:21:10 | LL | /// bar [BarA] bar | ^^^^ no item named `BarA` in scope @@ -53,7 +53,7 @@ LL | /// bar [BarA] bar = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarB` - --> $DIR/intra-links-warning.rs:27:9 + --> $DIR/warning.rs:27:9 | LL | * bar [BarB] bar | ^^^^ no item named `BarB` in scope @@ -61,7 +61,7 @@ LL | * bar [BarB] bar = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarC` - --> $DIR/intra-links-warning.rs:34:6 + --> $DIR/warning.rs:34:6 | LL | bar [BarC] bar | ^^^^ no item named `BarC` in scope @@ -69,7 +69,7 @@ LL | bar [BarC] bar = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarD` - --> $DIR/intra-links-warning.rs:45:1 + --> $DIR/warning.rs:45:1 | LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `BarF` - --> $DIR/intra-links-warning.rs:50:9 + --> $DIR/warning.rs:50:9 | LL | #[doc = $f] | ^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz"); = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) warning: unresolved link to `error` - --> $DIR/intra-links-warning.rs:58:30 + --> $DIR/warning.rs:58:30 | LL | * time to introduce a link [error]*/ | ^^^^^ no item named `error` in scope @@ -107,7 +107,7 @@ LL | * time to introduce a link [error]*/ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` - --> $DIR/intra-links-warning.rs:64:30 + --> $DIR/warning.rs:64:30 | LL | * time to introduce a link [error] | ^^^^^ no item named `error` in scope @@ -115,7 +115,7 @@ LL | * time to introduce a link [error] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` - --> $DIR/intra-links-warning.rs:68:1 + --> $DIR/warning.rs:68:1 | LL | #[doc = "single line [error]"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,7 +128,7 @@ LL | #[doc = "single line [error]"] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` - --> $DIR/intra-links-warning.rs:71:1 + --> $DIR/warning.rs:71:1 | LL | #[doc = "single line with \"escaping\" [error]"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,7 +141,7 @@ LL | #[doc = "single line with \"escaping\" [error]"] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error` - --> $DIR/intra-links-warning.rs:74:1 + --> $DIR/warning.rs:74:1 | LL | / /// Item docs. LL | | #[doc="Hello there!"] @@ -156,7 +156,7 @@ LL | | /// [error] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error1` - --> $DIR/intra-links-warning.rs:80:11 + --> $DIR/warning.rs:80:11 | LL | /// docs [error1] | ^^^^^^ no item named `error1` in scope @@ -164,7 +164,7 @@ LL | /// docs [error1] = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` warning: unresolved link to `error2` - --> $DIR/intra-links-warning.rs:82:11 + --> $DIR/warning.rs:82:11 | LL | /// docs [error2] | ^^^^^^ no item named `error2` in scope diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index b3fbe377f0b96..11ba68a388fba 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + #![crate_name = "foo"] #![unstable(feature = "humans", @@ -17,6 +19,7 @@ pub const unsafe fn foo() -> u32 { 42 } pub const fn foo2() -> u32 { 42 } // @has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32' +// @has - //span '1.0.0 (const: 1.0.0)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] pub const fn bar2() -> u32 { 42 } @@ -26,6 +29,7 @@ pub const fn bar2() -> u32 { 42 } pub const unsafe fn foo2_gated() -> u32 { 42 } // @has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32' +// @has - '//span[@class="since"]' '1.0.0 (const: 1.0.0)' #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rust1", since = "1.0.0")] pub const unsafe fn bar2_gated() -> u32 { 42 } @@ -40,4 +44,10 @@ impl Foo { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature="foo", issue = "none")] pub const unsafe fn gated() -> u32 { 42 } + + // @has 'foo/struct.Foo.html' '//h4[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32' + // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)' + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_stable(feature = "rust1", since = "1.2.0")] + pub const fn stable_impl() -> u32 { 42 } } diff --git a/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs b/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs deleted file mode 100644 index bd733e1023033..0000000000000 --- a/src/test/rustdoc/intra-doc-link-mod-ambiguity.rs +++ /dev/null @@ -1,18 +0,0 @@ -// ignore-tidy-linelength - -#![deny(broken_intra_doc_links)] - - -pub fn foo() { - -} - -pub mod foo {} -// @has intra_doc_link_mod_ambiguity/struct.A.html '//a/@href' '../intra_doc_link_mod_ambiguity/foo/index.html' -/// Module is [`module@foo`] -pub struct A; - - -// @has intra_doc_link_mod_ambiguity/struct.B.html '//a/@href' '../intra_doc_link_mod_ambiguity/fn.foo.html' -/// Function is [`fn@foo`] -pub struct B; diff --git a/src/test/rustdoc/intra-links-anchors.rs b/src/test/rustdoc/intra-doc/anchors.rs similarity index 50% rename from src/test/rustdoc/intra-links-anchors.rs rename to src/test/rustdoc/intra-doc/anchors.rs index f554e16b4f475..e4f0c737bdd33 100644 --- a/src/test/rustdoc/intra-links-anchors.rs +++ b/src/test/rustdoc/intra-doc/anchors.rs @@ -3,8 +3,8 @@ /// # Anchor! pub struct Something; -// @has intra_links_anchors/struct.SomeOtherType.html -// @has - '//a/@href' '../intra_links_anchors/struct.Something.html#Anchor!' +// @has anchors/struct.SomeOtherType.html +// @has - '//a/@href' '../anchors/struct.Something.html#Anchor!' /// I want... /// diff --git a/src/test/rustdoc/intra-doc/associated-defaults.rs b/src/test/rustdoc/intra-doc/associated-defaults.rs new file mode 100644 index 0000000000000..f99d9b5baea44 --- /dev/null +++ b/src/test/rustdoc/intra-doc/associated-defaults.rs @@ -0,0 +1,27 @@ +// ignore-tidy-linelength +#![deny(intra_doc_link_resolution_failure)] +#![feature(associated_type_defaults)] + +pub trait TraitWithDefault { + type T = usize; + fn f() -> Self::T { + 0 + } +} + +/// Link to [UsesDefaults::T] and [UsesDefaults::f] +// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="../associated_defaults/struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T' +// @has 'associated_defaults/struct.UsesDefaults.html' '//a[@href="../associated_defaults/struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f' +pub struct UsesDefaults; +impl TraitWithDefault for UsesDefaults {} + +/// Link to [OverridesDefaults::T] and [OverridesDefaults::f] +// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="../associated_defaults/struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T' +// @has 'associated_defaults/struct.OverridesDefaults.html' '//a[@href="../associated_defaults/struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f' +pub struct OverridesDefaults; +impl TraitWithDefault for OverridesDefaults { + type T = bool; + fn f() -> bool { + true + } +} diff --git a/src/test/rustdoc/intra-doc/associated-items.rs b/src/test/rustdoc/intra-doc/associated-items.rs new file mode 100644 index 0000000000000..09dfbfcf68a32 --- /dev/null +++ b/src/test/rustdoc/intra-doc/associated-items.rs @@ -0,0 +1,61 @@ +// ignore-tidy-linelength +#![deny(intra_doc_link_resolution_failure)] + +/// [`std::collections::BTreeMap::into_iter`] +/// [`String::from`] is ambiguous as to which `From` impl +/// [Vec::into_iter()] uses a disambiguator +// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter' +// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from' +// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter' +pub fn foo() {} + +/// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input] +// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html"]' 'MyStruct' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.method"]' 'link from struct' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.clone"]' 'MyStruct::clone' +// @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input' +pub struct MyStruct { foo: () } + +impl Clone for MyStruct { + fn clone(&self) -> Self { + MyStruct + } +} + +pub trait T { + type Input; + fn method(i: Self::Input); +} + +impl T for MyStruct { + type Input = usize; + + /// [link from method][MyStruct::method] on method + // @has 'associated_items/struct.MyStruct.html' '//a[@href="../associated_items/struct.MyStruct.html#method.method"]' 'link from method' + fn method(i: usize) { + } +} + +/// Ambiguity between which trait to use +pub trait T1 { + fn ambiguous_method(); +} + +pub trait T2 { + fn ambiguous_method(); +} + +/// Link to [S::ambiguous_method] +// FIXME: there is no way to disambiguate these. +// Since we have `#[deny(intra_doc_failure)]`, we still know it was one or the other. +pub struct S; + +impl T1 for S { + fn ambiguous_method() {} +} + +impl T2 for S { + fn ambiguous_method() {} +} + +fn main() {} diff --git a/src/test/rustdoc/auxiliary/intra-link-extern-crate.rs b/src/test/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs similarity index 100% rename from src/test/rustdoc/auxiliary/intra-link-extern-crate.rs rename to src/test/rustdoc/intra-doc/auxiliary/intra-link-extern-crate.rs diff --git a/src/test/rustdoc/auxiliary/intra-link-pub-use.rs b/src/test/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs similarity index 100% rename from src/test/rustdoc/auxiliary/intra-link-pub-use.rs rename to src/test/rustdoc/intra-doc/auxiliary/intra-link-pub-use.rs diff --git a/src/test/rustdoc/auxiliary/intra-link-reexport-additional-docs.rs b/src/test/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs similarity index 100% rename from src/test/rustdoc/auxiliary/intra-link-reexport-additional-docs.rs rename to src/test/rustdoc/intra-doc/auxiliary/intra-link-reexport-additional-docs.rs diff --git a/src/test/rustdoc/auxiliary/intra-links-external-traits.rs b/src/test/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs similarity index 100% rename from src/test/rustdoc/auxiliary/intra-links-external-traits.rs rename to src/test/rustdoc/intra-doc/auxiliary/intra-links-external-traits.rs diff --git a/src/test/rustdoc/auxiliary/my-core.rs b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs similarity index 100% rename from src/test/rustdoc/auxiliary/my-core.rs rename to src/test/rustdoc/intra-doc/auxiliary/my-core.rs diff --git a/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs b/src/test/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs similarity index 93% rename from src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs rename to src/test/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs index 04a431d99026e..5ba132f25b471 100644 --- a/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs +++ b/src/test/rustdoc/intra-doc/auxiliary/proc-macro-macro.rs @@ -3,7 +3,6 @@ // compile-flags: --crate-type proc-macro #![crate_type="proc-macro"] -#![crate_name="intra_link_proc_macro_macro"] extern crate proc_macro; diff --git a/src/test/rustdoc/auxiliary/through-proc-macro-aux.rs b/src/test/rustdoc/intra-doc/auxiliary/through-proc-macro-aux.rs similarity index 100% rename from src/test/rustdoc/auxiliary/through-proc-macro-aux.rs rename to src/test/rustdoc/intra-doc/auxiliary/through-proc-macro-aux.rs diff --git a/src/test/rustdoc/intra-links.rs b/src/test/rustdoc/intra-doc/basic.rs similarity index 52% rename from src/test/rustdoc/intra-links.rs rename to src/test/rustdoc/intra-doc/basic.rs index 751c10925c017..7760546e1fa1c 100644 --- a/src/test/rustdoc/intra-links.rs +++ b/src/test/rustdoc/intra-doc/basic.rs @@ -1,21 +1,21 @@ -// @has intra_links/index.html -// @has - '//a/@href' '../intra_links/struct.ThisType.html' -// @has - '//a/@href' '../intra_links/struct.ThisType.html#method.this_method' -// @has - '//a/@href' '../intra_links/enum.ThisEnum.html' -// @has - '//a/@href' '../intra_links/enum.ThisEnum.html#variant.ThisVariant' -// @has - '//a/@href' '../intra_links/trait.ThisTrait.html' -// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#tymethod.this_associated_method' -// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#associatedtype.ThisAssociatedType' -// @has - '//a/@href' '../intra_links/trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST' -// @has - '//a/@href' '../intra_links/trait.ThisTrait.html' -// @has - '//a/@href' '../intra_links/type.ThisAlias.html' -// @has - '//a/@href' '../intra_links/union.ThisUnion.html' -// @has - '//a/@href' '../intra_links/fn.this_function.html' -// @has - '//a/@href' '../intra_links/constant.THIS_CONST.html' -// @has - '//a/@href' '../intra_links/static.THIS_STATIC.html' -// @has - '//a/@href' '../intra_links/macro.this_macro.html' -// @has - '//a/@href' '../intra_links/trait.SoAmbiguous.html' -// @has - '//a/@href' '../intra_links/fn.SoAmbiguous.html' +// @has basic/index.html +// @has - '//a/@href' '../basic/struct.ThisType.html' +// @has - '//a/@href' '../basic/struct.ThisType.html#method.this_method' +// @has - '//a/@href' '../basic/enum.ThisEnum.html' +// @has - '//a/@href' '../basic/enum.ThisEnum.html#variant.ThisVariant' +// @has - '//a/@href' '../basic/trait.ThisTrait.html' +// @has - '//a/@href' '../basic/trait.ThisTrait.html#tymethod.this_associated_method' +// @has - '//a/@href' '../basic/trait.ThisTrait.html#associatedtype.ThisAssociatedType' +// @has - '//a/@href' '../basic/trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST' +// @has - '//a/@href' '../basic/trait.ThisTrait.html' +// @has - '//a/@href' '../basic/type.ThisAlias.html' +// @has - '//a/@href' '../basic/union.ThisUnion.html' +// @has - '//a/@href' '../basic/fn.this_function.html' +// @has - '//a/@href' '../basic/constant.THIS_CONST.html' +// @has - '//a/@href' '../basic/static.THIS_STATIC.html' +// @has - '//a/@href' '../basic/macro.this_macro.html' +// @has - '//a/@href' '../basic/trait.SoAmbiguous.html' +// @has - '//a/@href' '../basic/fn.SoAmbiguous.html' //! In this crate we would like to link to: //! //! * [`ThisType`](ThisType) @@ -46,7 +46,7 @@ macro_rules! this_macro { () => {}; } -// @has intra_links/struct.ThisType.html '//a/@href' '../intra_links/macro.this_macro.html' +// @has basic/struct.ThisType.html '//a/@href' '../basic/macro.this_macro.html' /// another link to [`this_macro!()`] pub struct ThisType; @@ -72,10 +72,10 @@ pub trait SoAmbiguous {} pub fn SoAmbiguous() {} -// @has intra_links/struct.SomeOtherType.html '//a/@href' '../intra_links/struct.ThisType.html' -// @has - '//a/@href' '../intra_links/struct.ThisType.html#method.this_method' -// @has - '//a/@href' '../intra_links/enum.ThisEnum.html' -// @has - '//a/@href' '../intra_links/enum.ThisEnum.html#variant.ThisVariant' +// @has basic/struct.SomeOtherType.html '//a/@href' '../basic/struct.ThisType.html' +// @has - '//a/@href' '../basic/struct.ThisType.html#method.this_method' +// @has - '//a/@href' '../basic/enum.ThisEnum.html' +// @has - '//a/@href' '../basic/enum.ThisEnum.html#variant.ThisVariant' /// Shortcut links for: /// * [`ThisType`] /// * [`ThisType::this_method`] diff --git a/src/test/rustdoc/intra-link-builtin-macros.rs b/src/test/rustdoc/intra-doc/builtin-macros.rs similarity index 66% rename from src/test/rustdoc/intra-link-builtin-macros.rs rename to src/test/rustdoc/intra-doc/builtin-macros.rs index 4d40eb3b88f1b..74216a587e1da 100644 --- a/src/test/rustdoc/intra-link-builtin-macros.rs +++ b/src/test/rustdoc/intra-doc/builtin-macros.rs @@ -1,3 +1,3 @@ -// @has intra_link_builtin_macros/index.html +// @has builtin_macros/index.html // @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html' //! [cfg] diff --git a/src/test/rustdoc/intra-doc-crate/additional_doc.rs b/src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/additional_doc.rs rename to src/test/rustdoc/intra-doc/cross-crate/additional_doc.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/additional_doc.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/additional_doc.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/hidden.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/hidden.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/intra-doc-basic.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/intra-doc-basic.rs diff --git a/src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs similarity index 100% rename from src/test/rustdoc/auxiliary/intra-link-cross-crate-crate.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/intra-link-cross-crate-crate.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/macro_inner.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/macro_inner.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/module.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/module.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/module.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/module.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/proc_macro.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/proc_macro.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/submodule-inner.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-inner.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/submodule-outer.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/submodule-outer.rs diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs b/src/test/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/auxiliary/traits.rs rename to src/test/rustdoc/intra-doc/cross-crate/auxiliary/traits.rs diff --git a/src/test/rustdoc/intra-doc-crate/basic.rs b/src/test/rustdoc/intra-doc/cross-crate/basic.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/basic.rs rename to src/test/rustdoc/intra-doc/cross-crate/basic.rs diff --git a/src/test/rustdoc/intra-link-cross-crate-crate.rs b/src/test/rustdoc/intra-doc/cross-crate/crate.rs similarity index 100% rename from src/test/rustdoc/intra-link-cross-crate-crate.rs rename to src/test/rustdoc/intra-doc/cross-crate/crate.rs diff --git a/src/test/rustdoc/intra-doc-crate/hidden.rs b/src/test/rustdoc/intra-doc/cross-crate/hidden.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/hidden.rs rename to src/test/rustdoc/intra-doc/cross-crate/hidden.rs diff --git a/src/test/rustdoc/intra-doc-crate/macro.rs b/src/test/rustdoc/intra-doc/cross-crate/macro.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/macro.rs rename to src/test/rustdoc/intra-doc/cross-crate/macro.rs diff --git a/src/test/rustdoc/intra-doc-crate/module.rs b/src/test/rustdoc/intra-doc/cross-crate/module.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/module.rs rename to src/test/rustdoc/intra-doc/cross-crate/module.rs diff --git a/src/test/rustdoc/intra-doc-crate/submodule-inner.rs b/src/test/rustdoc/intra-doc/cross-crate/submodule-inner.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/submodule-inner.rs rename to src/test/rustdoc/intra-doc/cross-crate/submodule-inner.rs diff --git a/src/test/rustdoc/intra-doc-crate/submodule-outer.rs b/src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/submodule-outer.rs rename to src/test/rustdoc/intra-doc/cross-crate/submodule-outer.rs diff --git a/src/test/rustdoc/intra-doc-crate/traits.rs b/src/test/rustdoc/intra-doc/cross-crate/traits.rs similarity index 100% rename from src/test/rustdoc/intra-doc-crate/traits.rs rename to src/test/rustdoc/intra-doc/cross-crate/traits.rs diff --git a/src/test/rustdoc/intra-doc/disambiguators-removed.rs b/src/test/rustdoc/intra-doc/disambiguators-removed.rs new file mode 100644 index 0000000000000..aa0ced62aaf30 --- /dev/null +++ b/src/test/rustdoc/intra-doc/disambiguators-removed.rs @@ -0,0 +1,51 @@ +// ignore-tidy-linelength +#![deny(intra_doc_link_resolution_failure)] +// first try backticks +/// Trait: [`trait@Name`], fn: [`fn@Name`], [`Name`][`macro@Name`] +// @has disambiguators_removed/struct.AtDisambiguator.html +// @has - '//a[@href="../disambiguators_removed/trait.Name.html"][code]' "Name" +// @has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name" +// @has - '//a[@href="../disambiguators_removed/macro.Name.html"][code]' "Name" +pub struct AtDisambiguator; + +/// fn: [`Name()`], macro: [`Name!`] +// @has disambiguators_removed/struct.SymbolDisambiguator.html +// @has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name()" +// @has - '//a[@href="../disambiguators_removed/macro.Name.html"][code]' "Name!" +pub struct SymbolDisambiguator; + +// Now make sure that backticks aren't added if they weren't already there +/// [fn@Name] +// @has disambiguators_removed/trait.Name.html +// @has - '//a[@href="../disambiguators_removed/fn.Name.html"]' "Name" +// @!has - '//a[@href="../disambiguators_removed/fn.Name.html"][code]' "Name" + +// FIXME: this will turn !() into ! alone +/// [Name!()] +// @has - '//a[@href="../disambiguators_removed/macro.Name.html"]' "Name!" +pub trait Name {} + +#[allow(non_snake_case)] + +// Try collapsed reference links +/// [macro@Name][] +// @has disambiguators_removed/fn.Name.html +// @has - '//a[@href="../disambiguators_removed/macro.Name.html"]' "Name" + +// Try links that have the same text as a generated URL +/// Weird URL aligned [../disambiguators_removed/macro.Name.html][trait@Name] +// @has - '//a[@href="../disambiguators_removed/trait.Name.html"]' "../disambiguators_removed/macro.Name.html" +pub fn Name() {} + +#[macro_export] +// Rustdoc doesn't currently handle links that have weird interspersing of inline code blocks. +/// [fn@Na`m`e] +// @has disambiguators_removed/macro.Name.html +// @has - '//a[@href="../disambiguators_removed/fn.Name.html"]' "fn@Name" + +// It also doesn't handle any case where the code block isn't the whole link text: +/// [trait@`Name`] +// @has - '//a[@href="../disambiguators_removed/trait.Name.html"]' "trait@Name" +macro_rules! Name { + () => () +} diff --git a/src/test/rustdoc/intra-doc-link-enum-struct-field.rs b/src/test/rustdoc/intra-doc/enum-struct-field.rs similarity index 100% rename from src/test/rustdoc/intra-doc-link-enum-struct-field.rs rename to src/test/rustdoc/intra-doc/enum-struct-field.rs diff --git a/src/test/rustdoc/intra-link-extern-crate.rs b/src/test/rustdoc/intra-doc/extern-crate.rs similarity index 100% rename from src/test/rustdoc/intra-link-extern-crate.rs rename to src/test/rustdoc/intra-doc/extern-crate.rs diff --git a/src/test/rustdoc/intra-doc/extern-type.rs b/src/test/rustdoc/intra-doc/extern-type.rs new file mode 100644 index 0000000000000..e1934698d1fad --- /dev/null +++ b/src/test/rustdoc/intra-doc/extern-type.rs @@ -0,0 +1,17 @@ +#![feature(extern_types)] + +extern { + pub type ExternType; +} + +impl ExternType { + pub fn f(&self) { + + } +} + +// @has 'extern_type/foreigntype.ExternType.html' +// @has 'extern_type/fn.links_to_extern_type.html' \ +// 'href="../extern_type/foreigntype.ExternType.html#method.f"' +/// See also [ExternType::f] +pub fn links_to_extern_type() {} diff --git a/src/test/rustdoc/intra-links-external-traits.rs b/src/test/rustdoc/intra-doc/external-traits.rs similarity index 100% rename from src/test/rustdoc/intra-links-external-traits.rs rename to src/test/rustdoc/intra-doc/external-traits.rs diff --git a/src/test/rustdoc/intra-doc-link-generic-params.rs b/src/test/rustdoc/intra-doc/generic-params.rs similarity index 100% rename from src/test/rustdoc/intra-doc-link-generic-params.rs rename to src/test/rustdoc/intra-doc/generic-params.rs diff --git a/src/test/rustdoc/intra-link-in-bodies.rs b/src/test/rustdoc/intra-doc/in-bodies.rs similarity index 100% rename from src/test/rustdoc/intra-link-in-bodies.rs rename to src/test/rustdoc/intra-doc/in-bodies.rs diff --git a/src/test/rustdoc/intra-link-libstd-re-export.rs b/src/test/rustdoc/intra-doc/libstd-re-export.rs similarity index 100% rename from src/test/rustdoc/intra-link-libstd-re-export.rs rename to src/test/rustdoc/intra-doc/libstd-re-export.rs diff --git a/src/test/rustdoc/intra-doc/mod-ambiguity.rs b/src/test/rustdoc/intra-doc/mod-ambiguity.rs new file mode 100644 index 0000000000000..feb013b22be65 --- /dev/null +++ b/src/test/rustdoc/intra-doc/mod-ambiguity.rs @@ -0,0 +1,16 @@ +#![deny(broken_intra_doc_links)] + + +pub fn foo() { + +} + +pub mod foo {} +// @has mod_ambiguity/struct.A.html '//a/@href' '../mod_ambiguity/foo/index.html' +/// Module is [`module@foo`] +pub struct A; + + +// @has mod_ambiguity/struct.B.html '//a/@href' '../mod_ambiguity/fn.foo.html' +/// Function is [`fn@foo`] +pub struct B; diff --git a/src/test/rustdoc/intra-doc/prim-assoc.rs b/src/test/rustdoc/intra-doc/prim-assoc.rs new file mode 100644 index 0000000000000..d687cbd69bb18 --- /dev/null +++ b/src/test/rustdoc/intra-doc/prim-assoc.rs @@ -0,0 +1,5 @@ +// ignore-tidy-linelength +#![deny(broken_intra_doc_links)] + +//! [i32::MAX] +// @has prim_assoc/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX" diff --git a/src/test/rustdoc/intra-link-prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs similarity index 90% rename from src/test/rustdoc/intra-link-prim-methods-external-core.rs rename to src/test/rustdoc/intra-doc/prim-methods-external-core.rs index c8ef4c015997b..434e03389835f 100644 --- a/src/test/rustdoc/intra-link-prim-methods-external-core.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs @@ -9,7 +9,7 @@ #![no_core] #![crate_type = "rlib"] -// @has intra_link_prim_methods_external_core/index.html +// @has prim_methods_external_core/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char' // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' diff --git a/src/test/rustdoc/intra-link-prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs similarity index 92% rename from src/test/rustdoc/intra-link-prim-methods-local.rs rename to src/test/rustdoc/intra-doc/prim-methods-local.rs index d448acf7f9682..9888f29db5bac 100644 --- a/src/test/rustdoc/intra-link-prim-methods-local.rs +++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs @@ -5,7 +5,7 @@ // ignore-tidy-linelength -// @has intra_link_prim_methods_local/index.html +// @has prim_methods_local/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char' // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' diff --git a/src/test/rustdoc/intra-link-prim-methods.rs b/src/test/rustdoc/intra-doc/prim-methods.rs similarity index 88% rename from src/test/rustdoc/intra-link-prim-methods.rs rename to src/test/rustdoc/intra-doc/prim-methods.rs index 94c80c996c1e0..f19cff7d34afa 100644 --- a/src/test/rustdoc/intra-link-prim-methods.rs +++ b/src/test/rustdoc/intra-doc/prim-methods.rs @@ -2,7 +2,7 @@ // ignore-tidy-linelength -// @has intra_link_prim_methods/index.html +// @has prim_methods/index.html // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char' // @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8' diff --git a/src/test/rustdoc/intra-doc/prim-precedence.rs b/src/test/rustdoc/intra-doc/prim-precedence.rs new file mode 100644 index 0000000000000..ed2c2cda7184d --- /dev/null +++ b/src/test/rustdoc/intra-doc/prim-precedence.rs @@ -0,0 +1,17 @@ +// ignore-tidy-linelength +#![deny(broken_intra_doc_links)] + +pub mod char { + /// [char] + // @has prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' + pub struct Inner; +} + +/// See [prim@char] +// @has prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' +pub struct MyString; + +/// See also [crate::char] and [mod@char] +// @has prim_precedence/struct.MyString2.html '//*[@href="../prim_precedence/char/index.html"]' 'crate::char' +// @has - '//*[@href="../prim_precedence/char/index.html"]' 'mod@char' +pub struct MyString2; diff --git a/src/test/rustdoc/intra-link-primitive-non-default-impl.rs b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs similarity index 88% rename from src/test/rustdoc/intra-link-primitive-non-default-impl.rs rename to src/test/rustdoc/intra-doc/primitive-non-default-impl.rs index 160b18a967b20..548eb090a3276 100644 --- a/src/test/rustdoc/intra-link-primitive-non-default-impl.rs +++ b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs @@ -2,7 +2,7 @@ // ignore-tidy-linelength -// @has intra_link_primitive_non_default_impl/fn.str_methods.html +// @has primitive_non_default_impl/fn.str_methods.html /// [`str::trim`] // @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim' /// [`str::to_lowercase`] @@ -13,7 +13,7 @@ // @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace' pub fn str_methods() {} -// @has intra_link_primitive_non_default_impl/fn.f32_methods.html +// @has primitive_non_default_impl/fn.f32_methods.html /// [f32::powi] // @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi' /// [f32::sqrt] @@ -22,7 +22,7 @@ pub fn str_methods() {} // @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add' pub fn f32_methods() {} -// @has intra_link_primitive_non_default_impl/fn.f64_methods.html +// @has primitive_non_default_impl/fn.f64_methods.html /// [`f64::powi`] // @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi' /// [`f64::sqrt`] diff --git a/src/test/rustdoc/intra-link-private.rs b/src/test/rustdoc/intra-doc/private-failures-ignored.rs similarity index 100% rename from src/test/rustdoc/intra-link-private.rs rename to src/test/rustdoc/intra-doc/private-failures-ignored.rs diff --git a/src/test/rustdoc/intra-doc-link-private.rs b/src/test/rustdoc/intra-doc/private.rs similarity index 100% rename from src/test/rustdoc/intra-doc-link-private.rs rename to src/test/rustdoc/intra-doc/private.rs diff --git a/src/test/rustdoc/intra-doc/proc-macro.rs b/src/test/rustdoc/intra-doc/proc-macro.rs new file mode 100644 index 0000000000000..ab4626ccfc3ab --- /dev/null +++ b/src/test/rustdoc/intra-doc/proc-macro.rs @@ -0,0 +1,27 @@ +// aux-build:proc-macro-macro.rs +// build-aux-docs +#![deny(broken_intra_doc_links)] + +extern crate proc_macro_macro; + + +pub use proc_macro_macro::{DeriveA, attr_a}; +use proc_macro_macro::{DeriveB, attr_b}; + +// @has proc_macro/struct.Foo.html +// @has - '//a/@href' '../proc_macro/derive.DeriveA.html' +// @has - '//a/@href' '../proc_macro/attr.attr_a.html' +// @has - '//a/@href' '../proc_macro/trait.DeriveTrait.html' +// @has - '//a/@href' '../proc_macro_macro/derive.DeriveB.html' +// @has - '//a/@href' '../proc_macro_macro/attr.attr_b.html' +/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait] +pub struct Foo; + +// @has proc_macro/struct.Bar.html +// @has - '//a/@href' '../proc_macro/derive.DeriveA.html' +// @has - '//a/@href' '../proc_macro/attr.attr_a.html' +/// Link to [deriveA](derive@DeriveA) [attr](macro@attr_a) +pub struct Bar; + +// this should not cause ambiguity errors +pub trait DeriveTrait {} diff --git a/src/test/rustdoc/intra-link-pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs similarity index 100% rename from src/test/rustdoc/intra-link-pub-use.rs rename to src/test/rustdoc/intra-doc/pub-use.rs diff --git a/src/test/rustdoc/intra-link-reexport-additional-docs.rs b/src/test/rustdoc/intra-doc/reexport-additional-docs.rs similarity index 100% rename from src/test/rustdoc/intra-link-reexport-additional-docs.rs rename to src/test/rustdoc/intra-doc/reexport-additional-docs.rs diff --git a/src/test/rustdoc/intra-link-self.rs b/src/test/rustdoc/intra-doc/self.rs similarity index 100% rename from src/test/rustdoc/intra-link-self.rs rename to src/test/rustdoc/intra-doc/self.rs diff --git a/src/test/rustdoc/through-proc-macro.rs b/src/test/rustdoc/intra-doc/through-proc-macro.rs similarity index 100% rename from src/test/rustdoc/through-proc-macro.rs rename to src/test/rustdoc/intra-doc/through-proc-macro.rs diff --git a/src/test/rustdoc/intra-link-trait-impl.rs b/src/test/rustdoc/intra-doc/trait-impl.rs similarity index 100% rename from src/test/rustdoc/intra-link-trait-impl.rs rename to src/test/rustdoc/intra-doc/trait-impl.rs diff --git a/src/test/rustdoc/intra-link-trait-item.rs b/src/test/rustdoc/intra-doc/trait-item.rs similarity index 69% rename from src/test/rustdoc/intra-link-trait-item.rs rename to src/test/rustdoc/intra-doc/trait-item.rs index 54270414c9dfe..de8585f4c9a78 100644 --- a/src/test/rustdoc/intra-link-trait-item.rs +++ b/src/test/rustdoc/intra-doc/trait-item.rs @@ -3,7 +3,7 @@ /// Link to [S::assoc_fn()] /// Link to [Default::default()] -// @has intra_link_trait_item/struct.S.html '//*[@href="../intra_link_trait_item/struct.S.html#method.assoc_fn"]' 'S::assoc_fn()' +// @has trait_item/struct.S.html '//*[@href="../trait_item/struct.S.html#method.assoc_fn"]' 'S::assoc_fn()' // @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()' pub struct S; diff --git a/src/test/rustdoc/intra-doc-link-true-false.rs b/src/test/rustdoc/intra-doc/true-false.rs similarity index 100% rename from src/test/rustdoc/intra-doc-link-true-false.rs rename to src/test/rustdoc/intra-doc/true-false.rs diff --git a/src/test/rustdoc/intra-link-associated-defaults.rs b/src/test/rustdoc/intra-link-associated-defaults.rs deleted file mode 100644 index 2051129b948f3..0000000000000 --- a/src/test/rustdoc/intra-link-associated-defaults.rs +++ /dev/null @@ -1,27 +0,0 @@ -// ignore-tidy-linelength -#![deny(intra_doc_link_resolution_failure)] -#![feature(associated_type_defaults)] - -pub trait TraitWithDefault { - type T = usize; - fn f() -> Self::T { - 0 - } -} - -/// Link to [UsesDefaults::T] and [UsesDefaults::f] -// @has 'intra_link_associated_defaults/struct.UsesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.UsesDefaults.html#associatedtype.T"]' 'UsesDefaults::T' -// @has 'intra_link_associated_defaults/struct.UsesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.UsesDefaults.html#method.f"]' 'UsesDefaults::f' -pub struct UsesDefaults; -impl TraitWithDefault for UsesDefaults {} - -/// Link to [OverridesDefaults::T] and [OverridesDefaults::f] -// @has 'intra_link_associated_defaults/struct.OverridesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.OverridesDefaults.html#associatedtype.T"]' 'OverridesDefaults::T' -// @has 'intra_link_associated_defaults/struct.OverridesDefaults.html' '//a[@href="../intra_link_associated_defaults/struct.OverridesDefaults.html#method.f"]' 'OverridesDefaults::f' -pub struct OverridesDefaults; -impl TraitWithDefault for OverridesDefaults { - type T = bool; - fn f() -> bool { - true - } -} diff --git a/src/test/rustdoc/intra-link-associated-items.rs b/src/test/rustdoc/intra-link-associated-items.rs deleted file mode 100644 index daf7075a91740..0000000000000 --- a/src/test/rustdoc/intra-link-associated-items.rs +++ /dev/null @@ -1,61 +0,0 @@ -// ignore-tidy-linelength -#![deny(intra_doc_link_resolution_failure)] - -/// [`std::collections::BTreeMap::into_iter`] -/// [`String::from`] is ambiguous as to which `From` impl -/// [Vec::into_iter()] uses a disambiguator -// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter' -// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from' -// @has 'intra_link_associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter' -pub fn foo() {} - -/// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input] -// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html"]' 'MyStruct' -// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.method"]' 'link from struct' -// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.clone"]' 'MyStruct::clone' -// @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#associatedtype.Input"]' 'MyStruct::Input' -pub struct MyStruct { foo: () } - -impl Clone for MyStruct { - fn clone(&self) -> Self { - MyStruct - } -} - -pub trait T { - type Input; - fn method(i: Self::Input); -} - -impl T for MyStruct { - type Input = usize; - - /// [link from method][MyStruct::method] on method - // @has 'intra_link_associated_items/struct.MyStruct.html' '//a[@href="../intra_link_associated_items/struct.MyStruct.html#method.method"]' 'link from method' - fn method(i: usize) { - } -} - -/// Ambiguity between which trait to use -pub trait T1 { - fn ambiguous_method(); -} - -pub trait T2 { - fn ambiguous_method(); -} - -/// Link to [S::ambiguous_method] -// FIXME: there is no way to disambiguate these. -// Since we have `#[deny(intra_doc_failure)]`, we still know it was one or the other. -pub struct S; - -impl T1 for S { - fn ambiguous_method() {} -} - -impl T2 for S { - fn ambiguous_method() {} -} - -fn main() {} diff --git a/src/test/rustdoc/intra-link-disambiguators-removed.rs b/src/test/rustdoc/intra-link-disambiguators-removed.rs deleted file mode 100644 index 26d05b484b919..0000000000000 --- a/src/test/rustdoc/intra-link-disambiguators-removed.rs +++ /dev/null @@ -1,51 +0,0 @@ -// ignore-tidy-linelength -#![deny(intra_doc_link_resolution_failure)] -// first try backticks -/// Trait: [`trait@Name`], fn: [`fn@Name`], [`Name`][`macro@Name`] -// @has intra_link_disambiguators_removed/struct.AtDisambiguator.html -// @has - '//a[@href="../intra_link_disambiguators_removed/trait.Name.html"][code]' "Name" -// @has - '//a[@href="../intra_link_disambiguators_removed/fn.Name.html"][code]' "Name" -// @has - '//a[@href="../intra_link_disambiguators_removed/macro.Name.html"][code]' "Name" -pub struct AtDisambiguator; - -/// fn: [`Name()`], macro: [`Name!`] -// @has intra_link_disambiguators_removed/struct.SymbolDisambiguator.html -// @has - '//a[@href="../intra_link_disambiguators_removed/fn.Name.html"][code]' "Name()" -// @has - '//a[@href="../intra_link_disambiguators_removed/macro.Name.html"][code]' "Name!" -pub struct SymbolDisambiguator; - -// Now make sure that backticks aren't added if they weren't already there -/// [fn@Name] -// @has intra_link_disambiguators_removed/trait.Name.html -// @has - '//a[@href="../intra_link_disambiguators_removed/fn.Name.html"]' "Name" -// @!has - '//a[@href="../intra_link_disambiguators_removed/fn.Name.html"][code]' "Name" - -// FIXME: this will turn !() into ! alone -/// [Name!()] -// @has - '//a[@href="../intra_link_disambiguators_removed/macro.Name.html"]' "Name!" -pub trait Name {} - -#[allow(non_snake_case)] - -// Try collapsed reference links -/// [macro@Name][] -// @has intra_link_disambiguators_removed/fn.Name.html -// @has - '//a[@href="../intra_link_disambiguators_removed/macro.Name.html"]' "Name" - -// Try links that have the same text as a generated URL -/// Weird URL aligned [../intra_link_disambiguators_removed/macro.Name.html][trait@Name] -// @has - '//a[@href="../intra_link_disambiguators_removed/trait.Name.html"]' "../intra_link_disambiguators_removed/macro.Name.html" -pub fn Name() {} - -#[macro_export] -// Rustdoc doesn't currently handle links that have weird interspersing of inline code blocks. -/// [fn@Na`m`e] -// @has intra_link_disambiguators_removed/macro.Name.html -// @has - '//a[@href="../intra_link_disambiguators_removed/fn.Name.html"]' "fn@Name" - -// It also doesn't handle any case where the code block isn't the whole link text: -/// [trait@`Name`] -// @has - '//a[@href="../intra_link_disambiguators_removed/trait.Name.html"]' "trait@Name" -macro_rules! Name { - () => () -} diff --git a/src/test/rustdoc/intra-link-extern-type.rs b/src/test/rustdoc/intra-link-extern-type.rs deleted file mode 100644 index 418e0d91ea7ef..0000000000000 --- a/src/test/rustdoc/intra-link-extern-type.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(extern_types)] - -extern { - pub type ExternType; -} - -impl ExternType { - pub fn f(&self) { - - } -} - -// @has 'intra_link_extern_type/foreigntype.ExternType.html' -// @has 'intra_link_extern_type/fn.links_to_extern_type.html' \ -// 'href="../intra_link_extern_type/foreigntype.ExternType.html#method.f"' -/// See also [ExternType::f] -pub fn links_to_extern_type() { -} diff --git a/src/test/rustdoc/intra-link-prim-assoc.rs b/src/test/rustdoc/intra-link-prim-assoc.rs deleted file mode 100644 index c0066885e1991..0000000000000 --- a/src/test/rustdoc/intra-link-prim-assoc.rs +++ /dev/null @@ -1,5 +0,0 @@ -// ignore-tidy-linelength -#![deny(broken_intra_doc_links)] - -//! [i32::MAX] -// @has intra_link_prim_assoc/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX" diff --git a/src/test/rustdoc/intra-link-prim-precedence.rs b/src/test/rustdoc/intra-link-prim-precedence.rs deleted file mode 100644 index 0a4e57ef643e7..0000000000000 --- a/src/test/rustdoc/intra-link-prim-precedence.rs +++ /dev/null @@ -1,17 +0,0 @@ -// ignore-tidy-linelength -#![deny(broken_intra_doc_links)] - -pub mod char { - /// [char] - // @has intra_link_prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' - pub struct Inner; -} - -/// See [prim@char] -// @has intra_link_prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html' -pub struct MyString; - -/// See also [crate::char] and [mod@char] -// @has intra_link_prim_precedence/struct.MyString2.html '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'crate::char' -// @has - '//*[@href="../intra_link_prim_precedence/char/index.html"]' 'mod@char' -pub struct MyString2; diff --git a/src/test/rustdoc/intra-link-proc-macro.rs b/src/test/rustdoc/intra-link-proc-macro.rs deleted file mode 100644 index 7a8403255edb6..0000000000000 --- a/src/test/rustdoc/intra-link-proc-macro.rs +++ /dev/null @@ -1,27 +0,0 @@ -// aux-build:intra-link-proc-macro-macro.rs -// build-aux-docs -#![deny(broken_intra_doc_links)] - -extern crate intra_link_proc_macro_macro; - - -pub use intra_link_proc_macro_macro::{DeriveA, attr_a}; -use intra_link_proc_macro_macro::{DeriveB, attr_b}; - -// @has intra_link_proc_macro/struct.Foo.html -// @has - '//a/@href' '../intra_link_proc_macro/derive.DeriveA.html' -// @has - '//a/@href' '../intra_link_proc_macro/attr.attr_a.html' -// @has - '//a/@href' '../intra_link_proc_macro/trait.DeriveTrait.html' -// @has - '//a/@href' '../intra_link_proc_macro_macro/derive.DeriveB.html' -// @has - '//a/@href' '../intra_link_proc_macro_macro/attr.attr_b.html' -/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait] -pub struct Foo; - -// @has intra_link_proc_macro/struct.Bar.html -// @has - '//a/@href' '../intra_link_proc_macro/derive.DeriveA.html' -// @has - '//a/@href' '../intra_link_proc_macro/attr.attr_a.html' -/// Link to [deriveA](derive@DeriveA) [attr](macro@attr_a) -pub struct Bar; - -// this should not cause ambiguity errors -pub trait DeriveTrait {} diff --git a/src/test/rustdoc/normalize-assoc-item.rs b/src/test/rustdoc/normalize-assoc-item.rs index 70b3c66fd2b86..ad1a868ee32b8 100644 --- a/src/test/rustdoc/normalize-assoc-item.rs +++ b/src/test/rustdoc/normalize-assoc-item.rs @@ -1,7 +1,7 @@ // ignore-tidy-linelength // aux-build:normalize-assoc-item.rs // build-aux-docs -// ignore-test +// compile-flags:-Znormalize-docs pub trait Trait { type X; diff --git a/src/test/ui/assert-eq-trailing-comma.rs b/src/test/ui/assert-eq-trailing-comma.rs deleted file mode 100644 index 7071f80d7f7ba..0000000000000 --- a/src/test/ui/assert-eq-trailing-comma.rs +++ /dev/null @@ -1,5 +0,0 @@ -// run-pass - -fn main() { - assert_eq!(1, 1,); -} diff --git a/src/test/ui/assert-escape.rs b/src/test/ui/assert-escape.rs deleted file mode 100644 index 00e51d42cab9e..0000000000000 --- a/src/test/ui/assert-escape.rs +++ /dev/null @@ -1,5 +0,0 @@ -// run-pass - -fn main() { - assert!(r#"☃\backslash"#.contains("\\")); -} diff --git a/src/test/ui/assert-ne-trailing-comma.rs b/src/test/ui/assert-ne-trailing-comma.rs deleted file mode 100644 index 03308db9a1fee..0000000000000 --- a/src/test/ui/assert-ne-trailing-comma.rs +++ /dev/null @@ -1,5 +0,0 @@ -// run-pass - -fn main() { - assert_ne!(1, 2,); -} diff --git a/src/test/ui/atomic-access-bool.rs b/src/test/ui/atomic-access-bool.rs deleted file mode 100644 index e9d48bb3b43d8..0000000000000 --- a/src/test/ui/atomic-access-bool.rs +++ /dev/null @@ -1,24 +0,0 @@ -// run-pass - -#![allow(stable_features)] -#![feature(atomic_access)] -use std::sync::atomic::AtomicBool; -use std::sync::atomic::Ordering::*; - -static mut ATOMIC: AtomicBool = AtomicBool::new(false); - -fn main() { - unsafe { - assert_eq!(*ATOMIC.get_mut(), false); - ATOMIC.store(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_or(false, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_and(false, SeqCst); - assert_eq!(*ATOMIC.get_mut(), false); - ATOMIC.fetch_nand(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), true); - ATOMIC.fetch_xor(true, SeqCst); - assert_eq!(*ATOMIC.get_mut(), false); - } -} diff --git a/src/test/ui/atomic-alignment.rs b/src/test/ui/atomic-alignment.rs deleted file mode 100644 index 5bda90d2eab02..0000000000000 --- a/src/test/ui/atomic-alignment.rs +++ /dev/null @@ -1,38 +0,0 @@ -// run-pass - -#![feature(cfg_target_has_atomic)] -#![feature(integer_atomics)] - -use std::mem::{align_of, size_of}; -use std::sync::atomic::*; - -fn main() { - #[cfg(target_has_atomic = "8")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "ptr")] - assert_eq!(align_of::>(), size_of::>()); - #[cfg(target_has_atomic = "8")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "8")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "16")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "16")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "32")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "32")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "64")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "64")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "128")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "128")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "ptr")] - assert_eq!(align_of::(), size_of::()); - #[cfg(target_has_atomic = "ptr")] - assert_eq!(align_of::(), size_of::()); -} diff --git a/src/test/ui/atomic-compare_exchange.rs b/src/test/ui/atomic-compare_exchange.rs deleted file mode 100644 index 9b327eef3c894..0000000000000 --- a/src/test/ui/atomic-compare_exchange.rs +++ /dev/null @@ -1,31 +0,0 @@ -// run-pass - -#![allow(stable_features)] - -#![feature(extended_compare_and_swap)] -use std::sync::atomic::AtomicIsize; -use std::sync::atomic::Ordering::*; - -static ATOMIC: AtomicIsize = AtomicIsize::new(0); - -fn main() { - // Make sure codegen can emit all the intrinsics correctly - ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Acquire, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Release, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed).ok(); - ATOMIC.compare_exchange(0, 1, Acquire, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, AcqRel, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, Acquire).ok(); - ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst).ok(); - ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed).ok(); - ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire).ok(); - ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst).ok(); -} diff --git a/src/test/ui/bool-not.rs b/src/test/ui/bool-not.rs deleted file mode 100644 index 84713d6818a3e..0000000000000 --- a/src/test/ui/bool-not.rs +++ /dev/null @@ -1,6 +0,0 @@ -// run-pass - -pub fn main() { - if !false { assert!((true)); } else { assert!((false)); } - if !true { assert!((false)); } else { assert!((true)); } -} diff --git a/src/test/ui/bool.rs b/src/test/ui/bool.rs deleted file mode 100644 index 92f36c8fd25ad..0000000000000 --- a/src/test/ui/bool.rs +++ /dev/null @@ -1,72 +0,0 @@ -// run-pass -// Basic boolean tests - - -use std::cmp::Ordering::{Equal, Greater, Less}; -use std::ops::{BitAnd, BitOr, BitXor}; - -fn main() { - assert_eq!(false.eq(&true), false); - assert_eq!(false == false, true); - assert_eq!(false != true, true); - assert_eq!(false.ne(&false), false); - - assert_eq!(false.bitand(false), false); - assert_eq!(true.bitand(false), false); - assert_eq!(false.bitand(true), false); - assert_eq!(true.bitand(true), true); - - assert_eq!(false & false, false); - assert_eq!(true & false, false); - assert_eq!(false & true, false); - assert_eq!(true & true, true); - - assert_eq!(false.bitor(false), false); - assert_eq!(true.bitor(false), true); - assert_eq!(false.bitor(true), true); - assert_eq!(true.bitor(true), true); - - assert_eq!(false | false, false); - assert_eq!(true | false, true); - assert_eq!(false | true, true); - assert_eq!(true | true, true); - - assert_eq!(false.bitxor(false), false); - assert_eq!(true.bitxor(false), true); - assert_eq!(false.bitxor(true), true); - assert_eq!(true.bitxor(true), false); - - assert_eq!(false ^ false, false); - assert_eq!(true ^ false, true); - assert_eq!(false ^ true, true); - assert_eq!(true ^ true, false); - - assert_eq!(!true, false); - assert_eq!(!false, true); - - let s = false.to_string(); - assert_eq!(s, "false"); - let s = true.to_string(); - assert_eq!(s, "true"); - - assert!(true > false); - assert!(!(false > true)); - - assert!(false < true); - assert!(!(true < false)); - - assert!(false <= false); - assert!(false >= false); - assert!(true <= true); - assert!(true >= true); - - assert!(false <= true); - assert!(!(false >= true)); - assert!(true >= false); - assert!(!(true <= false)); - - assert_eq!(true.cmp(&true), Equal); - assert_eq!(false.cmp(&false), Equal); - assert_eq!(true.cmp(&false), Greater); - assert_eq!(false.cmp(&true), Less); -} diff --git a/src/test/ui/char_unicode.rs b/src/test/ui/char_unicode.rs deleted file mode 100644 index 65dda47066f4e..0000000000000 --- a/src/test/ui/char_unicode.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass - -/// Tests access to the Unicode version constant. -pub fn main() { - check(std::char::UNICODE_VERSION); -} - -pub fn check(unicode_version: (u8, u8, u8)) { - assert!(unicode_version.0 >= 10); -} diff --git a/src/test/ui/cmp-default.rs b/src/test/ui/cmp-default.rs deleted file mode 100644 index bb5c39f5cdea9..0000000000000 --- a/src/test/ui/cmp-default.rs +++ /dev/null @@ -1,73 +0,0 @@ -// run-pass - -use std::cmp::Ordering; - -// Test default methods in PartialOrd and PartialEq -// -#[derive(Debug)] -struct Fool(bool); - -impl PartialEq for Fool { - fn eq(&self, other: &Fool) -> bool { - let Fool(this) = *self; - let Fool(other) = *other; - this != other - } -} - -struct Int(isize); - -impl PartialEq for Int { - fn eq(&self, other: &Int) -> bool { - let Int(this) = *self; - let Int(other) = *other; - this == other - } -} - -impl PartialOrd for Int { - fn partial_cmp(&self, other: &Int) -> Option { - let Int(this) = *self; - let Int(other) = *other; - this.partial_cmp(&other) - } -} - -struct RevInt(isize); - -impl PartialEq for RevInt { - fn eq(&self, other: &RevInt) -> bool { - let RevInt(this) = *self; - let RevInt(other) = *other; - this == other - } -} - -impl PartialOrd for RevInt { - fn partial_cmp(&self, other: &RevInt) -> Option { - let RevInt(this) = *self; - let RevInt(other) = *other; - other.partial_cmp(&this) - } -} - -pub fn main() { - assert!(Int(2) > Int(1)); - assert!(Int(2) >= Int(1)); - assert!(Int(1) >= Int(1)); - assert!(Int(1) < Int(2)); - assert!(Int(1) <= Int(2)); - assert!(Int(1) <= Int(1)); - - assert!(RevInt(2) < RevInt(1)); - assert!(RevInt(2) <= RevInt(1)); - assert!(RevInt(1) <= RevInt(1)); - assert!(RevInt(1) > RevInt(2)); - assert!(RevInt(1) >= RevInt(2)); - assert!(RevInt(1) >= RevInt(1)); - - assert_eq!(Fool(true), Fool(false)); - assert!(Fool(true) != Fool(true)); - assert!(Fool(false) != Fool(false)); - assert_eq!(Fool(false), Fool(true)); -} diff --git a/src/test/ui/consts/ascii_ctype.rs b/src/test/ui/consts/ascii_ctype.rs deleted file mode 100644 index ef2f7322f2718..0000000000000 --- a/src/test/ui/consts/ascii_ctype.rs +++ /dev/null @@ -1,53 +0,0 @@ -// run-pass - -macro_rules! suite { - ( $( $fn:ident => [$a:ident, $A:ident, $nine:ident, $dot:ident, $space:ident]; )* ) => { - $( - mod $fn { - const CHAR_A_LOWER: bool = 'a'.$fn(); - const CHAR_A_UPPER: bool = 'A'.$fn(); - const CHAR_NINE: bool = '9'.$fn(); - const CHAR_DOT: bool = '.'.$fn(); - const CHAR_SPACE: bool = ' '.$fn(); - - const U8_A_LOWER: bool = b'a'.$fn(); - const U8_A_UPPER: bool = b'A'.$fn(); - const U8_NINE: bool = b'9'.$fn(); - const U8_DOT: bool = b'.'.$fn(); - const U8_SPACE: bool = b' '.$fn(); - - pub fn run() { - assert_eq!(CHAR_A_LOWER, $a); - assert_eq!(CHAR_A_UPPER, $A); - assert_eq!(CHAR_NINE, $nine); - assert_eq!(CHAR_DOT, $dot); - assert_eq!(CHAR_SPACE, $space); - - assert_eq!(U8_A_LOWER, $a); - assert_eq!(U8_A_UPPER, $A); - assert_eq!(U8_NINE, $nine); - assert_eq!(U8_DOT, $dot); - assert_eq!(U8_SPACE, $space); - } - } - )* - - fn main() { - $( $fn::run(); )* - } - } -} - -suite! { - // 'a' 'A' '9' '.' ' ' - is_ascii_alphabetic => [true, true, false, false, false]; - is_ascii_uppercase => [false, true, false, false, false]; - is_ascii_lowercase => [true, false, false, false, false]; - is_ascii_alphanumeric => [true, true, true, false, false]; - is_ascii_digit => [false, false, true, false, false]; - is_ascii_hexdigit => [true, true, true, false, false]; - is_ascii_punctuation => [false, false, false, true, false]; - is_ascii_graphic => [true, true, true, true, false]; - is_ascii_whitespace => [false, false, false, false, true]; - is_ascii_control => [false, false, false, false, false]; -} diff --git a/src/test/ui/consts/const-fn-feature-flags.rs b/src/test/ui/consts/const-fn-feature-flags.rs deleted file mode 100644 index 30e7e102b8635..0000000000000 --- a/src/test/ui/consts/const-fn-feature-flags.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass -// Test use of stabilized const fns in std formerly using individual feature gates. - -use std::cell::Cell; - -const CELL: Cell = Cell::new(42); - -fn main() { - let v = CELL.get(); - CELL.set(v+1); - - assert_eq!(CELL.get(), v); -} diff --git a/src/test/ui/consts/const-str-ptr.rs b/src/test/ui/consts/const-str-ptr.rs deleted file mode 100644 index 56fd9d9f55ffc..0000000000000 --- a/src/test/ui/consts/const-str-ptr.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass -#![allow(unused_imports)] -use std::{str, string}; - -const A: [u8; 2] = ['h' as u8, 'i' as u8]; -const B: &'static [u8; 2] = &A; -const C: *const u8 = B as *const u8; - -pub fn main() { - unsafe { - let foo = &A as *const u8; - assert_eq!(foo, C); - assert_eq!(str::from_utf8_unchecked(&A), "hi"); - assert_eq!(*C, A[0]); - assert_eq!(*(&B[0] as *const u8), A[0]); - } -} diff --git a/src/test/ui/consts/std/net/ip.rs b/src/test/ui/consts/std/net/ip.rs deleted file mode 100644 index 6730946577d51..0000000000000 --- a/src/test/ui/consts/std/net/ip.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass - -use std::net::{IpAddr, Ipv4Addr}; - -fn main() { - const IP_ADDRESS : IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST); - - const IS_IP_V4 : bool = IP_ADDRESS.is_ipv4(); - assert!(IS_IP_V4); - - const IS_IP_V6 : bool = IP_ADDRESS.is_ipv6(); - assert!(!IS_IP_V6); -} diff --git a/src/test/ui/deref-mut-on-ref.rs b/src/test/ui/deref-mut-on-ref.rs deleted file mode 100644 index a6df5495a2775..0000000000000 --- a/src/test/ui/deref-mut-on-ref.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass -// Test that `&mut T` implements `DerefMut` - - -use std::ops::{Deref, DerefMut}; - -fn inc + DerefMut>(mut t: T) { - *t += 1; -} - -fn main() { - let mut x: isize = 5; - inc(&mut x); - assert_eq!(x, 6); -} diff --git a/src/test/ui/deref-on-ref.rs b/src/test/ui/deref-on-ref.rs deleted file mode 100644 index 973e61c9d59fa..0000000000000 --- a/src/test/ui/deref-on-ref.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// Test that `&T` and `&mut T` implement `Deref` - - -use std::ops::Deref; - -fn deref>(t: T) -> U { - *t -} - -fn main() { - let x: isize = 3; - let y = deref(&x); - assert_eq!(y, 3); - - let mut x: isize = 4; - let y = deref(&mut x); - assert_eq!(y, 4); -} diff --git a/src/test/ui/env-home-dir.rs b/src/test/ui/env-home-dir.rs deleted file mode 100644 index c597b4732d158..0000000000000 --- a/src/test/ui/env-home-dir.rs +++ /dev/null @@ -1,50 +0,0 @@ -// run-pass - -#![allow(unused_variables)] -#![allow(deprecated)] -// ignore-emscripten env vars don't work? -// ignore-sgx env vars cannot be modified - -use std::env::*; -use std::path::PathBuf; - -#[cfg(unix)] -fn main() { - let oldhome = var("HOME"); - - set_var("HOME", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - remove_var("HOME"); - if cfg!(target_os = "android") { - assert!(home_dir().is_none()); - } else { - // When HOME is not set, some platforms return `None`, - // but others return `Some` with a default. - // Just check that it is not "/home/MountainView". - assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - } -} - -#[cfg(windows)] -fn main() { - let oldhome = var("HOME"); - let olduserprofile = var("USERPROFILE"); - - remove_var("HOME"); - remove_var("USERPROFILE"); - - assert!(home_dir().is_some()); - - set_var("HOME", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - remove_var("HOME"); - - set_var("USERPROFILE", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - set_var("HOME", "/home/MountainView"); - set_var("USERPROFILE", "/home/PaloAlto"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); -} diff --git a/src/test/ui/extend-for-unit.rs b/src/test/ui/extend-for-unit.rs deleted file mode 100644 index 01d743f70bc0a..0000000000000 --- a/src/test/ui/extend-for-unit.rs +++ /dev/null @@ -1,12 +0,0 @@ -// run-pass - -pub fn main() { - let mut x = 0; - { - let iter = (0..5).map(|_| { - x += 1; - }); - ().extend(iter); - } - assert_eq!(x, 5); -} diff --git a/src/test/ui/offset_from.rs b/src/test/ui/offset_from.rs deleted file mode 100644 index aa59c119706ea..0000000000000 --- a/src/test/ui/offset_from.rs +++ /dev/null @@ -1,13 +0,0 @@ -// run-pass - -fn main() { - let mut a = [0; 5]; - let ptr1: *mut i32 = &mut a[1]; - let ptr2: *mut i32 = &mut a[3]; - unsafe { - assert_eq!(ptr2.offset_from(ptr1), 2); - assert_eq!(ptr1.offset_from(ptr2), -2); - assert_eq!(ptr1.offset(2), ptr2); - assert_eq!(ptr2.offset(-2), ptr1); - } -} diff --git a/src/test/ui/option-ext.rs b/src/test/ui/option-ext.rs deleted file mode 100644 index 76d0cf43984b3..0000000000000 --- a/src/test/ui/option-ext.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass - -pub fn main() { - let thing = "{{ f }}"; - let f = thing.find("{{"); - - if f.is_none() { - println!("None!"); - } -} diff --git a/src/test/ui/result-opt-conversions.rs b/src/test/ui/result-opt-conversions.rs deleted file mode 100644 index 57f258aab654a..0000000000000 --- a/src/test/ui/result-opt-conversions.rs +++ /dev/null @@ -1,47 +0,0 @@ -// run-pass - -#[derive(Copy, Clone, Debug, PartialEq)] -struct BadNumErr; - -fn try_num(x: i32) -> Result { - if x <= 5 { - Ok(x + 1) - } else { - Err(BadNumErr) - } -} - -type ResOpt = Result, BadNumErr>; -type OptRes = Option>; - -fn main() { - let mut x: ResOpt = Ok(Some(5)); - let mut y: OptRes = Some(Ok(5)); - assert_eq!(x, y.transpose()); - assert_eq!(x.transpose(), y); - - x = Ok(None); - y = None; - assert_eq!(x, y.transpose()); - assert_eq!(x.transpose(), y); - - x = Err(BadNumErr); - y = Some(Err(BadNumErr)); - assert_eq!(x, y.transpose()); - assert_eq!(x.transpose(), y); - - let res: Result, BadNumErr> = - (0..10) - .map(|x| { - let y = try_num(x)?; - Ok(if y % 2 == 0 { - Some(y - 1) - } else { - None - }) - }) - .filter_map(Result::transpose) - .collect(); - - assert_eq!(res, Err(BadNumErr)) -} diff --git a/src/test/ui/utf8.rs b/src/test/ui/utf8.rs deleted file mode 100644 index 75b6ddf7895c7..0000000000000 --- a/src/test/ui/utf8.rs +++ /dev/null @@ -1,50 +0,0 @@ -// run-pass - -pub fn main() { - let yen: char = '¥'; // 0xa5 - let c_cedilla: char = 'ç'; // 0xe7 - let thorn: char = 'þ'; // 0xfe - let y_diaeresis: char = 'ÿ'; // 0xff - let pi: char = 'Π'; // 0x3a0 - - assert_eq!(yen as isize, 0xa5); - assert_eq!(c_cedilla as isize, 0xe7); - assert_eq!(thorn as isize, 0xfe); - assert_eq!(y_diaeresis as isize, 0xff); - assert_eq!(pi as isize, 0x3a0); - - assert_eq!(pi as isize, '\u{3a0}' as isize); - assert_eq!('\x0a' as isize, '\n' as isize); - - let bhutan: String = "འབྲུག་ཡུལ།".to_string(); - let japan: String = "日本".to_string(); - let uzbekistan: String = "Ўзбекистон".to_string(); - let austria: String = "Österreich".to_string(); - - let bhutan_e: String = - "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); - let japan_e: String = "\u{65e5}\u{672c}".to_string(); - let uzbekistan_e: String = - "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); - let austria_e: String = "\u{d6}sterreich".to_string(); - - let oo: char = 'Ö'; - assert_eq!(oo as isize, 0xd6); - - fn check_str_eq(a: String, b: String) { - let mut i: isize = 0; - for ab in a.bytes() { - println!("{}", i); - println!("{}", ab); - let bb: u8 = b.as_bytes()[i as usize]; - println!("{}", bb); - assert_eq!(ab, bb); - i += 1; - } - } - - check_str_eq(bhutan, bhutan_e); - check_str_eq(japan, japan_e); - check_str_eq(uzbekistan, uzbekistan_e); - check_str_eq(austria, austria_e); -} diff --git a/src/test/ui/utf8_chars.rs b/src/test/ui/utf8_chars.rs deleted file mode 100644 index d764509813de1..0000000000000 --- a/src/test/ui/utf8_chars.rs +++ /dev/null @@ -1,31 +0,0 @@ -// run-pass - -use std::str; - -pub fn main() { - // Chars of 1, 2, 3, and 4 bytes - let chs: Vec = vec!['e', 'é', '€', '\u{10000}']; - let s: String = chs.iter().cloned().collect(); - let schs: Vec = s.chars().collect(); - - assert_eq!(s.len(), 10); - assert_eq!(s.chars().count(), 4); - assert_eq!(schs.len(), 4); - assert_eq!(schs.iter().cloned().collect::(), s); - - assert!((str::from_utf8(s.as_bytes()).is_ok())); - // invalid prefix - assert!((!str::from_utf8(&[0x80]).is_ok())); - // invalid 2 byte prefix - assert!((!str::from_utf8(&[0xc0]).is_ok())); - assert!((!str::from_utf8(&[0xc0, 0x10]).is_ok())); - // invalid 3 byte prefix - assert!((!str::from_utf8(&[0xe0]).is_ok())); - assert!((!str::from_utf8(&[0xe0, 0x10]).is_ok())); - assert!((!str::from_utf8(&[0xe0, 0xff, 0x10]).is_ok())); - // invalid 4 byte prefix - assert!((!str::from_utf8(&[0xf0]).is_ok())); - assert!((!str::from_utf8(&[0xf0, 0x10]).is_ok())); - assert!((!str::from_utf8(&[0xf0, 0xff, 0x10]).is_ok())); - assert!((!str::from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok())); -} diff --git a/src/test/ui/wrapping-int-api.rs b/src/test/ui/wrapping-int-api.rs deleted file mode 100644 index 6e2fc7f80b9c4..0000000000000 --- a/src/test/ui/wrapping-int-api.rs +++ /dev/null @@ -1,225 +0,0 @@ -// run-pass -// Test inherent wrapping_* methods for {i,u}{size,8,16,32,64}. - -// Don't warn about overflowing ops on 32-bit platforms -#![cfg_attr(target_pointer_width = "32", allow(const_err))] - -fn main() { - assert_eq!( i8::MAX.wrapping_add(1), i8::MIN); - assert_eq!( i16::MAX.wrapping_add(1), i16::MIN); - assert_eq!( i32::MAX.wrapping_add(1), i32::MIN); - assert_eq!( i64::MAX.wrapping_add(1), i64::MIN); - assert_eq!(isize::MAX.wrapping_add(1), isize::MIN); - - assert_eq!( i8::MIN.wrapping_sub(1), i8::MAX); - assert_eq!( i16::MIN.wrapping_sub(1), i16::MAX); - assert_eq!( i32::MIN.wrapping_sub(1), i32::MAX); - assert_eq!( i64::MIN.wrapping_sub(1), i64::MAX); - assert_eq!(isize::MIN.wrapping_sub(1), isize::MAX); - - assert_eq!( u8::MAX.wrapping_add(1), u8::MIN); - assert_eq!( u16::MAX.wrapping_add(1), u16::MIN); - assert_eq!( u32::MAX.wrapping_add(1), u32::MIN); - assert_eq!( u64::MAX.wrapping_add(1), u64::MIN); - assert_eq!(usize::MAX.wrapping_add(1), usize::MIN); - - assert_eq!( u8::MIN.wrapping_sub(1), u8::MAX); - assert_eq!( u16::MIN.wrapping_sub(1), u16::MAX); - assert_eq!( u32::MIN.wrapping_sub(1), u32::MAX); - assert_eq!( u64::MIN.wrapping_sub(1), u64::MAX); - assert_eq!(usize::MIN.wrapping_sub(1), usize::MAX); - - assert_eq!((0xfe_u8 as i8).wrapping_mul(16), - (0xe0_u8 as i8)); - assert_eq!((0xfedc_u16 as i16).wrapping_mul(16), - (0xedc0_u16 as i16)); - assert_eq!((0xfedc_ba98_u32 as i32).wrapping_mul(16), - (0xedcb_a980_u32 as i32)); - assert_eq!((0xfedc_ba98_7654_3217_u64 as i64).wrapping_mul(16), - (0xedcb_a987_6543_2170_u64 as i64)); - - match () { - #[cfg(target_pointer_width = "32")] - () => { - assert_eq!((0xfedc_ba98_u32 as isize).wrapping_mul(16), - (0xedcb_a980_u32 as isize)); - } - #[cfg(target_pointer_width = "64")] - () => { - assert_eq!((0xfedc_ba98_7654_3217_u64 as isize).wrapping_mul(16), - (0xedcb_a987_6543_2170_u64 as isize)); - } - } - - assert_eq!((0xfe as u8).wrapping_mul(16), - (0xe0 as u8)); - assert_eq!((0xfedc as u16).wrapping_mul(16), - (0xedc0 as u16)); - assert_eq!((0xfedc_ba98 as u32).wrapping_mul(16), - (0xedcb_a980 as u32)); - assert_eq!((0xfedc_ba98_7654_3217 as u64).wrapping_mul(16), - (0xedcb_a987_6543_2170 as u64)); - - match () { - #[cfg(target_pointer_width = "32")] - () => { - assert_eq!((0xfedc_ba98 as usize).wrapping_mul(16), - (0xedcb_a980 as usize)); - } - #[cfg(target_pointer_width = "64")] - () => { - assert_eq!((0xfedc_ba98_7654_3217 as usize).wrapping_mul(16), - (0xedcb_a987_6543_2170 as usize)); - } - } - - macro_rules! check_mul_no_wrap { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_mul($f), ($e) * $f); } - } - macro_rules! check_mul_wraps { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_mul($f), $e); } - } - - check_mul_no_wrap!(0xfe_u8 as i8, -1); - check_mul_no_wrap!(0xfedc_u16 as i16, -1); - check_mul_no_wrap!(0xfedc_ba98_u32 as i32, -1); - check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); - check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); - - check_mul_no_wrap!(0xfe_u8 as i8, -2); - check_mul_no_wrap!(0xfedc_u16 as i16, -2); - check_mul_no_wrap!(0xfedc_ba98_u32 as i32, -2); - check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); - check_mul_no_wrap!(0xfedc_ba98_fedc_ba98_u64 as u64 as isize, -2); - - check_mul_no_wrap!(0xfe_u8 as i8, 2); - check_mul_no_wrap!(0xfedc_u16 as i16, 2); - check_mul_no_wrap!(0xfedc_ba98_u32 as i32, 2); - check_mul_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); - check_mul_no_wrap!(0xfedc_ba98_fedc_ba98_u64 as u64 as isize, 2); - - check_mul_wraps!(0x80_u8 as i8, -1); - check_mul_wraps!(0x8000_u16 as i16, -1); - check_mul_wraps!(0x8000_0000_u32 as i32, -1); - check_mul_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); - match () { - #[cfg(target_pointer_width = "32")] - () => { - check_mul_wraps!(0x8000_0000_u32 as isize, -1); - } - #[cfg(target_pointer_width = "64")] - () => { - check_mul_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); - } - } - - macro_rules! check_div_no_wrap { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_div($f), ($e) / $f); } - } - macro_rules! check_div_wraps { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_div($f), $e); } - } - - check_div_no_wrap!(0xfe_u8 as i8, -1); - check_div_no_wrap!(0xfedc_u16 as i16, -1); - check_div_no_wrap!(0xfedc_ba98_u32 as i32, -1); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); - - check_div_no_wrap!(0xfe_u8 as i8, -2); - check_div_no_wrap!(0xfedc_u16 as i16, -2); - check_div_no_wrap!(0xfedc_ba98_u32 as i32, -2); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -2); - - check_div_no_wrap!(0xfe_u8 as i8, 2); - check_div_no_wrap!(0xfedc_u16 as i16, 2); - check_div_no_wrap!(0xfedc_ba98_u32 as i32, 2); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); - check_div_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, 2); - - check_div_wraps!(-128 as i8, -1); - check_div_wraps!(0x8000_u16 as i16, -1); - check_div_wraps!(0x8000_0000_u32 as i32, -1); - check_div_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); - match () { - #[cfg(target_pointer_width = "32")] - () => { - check_div_wraps!(0x8000_0000_u32 as isize, -1); - } - #[cfg(target_pointer_width = "64")] - () => { - check_div_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); - } - } - - - macro_rules! check_rem_no_wrap { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_rem($f), ($e) % $f); } - } - macro_rules! check_rem_wraps { - ($e:expr, $f:expr) => { assert_eq!(($e).wrapping_rem($f), 0); } - } - - check_rem_no_wrap!(0xfe_u8 as i8, -1); - check_rem_no_wrap!(0xfedc_u16 as i16, -1); - check_rem_no_wrap!(0xfedc_ba98_u32 as i32, -1); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -1); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -1); - - check_rem_no_wrap!(0xfe_u8 as i8, -2); - check_rem_no_wrap!(0xfedc_u16 as i16, -2); - check_rem_no_wrap!(0xfedc_ba98_u32 as i32, -2); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, -2); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, -2); - - check_rem_no_wrap!(0xfe_u8 as i8, 2); - check_rem_no_wrap!(0xfedc_u16 as i16, 2); - check_rem_no_wrap!(0xfedc_ba98_u32 as i32, 2); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64, 2); - check_rem_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize, 2); - - check_rem_wraps!(0x80_u8 as i8, -1); - check_rem_wraps!(0x8000_u16 as i16, -1); - check_rem_wraps!(0x8000_0000_u32 as i32, -1); - check_rem_wraps!(0x8000_0000_0000_0000_u64 as i64, -1); - match () { - #[cfg(target_pointer_width = "32")] - () => { - check_rem_wraps!(0x8000_0000_u32 as isize, -1); - } - #[cfg(target_pointer_width = "64")] - () => { - check_rem_wraps!(0x8000_0000_0000_0000_u64 as isize, -1); - } - } - - macro_rules! check_neg_no_wrap { - ($e:expr) => { assert_eq!(($e).wrapping_neg(), -($e)); } - } - macro_rules! check_neg_wraps { - ($e:expr) => { assert_eq!(($e).wrapping_neg(), ($e)); } - } - - check_neg_no_wrap!(0xfe_u8 as i8); - check_neg_no_wrap!(0xfedc_u16 as i16); - check_neg_no_wrap!(0xfedc_ba98_u32 as i32); - check_neg_no_wrap!(0xfedc_ba98_7654_3217_u64 as i64); - check_neg_no_wrap!(0xfedc_ba98_7654_3217_u64 as u64 as isize); - - check_neg_wraps!(0x80_u8 as i8); - check_neg_wraps!(0x8000_u16 as i16); - check_neg_wraps!(0x8000_0000_u32 as i32); - check_neg_wraps!(0x8000_0000_0000_0000_u64 as i64); - match () { - #[cfg(target_pointer_width = "32")] - () => { - check_neg_wraps!(0x8000_0000_u32 as isize); - } - #[cfg(target_pointer_width = "64")] - () => { - check_neg_wraps!(0x8000_0000_0000_0000_u64 as isize); - } - } - -} diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index 6b32ebdc284f4..0a69b18a33254 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -1,11 +1,11 @@ -use crate::Lint; +use crate::{Lint, LintExtractor}; use std::collections::{BTreeMap, BTreeSet}; use std::error::Error; use std::fmt::Write; use std::fs; -use std::path::Path; use std::process::Command; +/// Descriptions of rustc lint groups. static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("unused", "Lints that detect things being declared but not used, or excess syntax"), ("rustdoc", "Rustdoc-specific lints"), @@ -15,100 +15,123 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[ ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"), ]; -/// Updates the documentation of lint groups. -pub(crate) fn generate_group_docs( - lints: &[Lint], - rustc: crate::Rustc<'_>, - out_path: &Path, -) -> Result<(), Box> { - let groups = collect_groups(rustc)?; - let groups_path = out_path.join("groups.md"); - let contents = fs::read_to_string(&groups_path) - .map_err(|e| format!("could not read {}: {}", groups_path.display(), e))?; - let new_contents = contents.replace("{{groups-table}}", &make_groups_table(lints, &groups)?); - // Delete the output because rustbuild uses hard links in its copies. - let _ = fs::remove_file(&groups_path); - fs::write(&groups_path, new_contents) - .map_err(|e| format!("could not write to {}: {}", groups_path.display(), e))?; - Ok(()) -} - type LintGroups = BTreeMap>; -/// Collects the group names from rustc. -fn collect_groups(rustc: crate::Rustc<'_>) -> Result> { - let mut result = BTreeMap::new(); - let mut cmd = Command::new(rustc.path); - cmd.arg("-Whelp"); - let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?; - if !output.status.success() { - return Err(format!( - "failed to collect lint info: {:?}\n--- stderr\n{}--- stdout\n{}\n", - output.status, - std::str::from_utf8(&output.stderr).unwrap(), - std::str::from_utf8(&output.stdout).unwrap(), - ) - .into()); +impl<'a> LintExtractor<'a> { + /// Updates the documentation of lint groups. + pub(crate) fn generate_group_docs(&self, lints: &[Lint]) -> Result<(), Box> { + let groups = self.collect_groups()?; + let groups_path = self.out_path.join("groups.md"); + let contents = fs::read_to_string(&groups_path) + .map_err(|e| format!("could not read {}: {}", groups_path.display(), e))?; + let new_contents = + contents.replace("{{groups-table}}", &self.make_groups_table(lints, &groups)?); + // Delete the output because rustbuild uses hard links in its copies. + let _ = fs::remove_file(&groups_path); + fs::write(&groups_path, new_contents) + .map_err(|e| format!("could not write to {}: {}", groups_path.display(), e))?; + Ok(()) } - let stdout = std::str::from_utf8(&output.stdout).unwrap(); - let lines = stdout.lines(); - let group_start = lines.skip_while(|line| !line.contains("groups provided")).skip(1); - let table_start = group_start.skip_while(|line| !line.contains("----")).skip(1); - for line in table_start { - if line.is_empty() { - break; + + /// Collects the group names from rustc. + fn collect_groups(&self) -> Result> { + let mut result = BTreeMap::new(); + let mut cmd = Command::new(self.rustc_path); + cmd.arg("-Whelp"); + let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?; + if !output.status.success() { + return Err(format!( + "failed to collect lint info: {:?}\n--- stderr\n{}--- stdout\n{}\n", + output.status, + std::str::from_utf8(&output.stderr).unwrap(), + std::str::from_utf8(&output.stdout).unwrap(), + ) + .into()); } - let mut parts = line.trim().splitn(2, ' '); - let name = parts.next().expect("name in group"); - if name == "warnings" { - // This is special. - continue; + let stdout = std::str::from_utf8(&output.stdout).unwrap(); + let lines = stdout.lines(); + let group_start = lines.skip_while(|line| !line.contains("groups provided")).skip(1); + let table_start = group_start.skip_while(|line| !line.contains("----")).skip(1); + for line in table_start { + if line.is_empty() { + break; + } + let mut parts = line.trim().splitn(2, ' '); + let name = parts.next().expect("name in group"); + if name == "warnings" { + // This is special. + continue; + } + let lints = parts + .next() + .ok_or_else(|| format!("expected lints following name, got `{}`", line))?; + let lints = lints.split(',').map(|l| l.trim().to_string()).collect(); + assert!(result.insert(name.to_string(), lints).is_none()); } - let lints = - parts.next().ok_or_else(|| format!("expected lints following name, got `{}`", line))?; - let lints = lints.split(',').map(|l| l.trim().to_string()).collect(); - assert!(result.insert(name.to_string(), lints).is_none()); - } - if result.is_empty() { - return Err( - format!("expected at least one group in -Whelp output, got:\n{}", stdout).into() - ); + if result.is_empty() { + return Err( + format!("expected at least one group in -Whelp output, got:\n{}", stdout).into() + ); + } + Ok(result) } - Ok(result) -} -fn make_groups_table(lints: &[Lint], groups: &LintGroups) -> Result> { - let mut result = String::new(); - let mut to_link = Vec::new(); - result.push_str("| Group | Description | Lints |\n"); - result.push_str("|-------|-------------|-------|\n"); - result.push_str("| warnings | All lints that are set to issue warnings | See [warn-by-default] for the default set of warnings |\n"); - for (group_name, group_lints) in groups { - let description = GROUP_DESCRIPTIONS.iter().find(|(n, _)| n == group_name) - .ok_or_else(|| format!("lint group `{}` does not have a description, please update the GROUP_DESCRIPTIONS list", group_name))? - .1; - to_link.extend(group_lints); - let brackets: Vec<_> = group_lints.iter().map(|l| format!("[{}]", l)).collect(); - write!(result, "| {} | {} | {} |\n", group_name, description, brackets.join(", ")).unwrap(); - } - result.push('\n'); - result.push_str("[warn-by-default]: listing/warn-by-default.md\n"); - for lint_name in to_link { - let lint_def = - lints.iter().find(|l| l.name == lint_name.replace("-", "_")).ok_or_else(|| { - format!( - "`rustc -W help` defined lint `{}` but that lint does not appear to exist", - lint_name - ) - })?; - write!( - result, - "[{}]: listing/{}#{}\n", - lint_name, - lint_def.level.doc_filename(), - lint_name - ) - .unwrap(); + fn make_groups_table( + &self, + lints: &[Lint], + groups: &LintGroups, + ) -> Result> { + let mut result = String::new(); + let mut to_link = Vec::new(); + result.push_str("| Group | Description | Lints |\n"); + result.push_str("|-------|-------------|-------|\n"); + result.push_str("| warnings | All lints that are set to issue warnings | See [warn-by-default] for the default set of warnings |\n"); + for (group_name, group_lints) in groups { + let description = match GROUP_DESCRIPTIONS.iter().find(|(n, _)| n == group_name) { + Some((_, desc)) => desc, + None if self.validate => { + return Err(format!( + "lint group `{}` does not have a description, \ + please update the GROUP_DESCRIPTIONS list in \ + src/tools/lint-docs/src/groups.rs", + group_name + ) + .into()); + } + None => { + eprintln!( + "warning: lint group `{}` is missing from the GROUP_DESCRIPTIONS list\n\ + If this is a new lint group, please update the GROUP_DESCRIPTIONS in \ + src/tools/lint-docs/src/groups.rs", + group_name + ); + continue; + } + }; + to_link.extend(group_lints); + let brackets: Vec<_> = group_lints.iter().map(|l| format!("[{}]", l)).collect(); + write!(result, "| {} | {} | {} |\n", group_name, description, brackets.join(", ")) + .unwrap(); + } + result.push('\n'); + result.push_str("[warn-by-default]: listing/warn-by-default.md\n"); + for lint_name in to_link { + let lint_def = + lints.iter().find(|l| l.name == lint_name.replace("-", "_")).ok_or_else(|| { + format!( + "`rustc -W help` defined lint `{}` but that lint does not appear to exist", + lint_name + ) + })?; + write!( + result, + "[{}]: listing/{}#{}\n", + lint_name, + lint_def.level.doc_filename(), + lint_name + ) + .unwrap(); + } + Ok(result) } - Ok(result) } diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 6ca71dcaf3cd0..326b794809854 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -7,6 +7,22 @@ use walkdir::WalkDir; mod groups; +pub struct LintExtractor<'a> { + /// Path to the `src` directory, where it will scan for `.rs` files to + /// find lint declarations. + pub src_path: &'a Path, + /// Path where to save the output. + pub out_path: &'a Path, + /// Path to the `rustc` executable. + pub rustc_path: &'a Path, + /// The target arch to build the docs for. + pub rustc_target: &'a str, + /// Verbose output. + pub verbose: bool, + /// Validate the style and the code example. + pub validate: bool, +} + struct Lint { name: String, doc: Vec, @@ -26,6 +42,28 @@ impl Lint { .filter(|line| line.starts_with("```rust")) .all(|line| line.contains(",ignore")) } + + /// Checks the doc style of the lint. + fn check_style(&self) -> Result<(), Box> { + for &expected in &["### Example", "### Explanation", "{{produces}}"] { + if expected == "{{produces}}" && self.is_ignored() { + continue; + } + if !self.doc_contains(expected) { + return Err(format!("lint docs should contain the line `{}`", expected).into()); + } + } + if let Some(first) = self.doc.first() { + if !first.starts_with(&format!("The `{}` lint", self.name)) { + return Err(format!( + "lint docs should start with the text \"The `{}` lint\" to introduce the lint", + self.name + ) + .into()); + } + } + Ok(()) + } } #[derive(Clone, Copy, PartialEq)] @@ -45,382 +83,396 @@ impl Level { } } -#[derive(Copy, Clone)] -pub struct Rustc<'a> { - pub path: &'a Path, - pub target: &'a str, -} - -/// Collects all lints, and writes the markdown documentation at the given directory. -pub fn extract_lint_docs( - src_path: &Path, - out_path: &Path, - rustc: Rustc<'_>, - verbose: bool, -) -> Result<(), Box> { - let mut lints = gather_lints(src_path)?; - for lint in &mut lints { - generate_output_example(lint, rustc, verbose).map_err(|e| { - format!( - "failed to test example in lint docs for `{}` in {}:{}: {}", - lint.name, - lint.path.display(), - lint.lineno, - e - ) - })?; +impl<'a> LintExtractor<'a> { + /// Collects all lints, and writes the markdown documentation at the given directory. + pub fn extract_lint_docs(&self) -> Result<(), Box> { + let mut lints = self.gather_lints()?; + for lint in &mut lints { + self.generate_output_example(lint).map_err(|e| { + format!( + "failed to test example in lint docs for `{}` in {}:{}: {}", + lint.name, + lint.path.display(), + lint.lineno, + e + ) + })?; + } + self.save_lints_markdown(&lints)?; + self.generate_group_docs(&lints)?; + Ok(()) } - save_lints_markdown(&lints, &out_path.join("listing"))?; - groups::generate_group_docs(&lints, rustc, out_path)?; - Ok(()) -} -/// Collects all lints from all files in the given directory. -fn gather_lints(src_path: &Path) -> Result, Box> { - let mut lints = Vec::new(); - for entry in WalkDir::new(src_path).into_iter().filter_map(|e| e.ok()) { - if !entry.path().extension().map_or(false, |ext| ext == "rs") { - continue; + /// Collects all lints from all files in the given directory. + fn gather_lints(&self) -> Result, Box> { + let mut lints = Vec::new(); + for entry in WalkDir::new(self.src_path).into_iter().filter_map(|e| e.ok()) { + if !entry.path().extension().map_or(false, |ext| ext == "rs") { + continue; + } + lints.extend(self.lints_from_file(entry.path())?); } - lints.extend(lints_from_file(entry.path())?); - } - if lints.is_empty() { - return Err("no lints were found!".into()); + if lints.is_empty() { + return Err("no lints were found!".into()); + } + Ok(lints) } - Ok(lints) -} -/// Collects all lints from the given file. -fn lints_from_file(path: &Path) -> Result, Box> { - let mut lints = Vec::new(); - let contents = fs::read_to_string(path) - .map_err(|e| format!("could not read {}: {}", path.display(), e))?; - let mut lines = contents.lines().enumerate(); - loop { - // Find a lint declaration. - let lint_start = loop { - match lines.next() { - Some((lineno, line)) => { - if line.trim().starts_with("declare_lint!") { - break lineno + 1; + /// Collects all lints from the given file. + fn lints_from_file(&self, path: &Path) -> Result, Box> { + let mut lints = Vec::new(); + let contents = fs::read_to_string(path) + .map_err(|e| format!("could not read {}: {}", path.display(), e))?; + let mut lines = contents.lines().enumerate(); + 'outer: loop { + // Find a lint declaration. + let lint_start = loop { + match lines.next() { + Some((lineno, line)) => { + if line.trim().starts_with("declare_lint!") { + break lineno + 1; + } + } + None => return Ok(lints), + } + }; + // Read the lint. + let mut doc_lines = Vec::new(); + let (doc, name) = loop { + match lines.next() { + Some((lineno, line)) => { + let line = line.trim(); + if let Some(text) = line.strip_prefix("/// ") { + doc_lines.push(text.trim().to_string()); + } else if line.starts_with("///") { + doc_lines.push("".to_string()); + } else if line.starts_with("// ") { + // Ignore comments. + continue; + } else { + let name = lint_name(line).map_err(|e| { + format!( + "could not determine lint name in {}:{}: {}, line was `{}`", + path.display(), + lineno, + e, + line + ) + })?; + if doc_lines.is_empty() { + if self.validate { + return Err(format!( + "did not find doc lines for lint `{}` in {}", + name, + path.display() + ) + .into()); + } else { + eprintln!( + "warning: lint `{}` in {} does not define any doc lines, \ + these are required for the lint documentation", + name, + path.display() + ); + continue 'outer; + } + } + break (doc_lines, name); + } + } + None => { + return Err(format!( + "unexpected EOF for lint definition at {}:{}", + path.display(), + lint_start + ) + .into()); } } - None => return Ok(lints), + }; + // These lints are specifically undocumented. This should be reserved + // for internal rustc-lints only. + if name == "deprecated_in_future" { + continue; } - }; - // Read the lint. - let mut doc_lines = Vec::new(); - let (doc, name) = loop { - match lines.next() { - Some((lineno, line)) => { - let line = line.trim(); - if line.starts_with("/// ") { - doc_lines.push(line.trim()[4..].to_string()); - } else if line.starts_with("///") { - doc_lines.push("".to_string()); - } else if line.starts_with("// ") { - // Ignore comments. - continue; - } else { - let name = lint_name(line).map_err(|e| { - format!( - "could not determine lint name in {}:{}: {}, line was `{}`", - path.display(), - lineno, - e, - line - ) - })?; - if doc_lines.is_empty() { + // Read the level. + let level = loop { + match lines.next() { + // Ignore comments. + Some((_, line)) if line.trim().starts_with("// ") => {} + Some((lineno, line)) => match line.trim() { + "Allow," => break Level::Allow, + "Warn," => break Level::Warn, + "Deny," => break Level::Deny, + _ => { return Err(format!( - "did not find doc lines for lint `{}` in {}", - name, - path.display() + "unexpected lint level `{}` in {}:{}", + line, + path.display(), + lineno ) .into()); } - break (doc_lines, name); - } - } - None => { - return Err(format!( - "unexpected EOF for lint definition at {}:{}", - path.display(), - lint_start - ) - .into()); - } - } - }; - // These lints are specifically undocumented. This should be reserved - // for internal rustc-lints only. - if name == "deprecated_in_future" { - continue; - } - // Read the level. - let level = loop { - match lines.next() { - // Ignore comments. - Some((_, line)) if line.trim().starts_with("// ") => {} - Some((lineno, line)) => match line.trim() { - "Allow," => break Level::Allow, - "Warn," => break Level::Warn, - "Deny," => break Level::Deny, - _ => { + }, + None => { return Err(format!( - "unexpected lint level `{}` in {}:{}", - line, + "expected lint level in {}:{}, got EOF", path.display(), - lineno + lint_start ) .into()); } - }, - None => { - return Err(format!( - "expected lint level in {}:{}, got EOF", - path.display(), - lint_start - ) - .into()); } - } - }; - // The rest of the lint definition is ignored. - assert!(!doc.is_empty()); - lints.push(Lint { name, doc, level, path: PathBuf::from(path), lineno: lint_start }); - } -} - -/// Extracts the lint name (removing the visibility modifier, and checking validity). -fn lint_name(line: &str) -> Result { - // Skip over any potential `pub` visibility. - match line.trim().split(' ').next_back() { - Some(name) => { - if !name.ends_with(',') { - return Err("lint name should end with comma"); - } - let name = &name[..name.len() - 1]; - if !name.chars().all(|ch| ch.is_uppercase() || ch == '_') || name.is_empty() { - return Err("lint name did not have expected format"); - } - Ok(name.to_lowercase().to_string()) + }; + // The rest of the lint definition is ignored. + assert!(!doc.is_empty()); + lints.push(Lint { name, doc, level, path: PathBuf::from(path), lineno: lint_start }); } - None => Err("could not find lint name"), - } -} - -/// Mutates the lint definition to replace the `{{produces}}` marker with the -/// actual output from the compiler. -fn generate_output_example( - lint: &mut Lint, - rustc: Rustc<'_>, - verbose: bool, -) -> Result<(), Box> { - // Explicit list of lints that are allowed to not have an example. Please - // try to avoid adding to this list. - if matches!( - lint.name.as_str(), - "unused_features" // broken lint - | "unstable_features" // deprecated - ) { - return Ok(()); - } - if lint.doc_contains("[rustdoc book]") && !lint.doc_contains("{{produces}}") { - // Rustdoc lints are documented in the rustdoc book, don't check these. - return Ok(()); } - check_style(lint)?; - // Unfortunately some lints have extra requirements that this simple test - // setup can't handle (like extern crates). An alternative is to use a - // separate test suite, and use an include mechanism such as mdbook's - // `{{#rustdoc_include}}`. - if !lint.is_ignored() { - replace_produces(lint, rustc, verbose)?; - } - Ok(()) -} -/// Checks the doc style of the lint. -fn check_style(lint: &Lint) -> Result<(), Box> { - for &expected in &["### Example", "### Explanation", "{{produces}}"] { - if expected == "{{produces}}" && lint.is_ignored() { - continue; + /// Mutates the lint definition to replace the `{{produces}}` marker with the + /// actual output from the compiler. + fn generate_output_example(&self, lint: &mut Lint) -> Result<(), Box> { + // Explicit list of lints that are allowed to not have an example. Please + // try to avoid adding to this list. + if matches!( + lint.name.as_str(), + "unused_features" // broken lint + | "unstable_features" // deprecated + ) { + return Ok(()); } - if !lint.doc_contains(expected) { - return Err(format!("lint docs should contain the line `{}`", expected).into()); + if lint.doc_contains("[rustdoc book]") && !lint.doc_contains("{{produces}}") { + // Rustdoc lints are documented in the rustdoc book, don't check these. + return Ok(()); } - } - if let Some(first) = lint.doc.first() { - if !first.starts_with(&format!("The `{}` lint", lint.name)) { - return Err(format!( - "lint docs should start with the text \"The `{}` lint\" to introduce the lint", - lint.name - ) - .into()); + if self.validate { + lint.check_style()?; + } + // Unfortunately some lints have extra requirements that this simple test + // setup can't handle (like extern crates). An alternative is to use a + // separate test suite, and use an include mechanism such as mdbook's + // `{{#rustdoc_include}}`. + if !lint.is_ignored() { + if let Err(e) = self.replace_produces(lint) { + if self.validate { + return Err(e); + } + eprintln!( + "warning: the code example in lint `{}` in {} failed to \ + generate the expected output: {}", + lint.name, + lint.path.display(), + e + ); + } } + Ok(()) } - Ok(()) -} -/// Mutates the lint docs to replace the `{{produces}}` marker with the actual -/// output from the compiler. -fn replace_produces( - lint: &mut Lint, - rustc: Rustc<'_>, - verbose: bool, -) -> Result<(), Box> { - let mut lines = lint.doc.iter_mut(); - loop { - // Find start of example. - let options = loop { - match lines.next() { - Some(line) if line.starts_with("```rust") => { - break line[7..].split(',').collect::>(); + /// Mutates the lint docs to replace the `{{produces}}` marker with the actual + /// output from the compiler. + fn replace_produces(&self, lint: &mut Lint) -> Result<(), Box> { + let mut lines = lint.doc.iter_mut(); + loop { + // Find start of example. + let options = loop { + match lines.next() { + Some(line) if line.starts_with("```rust") => { + break line[7..].split(',').collect::>(); + } + Some(line) if line.contains("{{produces}}") => { + return Err("lint marker {{{{produces}}}} found, \ + but expected to immediately follow a rust code block" + .into()); + } + Some(_) => {} + None => return Ok(()), } - Some(line) if line.contains("{{produces}}") => { - return Err("lint marker {{{{produces}}}} found, \ - but expected to immediately follow a rust code block" + }; + // Find the end of example. + let mut example = Vec::new(); + loop { + match lines.next() { + Some(line) if line == "```" => break, + Some(line) => example.push(line), + None => { + return Err(format!( + "did not find end of example triple ticks ```, docs were:\n{:?}", + lint.doc + ) .into()); - } - Some(_) => {} - None => return Ok(()), - } - }; - // Find the end of example. - let mut example = Vec::new(); - loop { - match lines.next() { - Some(line) if line == "```" => break, - Some(line) => example.push(line), - None => { - return Err(format!( - "did not find end of example triple ticks ```, docs were:\n{:?}", - lint.doc - ) - .into()); + } } } - } - // Find the {{produces}} line. - loop { - match lines.next() { - Some(line) if line.is_empty() => {} - Some(line) if line == "{{produces}}" => { - let output = - generate_lint_output(&lint.name, &example, &options, rustc, verbose)?; - line.replace_range( - .., - &format!( - "This will produce:\n\ - \n\ - ```text\n\ - {}\ - ```", - output - ), - ); - break; + // Find the {{produces}} line. + loop { + match lines.next() { + Some(line) if line.is_empty() => {} + Some(line) if line == "{{produces}}" => { + let output = self.generate_lint_output(&lint.name, &example, &options)?; + line.replace_range( + .., + &format!( + "This will produce:\n\ + \n\ + ```text\n\ + {}\ + ```", + output + ), + ); + break; + } + // No {{produces}} after example, find next example. + Some(_line) => break, + None => return Ok(()), } - // No {{produces}} after example, find next example. - Some(_line) => break, - None => return Ok(()), } } } -} -/// Runs the compiler against the example, and extracts the output. -fn generate_lint_output( - name: &str, - example: &[&mut String], - options: &[&str], - rustc: Rustc<'_>, - verbose: bool, -) -> Result> { - if verbose { - eprintln!("compiling lint {}", name); - } - let tempdir = tempfile::TempDir::new()?; - let tempfile = tempdir.path().join("lint_example.rs"); - let mut source = String::new(); - let needs_main = !example.iter().any(|line| line.contains("fn main")); - // Remove `# ` prefix for hidden lines. - let unhidden = - example.iter().map(|line| if line.starts_with("# ") { &line[2..] } else { line }); - let mut lines = unhidden.peekable(); - while let Some(line) = lines.peek() { - if line.starts_with("#!") { + /// Runs the compiler against the example, and extracts the output. + fn generate_lint_output( + &self, + name: &str, + example: &[&mut String], + options: &[&str], + ) -> Result> { + if self.verbose { + eprintln!("compiling lint {}", name); + } + let tempdir = tempfile::TempDir::new()?; + let tempfile = tempdir.path().join("lint_example.rs"); + let mut source = String::new(); + let needs_main = !example.iter().any(|line| line.contains("fn main")); + // Remove `# ` prefix for hidden lines. + let unhidden = example.iter().map(|line| line.strip_prefix("# ").unwrap_or(line)); + let mut lines = unhidden.peekable(); + while let Some(line) = lines.peek() { + if line.starts_with("#!") { + source.push_str(line); + source.push('\n'); + lines.next(); + } else { + break; + } + } + if needs_main { + source.push_str("fn main() {\n"); + } + for line in lines { source.push_str(line); - source.push('\n'); - lines.next(); + source.push('\n') + } + if needs_main { + source.push_str("}\n"); + } + fs::write(&tempfile, source) + .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?; + let mut cmd = Command::new(self.rustc_path); + if options.contains(&"edition2015") { + cmd.arg("--edition=2015"); } else { - break; + cmd.arg("--edition=2018"); + } + cmd.arg("--error-format=json"); + cmd.arg("--target").arg(self.rustc_target); + if options.contains(&"test") { + cmd.arg("--test"); + } + cmd.arg("lint_example.rs"); + cmd.current_dir(tempdir.path()); + let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?; + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + let msgs = stderr + .lines() + .filter(|line| line.starts_with('{')) + .map(serde_json::from_str) + .collect::, _>>()?; + match msgs + .iter() + .find(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name)) + { + Some(msg) => { + let rendered = msg["rendered"].as_str().expect("rendered field should exist"); + Ok(rendered.to_string()) + } + None => { + match msgs.iter().find( + |msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)), + ) { + Some(msg) => { + let rendered = msg["rendered"].as_str().expect("rendered field should exist"); + Ok(rendered.to_string()) + } + None => { + let rendered: Vec<&str> = + msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); + let non_json: Vec<&str> = + stderr.lines().filter(|line| !line.starts_with('{')).collect(); + Err(format!( + "did not find lint `{}` in output of example, got:\n{}\n{}", + name, + non_json.join("\n"), + rendered.join("\n") + ) + .into()) + } + } + } } } - if needs_main { - source.push_str("fn main() {\n"); - } - for line in lines { - source.push_str(line); - source.push('\n') - } - if needs_main { - source.push_str("}\n"); - } - fs::write(&tempfile, source) - .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?; - let mut cmd = Command::new(rustc.path); - if options.contains(&"edition2015") { - cmd.arg("--edition=2015"); - } else { - cmd.arg("--edition=2018"); - } - cmd.arg("--error-format=json"); - cmd.arg("--target").arg(rustc.target); - if options.contains(&"test") { - cmd.arg("--test"); + + /// Saves the mdbook lint chapters at the given path. + fn save_lints_markdown(&self, lints: &[Lint]) -> Result<(), Box> { + self.save_level(lints, Level::Allow, ALLOWED_MD)?; + self.save_level(lints, Level::Warn, WARN_MD)?; + self.save_level(lints, Level::Deny, DENY_MD)?; + Ok(()) } - cmd.arg("lint_example.rs"); - cmd.current_dir(tempdir.path()); - let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?; - let stderr = std::str::from_utf8(&output.stderr).unwrap(); - let msgs = stderr - .lines() - .filter(|line| line.starts_with('{')) - .map(serde_json::from_str) - .collect::, _>>()?; - match msgs - .iter() - .find(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name)) - { - Some(msg) => { - let rendered = msg["rendered"].as_str().expect("rendered field should exist"); - Ok(rendered.to_string()) + + fn save_level(&self, lints: &[Lint], level: Level, header: &str) -> Result<(), Box> { + let mut result = String::new(); + result.push_str(header); + let mut these_lints: Vec<_> = lints.iter().filter(|lint| lint.level == level).collect(); + these_lints.sort_unstable_by_key(|lint| &lint.name); + for lint in &these_lints { + write!(result, "* [`{}`](#{})\n", lint.name, lint.name.replace("_", "-")).unwrap(); } - None => { - match msgs.iter().find( - |msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)), - ) { - Some(msg) => { - let rendered = msg["rendered"].as_str().expect("rendered field should exist"); - Ok(rendered.to_string()) - } - None => { - let rendered: Vec<&str> = - msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); - let non_json: Vec<&str> = - stderr.lines().filter(|line| !line.starts_with('{')).collect(); - Err(format!( - "did not find lint `{}` in output of example, got:\n{}\n{}", - name, - non_json.join("\n"), - rendered.join("\n") - ) - .into()) - } + result.push('\n'); + for lint in &these_lints { + write!(result, "## {}\n\n", lint.name.replace("_", "-")).unwrap(); + for line in &lint.doc { + result.push_str(line); + result.push('\n'); + } + result.push('\n'); + } + let out_path = self.out_path.join("listing").join(level.doc_filename()); + // Delete the output because rustbuild uses hard links in its copies. + let _ = fs::remove_file(&out_path); + fs::write(&out_path, result) + .map_err(|e| format!("could not write to {}: {}", out_path.display(), e))?; + Ok(()) + } +} + +/// Extracts the lint name (removing the visibility modifier, and checking validity). +fn lint_name(line: &str) -> Result { + // Skip over any potential `pub` visibility. + match line.trim().split(' ').next_back() { + Some(name) => { + if !name.ends_with(',') { + return Err("lint name should end with comma"); } + let name = &name[..name.len() - 1]; + if !name.chars().all(|ch| ch.is_uppercase() || ch == '_') || name.is_empty() { + return Err("lint name did not have expected format"); + } + Ok(name.to_lowercase().to_string()) } + None => Err("could not find lint name"), } } @@ -442,41 +494,3 @@ static DENY_MD: &str = r#"# Deny-by-default lints These lints are all set to the 'deny' level by default. "#; - -/// Saves the mdbook lint chapters at the given path. -fn save_lints_markdown(lints: &[Lint], out_dir: &Path) -> Result<(), Box> { - save_level(lints, Level::Allow, out_dir, ALLOWED_MD)?; - save_level(lints, Level::Warn, out_dir, WARN_MD)?; - save_level(lints, Level::Deny, out_dir, DENY_MD)?; - Ok(()) -} - -fn save_level( - lints: &[Lint], - level: Level, - out_dir: &Path, - header: &str, -) -> Result<(), Box> { - let mut result = String::new(); - result.push_str(header); - let mut these_lints: Vec<_> = lints.iter().filter(|lint| lint.level == level).collect(); - these_lints.sort_unstable_by_key(|lint| &lint.name); - for lint in &these_lints { - write!(result, "* [`{}`](#{})\n", lint.name, lint.name.replace("_", "-")).unwrap(); - } - result.push('\n'); - for lint in &these_lints { - write!(result, "## {}\n\n", lint.name.replace("_", "-")).unwrap(); - for line in &lint.doc { - result.push_str(line); - result.push('\n'); - } - result.push('\n'); - } - let out_path = out_dir.join(level.doc_filename()); - // Delete the output because rustbuild uses hard links in its copies. - let _ = fs::remove_file(&out_path); - fs::write(&out_path, result) - .map_err(|e| format!("could not write to {}: {}", out_path.display(), e))?; - Ok(()) -} diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs index 5db49007d375c..2055fed2b480c 100644 --- a/src/tools/lint-docs/src/main.rs +++ b/src/tools/lint-docs/src/main.rs @@ -3,7 +3,20 @@ use std::path::PathBuf; fn main() { if let Err(e) = doit() { - println!("error: {}", e); + eprintln!("error: {}", e); + eprintln!( + " +This error was generated by the lint-docs tool. +This tool extracts documentation for lints from the source code and places +them in the rustc book. See the declare_lint! documentation +https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/macro.declare_lint.html +for an example of the format of documentation this tool expects. + +To re-run these tests, run: ./x.py test --keep-stage=0 src/tools/lint-docs +The --keep-stage flag should be used if you have already built the compiler +and are only modifying the doc comments to avoid rebuilding the compiler. +" + ); std::process::exit(1); } } @@ -15,6 +28,7 @@ fn doit() -> Result<(), Box> { let mut rustc_path = None; let mut rustc_target = None; let mut verbose = false; + let mut validate = false; while let Some(arg) = args.next() { match arg.as_str() { "--src" => { @@ -42,6 +56,7 @@ fn doit() -> Result<(), Box> { }; } "-v" | "--verbose" => verbose = true, + "--validate" => validate = true, s => return Err(format!("unexpected argument `{}`", s).into()), } } @@ -57,13 +72,13 @@ fn doit() -> Result<(), Box> { if rustc_target.is_none() { return Err("--rustc-target must be specified to the rustc target".into()); } - lint_docs::extract_lint_docs( - &src_path.unwrap(), - &out_path.unwrap(), - lint_docs::Rustc { - path: rustc_path.as_deref().unwrap(), - target: rustc_target.as_deref().unwrap(), - }, + let le = lint_docs::LintExtractor { + src_path: &src_path.unwrap(), + out_path: &out_path.unwrap(), + rustc_path: &rustc_path.unwrap(), + rustc_target: &rustc_target.unwrap(), verbose, - ) + validate, + }; + le.extract_lint_docs() } diff --git a/src/tools/miri b/src/tools/miri index 746ea5b141baf..47acece7aa25d 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 746ea5b141baf1f86c2ad17753a37b135e0c1aa3 +Subproject commit 47acece7aa25d7b5edfae0bfd4b94e6e55a7b4b0