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:
bors 2024-03-22 12:29:42 +00:00
commit 1447f9d38c
73 changed files with 1199 additions and 247 deletions

View File

@ -4236,6 +4236,7 @@ name = "rustc_middle"
version = "0.0.0"
dependencies = [
"bitflags 2.4.2",
"derivative",
"either",
"field-offset",
"gsgdt",

View File

@ -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 {

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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 {

View File

@ -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) => {

View File

@ -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
{

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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 => {}

View File

@ -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");

View File

@ -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(

View File

@ -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.

View File

@ -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",

View File

@ -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 } => {

View File

@ -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

View File

@ -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(

View File

@ -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"

View File

@ -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,

View File

@ -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.

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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>;
}

View File

@ -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

View File

@ -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(),
_ => (),
}

View File

@ -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(_, _, _)

View File

@ -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)

View File

@ -1335,6 +1335,7 @@ symbols! {
poll,
poll_next,
post_dash_lto: "post-lto",
postfix_match,
powerpc_target_feature,
powf128,
powf16,

View File

@ -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);

View File

@ -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

View 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!(),
}
```

View File

@ -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),

View File

@ -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(_, _, _))

View File

@ -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,

View File

@ -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))?,

View File

@ -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),
)),
}
}
}

View 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 {
_ => (),
}
}

View 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 {
_ => (),
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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

View 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 {
_ => (),
}
}

View File

@ -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() {}

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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() {}

View File

@ -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`.

View File

@ -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]);
}

View 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() {}

View File

@ -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`.

View 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"
};
}

View 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`.

View File

@ -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() {}

View File

@ -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`.

View 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!()
}
}

View File

@ -0,0 +1,7 @@
#![feature(postfix_match)]
fn main() {
Some(1).match { //~ non-exhaustive patterns
None => {},
}
}

View 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`.

View 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
}
}

View 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`.

View 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, .. } => {},
_ => (),
};
}

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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`.

View File

@ -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
}

View File

@ -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`.

View 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() {}

View 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`.