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:
commit
686e313a9a
@ -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 ¶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(
|
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",
|
||||||
);
|
);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
///
|
///
|
||||||
|
@ -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
|
||||||
|
@ -552,7 +552,7 @@ impl Options {
|
|||||||
))
|
))
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
themes.push(StylePath { path: theme_file, disabled: true });
|
themes.push(StylePath { path: theme_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,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
@ -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()
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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> {#- -#}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
15
src/test/ui/generic-associated-types/equality-bound.rs
Normal file
15
src/test/ui/generic-associated-types/equality-bound.rs
Normal 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() {}
|
43
src/test/ui/generic-associated-types/equality-bound.stderr
Normal file
43
src/test/ui/generic-associated-types/equality-bound.stderr
Normal 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`.
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user