mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
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:
commit
0004b3b984
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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((
|
||||
|
@ -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((
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
(
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
@ -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>) {
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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" }
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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, _))
|
||||
|
@ -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
|
||||
|
302
library/core/src/slice/select.rs
Normal file
302
library/core/src/slice/select.rs
Normal 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
|
||||
}
|
@ -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[..]`.
|
||||
///
|
||||
|
@ -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].
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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",
|
||||
})
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/index.html '//del' 'strike'
|
||||
|
||||
/// ~~strike~~
|
||||
pub fn strike() {}
|
@ -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() {}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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`.
|
||||
|
22
tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
Normal file
22
tests/ui/impl-trait/arg-position-impl-trait-too-long.rs
Normal 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() {}
|
22
tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
Normal file
22
tests/ui/impl-trait/arg-position-impl-trait-too-long.stderr
Normal 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`.
|
@ -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)]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
||||
|
24
tests/ui/lint/lint-match-arms-2.rs
Normal file
24
tests/ui/lint/lint-match-arms-2.rs
Normal 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() { }
|
29
tests/ui/lint/lint-match-arms-2.stderr
Normal file
29
tests/ui/lint/lint-match-arms-2.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user