mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Auto merge of #122869 - matthiaskrgr:rollup-0navj4l, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #121619 (Experimental feature postfix match) - #122370 (Gracefully handle `AnonConst` in `diagnostic_hir_wf_check()`) - #122537 (interpret/allocation: fix aliasing issue in interpreter and refactor getters a bit) - #122542 (coverage: Clean up marker statements that aren't needed later) - #122800 (Add `NonNull::<[T]>::is_empty`.) - #122820 (Stop using `<DefId as Ord>` in various diagnostic situations) - #122847 (Suggest `RUST_MIN_STACK` workaround on overflow) - #122855 (Fix Itanium mangling usizes) - #122863 (add more ice tests ) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1447f9d38c
@ -4236,6 +4236,7 @@ name = "rustc_middle"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"derivative",
|
||||
"either",
|
||||
"field-offset",
|
||||
"gsgdt",
|
||||
|
@ -1437,7 +1437,7 @@ pub enum ExprKind {
|
||||
/// `'label: loop { block }`
|
||||
Loop(P<Block>, Option<Label>, Span),
|
||||
/// A `match` block.
|
||||
Match(P<Expr>, ThinVec<Arm>),
|
||||
Match(P<Expr>, ThinVec<Arm>, MatchKind),
|
||||
/// A closure (e.g., `move |a, b, c| a + b + c`).
|
||||
Closure(Box<Closure>),
|
||||
/// A block (`'label: { ... }`).
|
||||
@ -1762,6 +1762,15 @@ pub enum StrStyle {
|
||||
Raw(u8),
|
||||
}
|
||||
|
||||
/// The kind of match expression
|
||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq)]
|
||||
pub enum MatchKind {
|
||||
/// match expr { ... }
|
||||
Prefix,
|
||||
/// expr.match { ... }
|
||||
Postfix,
|
||||
}
|
||||
|
||||
/// A literal in a meta item.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct MetaItemLit {
|
||||
|
@ -1425,7 +1425,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
visit_opt(label, |label| vis.visit_label(label));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
ExprKind::Match(expr, arms) => {
|
||||
ExprKind::Match(expr, arms, _kind) => {
|
||||
vis.visit_expr(expr);
|
||||
arms.flat_map_in_place(|arm| vis.flat_map_arm(arm));
|
||||
}
|
||||
|
@ -923,7 +923,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
try_visit!(visitor.visit_block(block));
|
||||
}
|
||||
ExprKind::Match(subexpression, arms) => {
|
||||
ExprKind::Match(subexpression, arms, _kind) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
walk_list!(visitor, visit_arm, arms);
|
||||
}
|
||||
|
@ -181,10 +181,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
)
|
||||
}),
|
||||
ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
|
||||
ExprKind::Match(expr, arms) => hir::ExprKind::Match(
|
||||
ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
|
||||
self.lower_expr(expr),
|
||||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||
hir::MatchSource::Normal,
|
||||
match kind {
|
||||
MatchKind::Prefix => hir::MatchSource::Normal,
|
||||
MatchKind::Postfix => hir::MatchSource::Postfix,
|
||||
},
|
||||
),
|
||||
ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr),
|
||||
ExprKind::Closure(box Closure {
|
||||
|
@ -564,6 +564,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
gate_all!(generic_const_items, "generic const items are experimental");
|
||||
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
|
||||
if !visitor.features.never_patterns {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
|
||||
use ast::ForLoopKind;
|
||||
use ast::{ForLoopKind, MatchKind};
|
||||
use itertools::{Itertools, Position};
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
@ -589,12 +589,22 @@ impl<'a> State<'a> {
|
||||
self.word_nbsp("loop");
|
||||
self.print_block_with_attrs(blk, attrs);
|
||||
}
|
||||
ast::ExprKind::Match(expr, arms) => {
|
||||
ast::ExprKind::Match(expr, arms, match_kind) => {
|
||||
self.cbox(0);
|
||||
self.ibox(0);
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.space();
|
||||
|
||||
match match_kind {
|
||||
MatchKind::Prefix => {
|
||||
self.word_nbsp("match");
|
||||
self.print_expr_as_cond(expr);
|
||||
self.space();
|
||||
}
|
||||
MatchKind::Postfix => {
|
||||
self.print_expr_as_cond(expr);
|
||||
self.word_nbsp(".match");
|
||||
}
|
||||
}
|
||||
|
||||
self.bopen();
|
||||
self.print_inner_attributes_no_trailing_hardbreak(attrs);
|
||||
for arm in arms {
|
||||
|
@ -245,7 +245,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
ExprKind::Let(_, local_expr, _, _) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::Match(local_expr, _) => {
|
||||
ExprKind::Match(local_expr, ..) => {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
ExprKind::MethodCall(call) => {
|
||||
|
@ -132,7 +132,7 @@ fn cs_partial_cmp(
|
||||
// Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354
|
||||
|
||||
if !tag_then_data
|
||||
&& let ExprKind::Match(_, arms) = &mut expr1.kind
|
||||
&& let ExprKind::Match(_, arms, _) = &mut expr1.kind
|
||||
&& let Some(last) = arms.last_mut()
|
||||
&& let PatKind::Wild = last.pat.kind
|
||||
{
|
||||
|
@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
|
||||
use crate::deriving::generic::*;
|
||||
use crate::deriving::path_std;
|
||||
|
||||
use ast::EnumDef;
|
||||
use rustc_ast::{self as ast, MetaItem};
|
||||
use rustc_ast::{self as ast, EnumDef, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
@ -85,14 +85,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
|
||||
let bx = self;
|
||||
|
||||
match coverage.kind {
|
||||
// Marker statements have no effect during codegen,
|
||||
// so return early and don't create `func_coverage`.
|
||||
CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => return,
|
||||
// Match exhaustively to ensure that newly-added kinds are classified correctly.
|
||||
CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } => {}
|
||||
}
|
||||
|
||||
let Some(function_coverage_info) =
|
||||
bx.tcx.instance_mir(instance.def).function_coverage_info.as_deref()
|
||||
else {
|
||||
@ -109,7 +101,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
let Coverage { kind } = coverage;
|
||||
match *kind {
|
||||
CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!(
|
||||
"unexpected marker statement {kind:?} should have caused an early return"
|
||||
"marker statement {kind:?} should have been removed by CleanupPostBorrowck"
|
||||
),
|
||||
CoverageKind::CounterIncrement { id } => {
|
||||
func_coverage.mark_counter_id_seen(id);
|
||||
|
@ -1159,11 +1159,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
};
|
||||
|
||||
// Side-step AllocRef and directly access the underlying bytes more efficiently.
|
||||
// (We are staying inside the bounds here so all is good.)
|
||||
// (We are staying inside the bounds here and all bytes do get overwritten so all is good.)
|
||||
let alloc_id = alloc_ref.alloc_id;
|
||||
let bytes = alloc_ref
|
||||
.alloc
|
||||
.get_bytes_mut(&alloc_ref.tcx, alloc_ref.range)
|
||||
.get_bytes_unchecked_for_overwrite(&alloc_ref.tcx, alloc_ref.range)
|
||||
.map_err(move |e| e.to_interp_error(alloc_id))?;
|
||||
// `zip` would stop when the first iterator ends; we want to definitely
|
||||
// cover all of `bytes`.
|
||||
@ -1184,6 +1184,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
self.mem_copy_repeatedly(src, dest, size, 1, nonoverlapping)
|
||||
}
|
||||
|
||||
/// Performs `num_copies` many copies of `size` many bytes from `src` to `dest + i*size` (where
|
||||
/// `i` is the index of the copy).
|
||||
///
|
||||
/// Either `nonoverlapping` must be true or `num_copies` must be 1; doing repeated copies that
|
||||
/// may overlap is not supported.
|
||||
pub fn mem_copy_repeatedly(
|
||||
&mut self,
|
||||
src: Pointer<Option<M::Provenance>>,
|
||||
@ -1245,8 +1250,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
(dest_alloc_id, dest_prov),
|
||||
dest_range,
|
||||
)?;
|
||||
// Yes we do overwrite all bytes in `dest_bytes`.
|
||||
let dest_bytes = dest_alloc
|
||||
.get_bytes_mut_ptr(&tcx, dest_range)
|
||||
.get_bytes_unchecked_for_overwrite_ptr(&tcx, dest_range)
|
||||
.map_err(|e| e.to_interp_error(dest_alloc_id))?
|
||||
.as_mut_ptr();
|
||||
|
||||
@ -1280,6 +1286,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if num_copies > 1 {
|
||||
assert!(nonoverlapping, "multi-copy only supported in non-overlapping mode");
|
||||
}
|
||||
|
||||
let size_in_bytes = size.bytes_usize();
|
||||
// For particularly large arrays (where this is perf-sensitive) it's common that
|
||||
@ -1292,6 +1301,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
} else if src_alloc_id == dest_alloc_id {
|
||||
let mut dest_ptr = dest_bytes;
|
||||
for _ in 0..num_copies {
|
||||
// Here we rely on `src` and `dest` being non-overlapping if there is more than
|
||||
// one copy.
|
||||
ptr::copy(src_bytes, dest_ptr, size_in_bytes);
|
||||
dest_ptr = dest_ptr.add(size_in_bytes);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::traits::Reveal;
|
||||
use rustc_middle::mir::coverage::CoverageKind;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
@ -345,11 +346,21 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
|
||||
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
|
||||
}
|
||||
}
|
||||
StatementKind::Coverage(coverage) => {
|
||||
let kind = &coverage.kind;
|
||||
if self.mir_phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup)
|
||||
&& let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("{kind:?} should have been removed after analysis"),
|
||||
);
|
||||
}
|
||||
}
|
||||
StatementKind::Assign(..)
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Intrinsic(_)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::ConstEvalCounter
|
||||
| StatementKind::PlaceMention(..)
|
||||
| StatementKind::Nop => {}
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Signal handler for rustc
|
||||
//! Primarily used to extract a backtrace from stack overflow
|
||||
|
||||
use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
|
||||
use std::alloc::{alloc, Layout};
|
||||
use std::{fmt, mem, ptr};
|
||||
|
||||
@ -100,7 +101,10 @@ extern "C" fn print_stack_trace(_: libc::c_int) {
|
||||
written += 1;
|
||||
}
|
||||
raw_errln!("note: we would appreciate a report at https://github.com/rust-lang/rust");
|
||||
written += 1;
|
||||
// get the current stack size WITHOUT blocking and double it
|
||||
let new_size = STACK_SIZE.get().copied().unwrap_or(DEFAULT_STACK_SIZE) * 2;
|
||||
raw_errln!("help: you can increase rustc's stack size by setting RUST_MIN_STACK={new_size}");
|
||||
written += 2;
|
||||
if written > 24 {
|
||||
// We probably just scrolled the earlier "we got SIGSEGV" message off the terminal
|
||||
raw_errln!("note: backtrace dumped due to SIGSEGV! resuming signal");
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::base::ExtCtxt;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
|
||||
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp};
|
||||
use rustc_ast::{attr, token, util::literal};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
@ -524,7 +524,7 @@ impl<'a> ExtCtxt<'a> {
|
||||
}
|
||||
|
||||
pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
|
||||
self.expr(span, ast::ExprKind::Match(arg, arms))
|
||||
self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
|
||||
}
|
||||
|
||||
pub fn expr_if(
|
||||
|
@ -559,6 +559,8 @@ declare_features! (
|
||||
(unstable, offset_of_nested, "1.77.0", Some(120140)),
|
||||
/// Allows using `#[optimize(X)]`.
|
||||
(unstable, optimize_attribute, "1.34.0", Some(54882)),
|
||||
/// Allows postfix match `expr.match { ... }`
|
||||
(unstable, postfix_match, "CURRENT_RUSTC_VERSION", Some(121618)),
|
||||
/// Allows macro attributes on expressions, statements and non-inline modules.
|
||||
(unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
|
||||
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
|
||||
|
@ -2015,6 +2015,8 @@ pub enum LocalSource {
|
||||
pub enum MatchSource {
|
||||
/// A `match _ { .. }`.
|
||||
Normal,
|
||||
/// A `expr.match { .. }`.
|
||||
Postfix,
|
||||
/// A desugared `for _ in _ { .. }` loop.
|
||||
ForLoopDesugar,
|
||||
/// A desugared `?` operator.
|
||||
@ -2031,6 +2033,7 @@ impl MatchSource {
|
||||
use MatchSource::*;
|
||||
match self {
|
||||
Normal => "match",
|
||||
Postfix => ".match",
|
||||
ForLoopDesugar => "for",
|
||||
TryDesugar(_) => "?",
|
||||
AwaitDesugar => ".await",
|
||||
|
@ -163,6 +163,16 @@ fn diagnostic_hir_wf_check<'tcx>(
|
||||
kind: hir::GenericParamKind::Type { default: Some(ty), .. },
|
||||
..
|
||||
}) => vec![*ty],
|
||||
hir::Node::AnonConst(_)
|
||||
if let Some(const_param_id) =
|
||||
tcx.hir().opt_const_param_default_param_def_id(hir_id)
|
||||
&& let hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { ty, .. },
|
||||
..
|
||||
}) = tcx.hir_node_by_def_id(const_param_id) =>
|
||||
{
|
||||
vec![*ty]
|
||||
}
|
||||
ref node => bug!("Unexpected node {:?}", node),
|
||||
},
|
||||
WellFormedLoc::Param { function: _, param_idx } => {
|
||||
|
@ -48,12 +48,20 @@ pub fn add_configuration(cfg: &mut Cfg, sess: &mut Session, codegen_backend: &dy
|
||||
}
|
||||
}
|
||||
|
||||
const STACK_SIZE: usize = 8 * 1024 * 1024;
|
||||
pub static STACK_SIZE: OnceLock<usize> = OnceLock::new();
|
||||
pub const DEFAULT_STACK_SIZE: usize = 8 * 1024 * 1024;
|
||||
|
||||
fn get_stack_size() -> Option<usize> {
|
||||
// FIXME: Hacks on hacks. If the env is trying to override the stack size
|
||||
// then *don't* set it explicitly.
|
||||
env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
|
||||
fn init_stack_size() -> usize {
|
||||
// Obey the environment setting or default
|
||||
*STACK_SIZE.get_or_init(|| {
|
||||
env::var_os("RUST_MIN_STACK")
|
||||
.map(|os_str| os_str.to_string_lossy().into_owned())
|
||||
// ignore if it is set to nothing
|
||||
.filter(|s| s.trim() != "")
|
||||
.map(|s| s.trim().parse::<usize>().unwrap())
|
||||
// otherwise pick a consistent default
|
||||
.unwrap_or(DEFAULT_STACK_SIZE)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||
@ -66,10 +74,7 @@ pub(crate) fn run_in_thread_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||
// the parallel compiler, in particular to ensure there is no accidental
|
||||
// sharing of data between the main thread and the compilation thread
|
||||
// (which might cause problems for the parallel compiler).
|
||||
let mut builder = thread::Builder::new().name("rustc".to_string());
|
||||
if let Some(size) = get_stack_size() {
|
||||
builder = builder.stack_size(size);
|
||||
}
|
||||
let builder = thread::Builder::new().name("rustc".to_string()).stack_size(init_stack_size());
|
||||
|
||||
// We build the session globals and run `f` on the spawned thread, because
|
||||
// `SessionGlobals` does not impl `Send` in the non-parallel compiler.
|
||||
@ -120,7 +125,7 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||
});
|
||||
}
|
||||
|
||||
let mut builder = rayon::ThreadPoolBuilder::new()
|
||||
let builder = rayon::ThreadPoolBuilder::new()
|
||||
.thread_name(|_| "rustc".to_string())
|
||||
.acquire_thread_handler(jobserver::acquire_thread)
|
||||
.release_thread_handler(jobserver::release_thread)
|
||||
@ -144,10 +149,8 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
|
||||
on_panic.disable();
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
if let Some(size) = get_stack_size() {
|
||||
builder = builder.stack_size(size);
|
||||
}
|
||||
})
|
||||
.stack_size(init_stack_size());
|
||||
|
||||
// We create the session globals on the main thread, then create the thread
|
||||
// pool. Upon creation, each worker thread created gets a copy of the
|
||||
|
@ -865,7 +865,7 @@ trait UnusedDelimLint {
|
||||
(iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
|
||||
}
|
||||
|
||||
Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
|
||||
Match(ref head, ..) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||
(head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None, true)
|
||||
}
|
||||
@ -1133,7 +1133,7 @@ impl EarlyLintPass for UnusedParens {
|
||||
}
|
||||
return;
|
||||
}
|
||||
ExprKind::Match(ref _expr, ref arm) => {
|
||||
ExprKind::Match(ref _expr, ref arm, _) => {
|
||||
for a in arm {
|
||||
if let Some(body) = &a.body {
|
||||
self.check_unused_delims_expr(
|
||||
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
derivative = "2.2.0"
|
||||
either = "1.5.0"
|
||||
field-offset = "0.3.5"
|
||||
gsgdt = "0.1.2"
|
||||
|
@ -456,7 +456,7 @@ impl<'tcx> Const<'tcx> {
|
||||
}
|
||||
|
||||
/// An unevaluated (potentially generic) constant used in MIR.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable)]
|
||||
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct UnevaluatedConst<'tcx> {
|
||||
pub def: DefId,
|
||||
|
@ -88,14 +88,13 @@ pub enum CoverageKind {
|
||||
/// Marks a span that might otherwise not be represented in MIR, so that
|
||||
/// coverage instrumentation can associate it with its enclosing block/BCB.
|
||||
///
|
||||
/// Only used by the `InstrumentCoverage` pass, and has no effect during
|
||||
/// codegen.
|
||||
/// Should be erased before codegen (at some point after `InstrumentCoverage`).
|
||||
SpanMarker,
|
||||
|
||||
/// Marks its enclosing basic block with an ID that can be referred to by
|
||||
/// side data in [`BranchInfo`].
|
||||
///
|
||||
/// Has no effect during codegen.
|
||||
/// Should be erased before codegen (at some point after `InstrumentCoverage`).
|
||||
BlockMarker { id: BlockMarkerId },
|
||||
|
||||
/// Marks the point in MIR control flow represented by a coverage counter.
|
||||
|
@ -37,9 +37,16 @@ pub trait AllocBytes:
|
||||
/// Create a zeroed `AllocBytes` of the specified size and alignment.
|
||||
/// Returns `None` if we ran out of memory on the host.
|
||||
fn zeroed(size: Size, _align: Align) -> Option<Self>;
|
||||
|
||||
/// Gives direct access to the raw underlying storage.
|
||||
///
|
||||
/// Crucially this pointer is compatible with:
|
||||
/// - other pointers retunred by this method, and
|
||||
/// - references returned from `deref()`, as long as there was no write.
|
||||
fn as_mut_ptr(&mut self) -> *mut u8;
|
||||
}
|
||||
|
||||
// Default `bytes` for `Allocation` is a `Box<[u8]>`.
|
||||
/// Default `bytes` for `Allocation` is a `Box<u8>`.
|
||||
impl AllocBytes for Box<[u8]> {
|
||||
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
|
||||
Box::<[u8]>::from(slice.into())
|
||||
@ -51,6 +58,11 @@ impl AllocBytes for Box<[u8]> {
|
||||
let bytes = unsafe { bytes.assume_init() };
|
||||
Some(bytes)
|
||||
}
|
||||
|
||||
fn as_mut_ptr(&mut self) -> *mut u8 {
|
||||
// Carefully avoiding any intermediate references.
|
||||
ptr::addr_of_mut!(**self).cast()
|
||||
}
|
||||
}
|
||||
|
||||
/// This type represents an Allocation in the Miri/CTFE core engine.
|
||||
@ -399,10 +411,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
|
||||
/// Byte accessors.
|
||||
impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
|
||||
pub fn base_addr(&self) -> *const u8 {
|
||||
self.bytes.as_ptr()
|
||||
}
|
||||
|
||||
/// This is the entirely abstraction-violating way to just grab the raw bytes without
|
||||
/// caring about provenance or initialization.
|
||||
///
|
||||
@ -452,13 +460,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
Ok(self.get_bytes_unchecked(range))
|
||||
}
|
||||
|
||||
/// Just calling this already marks everything as defined and removes provenance,
|
||||
/// so be sure to actually put data there!
|
||||
/// This is the entirely abstraction-violating way to just get mutable access to the raw bytes.
|
||||
/// Just calling this already marks everything as defined and removes provenance, so be sure to
|
||||
/// actually overwrite all the data there!
|
||||
///
|
||||
/// It is the caller's responsibility to check bounds and alignment beforehand.
|
||||
/// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods
|
||||
/// on `InterpCx` instead.
|
||||
pub fn get_bytes_mut(
|
||||
pub fn get_bytes_unchecked_for_overwrite(
|
||||
&mut self,
|
||||
cx: &impl HasDataLayout,
|
||||
range: AllocRange,
|
||||
@ -469,8 +478,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
Ok(&mut self.bytes[range.start.bytes_usize()..range.end().bytes_usize()])
|
||||
}
|
||||
|
||||
/// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
|
||||
pub fn get_bytes_mut_ptr(
|
||||
/// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases
|
||||
/// into this memory.
|
||||
pub fn get_bytes_unchecked_for_overwrite_ptr(
|
||||
&mut self,
|
||||
cx: &impl HasDataLayout,
|
||||
range: AllocRange,
|
||||
@ -479,10 +489,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
self.provenance.clear(range, cx)?;
|
||||
|
||||
assert!(range.end().bytes_usize() <= self.bytes.len()); // need to do our own bounds-check
|
||||
// Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
|
||||
let begin_ptr = self.bytes.as_mut_ptr().wrapping_add(range.start.bytes_usize());
|
||||
let len = range.end().bytes_usize() - range.start.bytes_usize();
|
||||
Ok(ptr::slice_from_raw_parts_mut(begin_ptr, len))
|
||||
}
|
||||
|
||||
/// This gives direct mutable access to the entire buffer, just exposing their internal state
|
||||
/// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if
|
||||
/// `OFFSET_IS_ADDR` is true.
|
||||
pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8 {
|
||||
assert!(Prov::OFFSET_IS_ADDR);
|
||||
self.bytes.as_mut_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
/// Reading and writing.
|
||||
@ -589,7 +608,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
|
||||
};
|
||||
|
||||
let endian = cx.data_layout().endian;
|
||||
let dst = self.get_bytes_mut(cx, range)?;
|
||||
// Yes we do overwrite all the bytes in `dst`.
|
||||
let dst = self.get_bytes_unchecked_for_overwrite(cx, range)?;
|
||||
write_target_uint(endian, dst, bytes).unwrap();
|
||||
|
||||
// See if we have to also store some provenance.
|
||||
|
@ -284,8 +284,15 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
|
||||
/// order of the category, thereby influencing diagnostic output.
|
||||
///
|
||||
/// See also `rustc_const_eval::borrow_check::constraints`.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
PartialOrd,
|
||||
Ord,
|
||||
PartialOrd = "feature_allow_slow_enum",
|
||||
Ord = "feature_allow_slow_enum"
|
||||
)]
|
||||
pub enum ConstraintCategory<'tcx> {
|
||||
Return(ReturnConstraint),
|
||||
Yield,
|
||||
@ -295,6 +302,7 @@ pub enum ConstraintCategory<'tcx> {
|
||||
Cast {
|
||||
/// Whether this is an unsizing cast and if yes, this contains the target type.
|
||||
/// Region variables are erased to ReErased.
|
||||
#[derivative(PartialOrd = "ignore", Ord = "ignore")]
|
||||
unsize_to: Option<Ty<'tcx>>,
|
||||
},
|
||||
|
||||
@ -304,7 +312,7 @@ pub enum ConstraintCategory<'tcx> {
|
||||
ClosureBounds,
|
||||
|
||||
/// Contains the function type if available.
|
||||
CallArgument(Option<Ty<'tcx>>),
|
||||
CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option<Ty<'tcx>>),
|
||||
CopyBound,
|
||||
SizedBound,
|
||||
Assignment,
|
||||
|
@ -124,6 +124,7 @@ pub enum AnalysisPhase {
|
||||
/// * [`TerminatorKind::FalseEdge`]
|
||||
/// * [`StatementKind::FakeRead`]
|
||||
/// * [`StatementKind::AscribeUserType`]
|
||||
/// * [`StatementKind::Coverage`] with [`CoverageKind::BlockMarker`] or [`CoverageKind::SpanMarker`]
|
||||
/// * [`Rvalue::Ref`] with `BorrowKind::Fake`
|
||||
///
|
||||
/// Furthermore, `Deref` projections must be the first projection within any place (if they
|
||||
|
@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi;
|
||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use crate::query::TyCtxtAt;
|
||||
use crate::ty::normalize_erasing_regions::NormalizationError;
|
||||
use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_error_messages::DiagMessage;
|
||||
use rustc_errors::{
|
||||
Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
|
||||
@ -356,21 +356,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
.ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
|
||||
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
|
||||
}
|
||||
let len = tcx.expand_abstract_consts(len);
|
||||
let prev = ty::Const::from_target_usize(tcx, s.bytes());
|
||||
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
|
||||
return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
|
||||
};
|
||||
Ok(SizeSkeleton::Generic(gen_size))
|
||||
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
|
||||
}
|
||||
SizeSkeleton::Pointer { .. } => Err(err),
|
||||
SizeSkeleton::Generic(g) => {
|
||||
let len = tcx.expand_abstract_consts(len);
|
||||
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
|
||||
return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
|
||||
};
|
||||
Ok(SizeSkeleton::Generic(gen_size))
|
||||
}
|
||||
SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,56 +457,6 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
|
||||
/// to ensure that they have a canonical order and can be compared directly we combine all
|
||||
/// constants, and sort the other terms. This allows comparison of expressions of sizes,
|
||||
/// allowing for things like transmuting between types that depend on generic consts.
|
||||
/// This returns `None` if multiplication of constants overflows.
|
||||
fn mul_sorted_consts<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
a: ty::Const<'tcx>,
|
||||
b: ty::Const<'tcx>,
|
||||
) -> Option<ty::Const<'tcx>> {
|
||||
use crate::mir::BinOp::Mul;
|
||||
|
||||
let mut work = vec![a, b];
|
||||
let mut done = vec![];
|
||||
while let Some(n) = work.pop() {
|
||||
if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() {
|
||||
work.push(l);
|
||||
work.push(r)
|
||||
} else {
|
||||
done.push(n);
|
||||
}
|
||||
}
|
||||
let mut k = 1;
|
||||
let mut overflow = false;
|
||||
done.retain(|c| {
|
||||
let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
|
||||
return true;
|
||||
};
|
||||
let Some(next) = c.checked_mul(k) else {
|
||||
overflow = true;
|
||||
return false;
|
||||
};
|
||||
k = next;
|
||||
false
|
||||
});
|
||||
if overflow {
|
||||
return None;
|
||||
}
|
||||
if k != 1 {
|
||||
done.push(ty::Const::from_target_usize(tcx, k));
|
||||
} else if k == 0 {
|
||||
return Some(ty::Const::from_target_usize(tcx, 0));
|
||||
}
|
||||
done.sort_unstable();
|
||||
|
||||
// create a single tree from the buffer
|
||||
done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty()))
|
||||
}
|
||||
|
||||
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
}
|
||||
|
@ -481,6 +481,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
||||
// when the iterator is an uninhabited type. unreachable_code will trigger instead.
|
||||
hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {}
|
||||
hir::MatchSource::ForLoopDesugar
|
||||
| hir::MatchSource::Postfix
|
||||
| hir::MatchSource::Normal
|
||||
| hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report),
|
||||
// Unreachable patterns in try and await expressions occur when one of
|
||||
|
@ -5,15 +5,20 @@
|
||||
//! - [`AscribeUserType`]
|
||||
//! - [`FakeRead`]
|
||||
//! - [`Assign`] statements with a [`Fake`] borrow
|
||||
//! - [`Coverage`] statements of kind [`BlockMarker`] or [`SpanMarker`]
|
||||
//!
|
||||
//! [`AscribeUserType`]: rustc_middle::mir::StatementKind::AscribeUserType
|
||||
//! [`Assign`]: rustc_middle::mir::StatementKind::Assign
|
||||
//! [`FakeRead`]: rustc_middle::mir::StatementKind::FakeRead
|
||||
//! [`Nop`]: rustc_middle::mir::StatementKind::Nop
|
||||
//! [`Fake`]: rustc_middle::mir::BorrowKind::Fake
|
||||
//! [`Coverage`]: rustc_middle::mir::StatementKind::Coverage
|
||||
//! [`BlockMarker`]: rustc_middle::mir::coverage::CoverageKind::BlockMarker
|
||||
//! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker
|
||||
|
||||
use crate::MirPass;
|
||||
use rustc_middle::mir::{Body, BorrowKind, Rvalue, StatementKind, TerminatorKind};
|
||||
use rustc_middle::mir::coverage::CoverageKind;
|
||||
use rustc_middle::mir::{Body, BorrowKind, Coverage, Rvalue, StatementKind, TerminatorKind};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
pub struct CleanupPostBorrowck;
|
||||
@ -25,6 +30,12 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
|
||||
match statement.kind {
|
||||
StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Fake, _)))
|
||||
| StatementKind::Coverage(box Coverage {
|
||||
// These kinds of coverage statements are markers inserted during
|
||||
// MIR building, and are not needed after InstrumentCoverage.
|
||||
kind: CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. },
|
||||
..
|
||||
})
|
||||
| StatementKind::FakeRead(..) => statement.make_nop(),
|
||||
_ => (),
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use crate::errors;
|
||||
use crate::maybe_recover_from_interpolated_ty_qpath;
|
||||
use ast::mut_visit::{noop_visit_expr, MutVisitor};
|
||||
use ast::token::IdentIsRaw;
|
||||
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment};
|
||||
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment};
|
||||
use core::mem;
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_ast::ptr::P;
|
||||
@ -1379,6 +1379,13 @@ impl<'a> Parser<'a> {
|
||||
return Ok(self.mk_await_expr(self_arg, lo));
|
||||
}
|
||||
|
||||
// Post-fix match
|
||||
if self.eat_keyword(kw::Match) {
|
||||
let match_span = self.prev_token.span;
|
||||
self.psess.gated_spans.gate(sym::postfix_match, match_span);
|
||||
return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix);
|
||||
}
|
||||
|
||||
let fn_span_lo = self.token.span;
|
||||
let mut seg = self.parse_path_segment(PathStyle::Expr, None)?;
|
||||
self.check_trailing_angle_brackets(&seg, &[&token::OpenDelim(Delimiter::Parenthesis)]);
|
||||
@ -2894,8 +2901,20 @@ impl<'a> Parser<'a> {
|
||||
/// Parses a `match ... { ... }` expression (`match` token already eaten).
|
||||
fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
|
||||
let match_span = self.prev_token.span;
|
||||
let lo = self.prev_token.span;
|
||||
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
|
||||
|
||||
self.parse_match_block(match_span, match_span, scrutinee, MatchKind::Prefix)
|
||||
}
|
||||
|
||||
/// Parses the block of a `match expr { ... }` or a `expr.match { ... }`
|
||||
/// expression. This is after the match token and scrutinee are eaten
|
||||
fn parse_match_block(
|
||||
&mut self,
|
||||
lo: Span,
|
||||
match_span: Span,
|
||||
scrutinee: P<Expr>,
|
||||
match_kind: MatchKind,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
if let Err(mut e) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
|
||||
if self.token == token::Semi {
|
||||
e.span_suggestion_short(
|
||||
@ -2938,7 +2957,7 @@ impl<'a> Parser<'a> {
|
||||
});
|
||||
return Ok(self.mk_expr_with_attrs(
|
||||
span,
|
||||
ExprKind::Match(scrutinee, arms),
|
||||
ExprKind::Match(scrutinee, arms, match_kind),
|
||||
attrs,
|
||||
));
|
||||
}
|
||||
@ -2946,7 +2965,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
let hi = self.token.span;
|
||||
self.bump();
|
||||
Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs))
|
||||
Ok(self.mk_expr_with_attrs(lo.to(hi), ExprKind::Match(scrutinee, arms, match_kind), attrs))
|
||||
}
|
||||
|
||||
/// Attempt to recover from match arm body with statements and no surrounding braces.
|
||||
@ -3955,7 +3974,7 @@ impl MutVisitor for CondChecker<'_> {
|
||||
| ExprKind::While(_, _, _)
|
||||
| ExprKind::ForLoop { .. }
|
||||
| ExprKind::Loop(_, _, _)
|
||||
| ExprKind::Match(_, _)
|
||||
| ExprKind::Match(_, _, _)
|
||||
| ExprKind::Closure(_)
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Gen(_, _, _)
|
||||
|
@ -48,7 +48,7 @@ impl NonConstExpr {
|
||||
Self::Match(TryDesugar(_)) => &[sym::const_try],
|
||||
|
||||
// All other expressions are allowed.
|
||||
Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[],
|
||||
Self::Loop(Loop | While) | Self::Match(Normal | Postfix | FormatArgs) => &[],
|
||||
};
|
||||
|
||||
Some(gates)
|
||||
|
@ -1335,6 +1335,7 @@ symbols! {
|
||||
poll,
|
||||
poll_next,
|
||||
post_dash_lto: "post-lto",
|
||||
postfix_match,
|
||||
powerpc_target_feature,
|
||||
powf128,
|
||||
powf16,
|
||||
|
@ -525,8 +525,8 @@ fn encode_ty<'tcx>(
|
||||
"{}",
|
||||
&len.try_to_scalar()
|
||||
.unwrap()
|
||||
.to_u64()
|
||||
.unwrap_or_else(|_| panic!("failed to convert length to u64"))
|
||||
.to_target_usize(&tcx.data_layout)
|
||||
.expect("Array lens are defined in usize")
|
||||
);
|
||||
s.push_str(&encode_ty(tcx, *ty0, dict, options));
|
||||
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||
|
@ -1575,6 +1575,25 @@ impl<T> NonNull<[T]> {
|
||||
self.as_ptr().len()
|
||||
}
|
||||
|
||||
/// Returns `true` if the non-null raw slice has a length of 0.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(slice_ptr_is_empty_nonnull)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// let slice: NonNull<[i8]> = NonNull::slice_from_raw_parts(NonNull::dangling(), 3);
|
||||
/// assert!(!slice.is_empty());
|
||||
/// ```
|
||||
#[unstable(feature = "slice_ptr_is_empty_nonnull", issue = "71146")]
|
||||
#[rustc_const_unstable(feature = "const_slice_ptr_is_empty_nonnull", issue = "71146")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn is_empty(self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Returns a non-null pointer to the slice's buffer.
|
||||
///
|
||||
/// # Examples
|
||||
|
22
src/doc/unstable-book/src/language-features/postfix-match.md
Normal file
22
src/doc/unstable-book/src/language-features/postfix-match.md
Normal file
@ -0,0 +1,22 @@
|
||||
# `postfix-match`
|
||||
|
||||
`postfix-match` adds the feature for matching upon values postfix
|
||||
the expressions that generate the values.
|
||||
|
||||
```rust,edition2021
|
||||
#![feature(postfix_match)]
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz
|
||||
}
|
||||
|
||||
fn get_foo() -> Foo {
|
||||
Foo::Bar
|
||||
}
|
||||
|
||||
get_foo().match {
|
||||
Foo::Bar => {},
|
||||
Foo::Baz => panic!(),
|
||||
}
|
||||
```
|
@ -105,7 +105,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor {
|
||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||
self.is_break = match expr.kind {
|
||||
ExprKind::Break(..) | ExprKind::Continue(..) | ExprKind::Ret(..) => true,
|
||||
ExprKind::Match(_, ref arms) => arms.iter().all(|arm|
|
||||
ExprKind::Match(_, ref arms, _) => arms.iter().all(|arm|
|
||||
arm.body.is_none() || arm.body.as_deref().is_some_and(|body| self.check_expr(body))
|
||||
),
|
||||
ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els),
|
||||
|
@ -552,7 +552,7 @@ fn ident_difference_expr_with_base_location(
|
||||
| (Gen(_, _, _), Gen(_, _, _))
|
||||
| (Block(_, _), Block(_, _))
|
||||
| (Closure(_), Closure(_))
|
||||
| (Match(_, _), Match(_, _))
|
||||
| (Match(_, _, _), Match(_, _, _))
|
||||
| (Loop(_, _, _), Loop(_, _, _))
|
||||
| (ForLoop { .. }, ForLoop { .. })
|
||||
| (While(_, _, _), While(_, _, _))
|
||||
|
@ -198,7 +198,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
||||
},
|
||||
(AssignOp(lo, lp, lv), AssignOp(ro, rp, rv)) => lo.node == ro.node && eq_expr(lp, rp) && eq_expr(lv, rv),
|
||||
(Field(lp, lf), Field(rp, rf)) => eq_id(*lf, *rf) && eq_expr(lp, rp),
|
||||
(Match(ls, la), Match(rs, ra)) => eq_expr(ls, rs) && over(la, ra, eq_arm),
|
||||
(Match(ls, la, lkind), Match(rs, ra, rkind)) => (lkind == rkind) && eq_expr(ls, rs) && over(la, ra, eq_arm),
|
||||
(
|
||||
Closure(box ast::Closure {
|
||||
binder: lb,
|
||||
|
@ -3,7 +3,7 @@ use std::cmp::min;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::token::{Delimiter, Lit, LitKind};
|
||||
use rustc_ast::{ast, ptr, token, ForLoopKind};
|
||||
use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use crate::chains::rewrite_chain;
|
||||
@ -170,8 +170,8 @@ pub(crate) fn format_expr(
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Match(ref cond, ref arms) => {
|
||||
rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs)
|
||||
ast::ExprKind::Match(ref cond, ref arms, kind) => {
|
||||
rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind)
|
||||
}
|
||||
ast::ExprKind::Path(ref qself, ref path) => {
|
||||
rewrite_path(context, PathContext::Expr, qself, path, shape)
|
||||
@ -625,7 +625,7 @@ pub(crate) fn rewrite_cond(
|
||||
shape: Shape,
|
||||
) -> Option<String> {
|
||||
match expr.kind {
|
||||
ast::ExprKind::Match(ref cond, _) => {
|
||||
ast::ExprKind::Match(ref cond, _, MatchKind::Prefix) => {
|
||||
// `match `cond` {`
|
||||
let cond_shape = match context.config.indent_style() {
|
||||
IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::iter::repeat;
|
||||
|
||||
use rustc_ast::{ast, ptr};
|
||||
use rustc_ast::{ast, ptr, MatchKind};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use crate::comment::{combine_strs_with_missing_comments, rewrite_comment};
|
||||
@ -72,6 +72,7 @@ pub(crate) fn rewrite_match(
|
||||
shape: Shape,
|
||||
span: Span,
|
||||
attrs: &[ast::Attribute],
|
||||
match_kind: MatchKind,
|
||||
) -> Option<String> {
|
||||
// Do not take the rhs overhead from the upper expressions into account
|
||||
// when rewriting match condition.
|
||||
@ -131,15 +132,27 @@ pub(crate) fn rewrite_match(
|
||||
}
|
||||
} else {
|
||||
let span_after_cond = mk_sp(cond.span.hi(), span.hi());
|
||||
Some(format!(
|
||||
"match {}{}{{\n{}{}{}\n{}}}",
|
||||
cond_str,
|
||||
block_sep,
|
||||
inner_attrs_str,
|
||||
nested_indent_str,
|
||||
rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
|
||||
shape.indent.to_string(context.config),
|
||||
))
|
||||
|
||||
match match_kind {
|
||||
MatchKind::Prefix => Some(format!(
|
||||
"match {}{}{{\n{}{}{}\n{}}}",
|
||||
cond_str,
|
||||
block_sep,
|
||||
inner_attrs_str,
|
||||
nested_indent_str,
|
||||
rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
|
||||
shape.indent.to_string(context.config),
|
||||
)),
|
||||
MatchKind::Postfix => Some(format!(
|
||||
"{}.match{}{{\n{}{}{}\n{}}}",
|
||||
cond_str,
|
||||
block_sep,
|
||||
inner_attrs_str,
|
||||
nested_indent_str,
|
||||
rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
|
||||
shape.indent.to_string(context.config),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/tools/rustfmt/tests/source/postfix-match/pf-match.rs
Normal file
20
src/tools/rustfmt/tests/source/postfix-match/pf-match.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
let val = Some(42);
|
||||
|
||||
val.match {
|
||||
Some(_) => 2,
|
||||
_ => 1
|
||||
};
|
||||
|
||||
Some(2).match {
|
||||
Some(_) => true,
|
||||
None => false
|
||||
}.match {
|
||||
false => "ferris is cute",
|
||||
true => "I turn cats in to petted cats",
|
||||
}.match {
|
||||
_ => (),
|
||||
}
|
||||
}
|
20
src/tools/rustfmt/tests/target/postfix-match/pf-match.rs
Normal file
20
src/tools/rustfmt/tests/target/postfix-match/pf-match.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
let val = Some(42);
|
||||
|
||||
val.match {
|
||||
Some(_) => 2,
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
Some(2).match {
|
||||
Some(_) => true,
|
||||
None => false,
|
||||
}.match {
|
||||
false => "ferris is cute",
|
||||
true => "I turn cats in to petted cats",
|
||||
}.match {
|
||||
_ => (),
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
- // MIR for `main` before CleanupPostBorrowck
|
||||
+ // MIR for `main` after CleanupPostBorrowck
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let mut _1: bool;
|
||||
|
||||
coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0)
|
||||
|
||||
coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
|
||||
coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
|
||||
coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36;
|
||||
coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39;
|
||||
coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40;
|
||||
coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2;
|
||||
coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36;
|
||||
|
||||
bb0: {
|
||||
Coverage::CounterIncrement(0);
|
||||
- Coverage::SpanMarker;
|
||||
+ nop;
|
||||
StorageLive(_1);
|
||||
_1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(move _1) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
Coverage::CounterIncrement(1);
|
||||
- Coverage::BlockMarker(1);
|
||||
+ nop;
|
||||
_0 = const ();
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
Coverage::ExpressionUsed(0);
|
||||
- Coverage::BlockMarker(0);
|
||||
+ nop;
|
||||
_0 = const ();
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
Coverage::ExpressionUsed(1);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
||||
bb5 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
- // MIR for `main` before InstrumentCoverage
|
||||
+ // MIR for `main` after InstrumentCoverage
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: ();
|
||||
let mut _1: bool;
|
||||
|
||||
coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => /the/src/instrument_coverage_cleanup.rs:15:8: 15:36 (#0)
|
||||
|
||||
+ coverage ExpressionId(0) => Expression { lhs: Counter(0), op: Subtract, rhs: Counter(1) };
|
||||
+ coverage ExpressionId(1) => Expression { lhs: Counter(1), op: Add, rhs: Expression(0) };
|
||||
+ coverage Code(Counter(0)) => /the/src/instrument_coverage_cleanup.rs:14:1 - 15:36;
|
||||
+ coverage Code(Expression(0)) => /the/src/instrument_coverage_cleanup.rs:15:37 - 15:39;
|
||||
+ coverage Code(Counter(1)) => /the/src/instrument_coverage_cleanup.rs:15:39 - 15:40;
|
||||
+ coverage Code(Expression(1)) => /the/src/instrument_coverage_cleanup.rs:16:1 - 16:2;
|
||||
+ coverage Branch { true_term: Expression(0), false_term: Counter(1) } => /the/src/instrument_coverage_cleanup.rs:15:8 - 15:36;
|
||||
+
|
||||
bb0: {
|
||||
+ Coverage::CounterIncrement(0);
|
||||
Coverage::SpanMarker;
|
||||
StorageLive(_1);
|
||||
_1 = std::hint::black_box::<bool>(const true) -> [return: bb1, unwind: bb5];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
switchInt(move _1) -> [0: bb3, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb2: {
|
||||
+ Coverage::CounterIncrement(1);
|
||||
Coverage::BlockMarker(1);
|
||||
_0 = const ();
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
+ Coverage::ExpressionUsed(0);
|
||||
Coverage::BlockMarker(0);
|
||||
_0 = const ();
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
+ Coverage::ExpressionUsed(1);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
|
||||
bb5 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
||||
|
22
tests/mir-opt/instrument_coverage_cleanup.rs
Normal file
22
tests/mir-opt/instrument_coverage_cleanup.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Test that CleanupPostBorrowck cleans up the marker statements that are
|
||||
// inserted during MIR building (after InstrumentCoverage is done with them),
|
||||
// but leaves the statements that were added by InstrumentCoverage.
|
||||
//
|
||||
// Removed statement kinds: BlockMarker, SpanMarker
|
||||
// Retained statement kinds: CounterIncrement, ExpressionUsed
|
||||
|
||||
//@ unit-test: InstrumentCoverage
|
||||
//@ compile-flags: -Cinstrument-coverage -Zcoverage-options=branch -Zno-profiler-runtime
|
||||
//@ compile-flags: --remap-path-prefix={{src-base}}=/the/src
|
||||
|
||||
// EMIT_MIR instrument_coverage_cleanup.main.InstrumentCoverage.diff
|
||||
// EMIT_MIR instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
|
||||
fn main() {
|
||||
if !core::hint::black_box(true) {}
|
||||
}
|
||||
|
||||
// CHECK-NOT: Coverage::BlockMarker
|
||||
// CHECK-NOT: Coverage::SpanMarker
|
||||
// CHECK: Coverage::CounterIncrement
|
||||
// CHECK-NOT: Coverage::BlockMarker
|
||||
// CHECK-NOT: Coverage::SpanMarker
|
21
tests/pretty/postfix-match.rs
Normal file
21
tests/pretty/postfix-match.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
let val = Some(42);
|
||||
|
||||
val.match {
|
||||
Some(_) => 2,
|
||||
_ => 1
|
||||
};
|
||||
|
||||
|
||||
Some(2).match {
|
||||
Some(_) => true,
|
||||
None => false
|
||||
}.match {
|
||||
false => "ferris is cute",
|
||||
true => "I turn cats in to petted cats",
|
||||
}.match {
|
||||
_ => (),
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
// test for ICE "no entry found for key" in generics_of.rs #113017
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub fn foo()
|
||||
where
|
||||
for<const N: usize = { || {}; 1 }> ():,
|
||||
//~^ ERROR only lifetime parameters can be used in this context
|
||||
//~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
|
||||
{}
|
||||
|
||||
pub fn main() {}
|
@ -0,0 +1,19 @@
|
||||
error[E0658]: only lifetime parameters can be used in this context
|
||||
--> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:15
|
||||
|
|
||||
LL | for<const N: usize = { || {}; 1 }> ():,
|
||||
| ^
|
||||
|
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: defaults for generic parameters are not allowed in `for<...>` binders
|
||||
--> $DIR/ice-generics_of-no-entry-found-for-key-113017.rs:8:9
|
||||
|
|
||||
LL | for<const N: usize = { || {}; 1 }> ():,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,18 @@
|
||||
// test for ICE #119275 "no entry found for key" in predicates_of.rs
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn bug<const N: Nat>(&self)
|
||||
//~^ ERROR `self` parameter is only allowed in associated functions
|
||||
//~^^ ERROR cannot find type `Nat` in this scope
|
||||
where
|
||||
for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
|
||||
//~^ ERROR only lifetime parameters can be used in this context
|
||||
//~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
|
||||
//~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
|
||||
//~^^^^ ERROR failed to resolve: use of undeclared type `COT`
|
||||
{
|
||||
}
|
||||
|
||||
pub fn main() {}
|
@ -0,0 +1,46 @@
|
||||
error: `self` parameter is only allowed in associated functions
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:22
|
||||
|
|
||||
LL | fn bug<const N: Nat>(&self)
|
||||
| ^^^^^ not semantically valid as function parameter
|
||||
|
|
||||
= note: associated functions are those in `impl` or `trait` definitions
|
||||
|
||||
error[E0412]: cannot find type `Nat` in this scope
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:17
|
||||
|
|
||||
LL | fn bug<const N: Nat>(&self)
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0658]: only lifetime parameters can be used in this context
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:15
|
||||
|
|
||||
LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
|
||||
| ^ ^
|
||||
|
|
||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: defaults for generic parameters are not allowed in `for<...>` binders
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:9
|
||||
|
|
||||
LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: defaults for generic parameters are not allowed in `for<...>` binders
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:29
|
||||
|
|
||||
LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0433]: failed to resolve: use of undeclared type `COT`
|
||||
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:43
|
||||
|
|
||||
LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
|
||||
| ^^^ use of undeclared type `COT`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0412, E0433, E0658.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
@ -32,4 +32,79 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_3d<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [u32; D * W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [[u32; D * W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose_with_const<const W: usize, const H: usize>(
|
||||
v: [[u32; 2 * H]; W + W]
|
||||
) -> [[u32; W + W]; 2 * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
//~^ ERROR: cannot transmute between types of different sizes, or dependently-sized types
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H+1]; W]` (generic size (H + 1) * 4 * W)
|
||||
= note: target type: `[[u32; W+1]; H]` (generic size (W + 1) * 4 * H)
|
||||
= note: source type: `[[u32; H+1]; W]` (size can vary because of [u32; H+1])
|
||||
= note: target type: `[[u32; W+1]; H]` (size can vary because of [u32; W+1])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:16:5
|
||||
@ -22,8 +22,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (generic size 4 * H * W)
|
||||
= note: target type: `[u32; W * H * H]` (generic size 4 * H * H * W)
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:30:5
|
||||
@ -34,6 +34,87 @@ LL | std::mem::transmute(v)
|
||||
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
|
||||
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:37:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:50:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; H]; W]` (size can vary because of [u32; H])
|
||||
= note: target type: `[u32; W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:57:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u32; H*W]` (this type does not have a fixed size)
|
||||
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:66:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
|
||||
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:75:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[[u32; D]; H]; W]` (size can vary because of [u32; D])
|
||||
= note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:82:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u16; L]` (this type does not have a fixed size)
|
||||
= note: target type: `[u8; L * 2]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:89:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u8; L * 2]` (this type does not have a fixed size)
|
||||
= note: target type: `[u16; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:96:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[u8; L]` (this type does not have a fixed size)
|
||||
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
|
||||
|
||||
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
|
||||
--> $DIR/transmute-fail.rs:105:5
|
||||
|
|
||||
LL | std::mem::transmute(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
|
||||
= note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/transmute-fail.rs:12:53
|
||||
|
|
||||
@ -46,7 +127,7 @@ error[E0308]: mismatched types
|
||||
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
|
||||
| ^ expected `usize`, found `bool`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0512.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
@ -3,81 +3,12 @@
|
||||
#![feature(transmute_generic_consts)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_3d<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [u32; D * W * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
|
||||
v: [[[u32; D]; H]; W]
|
||||
) -> [[u32; D * W]; H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn transpose_with_const<const W: usize, const H: usize>(
|
||||
v: [[u32; 2 * H]; W + W]
|
||||
) -> [[u32; W + W]; 2 * H] {
|
||||
unsafe {
|
||||
std::mem::transmute(v)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = transpose([[0; 8]; 16]);
|
||||
let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
|
||||
let _ = ident([[0; 8]; 16]);
|
||||
let _ = flatten([[0; 13]; 5]);
|
||||
let _: [[_; 5]; 13] = coagulate([0; 65]);
|
||||
let _ = flatten_3d([[[0; 3]; 13]; 5]);
|
||||
let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
|
||||
let _ = known_size([16; 13]);
|
||||
let _: [u16; 5] = condense_bytes([16u8; 10]);
|
||||
let _ = singleton_each([16; 10]);
|
||||
}
|
||||
|
20
tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
Normal file
20
tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// test for #112824 ICE type mismatching when copying!
|
||||
|
||||
pub struct Opcode(pub u8);
|
||||
|
||||
pub struct Opcode2(&'a S);
|
||||
//~^ ERROR use of undeclared lifetime name `'a`
|
||||
//~^^ ERROR cannot find type `S` in this scope
|
||||
|
||||
impl Opcode2 {
|
||||
pub const OP2: Opcode2 = Opcode2(Opcode(0x1));
|
||||
}
|
||||
|
||||
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
|
||||
move |i| match msg_type {
|
||||
Opcode2::OP2 => unimplemented!(),
|
||||
//~^ ERROR could not evaluate constant pattern
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
@ -0,0 +1,29 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/ice-type-mismatch-when-copying-112824.rs:5:21
|
||||
|
|
||||
LL | pub struct Opcode2(&'a S);
|
||||
| - ^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'a` here: `<'a>`
|
||||
|
||||
error[E0412]: cannot find type `S` in this scope
|
||||
--> $DIR/ice-type-mismatch-when-copying-112824.rs:5:24
|
||||
|
|
||||
LL | pub struct Opcode2(&'a S);
|
||||
| ^ not found in this scope
|
||||
|
|
||||
help: you might be missing a type parameter
|
||||
|
|
||||
LL | pub struct Opcode2<S>(&'a S);
|
||||
| +++
|
||||
|
||||
error: could not evaluate constant pattern
|
||||
--> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
|
||||
|
|
||||
LL | Opcode2::OP2 => unimplemented!(),
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0261, E0412.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
17
tests/ui/feature-gates/feature-gate-postfix_match.rs
Normal file
17
tests/ui/feature-gates/feature-gate-postfix_match.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Testing that postfix match doesn't work without enabling the feature
|
||||
|
||||
fn main() {
|
||||
let val = Some(42);
|
||||
|
||||
val.match { //~ ERROR postfix match is experimental
|
||||
Some(42) => "the answer to life, the universe, and everything",
|
||||
_ => "might be the answer to something"
|
||||
};
|
||||
|
||||
// Test that the gate works behind a cfg
|
||||
#[cfg(FALSE)]
|
||||
val.match { //~ ERROR postfix match is experimental
|
||||
Some(42) => "the answer to life, the universe, and everything",
|
||||
_ => "might be the answer to something"
|
||||
};
|
||||
}
|
23
tests/ui/feature-gates/feature-gate-postfix_match.stderr
Normal file
23
tests/ui/feature-gates/feature-gate-postfix_match.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error[E0658]: postfix match is experimental
|
||||
--> $DIR/feature-gate-postfix_match.rs:6:9
|
||||
|
|
||||
LL | val.match {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information
|
||||
= help: add `#![feature(postfix_match)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: postfix match is experimental
|
||||
--> $DIR/feature-gate-postfix_match.rs:13:9
|
||||
|
|
||||
LL | val.match {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #121618 <https://github.com/rust-lang/rust/issues/121618> for more information
|
||||
= help: add `#![feature(postfix_match)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,30 @@
|
||||
// test for ICE #112823
|
||||
// Unexpected parameter Type(Repr) when substituting in region
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
trait Stream {}
|
||||
|
||||
trait X {
|
||||
type LineStream<'a, Repr>
|
||||
where
|
||||
Self: 'a;
|
||||
type LineStreamFut<'a, Repr>
|
||||
where
|
||||
Self: 'a;
|
||||
}
|
||||
|
||||
struct Y;
|
||||
|
||||
impl X for Y {
|
||||
type LineStream<'c, 'd> = impl Stream;
|
||||
//~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
|
||||
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
//~^ ERROR `()` is not a future
|
||||
//~^^ method `line_stream` is not a member of trait `X`
|
||||
}
|
||||
|
||||
pub fn main() {}
|
@ -0,0 +1,31 @@
|
||||
error[E0407]: method `line_stream` is not a member of trait `X`
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:5
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
|
||||
|
||||
error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:22:21
|
||||
|
|
||||
LL | type LineStream<'a, Repr>
|
||||
| -- ----
|
||||
| |
|
||||
| expected 1 type parameter
|
||||
...
|
||||
LL | type LineStream<'c, 'd> = impl Stream;
|
||||
| ^^ ^^
|
||||
| |
|
||||
| found 0 type parameters
|
||||
|
||||
error[E0277]: `()` is not a future
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:43
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `()`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0049, E0277, E0407.
|
||||
For more information about an error, try `rustc --explain E0049`.
|
16
tests/ui/match/postfix-match/pf-match-chain.rs
Normal file
16
tests/ui/match/postfix-match/pf-match-chain.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ run-pass
|
||||
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
1.match {
|
||||
2 => Some(0),
|
||||
_ => None,
|
||||
}.match {
|
||||
None => Ok(true),
|
||||
Some(_) => Err("nope")
|
||||
}.match {
|
||||
Ok(_) => (),
|
||||
Err(_) => panic!()
|
||||
}
|
||||
}
|
7
tests/ui/match/postfix-match/pf-match-exhaustiveness.rs
Normal file
7
tests/ui/match/postfix-match/pf-match-exhaustiveness.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
Some(1).match { //~ non-exhaustive patterns
|
||||
None => {},
|
||||
}
|
||||
}
|
21
tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr
Normal file
21
tests/ui/match/postfix-match/pf-match-exhaustiveness.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
|
||||
--> $DIR/pf-match-exhaustiveness.rs:4:5
|
||||
|
|
||||
LL | Some(1).match {
|
||||
| ^^^^^^^ pattern `Some(_)` not covered
|
||||
|
|
||||
note: `Option<i32>` defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
||||
|
|
||||
LL ~ None => {},
|
||||
LL ~ Some(_) => todo!(),
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
15
tests/ui/match/postfix-match/pf-match-types.rs
Normal file
15
tests/ui/match/postfix-match/pf-match-types.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![feature(postfix_match)]
|
||||
|
||||
fn main() {
|
||||
Some(10).match {
|
||||
//~^ NOTE `match` arms have incompatible types
|
||||
Some(5) => false,
|
||||
//~^ NOTE this is found to be of type `bool`
|
||||
Some(2) => true,
|
||||
//~^ NOTE this is found to be of type `bool`
|
||||
None => (),
|
||||
//~^ ERROR `match` arms have incompatible types
|
||||
//~| NOTE expected `bool`, found `()`
|
||||
_ => true
|
||||
}
|
||||
}
|
21
tests/ui/match/postfix-match/pf-match-types.stderr
Normal file
21
tests/ui/match/postfix-match/pf-match-types.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/pf-match-types.rs:10:20
|
||||
|
|
||||
LL | / Some(10).match {
|
||||
LL | |
|
||||
LL | | Some(5) => false,
|
||||
| | ----- this is found to be of type `bool`
|
||||
LL | |
|
||||
LL | | Some(2) => true,
|
||||
| | ---- this is found to be of type `bool`
|
||||
LL | |
|
||||
LL | | None => (),
|
||||
| | ^^ expected `bool`, found `()`
|
||||
... |
|
||||
LL | | _ => true
|
||||
LL | | }
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
62
tests/ui/match/postfix-match/postfix-match.rs
Normal file
62
tests/ui/match/postfix-match/postfix-match.rs
Normal file
@ -0,0 +1,62 @@
|
||||
//@ run-pass
|
||||
|
||||
#![feature(postfix_match)]
|
||||
|
||||
struct Bar {
|
||||
foo: u8,
|
||||
baz: u8,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let thing = Some("thing");
|
||||
|
||||
thing.match {
|
||||
Some("nothing") => {},
|
||||
Some(text) if text.eq_ignore_ascii_case("tapir") => {},
|
||||
Some("true") | Some("false") => {},
|
||||
Some("thing") => {},
|
||||
Some(_) => {},
|
||||
None => {}
|
||||
};
|
||||
|
||||
let num = 2u8;
|
||||
|
||||
num.match {
|
||||
0 => {},
|
||||
1..=5 => {},
|
||||
_ => {},
|
||||
};
|
||||
|
||||
let slic = &[1, 2, 3, 4][..];
|
||||
|
||||
slic.match {
|
||||
[1] => {},
|
||||
[2, _tail @ ..] => {},
|
||||
[1, _] => {},
|
||||
_ => {},
|
||||
};
|
||||
|
||||
slic[0].match {
|
||||
1 => 0,
|
||||
i => i,
|
||||
};
|
||||
|
||||
let out = (1, 2).match {
|
||||
(1, 3) => 0,
|
||||
(_, 1) => 0,
|
||||
(1, i) => i,
|
||||
_ => 3,
|
||||
};
|
||||
assert!(out == 2);
|
||||
|
||||
let strct = Bar {
|
||||
foo: 3,
|
||||
baz: 4
|
||||
};
|
||||
|
||||
strct.match {
|
||||
Bar { foo: 1, .. } => {},
|
||||
Bar { baz: 2, .. } => {},
|
||||
_ => (),
|
||||
};
|
||||
}
|
@ -53,17 +53,16 @@ LL | fn case2() {
|
||||
error[E0597]: `a` does not live long enough
|
||||
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
|
||||
|
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | let cell = Cell::new(&a);
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | let a = 0;
|
||||
| - binding `a` declared here
|
||||
LL | let cell = Cell::new(&a);
|
||||
| ----------^^-
|
||||
| | |
|
||||
| | borrowed value does not live long enough
|
||||
| argument requires that `a` is borrowed for `'static`
|
||||
...
|
||||
LL | / foo(cell, |cell_a, cell_x| {
|
||||
LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
|
||||
LL | | })
|
||||
| |______- argument requires that `a` is borrowed for `'static`
|
||||
LL | }
|
||||
| - `a` dropped here while still borrowed
|
||||
LL | }
|
||||
| - `a` dropped here while still borrowed
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,16 +1,17 @@
|
||||
error[E0597]: `c` does not live long enough
|
||||
--> $DIR/adt-nullary-enums.rs:33:41
|
||||
|
|
||||
LL | let c = 66;
|
||||
| - binding `c` declared here
|
||||
LL | / combine(
|
||||
LL | | SomeEnum::SomeVariant(Cell::new(&c)),
|
||||
| | ^^ borrowed value does not live long enough
|
||||
LL | | SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
|
||||
LL | | );
|
||||
| |_____- argument requires that `c` is borrowed for `'static`
|
||||
LL | }
|
||||
| - `c` dropped here while still borrowed
|
||||
LL | let c = 66;
|
||||
| - binding `c` declared here
|
||||
LL | combine(
|
||||
LL | SomeEnum::SomeVariant(Cell::new(&c)),
|
||||
| ----------^^-
|
||||
| | |
|
||||
| | borrowed value does not live long enough
|
||||
| argument requires that `c` is borrowed for `'static`
|
||||
...
|
||||
LL | }
|
||||
| - `c` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `c` does not live long enough
|
||||
--> $DIR/adt-nullary-enums.rs:41:41
|
||||
|
@ -0,0 +1,52 @@
|
||||
// test for #110696
|
||||
// failed to resolve instance for <Scope<()> as MyIndex<()>>::my_index
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
||||
trait MyIndex<T> {
|
||||
type O;
|
||||
fn my_index(self) -> Self::O;
|
||||
}
|
||||
trait MyFrom<T>: Sized {
|
||||
type Error;
|
||||
fn my_from(value: T) -> Result<Self, Self::Error>;
|
||||
}
|
||||
|
||||
|
||||
trait F {}
|
||||
impl F for () {}
|
||||
type DummyT<T> = impl F;
|
||||
fn _dummy_t<T>() -> DummyT<T> {}
|
||||
|
||||
struct Phantom1<T>(PhantomData<T>);
|
||||
struct Phantom2<T>(PhantomData<T>);
|
||||
struct Scope<T>(Phantom2<DummyT<T>>);
|
||||
|
||||
impl<T> Scope<T> {
|
||||
fn new() -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
|
||||
type Error = ();
|
||||
fn my_from(_: Phantom2<T>) -> Result<Self, Self::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl
|
||||
type O = T;
|
||||
fn my_index(self) -> Self::O {
|
||||
MyFrom::my_from(self.0).ok().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _pos: Phantom1<DummyT<()>> = Scope::new().my_index();
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/ice-failed-to-resolve-instance-for-110696.rs:42:6
|
||||
|
|
||||
LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0207`.
|
@ -0,0 +1,16 @@
|
||||
// test for ICE #121472 index out of bounds un_derefer.rs
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait T {}
|
||||
|
||||
type Alias<'a> = impl T;
|
||||
|
||||
struct S;
|
||||
impl<'a> T for &'a S {}
|
||||
|
||||
fn with_positive(fun: impl Fn(Alias<'_>)) {}
|
||||
|
||||
fn main() {
|
||||
with_positive(|&n| ());
|
||||
//~^ ERROR mismatched types
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/underef-index-out-of-bounds-121472.rs:14:20
|
||||
|
|
||||
LL | type Alias<'a> = impl T;
|
||||
| ------ the expected opaque type
|
||||
...
|
||||
LL | with_positive(|&n| ());
|
||||
| ^^
|
||||
| |
|
||||
| expected opaque type, found `&_`
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected opaque type `Alias<'_>`
|
||||
found reference `&_`
|
||||
help: consider removing `&` from the pattern
|
||||
|
|
||||
LL - with_positive(|&n| ());
|
||||
LL + with_positive(|n| ());
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
12
tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
Normal file
12
tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs
Normal file
@ -0,0 +1,12 @@
|
||||
trait Trait<const N: Trait = bar> {
|
||||
//~^ ERROR cannot find value `bar` in this scope
|
||||
//~| ERROR cycle detected when computing type of `Trait::N`
|
||||
//~| ERROR cycle detected when computing type of `Trait::N`
|
||||
//~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
|
||||
//~| WARN trait objects without an explicit `dyn` are deprecated
|
||||
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
||||
fn fnc(&self) {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
60
tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
Normal file
60
tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr
Normal file
@ -0,0 +1,60 @@
|
||||
error[E0425]: cannot find value `bar` in this scope
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:30
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^ not found in this scope
|
||||
|
||||
warning: trait objects without an explicit `dyn` are deprecated
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^
|
||||
|
|
||||
= 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: `#[warn(bare_trait_objects)]` on by default
|
||||
help: if this is an object-safe trait, use `dyn`
|
||||
|
|
||||
LL | trait Trait<const N: dyn Trait = bar> {
|
||||
| +++
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Trait::N`
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: ...which immediately requires computing type of `Trait::N` again
|
||||
note: cycle used when computing explicit predicates of trait `Trait`
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Trait::N`
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: ...which immediately requires computing type of `Trait::N` again
|
||||
note: cycle used when computing explicit predicates of trait `Trait`
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22
|
||||
|
|
||||
LL | trait Trait<const N: Trait = bar> {
|
||||
| ^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0391, E0425.
|
||||
For more information about an error, try `rustc --explain E0391`.
|
Loading…
Reference in New Issue
Block a user