From 2ff677dcbe2228323553447054d130a0c4585a91 Mon Sep 17 00:00:00 2001 From: The8472 Date: Fri, 2 Apr 2021 20:20:55 +0200 Subject: [PATCH 1/9] Weaken guarantee around advancing underlying iterators in zip The current guarantee is too strong as it would prevent adapters from exploiting knowledge about the iterator length and using counted loops for example because they would stop calling `next()` before it ever returned `None`. Additionally several nested zip iterators already fail to uphold this. This doesn't remove any of the specialization code that tries (and sometimes fails) to uphold the guarantee for `next()` because removing it would also affect `next_back()` in more surprising ways. --- library/core/src/iter/traits/iterator.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 6b24d33bebca3..25135018a5572 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -457,8 +457,10 @@ pub trait Iterator { /// In other words, it zips two iterators together, into a single one. /// /// If either iterator returns [`None`], [`next`] from the zipped iterator - /// will return [`None`]. If the first iterator returns [`None`], `zip` will - /// short-circuit and `next` will not be called on the second iterator. + /// will return [`None`]. + /// If the zipped iterator has no more elements to return then each further attempt to advance + /// it will first try to advance the first iterator at most one time and if it still yielded an item + /// try to advance the second iterator at most one time. /// /// # Examples /// From fd1494e9c3928ea13820f5e91748822a19a5abea Mon Sep 17 00:00:00 2001 From: The8472 Date: Thu, 18 Nov 2021 02:00:53 +0100 Subject: [PATCH 2/9] Document non-guarantees for Hash Dependence on endianness and type sizes was reported for enum discriminants in #74215 but it is a more general issue since for example the default implementation of `Hasher::write_usize` uses native endianness. Additionally the implementations of library types are occasionally changed as their internal fields change or hashing gets optimized. --- library/core/src/hash/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 540160bc4c2a4..44d517d6c9318 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -164,6 +164,19 @@ mod sip; /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", /// "bc")` hash differently. /// +/// ## Portability +/// +/// Due to differences in endianness and type sizes data fed by `Hash` to a `Hasher` +/// should not be considered portable across platforms. Additionally the data passed by most +/// standard library types should not be considered stable between compiler versions. +/// +/// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and +/// instead should check consistency with `Eq`. +/// +/// Serialization formats intended to he portable between platforms or compiler versions should +/// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that +/// provide additional guarantees. +/// /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`hash`]: Hash::hash From 39b98e8c1a86a2788c05930779b343dd4c334971 Mon Sep 17 00:00:00 2001 From: The8472 Date: Fri, 19 Nov 2021 22:52:09 +0100 Subject: [PATCH 3/9] Expand available_parallelism docs in anticipation of cgroup quotas The "fixed" in "fixed steady state limits" means to exclude load-dependent resource prioritization that would calculate to 100% of capacity on an idle system and less capacity on a loaded system. Additionally I also exclude "system load" since it would be silly to try to identify other, perhaps higher priority, processes hogging some CPU cores that aren't explicitly excluded by masks/quotas/whatever. --- library/std/src/thread/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 39b53b51bfa63..343d3ef8dc538 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1460,9 +1460,12 @@ fn _assert_sync_and_send() { /// The purpose of this API is to provide an easy and portable way to query /// the default amount of parallelism the program should use. Among other things it /// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities, and will not modify the program's -/// global state in order to more accurately query the amount of available -/// parallelism. +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. /// /// Resource limits can be changed during the runtime of a program, therefore the value is /// not cached and instead recomputed every time this function is called. It should not be From 53fc69f87c623cf3085127530b3f6a810bfd5a4a Mon Sep 17 00:00:00 2001 From: the8472 Date: Tue, 23 Nov 2021 23:55:05 +0100 Subject: [PATCH 4/9] Apply suggestions from code review Co-authored-by: pierwill <19642016+pierwill@users.noreply.github.com> --- library/core/src/hash/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 44d517d6c9318..3ff84cc9672eb 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -166,14 +166,14 @@ mod sip; /// /// ## Portability /// -/// Due to differences in endianness and type sizes data fed by `Hash` to a `Hasher` +/// Due to differences in endianness and type sizes, data fed by `Hash` to a `Hasher` /// should not be considered portable across platforms. Additionally the data passed by most /// standard library types should not be considered stable between compiler versions. /// /// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and /// instead should check consistency with `Eq`. /// -/// Serialization formats intended to he portable between platforms or compiler versions should +/// Serialization formats intended to be portable between platforms or compiler versions should /// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that /// provide additional guarantees. /// From 4954389a9dccf2e915a639155b7039f1454acc9c Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 25 Nov 2021 01:38:05 +0000 Subject: [PATCH 5/9] Account for incorrect `where T::Assoc = Ty` bound Provide suggestoin to constrain trait bound for associated type. Revert incorrect changes to `missing-bounds` test. Address part of #20041. --- .../rustc_ast_passes/src/ast_validation.rs | 49 ++++++++++++++++++- compiler/rustc_ast_passes/src/lib.rs | 1 + .../equality-bound.rs | 15 ++++++ .../equality-bound.stderr | 43 ++++++++++++++++ .../missing-bounds.fixed | 5 +- .../missing-bounds.rs | 5 +- .../missing-bounds.stderr | 30 +++++++++++- 7 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/generic-associated-types/equality-bound.rs create mode 100644 src/test/ui/generic-associated-types/equality-bound.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1822ba6ec9964..efc30121987e2 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; use std::mem; -use std::ops::DerefMut; +use std::ops::{Deref, DerefMut}; const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -1714,6 +1714,53 @@ fn deny_equality_constraints( } } } + // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. + if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { + if let [potential_param, potential_assoc] = &full_path.segments[..] { + for param in &generics.params { + if param.ident == potential_param.ident { + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound + { + if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { + let assoc = pprust::path_to_string(&ast::Path::from_ident( + potential_assoc.ident, + )); + let ty = pprust::ty_to_string(&predicate.rhs_ty); + let (args, span) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + continue; + }; + ( + format!(", {} = {}", assoc, ty), + arg.span().shrink_to_hi(), + ) + } + _ => continue, + }, + None => ( + format!("<{} = {}>", assoc, ty), + trait_segment.span().shrink_to_hi(), + ), + }; + err.multipart_suggestion( + &format!( + "if `{}::{}` is an associated type you're trying to set, \ + use the associated type binding syntax", + trait_segment.ident, potential_assoc.ident, + ), + vec![(span, args), (predicate.span, String::new())], + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } + } err.note( "see issue #20041 for more information", ); diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 47666670b2b63..adc4d117b805f 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -6,6 +6,7 @@ #![feature(iter_is_partitioned)] #![feature(box_patterns)] +#![feature(let_else)] #![recursion_limit = "256"] pub mod ast_validation; diff --git a/src/test/ui/generic-associated-types/equality-bound.rs b/src/test/ui/generic-associated-types/equality-bound.rs new file mode 100644 index 0000000000000..fcc2da8014f87 --- /dev/null +++ b/src/test/ui/generic-associated-types/equality-bound.rs @@ -0,0 +1,15 @@ +fn sum>(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum2(i: I) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses + panic!() +} +fn sum3(i: J) -> i32 where I::Item = i32 { +//~^ ERROR equality constraints are not yet supported in `where` clauses +//~| ERROR failed to resolve: use of undeclared type `I` + panic!() +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/equality-bound.stderr b/src/test/ui/generic-associated-types/equality-bound.stderr new file mode 100644 index 0000000000000..27432641958bd --- /dev/null +++ b/src/test/ui/generic-associated-types/equality-bound.stderr @@ -0,0 +1,43 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:1:51 + | +LL | fn sum>(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum>(i: I) -> i32 where I::Item = i32 { +LL + fn sum>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:5:41 + | +LL | fn sum2(i: I) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax + | +LL - fn sum2(i: I) -> i32 where I::Item = i32 { +LL + fn sum2>(i: I) -> i32 where { + | + +error: equality constraints are not yet supported in `where` clauses + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3(i: J) -> i32 where I::Item = i32 { + | ^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information + +error[E0433]: failed to resolve: use of undeclared type `I` + --> $DIR/equality-bound.rs:9:41 + | +LL | fn sum3(i: J) -> i32 where I::Item = i32 { + | ^ use of undeclared type `I` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/generic-associated-types/missing-bounds.fixed b/src/test/ui/generic-associated-types/missing-bounds.fixed index 54478d1628245..0e234120a51c5 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.fixed +++ b/src/test/ui/generic-associated-types/missing-bounds.fixed @@ -34,11 +34,12 @@ impl> Add for D { struct E(B); -impl Add for E where B: Add { +impl Add for E where B: Add, B: Add { + //~^ ERROR equality constraints are not yet supported in `where` clauses type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) + Self(self.0 + rhs.0) //~ ERROR mismatched types } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.rs b/src/test/ui/generic-associated-types/missing-bounds.rs index 962d2db9476bd..ffafff5e9f586 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.rs +++ b/src/test/ui/generic-associated-types/missing-bounds.rs @@ -34,11 +34,12 @@ impl Add for D { struct E(B); -impl Add for E where B: Add { +impl Add for E where ::Output = B { + //~^ ERROR equality constraints are not yet supported in `where` clauses type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) + Self(self.0 + rhs.0) //~ ERROR mismatched types } } diff --git a/src/test/ui/generic-associated-types/missing-bounds.stderr b/src/test/ui/generic-associated-types/missing-bounds.stderr index 4d33fe84829e0..c9603b8d1ea4a 100644 --- a/src/test/ui/generic-associated-types/missing-bounds.stderr +++ b/src/test/ui/generic-associated-types/missing-bounds.stderr @@ -1,3 +1,15 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/missing-bounds.rs:37:33 + | +LL | impl Add for E where ::Output = B { + | ^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: if `Output` is an associated type you're trying to set, use the associated type binding syntax + | +LL | impl Add for E where B: Add { + | ~~~~~~~~~~~~~~~~~~ + error[E0308]: mismatched types --> $DIR/missing-bounds.rs:11:11 | @@ -43,7 +55,23 @@ help: consider restricting type parameter `B` LL | impl> Add for D { | +++++++++++++++++++++++++++ -error: aborting due to 3 previous errors +error[E0308]: mismatched types + --> $DIR/missing-bounds.rs:42:14 + | +LL | impl Add for E where ::Output = B { + | - this type parameter +... +LL | Self(self.0 + rhs.0) + | ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type + | + = note: expected type parameter `B` + found associated type `::Output` +help: consider further restricting type parameter `B` + | +LL | impl Add for E where ::Output = B, B: Add { + | ++++++++++++++++++++ + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`. From 3649b90b33acbc0248efa0bc35675081977aefc2 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 22 Nov 2021 23:23:58 -0800 Subject: [PATCH 6/9] Simplify rendering of stylesheet links into HTML We carry around a list of stylesheets that can carry two different types of thing: 1. Internal stylesheets specific to a page type (only for settings) 2. Themes In this change I move the link generation for settings.css into settings(), so Context.style_files is reserved just for themes. We had two places where we extracted a base theme name from a list of StylePaths. I consolidated that code to be a method on StylePath. I moved generation of link tags for stylesheets into the page.html template. With that change, I made the template responsible for special handling of light.css (making it the default theme) and of the other themes (marking them disabled). That allowed getting rid of the `disabled` field on StylePath. --- src/librustdoc/config.rs | 2 +- src/librustdoc/error.rs | 5 ++- src/librustdoc/html/layout.rs | 22 ++++--------- src/librustdoc/html/render/context.rs | 18 ++++++---- src/librustdoc/html/render/mod.rs | 38 +++++++++------------- src/librustdoc/html/render/write_shared.rs | 4 +-- src/librustdoc/html/templates/page.html | 10 +++++- 7 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 493aa56fce6ef..6523d0cf3fc89 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -556,7 +556,7 @@ impl Options { )) .emit(); } - themes.push(StylePath { path: theme_file, disabled: true }); + themes.push(StylePath { path: theme_file }); } } diff --git a/src/librustdoc/error.rs b/src/librustdoc/error.rs index 82d0002b98b18..8eadbf63f33d9 100644 --- a/src/librustdoc/error.rs +++ b/src/librustdoc/error.rs @@ -39,7 +39,10 @@ macro_rules! try_none { match $e { Some(e) => e, None => { - return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file)); + return Err(::new( + io::Error::new(io::ErrorKind::Other, "not found"), + $file, + )); } } }}; diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 71d7cc1a09dce..03ad784ef77c5 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -2,8 +2,8 @@ use std::path::PathBuf; use rustc_data_structures::fx::FxHashMap; +use crate::error::Error; use crate::externalfiles::ExternalHtml; -use crate::html::escape::Escape; use crate::html::format::{Buffer, Print}; use crate::html::render::{ensure_trailing_slash, StylePath}; @@ -50,7 +50,7 @@ struct PageLayout<'a> { static_root_path: &'a str, page: &'a Page<'a>, layout: &'a Layout, - style_files: String, + themes: Vec, sidebar: String, content: String, krate_with_trailing_slash: String, @@ -66,26 +66,18 @@ crate fn render( ) -> String { let static_root_path = page.get_static_root_path(); let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); - let style_files = style_files + let themes = style_files .iter() - .filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled))) - .filter_map(|t| t.0.to_str().map(|path| (path, t.1))) - .map(|t| { - format!( - r#""#, - Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)), - if t.1 { "disabled" } else { "" }, - if t.0 == "light" { "id=\"themeStyle\"" } else { "" } - ) - }) - .collect::(); + .map(StylePath::basename) + .collect::>() + .unwrap_or_default(); let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let sidebar = Buffer::html().to_display(sidebar); let teractx = tera::Context::from_serialize(PageLayout { static_root_path, page, layout, - style_files, + themes, sidebar, content, krate_with_trailing_slash, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 069862efde640..365d959ad9f3b 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -504,9 +504,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // by the browser as the theme stylesheet. The theme system (hackily) works by // changing the href to this stylesheet. All other themes are disabled to // prevent rule conflicts - scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false }); - scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true }); - scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true }); + scx.style_files.push(StylePath { path: PathBuf::from("light.css") }); + scx.style_files.push(StylePath { path: PathBuf::from("dark.css") }); + scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") }); let dst = output; scx.ensure_dir(&dst)?; @@ -596,9 +596,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { page.description = "Settings of Rustdoc"; page.root_path = "./"; - let mut style_files = self.shared.style_files.clone(); let sidebar = "

Settings

"; - style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false }); + let theme_names: Vec = self + .shared + .style_files + .iter() + .map(StylePath::basename) + .collect::>()?; let v = layout::render( &self.shared.templates, &self.shared.layout, @@ -607,9 +611,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { settings( self.shared.static_root_path.as_deref().unwrap_or("./"), &self.shared.resource_suffix, - &self.shared.style_files, + theme_names, )?, - &style_files, + &self.shared.style_files, ); self.shared.fs.write(settings_file, v)?; if let Some(ref redirections) = self.shared.redirections { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 24baca285c6ff..39061a119faec 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -64,7 +64,6 @@ use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; use crate::clean::{self, ItemId, RenderedLink, SelfTy}; -use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -173,8 +172,12 @@ impl Serialize for TypeWithKind { crate struct StylePath { /// The path to the theme crate path: PathBuf, - /// What the `disabled` attribute should be set to in the HTML tag - crate disabled: bool, +} + +impl StylePath { + pub fn basename(&self) -> Result { + Ok(try_none!(try_none!(self.path.file_stem(), &self.path).to_str(), &self.path).to_string()) + } } fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { @@ -353,7 +356,7 @@ enum Setting { js_data_name: &'static str, description: &'static str, default_value: &'static str, - options: Vec<(String, String)>, + options: Vec, }, } @@ -393,10 +396,9 @@ impl Setting { options .iter() .map(|opt| format!( - "", - opt.0, - if opt.0 == default_value { "selected" } else { "" }, - opt.1, + "", + if opt == default_value { "selected" } else { "" }, + name = opt, )) .collect::(), root_path, @@ -421,18 +423,7 @@ impl> From<(&'static str, Vec)> for Setting { } } -fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result { - let theme_names: Vec<(String, String)> = themes - .iter() - .map(|entry| { - let theme = - try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path) - .to_string(); - - Ok((theme.clone(), theme)) - }) - .collect::>()?; - +fn settings(root_path: &str, suffix: &str, theme_names: Vec) -> Result { // (id, explanation, default value) let settings: &[Setting] = &[ ( @@ -469,10 +460,11 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> ResultRustdoc settings\ \
{}
\ - ", + \ + ", settings.iter().map(|s| s.display(root_path, suffix)).collect::(), - root_path, - suffix + root_path = root_path, + suffix = suffix )) } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 2d3b2490677e9..6b0f8dad4c501 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -228,12 +228,12 @@ pub(super) fn write_shared( let mut themes: FxHashSet = FxHashSet::default(); for entry in &cx.shared.style_files { - let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path); + let theme = entry.basename()?; let extension = try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); // Handle the official themes - match theme { + match theme.as_str() { "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?, "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?, "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?, diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index cf57d4cf3aa43..863bf53eff3ab 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -12,7 +12,15 @@ {#- -#} - {{- style_files | safe -}} + {%- for theme in themes -%} + {#- -#} + {%- endfor -%}