Auto merge of #76804 - tmandry:rollup-nwntt3q, r=tmandry

Rollup of 16 pull requests

Successful merges:

 - #75026 (Add array_windows fn)
 - #76642 (Do not lint ignored private doc tests)
 - #76719 (Change error message for ty param in const)
 - #76721 (Use intra-doc links in `core::mem`)
 - #76728 (Add a comment why `extern crate` is necessary for rustdoc)
 - #76735 (Remove unnecessary `clone()`s in bootstrap)
 - #76741 (Avoid printing dry run timings)
 - #76747 (Add missing code examples in libcore)
 - #76756 (fix a couple of stylistic clippy warnings)
 - #76758 ([fuchsia] Propagate the userspace UTC clock)
 - #76759 (Fix stabilization marker for future_readiness_fns)
 - #76760 (don't lazily evaluate some trivial values for Option::None replacements (clippy::unnecessary_lazy_evaluations))
 - #76764 (Update books)
 - #76775 (Strip a single leading tab when rendering dataflow diffs)
 - #76778 (Simplify iter fuse struct doc)
 - #76794 (Make graphviz font configurable)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-09-16 20:18:19 +00:00
commit 285fc7d704
54 changed files with 450 additions and 164 deletions

View File

@ -591,14 +591,14 @@ pub trait GraphWalk<'a> {
fn target(&'a self, edge: &Self::Edge) -> Self::Node;
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum RenderOption {
NoEdgeLabels,
NoNodeLabels,
NoEdgeStyles,
NoNodeStyles,
Monospace,
Fontname(String),
DarkTheme,
}
@ -633,11 +633,14 @@ where
// Global graph properties
let mut graph_attrs = Vec::new();
let mut content_attrs = Vec::new();
if options.contains(&RenderOption::Monospace) {
let font = r#"fontname="Courier, monospace""#;
graph_attrs.push(font);
content_attrs.push(font);
};
let font;
if let Some(fontname) = options.iter().find_map(|option| {
if let RenderOption::Fontname(fontname) = option { Some(fontname) } else { None }
}) {
font = format!(r#"fontname="{}""#, fontname);
graph_attrs.push(&font[..]);
content_attrs.push(&font[..]);
}
if options.contains(&RenderOption::DarkTheme) {
graph_attrs.push(r#"bgcolor="black""#);
content_attrs.push(r#"color="white""#);

View File

@ -85,7 +85,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
if sub == &ty::ReStatic
&& v.0.into_iter().find(|t| t.span.desugaring_kind().is_none()).is_some()
&& v.0.into_iter().any(|t| t.span.desugaring_kind().is_none())
{
// If the failure is due to a `'static` requirement coming from a `dyn` or
// `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case

View File

@ -961,7 +961,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
continue;
}
let span = sugared_span.take().unwrap_or_else(|| attr.span);
let span = sugared_span.take().unwrap_or(attr.span);
if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) {
cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {

View File

@ -170,7 +170,7 @@ impl Collector<'tcx> {
feature_err(
&self.tcx.sess.parse_sess,
sym::static_nobundle,
span.unwrap_or_else(|| rustc_span::DUMMY_SP),
span.unwrap_or(rustc_span::DUMMY_SP),
"kind=\"static-nobundle\" is unstable",
)
.emit();
@ -179,7 +179,7 @@ impl Collector<'tcx> {
feature_err(
&self.tcx.sess.parse_sess,
sym::raw_dylib,
span.unwrap_or_else(|| rustc_span::DUMMY_SP),
span.unwrap_or(rustc_span::DUMMY_SP),
"kind=\"raw-dylib\" is unstable",
)
.emit();

View File

@ -273,10 +273,10 @@ pub trait PrettyPrinter<'tcx>:
}
match self.tcx().trimmed_def_paths(LOCAL_CRATE).get(&def_id) {
None => return Ok((self, false)),
None => Ok((self, false)),
Some(symbol) => {
self.write_str(&symbol.as_str())?;
return Ok((self, true));
Ok((self, true))
}
}
}

View File

@ -387,7 +387,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let ReturnConstraint::ClosureUpvar(upvar) = kind {
let def_id = match self.regioncx.universal_regions().defining_ty {
DefiningTy::Closure(def_id, _) => def_id,
ty @ _ => bug!("unexpected DefiningTy {:?}", ty),
ty => bug!("unexpected DefiningTy {:?}", ty),
};
let upvar_def_span = self.infcx.tcx.hir().span(upvar);

View File

@ -306,7 +306,8 @@ where
let mut buf = Vec::new();
let graphviz = graphviz::Formatter::new(body, def_id, results, style);
let mut render_opts = vec![dot::RenderOption::Monospace];
let mut render_opts =
vec![dot::RenderOption::Fontname(tcx.sess.opts.debugging_opts.graphviz_font.clone())];
if tcx.sess.opts.debugging_opts.graphviz_dark_mode {
render_opts.push(dot::RenderOption::DarkTheme);
}

View File

@ -578,7 +578,7 @@ where
return String::new();
}
let re = Regex::new("\u{001f}([+-])").unwrap();
let re = Regex::new("\t?\u{001f}([+-])").unwrap();
let raw_diff = format!("{:#?}", DebugDiffWithAdapter { new, old, ctxt });

View File

@ -126,7 +126,7 @@ impl OptimizationFinder<'b, 'tcx> {
}
}
return None;
None
}
}

View File

@ -55,9 +55,9 @@ where
writeln!(w, "{} {}Mir_{} {{", kind, cluster, def_name)?;
// Global graph properties
let font = r#"fontname="Courier, monospace""#;
let mut graph_attrs = vec![font];
let mut content_attrs = vec![font];
let font = format!(r#"fontname="{}""#, tcx.sess.opts.debugging_opts.graphviz_font);
let mut graph_attrs = vec![&font[..]];
let mut content_attrs = vec![&font[..]];
let dark_mode = tcx.sess.opts.debugging_opts.graphviz_dark_mode;
if dark_mode {

View File

@ -466,7 +466,7 @@ impl<'a> Resolver<'a> {
);
err
}
ResolutionError::ParamInNonTrivialAnonConst(name) => {
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
let mut err = self.session.struct_span_err(
span,
"generic parameters must not be used inside of non trivial constant values",
@ -478,9 +478,17 @@ impl<'a> Resolver<'a> {
name
),
);
if is_type {
err.note("type parameters are currently not permitted in anonymous constants");
} else {
err.help(
&format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", name)
&format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants",
name
)
);
}
err
}
ResolutionError::SelfInTyParamDefault => {

View File

@ -1534,7 +1534,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
}
};
let lifetime_names: Vec<_> = lifetime_names.into_iter().collect();
let lifetime_names: Vec<_> = lifetime_names.iter().collect();
match (&lifetime_names[..], snippet.as_deref()) {
([name], Some("&")) => {
suggest_existing(err, &name.as_str()[..], &|name| format!("&{} ", name));

View File

@ -221,7 +221,7 @@ enum ResolutionError<'a> {
/// generic parameters must not be used inside of non trivial constant values.
///
/// This error is only emitted when using `min_const_generics`.
ParamInNonTrivialAnonConst(Symbol),
ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
/// Error E0735: type parameters with a default cannot use `Self`
SelfInTyParamDefault,
/// Error E0767: use of unreachable label
@ -2638,9 +2638,10 @@ impl<'a> Resolver<'a> {
if record_used {
self.report_error(
span,
ResolutionError::ParamInNonTrivialAnonConst(
rib_ident.name,
),
ResolutionError::ParamInNonTrivialAnonConst {
name: rib_ident.name,
is_type: true,
},
);
}
return Res::Err;
@ -2718,7 +2719,10 @@ impl<'a> Resolver<'a> {
if record_used {
self.report_error(
span,
ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
ResolutionError::ParamInNonTrivialAnonConst {
name: rib_ident.name,
is_type: false,
},
);
}
return Res::Err;

View File

@ -1762,6 +1762,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
}
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
debugging_opts.graphviz_font = graphviz_font;
}
if !cg.embed_bitcode {
match cg.lto {
LtoCli::No | LtoCli::Unspecified => {}

View File

@ -911,6 +911,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"set the optimization fuel quota for a crate"),
graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
"use dark-themed colors in graphviz output (default: no)"),
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
"use the given `fontname` in graphviz output; can be overridden by setting \
environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)"),
hir_stats: bool = (false, parse_bool, [UNTRACKED],
"print some statistics about AST and HIR (default: no)"),
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],

View File

@ -182,7 +182,7 @@ fn overlap_within_probe(
}
if !skip_leak_check.is_yes() {
if let Err(_) = infcx.leak_check(true, snapshot) {
if infcx.leak_check(true, snapshot).is_err() {
debug!("overlap: leak check failed");
return None;
}

View File

@ -164,7 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// If all the obligations hold (or there are no obligations) the tail expression
// we can suggest to return a boxed trait object instead of an opaque type.
if suggest_box { self.ret_type_span.clone() } else { None }
if suggest_box { self.ret_type_span } else { None }
}
_ => None,
};

View File

@ -1243,10 +1243,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if check_completeness && !error_happened && !remaining_fields.is_empty() {
let no_accessible_remaining_fields = remaining_fields
.iter()
.filter(|(_, (_, field))| {
.find(|(_, (_, field))| {
field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
})
.next()
.is_none();
if no_accessible_remaining_fields {

View File

@ -1141,10 +1141,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if !etc && !unmentioned_fields.is_empty() {
let no_accessible_unmentioned_fields = unmentioned_fields
.iter()
.filter(|(field, _)| {
.find(|(field, _)| {
field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
})
.next()
.is_none();
if no_accessible_unmentioned_fields {

View File

@ -76,6 +76,7 @@
#![cfg_attr(test, feature(test))]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_windows)]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(box_patterns)]

View File

@ -97,6 +97,8 @@ pub use core::slice::check_range;
pub use core::slice::ArrayChunks;
#[unstable(feature = "array_chunks", issue = "74985")]
pub use core::slice::ArrayChunksMut;
#[unstable(feature = "array_windows", issue = "75027")]
pub use core::slice::ArrayWindows;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use core::slice::SliceIndex;
#[stable(feature = "from_ref", since = "1.28.0")]

View File

@ -21,9 +21,9 @@ pub use self::future::Future;
#[unstable(feature = "into_future", issue = "67644")]
pub use into_future::IntoFuture;
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub use pending::{pending, Pending};
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub use ready::{ready, Ready};
#[unstable(feature = "future_poll_fn", issue = "72302")]

View File

@ -11,7 +11,7 @@ use crate::task::{Context, Poll};
/// documentation for more.
///
/// [`pending`]: fn.pending.html
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Pending<T> {
_data: marker::PhantomData<T>,
@ -31,12 +31,12 @@ pub struct Pending<T> {
/// unreachable!();
/// # }
/// ```
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub fn pending<T>() -> Pending<T> {
Pending { _data: marker::PhantomData }
}
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Future for Pending<T> {
type Output = T;
@ -45,17 +45,17 @@ impl<T> Future for Pending<T> {
}
}
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Unpin for Pending<T> {}
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Debug for Pending<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Pending").finish()
}
}
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Clone for Pending<T> {
fn clone(&self) -> Self {
pending()

View File

@ -8,15 +8,15 @@ use crate::task::{Context, Poll};
/// documentation for more.
///
/// [`ready`]: fn.ready.html
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
#[derive(Debug, Clone)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Ready<T>(Option<T>);
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Unpin for Ready<T> {}
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
impl<T> Future for Ready<T> {
type Output = T;
@ -42,7 +42,7 @@ impl<T> Future for Ready<T> {
/// assert_eq!(a.await, 1);
/// # }
/// ```
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub fn ready<T>(t: T) -> Ready<T> {
Ready(Some(t))
}

View File

@ -9,11 +9,8 @@ use crate::ops::Try;
/// An iterator that yields `None` forever after the underlying iterator
/// yields `None` once.
///
/// This `struct` is created by the [`fuse`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
/// This `struct` is created by [`Iterator::fuse`]. See its documentation
/// for more.
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -31,10 +31,10 @@ pub use crate::intrinsics::transmute;
/// forever in an unreachable state. However, it does not guarantee that pointers
/// to this memory will remain valid.
///
/// * If you want to leak memory, see [`Box::leak`][leak].
/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
/// * If you want to leak memory, see [`Box::leak`].
/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
/// * If you want to dispose of a value properly, running its destructor, see
/// [`mem::drop`][drop].
/// [`mem::drop`].
///
/// # Safety
///
@ -132,15 +132,11 @@ pub use crate::intrinsics::transmute;
/// ownership to `s` — the final step of interacting with `v` to dispose of it without
/// running its destructor is entirely avoided.
///
/// [drop]: fn.drop.html
/// [uninit]: fn.uninitialized.html
/// [clone]: ../clone/trait.Clone.html
/// [swap]: fn.swap.html
/// [box]: ../../std/boxed/struct.Box.html
/// [leak]: ../../std/boxed/struct.Box.html#method.leak
/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
/// [`Box`]: ../../std/boxed/struct.Box.html
/// [`Box::leak`]: ../../std/boxed/struct.Box.html#method.leak
/// [`Box::into_raw`]: ../../std/boxed/struct.Box.html#method.into_raw
/// [`mem::drop`]: drop
/// [ub]: ../../reference/behavior-considered-undefined.html
/// [`ManuallyDrop`]: struct.ManuallyDrop.html
#[inline]
#[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
#[stable(feature = "rust1", since = "1.0.0")]
@ -152,8 +148,6 @@ pub const fn forget<T>(t: T) {
///
/// This function is just a shim intended to be removed when the `unsized_locals` feature gets
/// stabilized.
///
/// [`forget`]: fn.forget.html
#[inline]
#[unstable(feature = "forget_unsized", issue = "none")]
pub fn forget_unsized<T: ?Sized>(t: T) {
@ -301,7 +295,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
/// assert_eq!(2, mem::size_of::<ExampleUnion>());
/// ```
///
/// [alignment]: ./fn.align_of.html
/// [alignment]: align_of
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
@ -365,7 +359,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
/// [slice]: ../../std/primitive.slice.html
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
/// [`size_of_val`]: ../../core/mem/fn.size_of_val.html
///
/// # Examples
///
@ -501,7 +494,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
/// [slice]: ../../std/primitive.slice.html
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
/// [`align_of_val`]: ../../core/mem/fn.align_of_val.html
///
/// # Examples
///
@ -540,7 +532,7 @@ pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
/// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop
/// values one at a time and should use this API.
///
/// [`drop_in_place`]: ../ptr/fn.drop_in_place.html
/// [`drop_in_place`]: crate::ptr::drop_in_place
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
///
/// # Examples
@ -595,9 +587,9 @@ pub const fn needs_drop<T>() -> bool {
/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
/// It is useful for FFI sometimes, but should generally be avoided.
///
/// [zeroed]: union.MaybeUninit.html#method.zeroed
/// [zeroed]: MaybeUninit::zeroed
/// [ub]: ../../reference/behavior-considered-undefined.html
/// [inv]: union.MaybeUninit.html#initialization-invariant
/// [inv]: MaybeUninit#initialization-invariant
///
/// # Examples
///
@ -650,10 +642,10 @@ pub unsafe fn zeroed<T>() -> T {
/// (Notice that the rules around uninitialized integers are not finalized yet, but
/// until they are, it is advisable to avoid them.)
///
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
/// [uninit]: union.MaybeUninit.html#method.uninit
/// [assume_init]: union.MaybeUninit.html#method.assume_init
/// [inv]: union.MaybeUninit.html#initialization-invariant
/// [`MaybeUninit<T>`]: MaybeUninit
/// [uninit]: MaybeUninit::uninit
/// [assume_init]: MaybeUninit::assume_init
/// [inv]: MaybeUninit#initialization-invariant
#[inline(always)]
#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
#[stable(feature = "rust1", since = "1.0.0")]
@ -686,9 +678,6 @@ pub unsafe fn uninitialized<T>() -> T {
/// assert_eq!(42, x);
/// assert_eq!(5, y);
/// ```
///
/// [`replace`]: fn.replace.html
/// [`take`]: fn.take.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) {
@ -754,10 +743,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
/// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
/// assert_eq!(buffer.buf.len(), 0);
/// ```
///
/// [`Clone`]: ../../std/clone/trait.Clone.html
/// [`replace`]: fn.replace.html
/// [`swap`]: fn.swap.html
#[inline]
#[stable(feature = "mem_take", since = "1.40.0")]
pub fn take<T: Default>(dest: &mut T) -> T {
@ -822,10 +807,6 @@ pub fn take<T: Default>(dest: &mut T) -> T {
/// assert_eq!(buffer.replace_index(0, 2), 0);
/// assert_eq!(buffer.buf[0], 2);
/// ```
///
/// [`Clone`]: ../../std/clone/trait.Clone.html
/// [`swap`]: fn.swap.html
/// [`take`]: fn.take.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you don't need the old value, you can just assign the new value directly"]
@ -851,7 +832,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// Because `_x` is moved into the function, it is automatically dropped before
/// the function returns.
///
/// [drop]: ../ops/trait.Drop.html
/// [drop]: Drop
///
/// # Examples
///
@ -894,8 +875,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// println!("x: {}, y: {}", x, y.0); // still available
/// ```
///
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
/// [`Copy`]: ../../std/marker/trait.Copy.html
/// [`RefCell`]: crate::cell::RefCell
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) {}
@ -914,7 +894,6 @@ pub fn drop<T>(_x: T) {}
/// `T`.
///
/// [ub]: ../../reference/behavior-considered-undefined.html
/// [size_of]: fn.size_of.html
///
/// # Examples
///
@ -960,8 +939,6 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
/// Opaque type representing the discriminant of an enum.
///
/// See the [`discriminant`] function in this module for more information.
///
/// [`discriminant`]: fn.discriminant.html
#[stable(feature = "discriminant_value", since = "1.21.0")]
pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant);

View File

@ -166,6 +166,16 @@ from_str_float_impl!(f64);
///
/// This error is used as the error type for the [`FromStr`] implementation
/// for [`f32`] and [`f64`].
///
/// # Example
///
/// ```
/// use std::str::FromStr;
///
/// if let Err(e) = f64::from_str("a.12") {
/// println!("Failed conversion to f64: {}", e);
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {

View File

@ -5286,6 +5286,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
///
/// [`str.trim()`]: ../../std/primitive.str.html#method.trim
/// [`i8::from_str_radix`]: ../../std/primitive.i8.html#method.from_str_radix
///
/// # Example
///
/// ```
/// if let Err(e) = i32::from_str_radix("a12", 10) {
/// println!("Failed conversion to i32: {}", e);
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseIntError {
@ -5293,6 +5301,18 @@ pub struct ParseIntError {
}
/// Enum to store the various types of errors that can cause parsing an integer to fail.
///
/// # Example
///
/// ```
/// #![feature(int_error_matching)]
///
/// # fn main() {
/// if let Err(e) = i32::from_str_radix("a12", 10) {
/// println!("Failed conversion to i32: {:?}", e.kind());
/// }
/// # }
/// ```
#[unstable(
feature = "int_error_matching",
reason = "it can be useful to match errors when making error messages \

View File

@ -1687,6 +1687,106 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
}
}
/// A windowed iterator over a slice in overlapping chunks (`N` elements at a
/// time), starting at the beginning of the slice
///
/// This struct is created by the [`array_windows`] method on [slices].
///
/// [`array_windows`]: ../../std/primitive.slice.html#method.array_windows
/// [slices]: ../../std/primitive.slice.html
#[derive(Debug, Clone, Copy)]
#[unstable(feature = "array_windows", issue = "75027")]
pub struct ArrayWindows<'a, T: 'a, const N: usize> {
pub(crate) slice_head: *const T,
pub(crate) num: usize,
pub(crate) marker: marker::PhantomData<&'a [T; N]>,
}
#[unstable(feature = "array_windows", issue = "75027")]
impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
type Item = &'a [T; N];
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.num == 0 {
return None;
}
// SAFETY:
// This is safe because it's indexing into a slice guaranteed to be length > N.
let ret = unsafe { &*self.slice_head.cast::<[T; N]>() };
// SAFETY: Guaranteed that there are at least 1 item remaining otherwise
// earlier branch would've been hit
self.slice_head = unsafe { self.slice_head.add(1) };
self.num -= 1;
Some(ret)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.num, Some(self.num))
}
#[inline]
fn count(self) -> usize {
self.num
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
if self.num <= n {
self.num = 0;
return None;
}
// SAFETY:
// This is safe because it's indexing into a slice guaranteed to be length > N.
let ret = unsafe { &*self.slice_head.add(n).cast::<[T; N]>() };
// SAFETY: Guaranteed that there are at least n items remaining
self.slice_head = unsafe { self.slice_head.add(n + 1) };
self.num -= n + 1;
Some(ret)
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
self.nth(self.num.checked_sub(1)?)
}
}
#[unstable(feature = "array_windows", issue = "75027")]
impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T; N]> {
if self.num == 0 {
return None;
}
// SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
let ret = unsafe { &*self.slice_head.add(self.num - 1).cast::<[T; N]>() };
self.num -= 1;
Some(ret)
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<&'a [T; N]> {
if self.num <= n {
self.num = 0;
return None;
}
// SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
let ret = unsafe { &*self.slice_head.add(self.num - (n + 1)).cast::<[T; N]>() };
self.num -= n + 1;
Some(ret)
}
}
#[unstable(feature = "array_windows", issue = "75027")]
impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
fn is_empty(&self) -> bool {
self.num == 0
}
}
/// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
/// time), starting at the beginning of the slice.
///

View File

@ -56,6 +56,9 @@ pub use iter::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
#[unstable(feature = "array_chunks", issue = "74985")]
pub use iter::{ArrayChunks, ArrayChunksMut};
#[unstable(feature = "array_windows", issue = "75027")]
pub use iter::ArrayWindows;
#[unstable(feature = "split_inclusive", issue = "72360")]
pub use iter::{SplitInclusive, SplitInclusiveMut};
@ -1026,6 +1029,40 @@ impl<T> [T] {
}
}
/// Returns an iterator over overlapping windows of `N` elements of a slice,
/// starting at the beginning of the slice.
///
/// This is the const generic equivalent of [`windows`].
///
/// If `N` is smaller than the size of the array, it will return no windows.
///
/// # Panics
///
/// Panics if `N` is 0. This check will most probably get changed to a compile time
/// error before this method gets stabilized.
///
/// # Examples
///
/// ```
/// #![feature(array_windows)]
/// let slice = [0, 1, 2, 3];
/// let mut iter = slice.array_windows();
/// assert_eq!(iter.next().unwrap(), &[0, 1]);
/// assert_eq!(iter.next().unwrap(), &[1, 2]);
/// assert_eq!(iter.next().unwrap(), &[2, 3]);
/// assert!(iter.next().is_none());
/// ```
///
/// [`windows`]: #method.windows
#[unstable(feature = "array_windows", issue = "75027")]
#[inline]
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
assert_ne!(N, 0);
let num_windows = self.len().saturating_sub(N - 1);
ArrayWindows { slice_head: self.as_ptr(), num: num_windows, marker: marker::PhantomData }
}
/// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
/// of the slice.
///

View File

@ -2,6 +2,7 @@
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_map)]
#![feature(array_windows)]
#![feature(bool_to_option)]
#![feature(bound_cloned)]
#![feature(box_syntax)]

View File

@ -657,6 +657,55 @@ fn test_array_chunks_mut_zip() {
assert_eq!(v1, [13, 14, 19, 20, 4]);
}
#[test]
fn test_array_windows_infer() {
let v: &[i32] = &[0, 1, 0, 1];
assert_eq!(v.array_windows::<2>().count(), 3);
let c = v.array_windows();
for &[a, b] in c {
assert_eq!(a + b, 1);
}
let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
let total = v2.array_windows().map(|&[a, b, c]| a + b + c).sum::<i32>();
assert_eq!(total, 3 + 6 + 9 + 12 + 15);
}
#[test]
fn test_array_windows_count() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let c = v.array_windows::<3>();
assert_eq!(c.count(), 4);
let v2: &[i32] = &[0, 1, 2, 3, 4];
let c2 = v2.array_windows::<6>();
assert_eq!(c2.count(), 0);
let v3: &[i32] = &[];
let c3 = v3.array_windows::<2>();
assert_eq!(c3.count(), 0);
}
#[test]
fn test_array_windows_nth() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let snd = v.array_windows::<4>().nth(1);
assert_eq!(snd, Some(&[1, 2, 3, 4]));
let mut arr_windows = v.array_windows::<2>();
assert_ne!(arr_windows.nth(0), arr_windows.nth(0));
let last = v.array_windows::<3>().last();
assert_eq!(last, Some(&[3, 4, 5]));
}
#[test]
fn test_array_windows_nth_back() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let snd = v.array_windows::<4>().nth_back(1);
assert_eq!(snd, Some(&[1, 2, 3, 4]));
let mut arr_windows = v.array_windows::<2>();
assert_ne!(arr_windows.nth_back(0), arr_windows.nth_back(0));
}
#[test]
fn test_rchunks_count() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];

View File

@ -9,7 +9,7 @@ pub use core::future::Future;
pub use core::future::{from_generator, get_context, ResumeTy};
#[doc(inline)]
#[stable(feature = "future_readiness_fns", since = "1.47.0")]
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub use core::future::{pending, ready, Pending, Ready};
#[doc(inline)]

View File

@ -118,7 +118,8 @@ impl Command {
FDIO_SPAWN_CLONE_JOB
| FDIO_SPAWN_CLONE_LDSVC
| FDIO_SPAWN_CLONE_NAMESPACE
| FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null
| FDIO_SPAWN_CLONE_ENVIRON // this is ignored when envp is non-null
| FDIO_SPAWN_CLONE_UTC_CLOCK,
self.get_program().as_ptr(),
self.get_argv().as_ptr(),
envp,

View File

@ -138,6 +138,7 @@ pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020;
pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;
// fdio_spawn_etc actions

View File

@ -1209,7 +1209,7 @@ impl<'a> Builder<'a> {
cargo.env(format!("CC_{}", target.triple), &cc);
let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
cargo.env(format!("CFLAGS_{}", target.triple), cflags.clone());
cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
if let Some(ar) = self.ar(target) {
let ranlib = format!("{} s", ar.display());
@ -1394,7 +1394,7 @@ impl<'a> Builder<'a> {
(out, dur - deps)
};
if self.config.print_step_timings {
if self.config.print_step_timings && !self.config.dry_run {
println!("[TIMING] {:?} -- {}.{:03}", step, dur.as_secs(), dur.subsec_millis());
}

View File

@ -500,6 +500,7 @@ impl Config {
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
let mut config = Config::default_opts();
config.exclude = flags.exclude;
config.rustc_error_format = flags.rustc_error_format;
@ -551,14 +552,14 @@ impl Config {
let has_targets = build.target.is_some() || flags.target.is_some();
config.skip_only_host_steps = !has_hosts && has_targets;
config.hosts = if let Some(arg_host) = flags.host.clone() {
config.hosts = if let Some(arg_host) = flags.host {
arg_host
} else if let Some(file_host) = build.host {
file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
} else {
vec![config.build]
};
config.targets = if let Some(arg_target) = flags.target.clone() {
config.targets = if let Some(arg_target) = flags.target {
arg_target
} else if let Some(file_target) = build.target {
file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
@ -628,14 +629,14 @@ impl Config {
config.verbose = cmp::max(config.verbose, flags.verbose);
if let Some(ref install) = toml.install {
config.prefix = install.prefix.clone().map(PathBuf::from);
config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
config.datadir = install.datadir.clone().map(PathBuf::from);
config.docdir = install.docdir.clone().map(PathBuf::from);
set(&mut config.bindir, install.bindir.clone().map(PathBuf::from));
config.libdir = install.libdir.clone().map(PathBuf::from);
config.mandir = install.mandir.clone().map(PathBuf::from);
if let Some(install) = toml.install {
config.prefix = install.prefix.map(PathBuf::from);
config.sysconfdir = install.sysconfdir.map(PathBuf::from);
config.datadir = install.datadir.map(PathBuf::from);
config.docdir = install.docdir.map(PathBuf::from);
set(&mut config.bindir, install.bindir.map(PathBuf::from));
config.libdir = install.libdir.map(PathBuf::from);
config.mandir = install.mandir.map(PathBuf::from);
}
// We want the llvm-skip-rebuild flag to take precedence over the
@ -658,7 +659,7 @@ impl Config {
let mut optimize = None;
let mut ignore_git = None;
if let Some(ref llvm) = toml.llvm {
if let Some(llvm) = toml.llvm {
match llvm.ccache {
Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
Some(StringOrBool::Bool(true)) => {
@ -726,7 +727,7 @@ impl Config {
}
}
if let Some(ref rust) = toml.rust {
if let Some(rust) = toml.rust {
debug = rust.debug;
debug_assertions = rust.debug_assertions;
debug_assertions_std = rust.debug_assertions_std;
@ -746,7 +747,7 @@ impl Config {
set(&mut config.test_compare_mode, rust.test_compare_mode);
set(&mut config.llvm_libunwind, rust.llvm_libunwind);
set(&mut config.backtrace, rust.backtrace);
set(&mut config.channel, rust.channel.clone());
set(&mut config.channel, rust.channel);
set(&mut config.rust_dist_src, rust.dist_src);
set(&mut config.verbose_tests, rust.verbose_tests);
// in the case "false" is set explicitly, do not overwrite the command line args
@ -757,9 +758,9 @@ impl Config {
set(&mut config.lld_enabled, rust.lld);
set(&mut config.llvm_tools_enabled, rust.llvm_tools);
config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
config.rustc_default_linker = rust.default_linker.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
config.rustc_default_linker = rust.default_linker;
config.musl_root = rust.musl_root.map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
@ -776,9 +777,9 @@ impl Config {
config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
}
if let Some(ref t) = toml.target {
if let Some(t) = toml.target {
for (triple, cfg) in t {
let mut target = Target::from_triple(triple);
let mut target = Target::from_triple(&triple);
if let Some(ref s) = cfg.llvm_config {
target.llvm_config = Some(config.src.join(s));
@ -792,18 +793,18 @@ impl Config {
if let Some(s) = cfg.no_std {
target.no_std = s;
}
target.cc = cfg.cc.clone().map(PathBuf::from);
target.cxx = cfg.cxx.clone().map(PathBuf::from);
target.ar = cfg.ar.clone().map(PathBuf::from);
target.ranlib = cfg.ranlib.clone().map(PathBuf::from);
target.linker = cfg.linker.clone().map(PathBuf::from);
target.cc = cfg.cc.map(PathBuf::from);
target.cxx = cfg.cxx.map(PathBuf::from);
target.ar = cfg.ar.map(PathBuf::from);
target.ranlib = cfg.ranlib.map(PathBuf::from);
target.linker = cfg.linker.map(PathBuf::from);
target.crt_static = cfg.crt_static;
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
target.musl_libdir = cfg.musl_libdir.clone().map(PathBuf::from);
target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from);
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
target.musl_root = cfg.musl_root.map(PathBuf::from);
target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
target.wasi_root = cfg.wasi_root.map(PathBuf::from);
target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
config.target_config.insert(TargetSelection::from_user(triple), target);
config.target_config.insert(TargetSelection::from_user(&triple), target);
}
}
@ -821,10 +822,10 @@ impl Config {
build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
}
if let Some(ref t) = toml.dist {
config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from);
config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from);
config.dist_upload_addr = t.upload_addr.clone();
if let Some(t) = toml.dist {
config.dist_sign_folder = t.sign_folder.map(PathBuf::from);
config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from);
config.dist_upload_addr = t.upload_addr;
set(&mut config.rust_dist_src, t.src_tarball);
set(&mut config.missing_tools, t.missing_tools);
}

View File

@ -105,15 +105,13 @@ pub fn format(build: &Build, check: bool) {
eprintln!("./x.py fmt is not supported on this channel");
std::process::exit(1);
});
let src = build.src.clone();
let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
let src = &build.src;
let walker = WalkBuilder::new(src).types(matcher).overrides(ignore_fmt).build_parallel();
walker.run(|| {
let src = src.clone();
let rustfmt_path = rustfmt_path.clone();
Box::new(move |entry| {
let entry = t!(entry);
if entry.file_type().map_or(false, |t| t.is_file()) {
rustfmt(&src, &rustfmt_path, &entry.path(), check);
rustfmt(src, &rustfmt_path, &entry.path(), check);
}
ignore::WalkState::Continue
})

View File

@ -30,8 +30,8 @@ impl Finder {
Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
}
pub fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
let cmd: OsString = cmd.as_ref().into();
pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
let cmd: OsString = cmd.into();
let path = &self.path;
self.cache
.entry(cmd.clone())

@ -1 +1 @@
Subproject commit e5ed97128302d5fa45dbac0e64426bc7649a558c
Subproject commit cb28dee95e5e50b793e6ba9291c5d1568d3ad72e

@ -1 +1 @@
Subproject commit 25854752549d44d76fbd7650e17cb4f167a0b8fb
Subproject commit 6e57e64501f61873ab80cb78a07180a22751a5d6

@ -1 +1 @@
Subproject commit 25391dba46262f882fa846beefaff54a966a8fa5
Subproject commit 56a13c082ee90736c08d6abdcd90462517b703d3

View File

@ -16,6 +16,16 @@
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate tracing;
// N.B. these need `extern crate` even in 2018 edition
// because they're loaded implicitly from the sysroot.
// The reason they're loaded from the sysroot is because
// the rustdoc artifacts aren't stored in rustc's cargo target directory.
// So if `rustc` was specified in Cargo.toml, this would spuriously rebuild crates.
//
// Dependencies listed in Cargo.toml do not need `extern crate`.
extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
@ -42,8 +52,6 @@ extern crate rustc_target;
extern crate rustc_trait_selection;
extern crate rustc_typeck;
extern crate test as testing;
#[macro_use]
extern crate tracing;
use std::default::Default;
use std::env;

View File

@ -8,7 +8,7 @@ use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
use rustc_session::lint;
pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
@ -48,16 +48,12 @@ pub(crate) struct Tests {
pub(crate) found_tests: usize,
}
impl Tests {
pub(crate) fn new() -> Tests {
Tests { found_tests: 0 }
}
}
impl crate::doctest::Tester for Tests {
fn add_test(&mut self, _: String, _: LangString, _: usize) {
fn add_test(&mut self, _: String, config: LangString, _: usize) {
if config.rust && config.ignore == Ignore::None {
self.found_tests += 1;
}
}
}
pub fn should_have_doc_example(item_kind: &clean::ItemEnum) -> bool {
@ -85,7 +81,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
}
};
let mut tests = Tests::new();
let mut tests = Tests { found_tests: 0 };
find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);

View File

@ -1,7 +1,7 @@
+-------------------------------------+------------+------------+------------+------------+
| File | Documented | Percentage | Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 2 | 50.0% |
| ...tdoc-ui/coverage/doc-examples.rs | 4 | 100.0% | 1 | 25.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total | 4 | 100.0% | 2 | 50.0% |
| Total | 4 | 100.0% | 1 | 25.0% |
+-------------------------------------+------------+------------+------------+------------+

View File

@ -0,0 +1,12 @@
// check-pass
#![deny(private_doc_tests)]
mod foo {
/// private doc test
///
/// ```ignore (used for testing ignored doc tests)
/// assert!(false);
/// ```
fn bar() {}
}

View File

@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
| ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
|
= help: it is currently only allowed to use either `T` or `{ T }` as generic constants
= note: type parameters are currently not permitted in anonymous constants
error: generic parameters must not be used inside of non trivial constant values
--> $DIR/issue-64494.rs:19:38
@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
| ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
|
= help: it is currently only allowed to use either `T` or `{ T }` as generic constants
= note: type parameters are currently not permitted in anonymous constants
error[E0119]: conflicting implementations of trait `MyTrait`:
--> $DIR/issue-64494.rs:19:1

View File

@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
LL | [0u8; mem::size_of::<Self::Associated>()];
| ^^^^^^^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
|
= help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
= note: type parameters are currently not permitted in anonymous constants
error: aborting due to previous error

View File

@ -0,0 +1,18 @@
error: constant expression depends on a generic parameter
--> $DIR/issue-76701-ty-param-in-const.rs:6:21
|
LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/issue-76701-ty-param-in-const.rs:12:37
|
LL | fn const_param<const N: usize>() -> [u8; N + 1] {
| ^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to 2 previous errors

View File

@ -0,0 +1,18 @@
error: generic parameters must not be used inside of non trivial constant values
--> $DIR/issue-76701-ty-param-in-const.rs:6:46
|
LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
| ^ non-trivial anonymous constants must not depend on the parameter `T`
|
= note: type parameters are currently not permitted in anonymous constants
error: generic parameters must not be used inside of non trivial constant values
--> $DIR/issue-76701-ty-param-in-const.rs:12:42
|
LL | fn const_param<const N: usize>() -> [u8; N + 1] {
| ^ non-trivial anonymous constants must not depend on the parameter `N`
|
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
error: aborting due to 2 previous errors

View File

@ -0,0 +1,18 @@
// revisions: full min
#![cfg_attr(full, feature(const_generics))]
#![cfg_attr(full, allow(incomplete_features))]
#![cfg_attr(min, feature(min_const_generics))]
fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
//[full]~^ ERROR constant expression depends on a generic parameter
//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
todo!()
}
fn const_param<const N: usize>() -> [u8; N + 1] {
//[full]~^ ERROR constant expression depends on a generic parameter
//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
todo!()
}
fn main() {}

View File

@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
LL | fn t1() -> [u8; std::mem::size_of::<Self>()];
| ^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
|
= help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
= note: type parameters are currently not permitted in anonymous constants
error: generic `Self` types are currently not permitted in anonymous constants
--> $DIR/self-ty-in-const-1.rs:14:41

View File

@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
| ^ non-trivial anonymous constants must not depend on the parameter `T`
|
= help: it is currently only allowed to use either `T` or `{ T }` as generic constants
= note: type parameters are currently not permitted in anonymous constants
error: constant values inside of type parameter defaults must not depend on generic parameters
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21

View File

@ -5,21 +5,21 @@
#![cfg_attr(min, feature(min_const_generics))]
trait SliceExt<T: Clone> {
fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N>;
fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>;
}
impl <T: Clone> SliceExt<T> for [T] {
fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N> {
ArrayWindows{ idx: 0, slice: &self }
fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N> {
ArrayWindowsExample{ idx: 0, slice: &self }
}
}
struct ArrayWindows<'a, T, const N: usize> {
struct ArrayWindowsExample<'a, T, const N: usize> {
slice: &'a [T],
idx: usize,
}
impl <'a, T: Clone, const N: usize> Iterator for ArrayWindows<'a, T, N> {
impl <'a, T: Clone, const N: usize> Iterator for ArrayWindowsExample<'a, T, N> {
type Item = [T; N];
fn next(&mut self) -> Option<Self::Item> {
// Note: this is unsound for some `T` and not meant as an example
@ -45,7 +45,7 @@ const FOUR: usize = 4;
fn main() {
let v: Vec<usize> = vec![0; 100];
for array in v.as_slice().array_windows::<FOUR>() {
for array in v.as_slice().array_windows_example::<FOUR>() {
assert_eq!(array, [0, 0, 0, 0])
}
}