Auto merge of #111960 - compiler-errors:rollup-onka2dl, r=compiler-errors

Rollup of 7 pull requests

Successful merges:

 - #107522 (Add Median of Medians fallback to introselect)
 - #111152 (update `pulldown-cmark` to `0.9.3`)
 - #111757 (Consider lint check attributes on match arms)
 - #111831 (Always capture slice when pattern requires checking the length)
 - #111929 (Don't print newlines in APITs)
 - #111945 (Migrate GUI colors test to original CSS color format)
 - #111950 (Remove ExpnKind::Inlined.)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-05-25 22:04:33 +00:00
commit 0004b3b984
37 changed files with 856 additions and 411 deletions

View File

@ -2779,9 +2779,9 @@ dependencies = [
[[package]]
name = "pulldown-cmark"
version = "0.9.2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
dependencies = [
"bitflags",
"memchr",

View File

@ -1425,7 +1425,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
DefPathData::ImplTrait,
span,
);
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
// HACK: pprust breaks strings with newlines when the type
// gets too long. We don't want these to show up in compiler
// output or built artifacts, so replace them here...
// Perhaps we should instead format APITs more robustly.
let ident = Ident::from_str_and_span(
&pprust::ty_to_string(t).replace('\n', " "),
span,
);
let (param, bounds, path) = self.lower_universal_param_and_bounds(
*def_node_id,
span,

View File

@ -413,11 +413,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
// Note: must be kept in sync with get_caller_location from cg_ssa
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, mut span: Span| {
// Remove `Inlined` marks as they pollute `expansion_cause`.
while span.is_inlined() {
span.remove_mark();
}
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = fx.tcx.const_caller_location((

View File

@ -1450,11 +1450,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> OperandRef<'tcx, Bx::Value> {
let tcx = bx.tcx();
let mut span_to_caller_location = |mut span: Span| {
// Remove `Inlined` marks as they pollute `expansion_cause`.
while span.is_inlined() {
span.remove_mark();
}
let mut span_to_caller_location = |span: Span| {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
let const_loc = tcx.const_caller_location((

View File

@ -949,7 +949,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// This deliberately does *not* honor `requires_caller_location` since it is used for much
// more than just panics.
for frame in stack.iter().rev() {
let span = frame.current_span();
let span = match frame.loc {
Left(loc) => {
// If the stacktrace passes through MIR-inlined source scopes, add them.
let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
let mut scope_data = &frame.body.source_scopes[scope];
while let Some((instance, call_span)) = scope_data.inlined {
frames.push(FrameInfo { span, instance });
span = call_span;
scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
}
span
}
Right(span) => span,
};
frames.push(FrameInfo { span, instance: frame.instance });
}
trace!("generate stacktrace: {:#?}", frames);

View File

@ -111,11 +111,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
location
}
pub(crate) fn location_triple_for_span(&self, mut span: Span) -> (Symbol, u32, u32) {
// Remove `Inlined` marks as they pollute `expansion_cause`.
while span.is_inlined() {
span.remove_mark();
}
pub(crate) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
(

View File

@ -332,7 +332,7 @@ pub trait Emitter: Translate {
// Skip past non-macro entries, just in case there
// are some which do actually involve macros.
ExpnKind::Inlined | ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None,
ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)),
}
@ -403,7 +403,7 @@ pub trait Emitter: Translate {
continue;
}
if always_backtrace && !matches!(trace.kind, ExpnKind::Inlined) {
if always_backtrace {
new_labels.push((
trace.def_site,
format!(
@ -442,7 +442,6 @@ pub trait Emitter: Translate {
"this derive macro expansion".into()
}
ExpnKind::Macro(MacroKind::Bang, _) => "this macro invocation".into(),
ExpnKind::Inlined => "this inlined function call".into(),
ExpnKind::Root => "the crate root".into(),
ExpnKind::AstPass(kind) => kind.descr().into(),
ExpnKind::Desugaring(kind) => {

View File

@ -438,12 +438,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
// to borrow discr.
needs_to_be_read = true;
}
PatKind::Or(_)
| PatKind::Box(_)
| PatKind::Slice(..)
| PatKind::Ref(..)
| PatKind::Wild => {
// If the PatKind is Or, Box, Slice or Ref, the decision is made later
PatKind::Slice(lhs, wild, rhs) => {
// We don't need to test the length if the pattern is `[..]`
if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
// Arrays have a statically known size, so
// there is no need to read their length
|| discr_place.place.base_ty.is_array()
{
} else {
needs_to_be_read = true;
}
}
PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => {
// If the PatKind is Or, Box, or Ref, the decision is made later
// as these patterns contains subpatterns
// If the PatKind is Wild, the decision is made based on the other patterns being
// examined

View File

@ -240,8 +240,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
}
fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
lint_callback!(self, check_arm, a);
hir_visit::walk_arm(self, a);
self.with_lint_attrs(a.hir_id, |cx| {
lint_callback!(cx, check_arm, a);
hir_visit::walk_arm(cx, a);
})
}
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {

View File

@ -468,8 +468,7 @@ pub fn struct_lint_level(
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let expn_data = span.ctxt().outer_expn_data();
match expn_data.kind {
ExpnKind::Inlined
| ExpnKind::Root
ExpnKind::Root
| ExpnKind::Desugaring(
DesugaringKind::ForLoop | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy,
) => false,

View File

@ -2488,9 +2488,7 @@ impl<'tcx> TyCtxt<'tcx> {
&& if self.features().collapse_debuginfo {
span.in_macro_expansion_with_collapse_debuginfo()
} else {
// Inlined spans should not be collapsed as that leads to all of the
// inlined code being attributed to the inline callsite.
span.from_expansion() && !span.is_inlined()
span.from_expansion()
}
}

View File

@ -90,35 +90,34 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
#[instrument(level = "trace", skip(self))]
fn visit_arm(&mut self, arm: &Arm<'tcx>) {
match arm.guard {
Some(Guard::If(expr)) => {
self.with_let_source(LetSource::IfLetGuard, |this| {
this.visit_expr(&this.thir[expr])
});
self.with_lint_level(arm.lint_level, |this| {
match arm.guard {
Some(Guard::If(expr)) => {
this.with_let_source(LetSource::IfLetGuard, |this| {
this.visit_expr(&this.thir[expr])
});
}
Some(Guard::IfLet(ref pat, expr)) => {
this.with_let_source(LetSource::IfLetGuard, |this| {
this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
this.visit_pat(pat);
this.visit_expr(&this.thir[expr]);
});
}
None => {}
}
Some(Guard::IfLet(ref pat, expr)) => {
self.with_let_source(LetSource::IfLetGuard, |this| {
this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
this.visit_pat(pat);
this.visit_expr(&this.thir[expr]);
});
}
None => {}
}
self.visit_pat(&arm.pattern);
self.visit_expr(&self.thir[arm.body]);
this.visit_pat(&arm.pattern);
this.visit_expr(&self.thir[arm.body]);
});
}
#[instrument(level = "trace", skip(self))]
fn visit_expr(&mut self, ex: &Expr<'tcx>) {
match ex.kind {
ExprKind::Scope { value, lint_level, .. } => {
let old_lint_level = self.lint_level;
if let LintLevel::Explicit(hir_id) = lint_level {
self.lint_level = hir_id;
}
self.visit_expr(&self.thir[value]);
self.lint_level = old_lint_level;
self.with_lint_level(lint_level, |this| {
this.visit_expr(&this.thir[value]);
});
return;
}
ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
@ -190,6 +189,17 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
self.let_source = old_let_source;
}
fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) {
if let LintLevel::Explicit(hir_id) = new_lint_level {
let old_lint_level = self.lint_level;
self.lint_level = hir_id;
f(self);
self.lint_level = old_lint_level;
} else {
f(self);
}
}
fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
check_for_bindings_named_same_as_variants(self, pat, rf);
@ -236,7 +246,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
for &arm in arms {
// Check the arm for some things unrelated to exhaustiveness.
let arm = &self.thir.arms[arm];
self.check_patterns(&arm.pattern, Refutable);
self.with_lint_level(arm.lint_level, |this| {
this.check_patterns(&arm.pattern, Refutable);
});
}
let tarms: Vec<_> = arms

View File

@ -10,7 +10,6 @@ use rustc_middle::mir::*;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_target::spec::abi::Abi;
@ -551,16 +550,6 @@ impl<'tcx> Inliner<'tcx> {
// Copy the arguments if needed.
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
let mut expn_data = ExpnData::default(
ExpnKind::Inlined,
callsite.source_info.span,
self.tcx.sess.edition(),
None,
None,
);
expn_data.def_site = callee_body.span;
let expn_data =
self.tcx.with_stable_hashing_context(|hcx| LocalExpnId::fresh(expn_data, hcx));
let mut integrator = Integrator {
args: &args,
new_locals: Local::new(caller_body.local_decls.len())..,
@ -572,7 +561,6 @@ impl<'tcx> Inliner<'tcx> {
cleanup_block: unwind,
in_cleanup_block: false,
tcx: self.tcx,
expn_data,
always_live_locals: BitSet::new_filled(callee_body.local_decls.len()),
};
@ -956,7 +944,6 @@ struct Integrator<'a, 'tcx> {
cleanup_block: UnwindAction,
in_cleanup_block: bool,
tcx: TyCtxt<'tcx>,
expn_data: LocalExpnId,
always_live_locals: BitSet<Local>,
}
@ -1042,11 +1029,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
*scope = self.map_scope(*scope);
}
fn visit_span(&mut self, span: &mut Span) {
// Make sure that all spans track the fact that they were inlined.
*span = span.fresh_expansion(self.expn_data);
}
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data);

View File

@ -7,7 +7,7 @@ edition = "2021"
[dependencies]
bitflags = "1.2.1"
pulldown-cmark = { version = "0.9.2", default-features = false }
pulldown-cmark = { version = "0.9.3", default-features = false }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }

View File

@ -320,7 +320,6 @@ impl ExpnId {
// Stop going up the backtrace once include! is encountered
if expn_data.is_root()
|| expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include)
|| expn_data.kind == ExpnKind::Inlined
{
break;
}
@ -1058,8 +1057,6 @@ pub enum ExpnKind {
AstPass(AstPass),
/// Desugaring done by the compiler during HIR lowering.
Desugaring(DesugaringKind),
/// MIR inlining
Inlined,
}
impl ExpnKind {
@ -1073,7 +1070,6 @@ impl ExpnKind {
},
ExpnKind::AstPass(kind) => kind.descr().to_string(),
ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()),
ExpnKind::Inlined => "inlined source".to_string(),
}
}
}

View File

@ -594,12 +594,6 @@ impl Span {
matches!(outer_expn.kind, ExpnKind::Macro(..)) && outer_expn.collapse_debuginfo
}
/// Returns `true` if this span comes from MIR inlining.
pub fn is_inlined(self) -> bool {
let outer_expn = self.ctxt().outer_expn_data();
matches!(outer_expn.kind, ExpnKind::Inlined)
}
/// Returns `true` if `span` originates in a derive-macro's expansion.
pub fn in_derive_expansion(self) -> bool {
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))

View File

@ -42,6 +42,7 @@ mod index;
mod iter;
mod raw;
mod rotate;
mod select;
mod specialize;
#[unstable(feature = "str_internals", issue = "none")]
@ -3034,7 +3035,7 @@ impl<T> [T] {
where
T: Ord,
{
sort::partition_at_index(self, index, T::lt)
select::partition_at_index(self, index, T::lt)
}
/// Reorder the slice with a comparator function such that the element at `index` is at its
@ -3089,7 +3090,7 @@ impl<T> [T] {
where
F: FnMut(&T, &T) -> Ordering,
{
sort::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
}
/// Reorder the slice with a key extraction function such that the element at `index` is at its
@ -3145,7 +3146,7 @@ impl<T> [T] {
F: FnMut(&T) -> K,
K: Ord,
{
sort::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
select::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
}
/// Moves all consecutive repeated elements to the end of the slice according to the

View File

@ -0,0 +1,302 @@
//! Slice selection
//!
//! This module contains the implementation for `slice::select_nth_unstable`.
//! It uses an introselect algorithm based on Orson Peters' pattern-defeating quicksort,
//! published at: <https://github.com/orlp/pdqsort>
//!
//! The fallback algorithm used for introselect is Median of Medians using Tukey's Ninther
//! for pivot selection. Using this as a fallback ensures O(n) worst case running time with
//! better performance than one would get using heapsort as fallback.
use crate::cmp;
use crate::mem::{self, SizedTypeProperties};
use crate::slice::sort::{
break_patterns, choose_pivot, insertion_sort_shift_left, partition, partition_equal,
};
// For slices of up to this length it's probably faster to simply sort them.
// Defined at the module scope because it's used in multiple functions.
const MAX_INSERTION: usize = 10;
fn partition_at_index_loop<'a, T, F>(
mut v: &'a mut [T],
mut index: usize,
is_less: &mut F,
mut pred: Option<&'a T>,
) where
F: FnMut(&T, &T) -> bool,
{
// Limit the amount of iterations and fall back to fast deterministic selection
// to ensure O(n) worst case running time. This limit needs to be constant, because
// using `ilog2(len)` like in `sort` would result in O(n log n) time complexity.
// The exact value of the limit is chosen somewhat arbitrarily, but for most inputs bad pivot
// selections should be relatively rare, so the limit usually shouldn't be reached
// anyways.
let mut limit = 16;
// True if the last partitioning was reasonably balanced.
let mut was_balanced = true;
loop {
if v.len() <= MAX_INSERTION {
if v.len() > 1 {
insertion_sort_shift_left(v, 1, is_less);
}
return;
}
if limit == 0 {
median_of_medians(v, is_less, index);
return;
}
// If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
// some elements around. Hopefully we'll choose a better pivot this time.
if !was_balanced {
break_patterns(v);
limit -= 1;
}
// Choose a pivot
let (pivot, _) = choose_pivot(v, is_less);
// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
// slice. Partition the slice into elements equal to and elements greater than the pivot.
// This case is usually hit when the slice contains many duplicate elements.
if let Some(p) = pred {
if !is_less(p, &v[pivot]) {
let mid = partition_equal(v, pivot, is_less);
// If we've passed our index, then we're good.
if mid > index {
return;
}
// Otherwise, continue sorting elements greater than the pivot.
v = &mut v[mid..];
index = index - mid;
pred = None;
continue;
}
}
let (mid, _) = partition(v, pivot, is_less);
was_balanced = cmp::min(mid, v.len() - mid) >= v.len() / 8;
// Split the slice into `left`, `pivot`, and `right`.
let (left, right) = v.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];
if mid < index {
v = right;
index = index - mid - 1;
pred = Some(pivot);
} else if mid > index {
v = left;
} else {
// If mid == index, then we're done, since partition() guaranteed that all elements
// after mid are greater than or equal to mid.
return;
}
}
}
/// Helper function that returns the index of the minimum element in the slice using the given
/// comparator function
fn min_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
slice
.iter()
.enumerate()
.reduce(|acc, t| if is_less(t.1, acc.1) { t } else { acc })
.map(|(i, _)| i)
}
/// Helper function that returns the index of the maximum element in the slice using the given
/// comparator function
fn max_index<T, F: FnMut(&T, &T) -> bool>(slice: &[T], is_less: &mut F) -> Option<usize> {
slice
.iter()
.enumerate()
.reduce(|acc, t| if is_less(acc.1, t.1) { t } else { acc })
.map(|(i, _)| i)
}
/// Reorder the slice such that the element at `index` is at its final sorted position.
pub fn partition_at_index<T, F>(
v: &mut [T],
index: usize,
mut is_less: F,
) -> (&mut [T], &mut T, &mut [T])
where
F: FnMut(&T, &T) -> bool,
{
if index >= v.len() {
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
}
if T::IS_ZST {
// Sorting has no meaningful behavior on zero-sized types. Do nothing.
} else if index == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let max_idx = max_index(v, &mut is_less).unwrap();
v.swap(max_idx, index);
} else if index == 0 {
// Find min element and place it in the first position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let min_idx = min_index(v, &mut is_less).unwrap();
v.swap(min_idx, index);
} else {
partition_at_index_loop(v, index, &mut is_less, None);
}
let (left, right) = v.split_at_mut(index);
let (pivot, right) = right.split_at_mut(1);
let pivot = &mut pivot[0];
(left, pivot, right)
}
/// Selection algorithm to select the k-th element from the slice in guaranteed O(n) time.
/// This is essentially a quickselect that uses Tukey's Ninther for pivot selection
fn median_of_medians<T, F: FnMut(&T, &T) -> bool>(mut v: &mut [T], is_less: &mut F, mut k: usize) {
// Since this function isn't public, it should never be called with an out-of-bounds index.
debug_assert!(k < v.len());
// If T is as ZST, `partition_at_index` will already return early.
debug_assert!(!T::IS_ZST);
// We now know that `k < v.len() <= isize::MAX`
loop {
if v.len() <= MAX_INSERTION {
if v.len() > 1 {
insertion_sort_shift_left(v, 1, is_less);
}
return;
}
// `median_of_{minima,maxima}` can't handle the extreme cases of the first/last element,
// so we catch them here and just do a linear search.
if k == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let max_idx = max_index(v, is_less).unwrap();
v.swap(max_idx, k);
return;
} else if k == 0 {
// Find min element and place it in the first position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let min_idx = min_index(v, is_less).unwrap();
v.swap(min_idx, k);
return;
}
let p = median_of_ninthers(v, is_less);
if p == k {
return;
} else if p > k {
v = &mut v[..p];
} else {
// Since `p < k < v.len()`, `p + 1` doesn't overflow and is
// a valid index into the slice.
v = &mut v[p + 1..];
k -= p + 1;
}
}
}
// Optimized for when `k` lies somewhere in the middle of the slice. Selects a pivot
// as close as possible to the median of the slice. For more details on how the algorithm
// operates, refer to the paper <https://drops.dagstuhl.de/opus/volltexte/2017/7612/pdf/LIPIcs-SEA-2017-24.pdf>.
fn median_of_ninthers<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut F) -> usize {
// use `saturating_mul` so the multiplication doesn't overflow on 16-bit platforms.
let frac = if v.len() <= 1024 {
v.len() / 12
} else if v.len() <= 128_usize.saturating_mul(1024) {
v.len() / 64
} else {
v.len() / 1024
};
let pivot = frac / 2;
let lo = v.len() / 2 - pivot;
let hi = frac + lo;
let gap = (v.len() - 9 * frac) / 4;
let mut a = lo - 4 * frac - gap;
let mut b = hi + gap;
for i in lo..hi {
ninther(v, is_less, a, i - frac, b, a + 1, i, b + 1, a + 2, i + frac, b + 2);
a += 3;
b += 3;
}
median_of_medians(&mut v[lo..lo + frac], is_less, pivot);
partition(v, lo + pivot, is_less).0
}
/// Moves around the 9 elements at the indices a..i, such that
/// `v[d]` contains the median of the 9 elements and the other
/// elements are partitioned around it.
fn ninther<T, F: FnMut(&T, &T) -> bool>(
v: &mut [T],
is_less: &mut F,
a: usize,
mut b: usize,
c: usize,
mut d: usize,
e: usize,
mut f: usize,
g: usize,
mut h: usize,
i: usize,
) {
b = median_idx(v, is_less, a, b, c);
h = median_idx(v, is_less, g, h, i);
if is_less(&v[h], &v[b]) {
mem::swap(&mut b, &mut h);
}
if is_less(&v[f], &v[d]) {
mem::swap(&mut d, &mut f);
}
if is_less(&v[e], &v[d]) {
// do nothing
} else if is_less(&v[f], &v[e]) {
d = f;
} else {
if is_less(&v[e], &v[b]) {
v.swap(e, b);
} else if is_less(&v[h], &v[e]) {
v.swap(e, h);
}
return;
}
if is_less(&v[d], &v[b]) {
d = b;
} else if is_less(&v[h], &v[d]) {
d = h;
}
v.swap(d, e);
}
/// returns the index pointing to the median of the 3
/// elements `v[a]`, `v[b]` and `v[c]`
fn median_idx<T, F: FnMut(&T, &T) -> bool>(
v: &[T],
is_less: &mut F,
mut a: usize,
b: usize,
mut c: usize,
) -> usize {
if is_less(&v[c], &v[a]) {
mem::swap(&mut a, &mut c);
}
if is_less(&v[c], &v[b]) {
return c;
}
if is_less(&v[b], &v[a]) {
return a;
}
b
}

View File

@ -145,7 +145,7 @@ where
/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no
/// performance impact. Even improving performance in some cases.
#[inline(never)]
fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
pub(super) fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
@ -557,7 +557,7 @@ where
///
/// 1. Number of elements smaller than `v[pivot]`.
/// 2. True if `v` was already partitioned.
fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
pub(super) fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
@ -612,7 +612,7 @@ where
///
/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
/// elements smaller than the pivot.
fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
pub(super) fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
where
F: FnMut(&T, &T) -> bool,
{
@ -670,7 +670,7 @@ where
/// Scatters some elements around in an attempt to break patterns that might cause imbalanced
/// partitions in quicksort.
#[cold]
fn break_patterns<T>(v: &mut [T]) {
pub(super) fn break_patterns<T>(v: &mut [T]) {
let len = v.len();
if len >= 8 {
let mut seed = len;
@ -719,7 +719,7 @@ fn break_patterns<T>(v: &mut [T]) {
/// Chooses a pivot in `v` and returns the index and `true` if the slice is likely already sorted.
///
/// Elements in `v` might be reordered in the process.
fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
pub(super) fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
@ -897,138 +897,6 @@ where
recurse(v, &mut is_less, None, limit);
}
fn partition_at_index_loop<'a, T, F>(
mut v: &'a mut [T],
mut index: usize,
is_less: &mut F,
mut pred: Option<&'a T>,
) where
F: FnMut(&T, &T) -> bool,
{
// Limit the amount of iterations and fall back to heapsort, similarly to `slice::sort_unstable`.
// This lowers the worst case running time from O(n^2) to O(n log n).
// FIXME: Investigate whether it would be better to use something like Median of Medians
// or Fast Deterministic Selection to guarantee O(n) worst case.
let mut limit = usize::BITS - v.len().leading_zeros();
// True if the last partitioning was reasonably balanced.
let mut was_balanced = true;
loop {
let len = v.len();
// For slices of up to this length it's probably faster to simply sort them.
const MAX_INSERTION: usize = 10;
if len <= MAX_INSERTION {
if len >= 2 {
insertion_sort_shift_left(v, 1, is_less);
}
return;
}
if limit == 0 {
heapsort(v, is_less);
return;
}
// If the last partitioning was imbalanced, try breaking patterns in the slice by shuffling
// some elements around. Hopefully we'll choose a better pivot this time.
if !was_balanced {
break_patterns(v);
limit -= 1;
}
// Choose a pivot
let (pivot, _) = choose_pivot(v, is_less);
// If the chosen pivot is equal to the predecessor, then it's the smallest element in the
// slice. Partition the slice into elements equal to and elements greater than the pivot.
// This case is usually hit when the slice contains many duplicate elements.
if let Some(p) = pred {
if !is_less(p, &v[pivot]) {
let mid = partition_equal(v, pivot, is_less);
// If we've passed our index, then we're good.
if mid > index {
return;
}
// Otherwise, continue sorting elements greater than the pivot.
v = &mut v[mid..];
index = index - mid;
pred = None;
continue;
}
}
let (mid, _) = partition(v, pivot, is_less);
was_balanced = cmp::min(mid, len - mid) >= len / 8;
// Split the slice into `left`, `pivot`, and `right`.
let (left, right) = v.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];
if mid < index {
v = right;
index = index - mid - 1;
pred = Some(pivot);
} else if mid > index {
v = left;
} else {
// If mid == index, then we're done, since partition() guaranteed that all elements
// after mid are greater than or equal to mid.
return;
}
}
}
/// Reorder the slice such that the element at `index` is at its final sorted position.
pub fn partition_at_index<T, F>(
v: &mut [T],
index: usize,
mut is_less: F,
) -> (&mut [T], &mut T, &mut [T])
where
F: FnMut(&T, &T) -> bool,
{
use cmp::Ordering::Greater;
use cmp::Ordering::Less;
if index >= v.len() {
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
}
if T::IS_ZST {
// Sorting has no meaningful behavior on zero-sized types. Do nothing.
} else if index == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let (max_index, _) = v
.iter()
.enumerate()
.max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
.unwrap();
v.swap(max_index, index);
} else if index == 0 {
// Find min element and place it in the first position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
let (min_index, _) = v
.iter()
.enumerate()
.min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
.unwrap();
v.swap(min_index, index);
} else {
partition_at_index_loop(v, index, &mut is_less, None);
}
let (left, right) = v.split_at_mut(index);
let (pivot, right) = right.split_at_mut(1);
let pivot = &mut pivot[0];
(left, pivot, right)
}
/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and
/// stores the result into `v[..]`.
///

View File

@ -165,15 +165,15 @@ extensions:
### Strikethrough
Text may be rendered with a horizontal line through the center by wrapping the
text with two tilde characters on each side:
text with one or two tilde characters on each side:
```text
An example of ~~strikethrough text~~.
An example of ~~strikethrough text~~. You can also use ~single tildes~.
```
This example will render as:
> An example of ~~strikethrough text~~.
> An example of ~~strikethrough text~~. You can also use ~single tildes~.
This follows the [GitHub Strikethrough extension][strikethrough].

View File

@ -12,13 +12,13 @@ impl Drop for Foo {
#[inline(always)]
fn has_cleanup() {
//~^ ERROR: panic in a function that cannot unwind
let _f = Foo;
panic!();
}
extern "C" fn panic_abort() {
has_cleanup();
//~^ ERROR: panic in a function that cannot unwind
}
fn main() {

View File

@ -6,15 +6,18 @@ error: abnormal termination: panic in a function that cannot unwind
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | / fn has_cleanup() {
LL | |
LL | | let _f = Foo;
LL | | panic!();
LL | | }
| |_^ panic in a function that cannot unwind
...
LL | has_cleanup();
| ------------- in this inlined function call
|
= note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC
= note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
note: inside `panic_abort`
--> $DIR/terminate-terminator.rs:LL:CC
|
LL | has_cleanup();
| ^^^^^^^^^^^^^
note: inside `main`
--> $DIR/terminate-terminator.rs:LL:CC
|

View File

@ -43,52 +43,52 @@ define-function: (
call-function: ("check-colors", {
"theme": "ayu",
"kw": "rgb(255, 119, 51)",
"kw2": "rgb(255, 119, 51)",
"prelude_ty": "rgb(105, 242, 223)",
"prelude_val": "rgb(255, 119, 51)",
"lifetime": "rgb(255, 119, 51)",
"number": "rgb(184, 204, 82)",
"string": "rgb(184, 204, 82)",
"bool_val": "rgb(255, 119, 51)",
"self": "rgb(54, 163, 217)",
"attr": "rgb(230, 225, 207)",
"macro": "rgb(163, 122, 204)",
"question_mark": "rgb(255, 144, 17)",
"comment": "rgb(120, 135, 151)",
"doc_comment": "rgb(161, 172, 136)",
"kw": "#ff7733",
"kw2": "#ff7733",
"prelude_ty": "#69f2df",
"prelude_val": "#ff7733",
"lifetime": "#ff7733",
"number": "#b8cc52",
"string": "#b8cc52",
"bool_val": "#ff7733",
"self": "#36a3d9",
"attr": "#e6e1cf",
"macro": "#a37acc",
"question_mark": "#ff9011",
"comment": "#788797",
"doc_comment": "#a1ac88",
})
call-function: ("check-colors", {
"theme": "dark",
"kw": "rgb(171, 138, 193)",
"kw2": "rgb(118, 154, 203)",
"prelude_ty": "rgb(118, 154, 203)",
"prelude_val": "rgb(238, 104, 104)",
"lifetime": "rgb(217, 127, 38)",
"number": "rgb(131, 163, 0)",
"string": "rgb(131, 163, 0)",
"bool_val": "rgb(238, 104, 104)",
"self": "rgb(238, 104, 104)",
"attr": "rgb(238, 104, 104)",
"macro": "rgb(62, 153, 159)",
"question_mark": "rgb(255, 144, 17)",
"comment": "rgb(141, 141, 139)",
"doc_comment": "rgb(140, 163, 117)",
"kw": "#ab8ac1",
"kw2": "#769acb",
"prelude_ty": "#769acb",
"prelude_val": "#ee6868",
"lifetime": "#d97f26",
"number": "#83a300",
"string": "#83a300",
"bool_val": "#ee6868",
"self": "#ee6868",
"attr": "#ee6868",
"macro": "#3e999f",
"question_mark": "#ff9011",
"comment": "#8d8d8b",
"doc_comment": "#8ca375",
})
call-function: ("check-colors", {
"theme": "light",
"kw": "rgb(137, 89, 168)",
"kw2": "rgb(66, 113, 174)",
"prelude_ty": "rgb(66, 113, 174)",
"prelude_val": "rgb(200, 40, 41)",
"lifetime": "rgb(183, 101, 20)",
"number": "rgb(113, 140, 0)",
"string": "rgb(113, 140, 0)",
"bool_val": "rgb(200, 40, 41)",
"self": "rgb(200, 40, 41)",
"attr": "rgb(200, 40, 41)",
"macro": "rgb(62, 153, 159)",
"question_mark": "rgb(255, 144, 17)",
"comment": "rgb(142, 144, 140)",
"doc_comment": "rgb(77, 77, 76)",
"kw": "#8959a8",
"kw2": "#4271ae",
"prelude_ty": "#4271ae",
"prelude_val": "#c82829",
"lifetime": "#b76514",
"number": "#718c00",
"string": "#718c00",
"bool_val": "#c82829",
"self": "#c82829",
"attr": "#c82829",
"macro": "#3e999f",
"question_mark": "#ff9011",
"comment": "#8e908c",
"doc_comment": "#4d4d4c",
})

View File

@ -340,3 +340,15 @@ id! {
/// level changes.
pub mod tracing_macro {}
}
/// Regression test for <https://github.com/rust-lang/rust/issues/111117>
pub mod trillium_server_common {
/// One-indexed, because the first CloneCounter is included. If you don't
/// want the original to count, construct a [``CloneCounterObserver`]
/// instead and use [`CloneCounterObserver::counter`] to increment.
//~^ ERROR unescaped backtick
pub struct CloneCounter;
/// This is used by the above.
pub struct CloneCounterObserver;
}

View File

@ -341,6 +341,18 @@ LL | | /// level changes.
change: [`rebuild_interest_cache`][rebuild] is called after the value of the max
to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:348:56
|
LL | /// instead and use [`CloneCounterObserver::counter`] to increment.
| ^
|
= help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
|
LL | /// instead and use [`CloneCounterObserver::counter\`] to increment.
| +
error: unescaped backtick
--> $DIR/unescaped_backticks.rs:11:5
|
@ -955,5 +967,5 @@ help: if you meant to use a literal backtick, escape it
LL | /// | table`( | )\`body |
| +
error: aborting due to 63 previous errors
error: aborting due to 64 previous errors

View File

@ -1,6 +0,0 @@
#![crate_name = "foo"]
// @has foo/index.html '//del' 'strike'
/// ~~strike~~
pub fn strike() {}

View File

@ -1,6 +1,13 @@
#![crate_name = "foo"]
// @has foo/fn.f.html
// @has - //del "Y"
/// ~~Y~~
// Test that strikethrough works with single and double tildes and that it shows up on
// the item's dedicated page as well as the parent module's summary of items.
// @has foo/index.html //del 'strike'
// @has foo/index.html //del 'through'
// @has foo/fn.f.html //del 'strike'
// @has foo/fn.f.html //del 'through'
/// ~~strike~~ ~through~
pub fn f() {}

View File

@ -1,6 +1,7 @@
// edition:2021
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
// Should capture the discriminant since a variant of a multivariant enum is
// mentioned in the match arm; the discriminant is captured by the closure regardless
@ -8,9 +9,6 @@
fn test_1_should_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@ -29,8 +27,6 @@ fn test_1_should_capture() {
fn test_2_should_not_capture() {
let variant = Some(2229);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match variant {
@ -50,8 +46,6 @@ enum SingleVariant {
fn test_3_should_not_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match variant {
@ -66,8 +60,6 @@ fn test_3_should_not_capture_single_variant() {
fn test_6_should_capture_single_variant() {
let variant = SingleVariant::Points(1);
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@ -88,8 +80,6 @@ fn test_6_should_capture_single_variant() {
fn test_4_should_not_capture_array() {
let array: [i32; 3] = [0; 3];
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
match array {
@ -112,8 +102,6 @@ enum MVariant {
fn test_5_should_capture_multi_variant() {
let variant = MVariant::A;
let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
@ -127,6 +115,62 @@ fn test_5_should_capture_multi_variant() {
c();
}
// Even though all patterns are wild, we need to read the discriminant
// in order to test the slice length
fn test_7_should_capture_slice_len() {
let slice: &[i32] = &[1, 2, 3];
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match slice {
//~^ NOTE: Capturing slice[] -> ImmBorrow
//~| NOTE: Min Capture slice[] -> ImmBorrow
[_,_,_] => {},
_ => {}
}
};
c();
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match slice {
//~^ NOTE: Capturing slice[] -> ImmBorrow
//~| NOTE: Min Capture slice[] -> ImmBorrow
[] => {},
_ => {}
}
};
c();
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
//~| Min Capture analysis includes:
match slice {
//~^ NOTE: Capturing slice[] -> ImmBorrow
//~| NOTE: Min Capture slice[] -> ImmBorrow
[_, .. ,_] => {},
_ => {}
}
};
c();
}
// Wild pattern that doesn't bind, so no capture
fn test_8_capture_slice_wild() {
let slice: &[i32] = &[1, 2, 3];
let c = #[rustc_capture_analysis]
|| {
//~^ First Pass analysis includes:
match slice {
[..] => {},
_ => {}
}
};
c();
}
fn main() {
test_1_should_capture();
test_2_should_not_capture();
@ -134,4 +178,6 @@ fn main() {
test_6_should_capture_single_variant();
test_4_should_not_capture_array();
test_5_should_capture_multi_variant();
test_7_should_capture_slice_len();
test_8_capture_slice_wild();
}

View File

@ -1,59 +1,5 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:10:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:31:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:52:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:68:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:90:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error[E0658]: attributes on expressions are experimental
--> $DIR/patterns-capture-analysis.rs:114:14
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:14:5
--> $DIR/patterns-capture-analysis.rs:12:5
|
LL | / || {
LL | |
@ -65,13 +11,13 @@ LL | | };
| |_____^
|
note: Capturing variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:17:15
--> $DIR/patterns-capture-analysis.rs:15:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:14:5
--> $DIR/patterns-capture-analysis.rs:12:5
|
LL | / || {
LL | |
@ -83,13 +29,13 @@ LL | | };
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:17:15
--> $DIR/patterns-capture-analysis.rs:15:15
|
LL | match variant {
| ^^^^^^^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:34:5
--> $DIR/patterns-capture-analysis.rs:30:5
|
LL | / || {
LL | |
@ -100,7 +46,7 @@ LL | | };
| |_____^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:55:5
--> $DIR/patterns-capture-analysis.rs:49:5
|
LL | / || {
LL | |
@ -111,7 +57,7 @@ LL | | };
| |_____^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:71:5
--> $DIR/patterns-capture-analysis.rs:63:5
|
LL | / || {
LL | |
@ -123,18 +69,18 @@ LL | | };
| |_____^
|
note: Capturing variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:74:15
--> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
note: Capturing variant[(0, 0)] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:74:15
--> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:71:5
--> $DIR/patterns-capture-analysis.rs:63:5
|
LL | / || {
LL | |
@ -146,13 +92,13 @@ LL | | };
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:74:15
--> $DIR/patterns-capture-analysis.rs:66:15
|
LL | match variant {
| ^^^^^^^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:93:5
--> $DIR/patterns-capture-analysis.rs:83:5
|
LL | / || {
LL | |
@ -163,7 +109,7 @@ LL | | };
| |_____^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:117:5
--> $DIR/patterns-capture-analysis.rs:105:5
|
LL | / || {
LL | |
@ -175,13 +121,13 @@ LL | | };
| |_____^
|
note: Capturing variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:120:15
--> $DIR/patterns-capture-analysis.rs:108:15
|
LL | match variant {
| ^^^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:117:5
--> $DIR/patterns-capture-analysis.rs:105:5
|
LL | / || {
LL | |
@ -193,11 +139,130 @@ LL | | };
| |_____^
|
note: Min Capture variant[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:120:15
--> $DIR/patterns-capture-analysis.rs:108:15
|
LL | match variant {
| ^^^^^^^
error: aborting due to 15 previous errors
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:123:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Capturing slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:126:15
|
LL | match slice {
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:123:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Min Capture slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:126:15
|
LL | match slice {
| ^^^^^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:135:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Capturing slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:138:15
|
LL | match slice {
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:135:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Min Capture slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:138:15
|
LL | match slice {
| ^^^^^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:147:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Capturing slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:150:15
|
LL | match slice {
| ^^^^^
error: Min Capture analysis includes:
--> $DIR/patterns-capture-analysis.rs:147:5
|
LL | / || {
LL | |
LL | |
LL | | match slice {
... |
LL | | }
LL | | };
| |_____^
|
note: Min Capture slice[] -> ImmBorrow
--> $DIR/patterns-capture-analysis.rs:150:15
|
LL | match slice {
| ^^^^^
error: First Pass analysis includes:
--> $DIR/patterns-capture-analysis.rs:164:5
|
LL | / || {
LL | |
LL | | match slice {
LL | | [..] => {},
LL | | _ => {}
LL | | }
LL | | };
| |_____^
error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,22 @@
struct Header;
struct EntryMetadata;
struct Entry<A, B>(A, B);
trait Tr {
type EncodedKey;
type EncodedValue;
}
fn test<C: Tr, R>(
// This APIT is long, however we shouldn't render the type name with a newline in it.
y: impl FnOnce(
&mut Header,
&mut [EntryMetadata],
&mut [Entry<C::EncodedKey, C::EncodedValue>]
) -> R,
) {
let () = y;
//~^ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,22 @@
error[E0308]: mismatched types
--> $DIR/arg-position-impl-trait-too-long.rs:18:9
|
LL | y: impl FnOnce(
| ________-
LL | | &mut Header,
LL | | &mut [EntryMetadata],
LL | | &mut [Entry<C::EncodedKey, C::EncodedValue>]
LL | | ) -> R,
| |__________- this type parameter
LL | ) {
LL | let () = y;
| ^^ - this expression has type `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
| |
| expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`, found `()`
|
= note: expected type parameter `impl FnOnce(&mut Header, &mut [EntryMetadata], &mut [Entry<C::EncodedKey, C::EncodedValue>]) -> R`
found unit type `()`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -134,6 +134,14 @@ fn expressions() {
}
}
match f {
#[deny(ellipsis_inclusive_range_patterns)]
Match{f1: 0...100} => {}
//~^ ERROR range patterns are deprecated
//~| WARNING this is accepted in the current edition
_ => {}
}
// Statement Block
{
#![deny(unsafe_code)]

View File

@ -384,92 +384,106 @@ note: the lint level is defined here
LL | #[deny(while_true)]
| ^^^^^^^^^^
error: `...` range patterns are deprecated
--> $DIR/lint-attr-everywhere-early.rs:139:20
|
LL | Match{f1: 0...100} => {}
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:138:16
|
LL | #[deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:140:9
--> $DIR/lint-attr-everywhere-early.rs:148:9
|
LL | unsafe {}
| ^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:139:17
--> $DIR/lint-attr-everywhere-early.rs:147:17
|
LL | #![deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:144:9
--> $DIR/lint-attr-everywhere-early.rs:152:9
|
LL | unsafe {}
| ^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:143:16
--> $DIR/lint-attr-everywhere-early.rs:151:16
|
LL | #[deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:149:5
--> $DIR/lint-attr-everywhere-early.rs:157:5
|
LL | unsafe {};
| ^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:148:12
--> $DIR/lint-attr-everywhere-early.rs:156:12
|
LL | #[deny(unsafe_code)]
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:151:27
--> $DIR/lint-attr-everywhere-early.rs:159:27
|
LL | [#[deny(unsafe_code)] unsafe {123}];
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:151:13
--> $DIR/lint-attr-everywhere-early.rs:159:13
|
LL | [#[deny(unsafe_code)] unsafe {123}];
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:152:27
--> $DIR/lint-attr-everywhere-early.rs:160:27
|
LL | (#[deny(unsafe_code)] unsafe {123},);
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:152:13
--> $DIR/lint-attr-everywhere-early.rs:160:13
|
LL | (#[deny(unsafe_code)] unsafe {123},);
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:154:31
--> $DIR/lint-attr-everywhere-early.rs:162:31
|
LL | call(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:154:17
--> $DIR/lint-attr-everywhere-early.rs:162:17
|
LL | call(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^
error: usage of an `unsafe` block
--> $DIR/lint-attr-everywhere-early.rs:156:38
--> $DIR/lint-attr-everywhere-early.rs:164:38
|
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:156:24
--> $DIR/lint-attr-everywhere-early.rs:164:24
|
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
| ^^^^^^^^^^^
error: `...` range patterns are deprecated
--> $DIR/lint-attr-everywhere-early.rs:167:18
--> $DIR/lint-attr-everywhere-early.rs:175:18
|
LL | f1: 0...100,
| ^^^ help: use `..=` for an inclusive range
@ -477,10 +491,10 @@ LL | f1: 0...100,
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:166:20
--> $DIR/lint-attr-everywhere-early.rs:174:20
|
LL | #[deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 36 previous errors
error: aborting due to 37 previous errors

View File

@ -162,6 +162,11 @@ fn expressions() {
}
}
match 123 {
#[deny(non_snake_case)]
ARM_VAR => {} //~ ERROR variable `ARM_VAR` should have a snake case name
}
// Statement Block
{
#![deny(enum_intrinsics_non_enums)]

View File

@ -305,124 +305,136 @@ note: the lint level is defined here
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: variable `ARM_VAR` should have a snake case name
--> $DIR/lint-attr-everywhere-late.rs:167:9
|
LL | ARM_VAR => {}
| ^^^^^^^ help: convert the identifier to snake case: `arm_var`
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:166:16
|
LL | #[deny(non_snake_case)]
| ^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:168:9
--> $DIR/lint-attr-everywhere-late.rs:173:9
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:168:29
--> $DIR/lint-attr-everywhere-late.rs:173:29
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:167:17
--> $DIR/lint-attr-everywhere-late.rs:172:17
|
LL | #![deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:172:9
--> $DIR/lint-attr-everywhere-late.rs:177:9
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:172:29
--> $DIR/lint-attr-everywhere-late.rs:177:29
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:171:16
--> $DIR/lint-attr-everywhere-late.rs:176:16
|
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:177:5
--> $DIR/lint-attr-everywhere-late.rs:182:5
|
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:177:25
--> $DIR/lint-attr-everywhere-late.rs:182:25
|
LL | discriminant::<i32>(&123);
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:176:12
--> $DIR/lint-attr-everywhere-late.rs:181:12
|
LL | #[deny(enum_intrinsics_non_enums)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:179:41
--> $DIR/lint-attr-everywhere-late.rs:184:41
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:179:61
--> $DIR/lint-attr-everywhere-late.rs:184:61
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:179:13
--> $DIR/lint-attr-everywhere-late.rs:184:13
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:180:41
--> $DIR/lint-attr-everywhere-late.rs:185:41
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:180:61
--> $DIR/lint-attr-everywhere-late.rs:185:61
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:180:13
--> $DIR/lint-attr-everywhere-late.rs:185:13
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:182:45
--> $DIR/lint-attr-everywhere-late.rs:187:45
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:182:65
--> $DIR/lint-attr-everywhere-late.rs:187:65
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:182:17
--> $DIR/lint-attr-everywhere-late.rs:187:17
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:184:52
--> $DIR/lint-attr-everywhere-late.rs:189:52
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:184:72
--> $DIR/lint-attr-everywhere-late.rs:189:72
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:184:24
--> $DIR/lint-attr-everywhere-late.rs:189:24
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 31 previous errors
error: aborting due to 32 previous errors

View File

@ -0,0 +1,24 @@
#![feature(if_let_guard)]
#![allow(unused, non_snake_case)]
enum E {
A,
}
#[allow(bindings_with_variant_name, irrefutable_let_patterns)]
fn foo() {
match E::A {
#[deny(bindings_with_variant_name)]
A => {}
//~^ ERROR pattern binding `A` is named the same as one of the variants of the type `E`
}
match &E::A {
#[deny(irrefutable_let_patterns)]
a if let b = a => {}
//~^ ERROR irrefutable `if let` guard pattern
_ => {}
}
}
fn main() { }

View File

@ -0,0 +1,29 @@
error[E0170]: pattern binding `A` is named the same as one of the variants of the type `E`
--> $DIR/lint-match-arms-2.rs:12:9
|
LL | A => {}
| ^ help: to match on the variant, qualify the path: `E::A`
|
note: the lint level is defined here
--> $DIR/lint-match-arms-2.rs:11:16
|
LL | #[deny(bindings_with_variant_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: irrefutable `if let` guard pattern
--> $DIR/lint-match-arms-2.rs:18:18
|
LL | a if let b = a => {}
| ^
|
= note: this pattern will always match, so the guard is useless
= help: consider removing the guard and adding a `let` inside the match arm
note: the lint level is defined here
--> $DIR/lint-match-arms-2.rs:17:16
|
LL | #[deny(irrefutable_let_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0170`.