Auto merge of #91288 - matthiaskrgr:rollup-yp5h41r, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #83791 (Weaken guarantee around advancing underlying iterators in zip)
 - #90995 (Document non-guarantees for Hash)
 - #91057 (Expand `available_parallelism` docs in anticipation of cgroup quota support)
 - #91062 (rustdoc: Consolidate static-file replacement mechanism)
 - #91208 (Account for incorrect `where T::Assoc = Ty` bound)
 - #91266 (Use non-generic inner function for pointer formatting)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-11-27 14:29:12 +00:00
commit 686e313a9a
22 changed files with 306 additions and 160 deletions

View File

@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use std::mem; use std::mem;
use std::ops::DerefMut; use std::ops::{Deref, DerefMut};
const MORE_EXTERN: &str = const MORE_EXTERN: &str =
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; "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<Bar = RhsTy>`.
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 &param.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( err.note(
"see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information", "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
); );

View File

@ -6,6 +6,7 @@
#![feature(iter_is_partitioned)] #![feature(iter_is_partitioned)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(let_else)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
pub mod ast_validation; pub mod ast_validation;

View File

@ -2186,28 +2186,34 @@ impl Display for char {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Pointer for *const T { impl<T: ?Sized> Pointer for *const T {
fn fmt(&self, f: &mut Formatter<'_>) -> Result { fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let old_width = f.width; /// Since the formatting will be identical for all pointer types, use a non-monomorphized
let old_flags = f.flags; /// implementation for the actual formatting to reduce the amount of codegen work needed
fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result {
let old_width = f.width;
let old_flags = f.flags;
// The alternate flag is already treated by LowerHex as being special- // The alternate flag is already treated by LowerHex as being special-
// it denotes whether to prefix with 0x. We use it to work out whether // it denotes whether to prefix with 0x. We use it to work out whether
// or not to zero extend, and then unconditionally set it to get the // or not to zero extend, and then unconditionally set it to get the
// prefix. // prefix.
if f.alternate() { if f.alternate() {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
if f.width.is_none() { if f.width.is_none() {
f.width = Some((usize::BITS / 4) as usize + 2); f.width = Some((usize::BITS / 4) as usize + 2);
}
} }
f.flags |= 1 << (FlagV1::Alternate as u32);
let ret = LowerHex::fmt(&(ptr as usize), f);
f.width = old_width;
f.flags = old_flags;
ret
} }
f.flags |= 1 << (FlagV1::Alternate as u32);
let ret = LowerHex::fmt(&(*self as *const () as usize), f); inner(*self as *const (), f)
f.width = old_width;
f.flags = old_flags;
ret
} }
} }

View File

@ -164,6 +164,19 @@ mod sip;
/// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a",
/// "bc")` hash differently. /// "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 be 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 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`hash`]: Hash::hash /// [`hash`]: Hash::hash

View File

@ -458,8 +458,10 @@ pub trait Iterator {
/// In other words, it zips two iterators together, into a single one. /// In other words, it zips two iterators together, into a single one.
/// ///
/// If either iterator returns [`None`], [`next`] from the zipped iterator /// If either iterator returns [`None`], [`next`] from the zipped iterator
/// will return [`None`]. If the first iterator returns [`None`], `zip` will /// will return [`None`].
/// short-circuit and `next` will not be called on the second iterator. /// 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 /// # Examples
/// ///

View File

@ -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 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 /// the default amount of parallelism the program should use. Among other things it
/// does not expose information on NUMA regions, does not account for /// does not expose information on NUMA regions, does not account for
/// differences in (co)processor capabilities, and will not modify the program's /// differences in (co)processor capabilities or current system load,
/// global state in order to more accurately query the amount of available /// and will not modify the program's global state in order to more accurately
/// parallelism. /// 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 /// 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 /// not cached and instead recomputed every time this function is called. It should not be

View File

@ -552,7 +552,7 @@ impl Options {
)) ))
.emit(); .emit();
} }
themes.push(StylePath { path: theme_file, disabled: true }); themes.push(StylePath { path: theme_file });
} }
} }

View File

@ -39,7 +39,10 @@ macro_rules! try_none {
match $e { match $e {
Some(e) => e, Some(e) => e,
None => { None => {
return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file)); return Err(<crate::error::Error as crate::docfs::PathError>::new(
io::Error::new(io::ErrorKind::Other, "not found"),
$file,
));
} }
} }
}}; }};

View File

@ -2,8 +2,8 @@ use std::path::PathBuf;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use crate::error::Error;
use crate::externalfiles::ExternalHtml; use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print}; use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath}; use crate::html::render::{ensure_trailing_slash, StylePath};
@ -50,10 +50,11 @@ struct PageLayout<'a> {
static_root_path: &'a str, static_root_path: &'a str,
page: &'a Page<'a>, page: &'a Page<'a>,
layout: &'a Layout, layout: &'a Layout,
style_files: String, themes: Vec<String>,
sidebar: String, sidebar: String,
content: String, content: String,
krate_with_trailing_slash: String, krate_with_trailing_slash: String,
crate rustdoc_version: &'a str,
} }
crate fn render<T: Print, S: Print>( crate fn render<T: Print, S: Print>(
@ -66,29 +67,24 @@ crate fn render<T: Print, S: Print>(
) -> String { ) -> String {
let static_root_path = page.get_static_root_path(); let static_root_path = page.get_static_root_path();
let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string(); let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
let style_files = style_files let mut themes: Vec<String> = style_files
.iter() .iter()
.filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled))) .map(StylePath::basename)
.filter_map(|t| t.0.to_str().map(|path| (path, t.1))) .collect::<Result<_, Error>>()
.map(|t| { .unwrap_or_default();
format!( themes.sort();
r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#, let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
if t.1 { "disabled" } else { "" },
if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
)
})
.collect::<String>();
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar. let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
let sidebar = Buffer::html().to_display(sidebar); let sidebar = Buffer::html().to_display(sidebar);
let teractx = tera::Context::from_serialize(PageLayout { let teractx = tera::Context::from_serialize(PageLayout {
static_root_path, static_root_path,
page, page,
layout, layout,
style_files, themes,
sidebar, sidebar,
content, content,
krate_with_trailing_slash, krate_with_trailing_slash,
rustdoc_version,
}) })
.unwrap(); .unwrap();
templates.render("page.html", &teractx).unwrap() templates.render("page.html", &teractx).unwrap()

View File

@ -504,9 +504,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// by the browser as the theme stylesheet. The theme system (hackily) works by // 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 // changing the href to this stylesheet. All other themes are disabled to
// prevent rule conflicts // prevent rule conflicts
scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false }); scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true }); scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true }); scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });
let dst = output; let dst = output;
scx.ensure_dir(&dst)?; scx.ensure_dir(&dst)?;
@ -596,9 +596,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
page.description = "Settings of Rustdoc"; page.description = "Settings of Rustdoc";
page.root_path = "./"; page.root_path = "./";
let mut style_files = self.shared.style_files.clone();
let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>"; let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false }); let theme_names: Vec<String> = self
.shared
.style_files
.iter()
.map(StylePath::basename)
.collect::<Result<_, Error>>()?;
let v = layout::render( let v = layout::render(
&self.shared.templates, &self.shared.templates,
&self.shared.layout, &self.shared.layout,
@ -607,9 +611,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
settings( settings(
self.shared.static_root_path.as_deref().unwrap_or("./"), self.shared.static_root_path.as_deref().unwrap_or("./"),
&self.shared.resource_suffix, &self.shared.resource_suffix,
&self.shared.style_files, theme_names,
)?, )?,
&style_files, &self.shared.style_files,
); );
self.shared.fs.write(settings_file, v)?; self.shared.fs.write(settings_file, v)?;
if let Some(ref redirections) = self.shared.redirections { if let Some(ref redirections) = self.shared.redirections {

View File

@ -64,7 +64,6 @@ use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use crate::clean::{self, ItemId, RenderedLink, SelfTy}; use crate::clean::{self, ItemId, RenderedLink, SelfTy};
use crate::docfs::PathError;
use crate::error::Error; use crate::error::Error;
use crate::formats::cache::Cache; use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
@ -173,8 +172,12 @@ impl Serialize for TypeWithKind {
crate struct StylePath { crate struct StylePath {
/// The path to the theme /// The path to the theme
crate path: PathBuf, 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<String, Error> {
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) { fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
@ -353,7 +356,7 @@ enum Setting {
js_data_name: &'static str, js_data_name: &'static str,
description: &'static str, description: &'static str,
default_value: &'static str, default_value: &'static str,
options: Vec<(String, String)>, options: Vec<String>,
}, },
} }
@ -393,10 +396,9 @@ impl Setting {
options options
.iter() .iter()
.map(|opt| format!( .map(|opt| format!(
"<option value=\"{}\" {}>{}</option>", "<option value=\"{name}\" {}>{name}</option>",
opt.0, if opt == default_value { "selected" } else { "" },
if opt.0 == default_value { "selected" } else { "" }, name = opt,
opt.1,
)) ))
.collect::<String>(), .collect::<String>(),
root_path, root_path,
@ -421,18 +423,7 @@ impl<T: Into<Setting>> From<(&'static str, Vec<T>)> for Setting {
} }
} }
fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<String, Error> { fn settings(root_path: &str, suffix: &str, theme_names: Vec<String>) -> Result<String, Error> {
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::<Result<_, Error>>()?;
// (id, explanation, default value) // (id, explanation, default value)
let settings: &[Setting] = &[ let settings: &[Setting] = &[
( (
@ -469,10 +460,11 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
<span class=\"in-band\">Rustdoc settings</span>\ <span class=\"in-band\">Rustdoc settings</span>\
</h1>\ </h1>\
<div class=\"settings\">{}</div>\ <div class=\"settings\">{}</div>\
<script src=\"{}settings{}.js\"></script>", <link rel=\"stylesheet\" href=\"{root_path}settings{suffix}.css\">\
<script src=\"{root_path}settings{suffix}.js\"></script>",
settings.iter().map(|s| s.display(root_path, suffix)).collect::<String>(), settings.iter().map(|s| s.display(root_path, suffix)).collect::<String>(),
root_path, root_path = root_path,
suffix suffix = suffix
)) ))
} }

View File

@ -181,42 +181,34 @@ pub(super) fn write_shared(
cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit) cx.write_shared(SharedResource::InvocationSpecific { basename: p }, content, &options.emit)
}; };
fn add_background_image_to_css( // Given "foo.svg", return e.g. "url(\"foo1.58.0.svg\")"
cx: &Context<'_>, fn ver_url(cx: &Context<'_>, basename: &'static str) -> String {
css: &mut String, format!(
rule: &str, "url(\"{}\")",
file: &'static str, SharedResource::ToolchainSpecific { basename }
) {
css.push_str(&format!(
"{} {{ background-image: url({}); }}",
rule,
SharedResource::ToolchainSpecific { basename: file }
.path(cx) .path(cx)
.file_name() .file_name()
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap() .unwrap()
)) )
} }
// Add all the static files. These may already exist, but we just // We use the AUTOREPLACE mechanism to inject into our static JS and CSS certain
// overwrite them anyway to make sure that they're fresh and up-to-date. // values that are only known at doc build time. Since this mechanism is somewhat
let mut rustdoc_css = static_files::RUSTDOC_CSS.to_owned(); // surprising when reading the code, please limit it to rustdoc.css.
add_background_image_to_css( write_minify(
"rustdoc.css",
static_files::RUSTDOC_CSS
.replace(
"/* AUTOREPLACE: */url(\"toggle-minus.svg\")",
&ver_url(cx, "toggle-minus.svg"),
)
.replace("/* AUTOREPLACE: */url(\"toggle-plus.svg\")", &ver_url(cx, "toggle-plus.svg"))
.replace("/* AUTOREPLACE: */url(\"down-arrow.svg\")", &ver_url(cx, "down-arrow.svg")),
cx, cx,
&mut rustdoc_css, options,
"details.undocumented[open] > summary::before, \ )?;
details.rustdoc-toggle[open] > summary::before, \
details.rustdoc-toggle[open] > summary.hideme::before",
"toggle-minus.svg",
);
add_background_image_to_css(
cx,
&mut rustdoc_css,
"details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
"toggle-plus.svg",
);
write_minify("rustdoc.css", rustdoc_css, cx, options)?;
// Add all the static files. These may already exist, but we just // Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date. // overwrite them anyway to make sure that they're fresh and up-to-date.
@ -228,12 +220,12 @@ pub(super) fn write_shared(
let mut themes: FxHashSet<String> = FxHashSet::default(); let mut themes: FxHashSet<String> = FxHashSet::default();
for entry in &cx.shared.style_files { 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 = let extension =
try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
// Handle the official themes // Handle the official themes
match theme { match theme.as_str() {
"light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?, "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
"dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?, "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
"ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?, "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
@ -265,26 +257,7 @@ pub(super) fn write_shared(
let mut themes: Vec<&String> = themes.iter().collect(); let mut themes: Vec<&String> = themes.iter().collect();
themes.sort(); themes.sort();
// FIXME: this should probably not be a toolchain file since it depends on `--theme`. write_minify("main.js", static_files::MAIN_JS, cx, options)?;
// But it seems a shame to copy it over and over when it's almost always the same.
// Maybe we can change the representation to move this out of main.js?
write_minify(
"main.js",
static_files::MAIN_JS
.replace(
"/* INSERT THEMES HERE */",
&format!(" = {}", serde_json::to_string(&themes).unwrap()),
)
.replace(
"/* INSERT RUSTDOC_VERSION HERE */",
&format!(
"rustdoc {}",
rustc_interface::util::version_str().unwrap_or("unknown version")
),
),
cx,
options,
)?;
write_minify("search.js", static_files::SEARCH_JS, cx, options)?; write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?; write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
@ -292,18 +265,7 @@ pub(super) fn write_shared(
write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?; write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
} }
{ write_minify("storage.js", static_files::STORAGE_JS, cx, options)?;
write_minify(
"storage.js",
format!(
"var resourcesSuffix = \"{}\";{}",
cx.shared.resource_suffix,
static_files::STORAGE_JS
),
cx,
options,
)?;
}
if cx.shared.layout.scrape_examples_extension { if cx.shared.layout.scrape_examples_extension {
cx.write_minify( cx.write_minify(

View File

@ -828,6 +828,7 @@ h2.small-section-header > .anchor {
background-color: transparent; background-color: transparent;
background-size: 20px; background-size: 20px;
background-position: calc(100% - 1px) 56%; background-position: calc(100% - 1px) 56%;
background-image: /* AUTOREPLACE: */url("down-arrow.svg");
} }
.search-container > .top-button { .search-container > .top-button {
position: absolute; position: absolute;
@ -1610,6 +1611,16 @@ details.rustdoc-toggle[open] > summary.hideme > span {
display: none; display: none;
} }
details.undocumented[open] > summary::before,
details.rustdoc-toggle[open] > summary::before,
details.rustdoc-toggle[open] > summary.hideme::before {
background-image: /* AUTOREPLACE: */url("toggle-minus.svg");
}
details.undocumented > summary::before, details.rustdoc-toggle > summary::before {
background-image: /* AUTOREPLACE: */url("toggle-plus.svg");
}
details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle[open] > summary::before,
details.rustdoc-toggle[open] > summary.hideme::before { details.rustdoc-toggle[open] > summary.hideme::before {
width: 17px; width: 17px;

View File

@ -37,14 +37,29 @@ if (!DOMTokenList.prototype.remove) {
}; };
} }
(function () { // Get a value from the rustdoc-vars div, which is used to convey data from
var rustdocVars = document.getElementById("rustdoc-vars"); // Rust to the JS. If there is no such element, return null.
if (rustdocVars) { function getVar(name) {
window.rootPath = rustdocVars.attributes["data-root-path"].value; var el = document.getElementById("rustdoc-vars");
window.currentCrate = rustdocVars.attributes["data-current-crate"].value; if (el) {
window.searchJS = rustdocVars.attributes["data-search-js"].value; return el.attributes["data-" + name].value;
window.searchIndexJS = rustdocVars.attributes["data-search-index-js"].value; } else {
return null;
} }
}
// Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
// for a resource under the root-path, with the resource-suffix.
function resourcePath(basename, extension) {
return getVar("root-path") + basename + getVar("resource-suffix") + extension;
}
(function () {
window.rootPath = getVar("root-path");
window.currentCrate = getVar("current-crate");
window.searchJS = resourcePath("search", ".js");
window.searchIndexJS = resourcePath("search-index", ".js");
var sidebarVars = document.getElementById("sidebar-vars"); var sidebarVars = document.getElementById("sidebar-vars");
if (sidebarVars) { if (sidebarVars) {
window.sidebarCurrent = { window.sidebarCurrent = {
@ -115,7 +130,7 @@ function hideThemeButtonState() {
(function () { (function () {
var themeChoices = getThemesElement(); var themeChoices = getThemesElement();
var themePicker = getThemePickerElement(); var themePicker = getThemePickerElement();
var availableThemes/* INSERT THEMES HERE */; var availableThemes = getVar("themes").split(",");
function switchThemeButtonState() { function switchThemeButtonState() {
if (themeChoices.style.display === "block") { if (themeChoices.style.display === "block") {
@ -980,7 +995,7 @@ function hideThemeButtonState() {
var rustdoc_version = document.createElement("span"); var rustdoc_version = document.createElement("span");
rustdoc_version.className = "bottom"; rustdoc_version.className = "bottom";
var rustdoc_version_code = document.createElement("code"); var rustdoc_version_code = document.createElement("code");
rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */"; rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
rustdoc_version.appendChild(rustdoc_version_code); rustdoc_version.appendChild(rustdoc_version_code);
container.appendChild(rustdoc_version); container.appendChild(rustdoc_version);

View File

@ -1,5 +1,3 @@
// From rust:
/* global resourcesSuffix */
var darkThemes = ["dark", "ayu"]; var darkThemes = ["dark", "ayu"];
window.currentTheme = document.getElementById("themeStyle"); window.currentTheme = document.getElementById("themeStyle");
window.mainTheme = document.getElementById("mainThemeStyle"); window.mainTheme = document.getElementById("mainThemeStyle");
@ -107,9 +105,8 @@ function getCurrentValue(name) {
} }
function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) { function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
var fullBasicCss = "rustdoc" + resourcesSuffix + ".css"; var newHref = mainStyleElem.href.replace(
var fullNewTheme = newTheme + resourcesSuffix + ".css"; /\/rustdoc([^/]*)\.css/, "/" + newTheme + "$1" + ".css");
var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
// If this new value comes from a system setting or from the previously // If this new value comes from a system setting or from the previously
// saved theme, no need to save it. // saved theme, no need to save it.

View File

@ -12,7 +12,16 @@
<link rel="stylesheet" type="text/css" {# -#} <link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#} href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
id="mainThemeStyle"> {#- -#} id="mainThemeStyle"> {#- -#}
{{- style_files | safe -}} {%- for theme in themes -%}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {#- -#}
{%- if theme == "light" -%}
id="themeStyle"
{%- else -%}
disabled
{%- endif -%}
>
{%- endfor -%}
<script id="default-settings" {# -#} <script id="default-settings" {# -#}
{% for k, v in layout.default_settings %} {% for k, v in layout.default_settings %}
data-{{k}}="{{v}}" data-{{k}}="{{v}}"
@ -49,11 +58,6 @@
href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#} href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
{%- endif -%} {%- endif -%}
{{- layout.external_html.in_header | safe -}} {{- layout.external_html.in_header | safe -}}
<style type="text/css"> {#- -#}
#crate-search{ {#- -#}
background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
} {#- -#}
</style> {#- -#}
</head> {#- -#} </head> {#- -#}
<body class="rustdoc {{page.css_class}}"> {#- -#} <body class="rustdoc {{page.css_class}}"> {#- -#}
<!--[if lte IE 11]> {#- -#} <!--[if lte IE 11]> {#- -#}
@ -114,8 +118,10 @@
<div id="rustdoc-vars" {# -#} <div id="rustdoc-vars" {# -#}
data-root-path="{{page.root_path | safe}}" {# -#} data-root-path="{{page.root_path | safe}}" {# -#}
data-current-crate="{{layout.krate}}" {# -#} data-current-crate="{{layout.krate}}" {# -#}
data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#} data-themes="{{themes | join(sep=",") }}" {# -#}
data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#} data-resource-suffix="{{page.resource_suffix}}" {# -#}
data-rustdoc-version="{{rustdoc_version}}" {# -#}
> {#- -#}
</div> </div>
</body> {#- -#} </body> {#- -#}
</html> {#- -#} </html> {#- -#}

View File

@ -3,7 +3,7 @@
// @has static_root_path/struct.SomeStruct.html // @has static_root_path/struct.SomeStruct.html
// @matches - '"/cache/main\.js"' // @matches - '"/cache/main\.js"'
// @!matches - '"\.\./main\.js"' // @!matches - '"\.\./main\.js"'
// @matches - '"\.\./search-index\.js"' // @matches - 'data-root-path="\.\./"'
// @!matches - '"/cache/search-index\.js"' // @!matches - '"/cache/search-index\.js"'
pub struct SomeStruct; pub struct SomeStruct;

View File

@ -0,0 +1,15 @@
fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
//~^ ERROR equality constraints are not yet supported in `where` clauses
panic!()
}
fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
//~^ ERROR equality constraints are not yet supported in `where` clauses
panic!()
}
fn sum3<J: Iterator>(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() {}

View File

@ -0,0 +1,43 @@
error: equality constraints are not yet supported in `where` clauses
--> $DIR/equality-bound.rs:1:51
|
LL | fn sum<I: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
| ^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/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: Iterator<Item = ()>>(i: I) -> i32 where I::Item = i32 {
LL + fn sum<I: Iterator<Item = (), Item = i32>>(i: I) -> i32 where {
|
error: equality constraints are not yet supported in `where` clauses
--> $DIR/equality-bound.rs:5:41
|
LL | fn sum2<I: Iterator>(i: I) -> i32 where I::Item = i32 {
| ^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/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: Iterator>(i: I) -> i32 where I::Item = i32 {
LL + fn sum2<I: Iterator<Item = i32>>(i: I) -> i32 where {
|
error: equality constraints are not yet supported in `where` clauses
--> $DIR/equality-bound.rs:9:41
|
LL | fn sum3<J: Iterator>(i: J) -> i32 where I::Item = i32 {
| ^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
error[E0433]: failed to resolve: use of undeclared type `I`
--> $DIR/equality-bound.rs:9:41
|
LL | fn sum3<J: Iterator>(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`.

View File

@ -34,11 +34,12 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
struct E<B>(B); struct E<B>(B);
impl<B: Add> Add for E<B> where B: Add<Output = B> { impl<B: Add> Add for E<B> where B: Add<Output = B>, B: Add<Output = B> {
//~^ ERROR equality constraints are not yet supported in `where` clauses
type Output = Self; type Output = Self;
fn add(self, rhs: Self) -> Self { fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0) Self(self.0 + rhs.0) //~ ERROR mismatched types
} }
} }

View File

@ -34,11 +34,12 @@ impl<B> Add for D<B> {
struct E<B>(B); struct E<B>(B);
impl<B: Add> Add for E<B> where B: Add<Output = B> { impl<B: Add> Add for E<B> where <B as Add>::Output = B {
//~^ ERROR equality constraints are not yet supported in `where` clauses
type Output = Self; type Output = Self;
fn add(self, rhs: Self) -> Self { fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0) Self(self.0 + rhs.0) //~ ERROR mismatched types
} }
} }

View File

@ -1,3 +1,15 @@
error: equality constraints are not yet supported in `where` clauses
--> $DIR/missing-bounds.rs:37:33
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
|
LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
| ~~~~~~~~~~~~~~~~~~
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/missing-bounds.rs:11:11 --> $DIR/missing-bounds.rs:11:11
| |
@ -43,7 +55,23 @@ help: consider restricting type parameter `B`
LL | impl<B: std::ops::Add<Output = B>> Add for D<B> { LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
| +++++++++++++++++++++++++++ | +++++++++++++++++++++++++++
error: aborting due to 3 previous errors error[E0308]: mismatched types
--> $DIR/missing-bounds.rs:42:14
|
LL | impl<B: Add> Add for E<B> where <B as Add>::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 `<B as Add>::Output`
help: consider further restricting type parameter `B`
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B, B: Add<Output = B> {
| ++++++++++++++++++++
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0369. Some errors have detailed explanations: E0308, E0369.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0308`.