diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 13df1892a5f17..84e6ff648a38f 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -202,23 +202,34 @@ impl ops::Not for Cfg { impl ops::BitAndAssign for Cfg { fn bitand_assign(&mut self, other: Cfg) { - if *self == other { - return; - } match (self, other) { (&mut Cfg::False, _) | (_, Cfg::True) => {} (s, Cfg::False) => *s = Cfg::False, (s @ &mut Cfg::True, b) => *s = b, - (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => a.append(b), - (&mut Cfg::All(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)), + (&mut Cfg::All(ref mut a), Cfg::All(ref mut b)) => { + for c in b.drain(..) { + if !a.contains(&c) { + a.push(c); + } + } + } + (&mut Cfg::All(ref mut a), ref mut b) => { + if !a.contains(b) { + a.push(mem::replace(b, Cfg::True)); + } + } (s, Cfg::All(mut a)) => { let b = mem::replace(s, Cfg::True); - a.push(b); + if !a.contains(&b) { + a.push(b); + } *s = Cfg::All(a); } (s, b) => { - let a = mem::replace(s, Cfg::True); - *s = Cfg::All(vec![a, b]); + if *s != b { + let a = mem::replace(s, Cfg::True); + *s = Cfg::All(vec![a, b]); + } } } } @@ -234,23 +245,34 @@ impl ops::BitAnd for Cfg { impl ops::BitOrAssign for Cfg { fn bitor_assign(&mut self, other: Cfg) { - if *self == other { - return; - } match (self, other) { (&mut Cfg::True, _) | (_, Cfg::False) => {} (s, Cfg::True) => *s = Cfg::True, (s @ &mut Cfg::False, b) => *s = b, - (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => a.append(b), - (&mut Cfg::Any(ref mut a), ref mut b) => a.push(mem::replace(b, Cfg::True)), + (&mut Cfg::Any(ref mut a), Cfg::Any(ref mut b)) => { + for c in b.drain(..) { + if !a.contains(&c) { + a.push(c); + } + } + } + (&mut Cfg::Any(ref mut a), ref mut b) => { + if !a.contains(b) { + a.push(mem::replace(b, Cfg::True)); + } + } (s, Cfg::Any(mut a)) => { let b = mem::replace(s, Cfg::True); - a.push(b); + if !a.contains(&b) { + a.push(b); + } *s = Cfg::Any(a); } (s, b) => { - let a = mem::replace(s, Cfg::True); - *s = Cfg::Any(vec![a, b]); + if *s != b { + let a = mem::replace(s, Cfg::True); + *s = Cfg::Any(vec![a, b]); + } } } } diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 309f72040615d..d090bf325038f 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -87,6 +87,12 @@ fn test_cfg_and() { x &= word_cfg("test3"); assert_eq!(x, word_cfg("test3")); + x &= word_cfg("test3"); + assert_eq!(x, word_cfg("test3")); + + x &= word_cfg("test4"); + assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")])); + x &= word_cfg("test4"); assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")])); @@ -105,6 +111,18 @@ fn test_cfg_and() { ]) ); + x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]); + assert_eq!( + x, + Cfg::All(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + ]) + ); + let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]); y &= x; assert_eq!( @@ -119,6 +137,14 @@ fn test_cfg_and() { ]) ); + let mut z = word_cfg("test8"); + z &= Cfg::All(vec![word_cfg("test9"), word_cfg("test10")]); + assert_eq!(z, Cfg::All(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")])); + + let mut z = word_cfg("test11"); + z &= Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]); + assert_eq!(z, Cfg::All(vec![word_cfg("test11"), word_cfg("test12")])); + assert_eq!( word_cfg("a") & word_cfg("b") & word_cfg("c"), Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) @@ -145,6 +171,12 @@ fn test_cfg_or() { x |= word_cfg("test3"); assert_eq!(x, word_cfg("test3")); + x |= word_cfg("test3"); + assert_eq!(x, word_cfg("test3")); + + x |= word_cfg("test4"); + assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")])); + x |= word_cfg("test4"); assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")])); @@ -163,6 +195,18 @@ fn test_cfg_or() { ]) ); + x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]); + assert_eq!( + x, + Cfg::Any(vec![ + word_cfg("test3"), + word_cfg("test4"), + word_cfg("test5"), + word_cfg("test6"), + word_cfg("test7"), + ]) + ); + let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]); y |= x; assert_eq!( @@ -177,6 +221,14 @@ fn test_cfg_or() { ]) ); + let mut z = word_cfg("test8"); + z |= Cfg::Any(vec![word_cfg("test9"), word_cfg("test10")]); + assert_eq!(z, Cfg::Any(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")])); + + let mut z = word_cfg("test11"); + z |= Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]); + assert_eq!(z, Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")])); + assert_eq!( word_cfg("a") | word_cfg("b") | word_cfg("c"), Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")]) diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index 505d6ee769ab3..9ccc5d7882eb8 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -1,15 +1,42 @@ +// ignore-tidy-linelength + #![crate_name = "foo"] #![feature(doc_cfg)] -// @has 'foo/index.html' -// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and' -// @has '-' '//*[@class="stab portability"]' 'feature="sync"' +// @has 'foo/struct.Foo.html' +// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.' #[doc(cfg(feature = "sync"))] #[doc(cfg(feature = "sync"))] pub struct Foo; +// @has 'foo/bar/struct.Bar.html' +// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.' #[doc(cfg(feature = "sync"))] pub mod bar { #[doc(cfg(feature = "sync"))] pub struct Bar; } + +// @has 'foo/baz/struct.Baz.html' +// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.' +#[doc(cfg(all(feature = "sync", feature = "send")))] +pub mod baz { + #[doc(cfg(feature = "sync"))] + pub struct Baz; +} + +// @has 'foo/qux/struct.Qux.html' +// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.' +#[doc(cfg(feature = "sync"))] +pub mod qux { + #[doc(cfg(all(feature = "sync", feature = "send")))] + pub struct Qux; +} + +// @has 'foo/quux/struct.Quux.html' +// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" and foo and bar only.' +#[doc(cfg(all(feature = "sync", feature = "send", foo)))] +pub mod quux { + #[doc(cfg(all(feature = "send", feature = "sync", bar)))] + pub struct Quux; +}