mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 22:16:53 +00:00
Auto merge of #125415 - fmease:rollup-n2bg7q5, r=fmease
Rollup of 5 pull requests Successful merges: - #124896 (miri: rename intrinsic_fallback_checks_ub to intrinsic_fallback_is_spec) - #125015 (Pattern types: Prohibit generic args on const params) - #125049 (Disallow cast with trailing braced macro in let-else) - #125259 (An async closure may implement `FnMut`/`Fn` if it has no self-borrows) - #125296 (Fix `unexpected_cfgs` lint on std) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
93e7cb835a
@ -81,8 +81,17 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum TrailingBrace<'a> {
|
||||
/// Trailing brace in a macro call, like the one in `x as *const brace! {}`.
|
||||
/// We will suggest changing the macro call to a different delimiter.
|
||||
MacCall(&'a ast::MacCall),
|
||||
/// Trailing brace in any other expression, such as `a + B {}`. We will
|
||||
/// suggest wrapping the innermost expression in parentheses: `a + (B {})`.
|
||||
Expr(&'a ast::Expr),
|
||||
}
|
||||
|
||||
/// If an expression ends with `}`, returns the innermost expression ending in the `}`
|
||||
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||
pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> {
|
||||
loop {
|
||||
match &expr.kind {
|
||||
AddrOf(_, _, e)
|
||||
@ -111,10 +120,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||
| Struct(..)
|
||||
| TryBlock(..)
|
||||
| While(..)
|
||||
| ConstBlock(_) => break Some(expr),
|
||||
| ConstBlock(_) => break Some(TrailingBrace::Expr(expr)),
|
||||
|
||||
Cast(_, ty) => {
|
||||
break type_trailing_braced_mac_call(ty).map(TrailingBrace::MacCall);
|
||||
}
|
||||
|
||||
MacCall(mac) => {
|
||||
break (mac.args.delim == Delimiter::Brace).then_some(expr);
|
||||
break (mac.args.delim == Delimiter::Brace).then_some(TrailingBrace::MacCall(mac));
|
||||
}
|
||||
|
||||
InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => {
|
||||
@ -131,7 +144,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||
| MethodCall(_)
|
||||
| Tup(_)
|
||||
| Lit(_)
|
||||
| Cast(_, _)
|
||||
| Type(_, _)
|
||||
| Await(_, _)
|
||||
| Field(_, _)
|
||||
@ -148,3 +160,78 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If the type's last token is `}`, it must be due to a braced macro call, such
|
||||
/// as in `*const brace! { ... }`. Returns that trailing macro call.
|
||||
fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
|
||||
loop {
|
||||
match &ty.kind {
|
||||
ast::TyKind::MacCall(mac) => {
|
||||
break (mac.args.delim == Delimiter::Brace).then_some(mac);
|
||||
}
|
||||
|
||||
ast::TyKind::Ptr(mut_ty) | ast::TyKind::Ref(_, mut_ty) => {
|
||||
ty = &mut_ty.ty;
|
||||
}
|
||||
|
||||
ast::TyKind::BareFn(fn_ty) => match &fn_ty.decl.output {
|
||||
ast::FnRetTy::Default(_) => break None,
|
||||
ast::FnRetTy::Ty(ret) => ty = ret,
|
||||
},
|
||||
|
||||
ast::TyKind::Path(_, path) => match path_return_type(path) {
|
||||
Some(trailing_ty) => ty = trailing_ty,
|
||||
None => break None,
|
||||
},
|
||||
|
||||
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds, _) => {
|
||||
match bounds.last() {
|
||||
Some(ast::GenericBound::Trait(bound, _)) => {
|
||||
match path_return_type(&bound.trait_ref.path) {
|
||||
Some(trailing_ty) => ty = trailing_ty,
|
||||
None => break None,
|
||||
}
|
||||
}
|
||||
Some(ast::GenericBound::Outlives(_)) | None => break None,
|
||||
}
|
||||
}
|
||||
|
||||
ast::TyKind::Slice(..)
|
||||
| ast::TyKind::Array(..)
|
||||
| ast::TyKind::Never
|
||||
| ast::TyKind::Tup(..)
|
||||
| ast::TyKind::Paren(..)
|
||||
| ast::TyKind::Typeof(..)
|
||||
| ast::TyKind::Infer
|
||||
| ast::TyKind::ImplicitSelf
|
||||
| ast::TyKind::CVarArgs
|
||||
| ast::TyKind::Pat(..)
|
||||
| ast::TyKind::Dummy
|
||||
| ast::TyKind::Err(..) => break None,
|
||||
|
||||
// These end in brace, but cannot occur in a let-else statement.
|
||||
// They are only parsed as fields of a data structure. For the
|
||||
// purpose of denying trailing braces in the expression of a
|
||||
// let-else, we can disregard these.
|
||||
ast::TyKind::AnonStruct(..) | ast::TyKind::AnonUnion(..) => break None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the trailing return type in the given path, if it has one.
|
||||
///
|
||||
/// ```ignore (illustrative)
|
||||
/// ::std::ops::FnOnce(&str) -> fn() -> *const c_void
|
||||
/// ^^^^^^^^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
|
||||
let last_segment = path.segments.last()?;
|
||||
let args = last_segment.args.as_ref()?;
|
||||
match &**args {
|
||||
ast::GenericArgs::Parenthesized(args) => match &args.output {
|
||||
ast::FnRetTy::Default(_) => None,
|
||||
ast::FnRetTy::Ty(ret) => Some(ret),
|
||||
},
|
||||
ast::GenericArgs::AngleBracketed(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -371,9 +371,9 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
|
||||
.suggestion = cast the value to `{$cast_ty}`
|
||||
.help = cast the value to `{$cast_ty}`
|
||||
|
||||
hir_analysis_pattern_type_non_const_range = "range patterns must have constant range start and end"
|
||||
hir_analysis_pattern_type_wild_pat = "wildcard patterns are not permitted for pattern types"
|
||||
.label = "this type is the same as the inner type without a pattern"
|
||||
hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end
|
||||
hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types
|
||||
.label = this type is the same as the inner type without a pattern
|
||||
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
|
||||
.label = not allowed in type signatures
|
||||
|
||||
|
@ -1382,7 +1382,7 @@ pub enum GenericsArgsErrExtend<'tcx> {
|
||||
span: Span,
|
||||
},
|
||||
SelfTyParam(Span),
|
||||
TyParam(DefId),
|
||||
Param(DefId),
|
||||
DefVariant,
|
||||
None,
|
||||
}
|
||||
@ -1498,11 +1498,11 @@ fn generics_args_err_extend<'a>(
|
||||
GenericsArgsErrExtend::DefVariant => {
|
||||
err.note("enum variants can't have type parameters");
|
||||
}
|
||||
GenericsArgsErrExtend::TyParam(def_id) => {
|
||||
if let Some(span) = tcx.def_ident_span(def_id) {
|
||||
let name = tcx.item_name(def_id);
|
||||
err.span_note(span, format!("type parameter `{name}` defined here"));
|
||||
}
|
||||
GenericsArgsErrExtend::Param(def_id) => {
|
||||
let span = tcx.def_ident_span(def_id).unwrap();
|
||||
let kind = tcx.def_descr(def_id);
|
||||
let name = tcx.item_name(def_id);
|
||||
err.span_note(span, format!("{kind} `{name}` defined here"));
|
||||
}
|
||||
GenericsArgsErrExtend::SelfTyParam(span) => {
|
||||
err.span_suggestion_verbose(
|
||||
|
@ -1758,7 +1758,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.iter(),
|
||||
GenericsArgsErrExtend::TyParam(def_id),
|
||||
GenericsArgsErrExtend::Param(def_id),
|
||||
);
|
||||
self.lower_ty_param(hir_id)
|
||||
}
|
||||
@ -2191,10 +2191,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
_,
|
||||
&hir::Path {
|
||||
res: Res::Def(DefKind::ConstParam, def_id), ..
|
||||
path @ &hir::Path {
|
||||
res: Res::Def(DefKind::ConstParam, def_id),
|
||||
..
|
||||
},
|
||||
)) => {
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.iter(),
|
||||
GenericsArgsErrExtend::Param(def_id),
|
||||
);
|
||||
let ty = tcx
|
||||
.type_of(def_id)
|
||||
.no_bound_vars()
|
||||
|
@ -401,6 +401,45 @@ impl<'tcx> CoroutineClosureArgs<'tcx> {
|
||||
pub fn coroutine_witness_ty(self) -> Ty<'tcx> {
|
||||
self.split().coroutine_witness_ty
|
||||
}
|
||||
|
||||
pub fn has_self_borrows(&self) -> bool {
|
||||
match self.coroutine_captures_by_ref_ty().kind() {
|
||||
ty::FnPtr(sig) => sig
|
||||
.skip_binder()
|
||||
.visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST })
|
||||
.is_break(),
|
||||
ty::Error(_) => true,
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will
|
||||
/// detect only regions bound *at* the debruijn index.
|
||||
struct HasRegionsBoundAt {
|
||||
binder: ty::DebruijnIndex,
|
||||
}
|
||||
// FIXME: Could be optimized to not walk into components with no escaping bound vars.
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt {
|
||||
type Result = ControlFlow<()>;
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
t: &ty::Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
self.binder.shift_in(1);
|
||||
t.super_visit_with(self)?;
|
||||
self.binder.shift_out(1);
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
||||
if let ty::ReBound(binder, _) = *r
|
||||
&& self.binder == binder
|
||||
{
|
||||
ControlFlow::Break(())
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
||||
|
@ -15,7 +15,7 @@ use ast::Label;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, TokenKind};
|
||||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::classify::{self, TrailingBrace};
|
||||
use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
|
||||
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt};
|
||||
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
|
||||
@ -407,18 +407,24 @@ impl<'a> Parser<'a> {
|
||||
|
||||
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
|
||||
if let Some(trailing) = classify::expr_trailing_brace(init) {
|
||||
let sugg = match &trailing.kind {
|
||||
ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs {
|
||||
left: mac.args.dspan.open,
|
||||
right: mac.args.dspan.close,
|
||||
},
|
||||
_ => errors::WrapInParentheses::Expression {
|
||||
left: trailing.span.shrink_to_lo(),
|
||||
right: trailing.span.shrink_to_hi(),
|
||||
},
|
||||
let (span, sugg) = match trailing {
|
||||
TrailingBrace::MacCall(mac) => (
|
||||
mac.span(),
|
||||
errors::WrapInParentheses::MacroArgs {
|
||||
left: mac.args.dspan.open,
|
||||
right: mac.args.dspan.close,
|
||||
},
|
||||
),
|
||||
TrailingBrace::Expr(expr) => (
|
||||
expr.span,
|
||||
errors::WrapInParentheses::Expression {
|
||||
left: expr.span.shrink_to_lo(),
|
||||
right: expr.span.shrink_to_hi(),
|
||||
},
|
||||
),
|
||||
};
|
||||
self.dcx().emit_err(errors::InvalidCurlyInLetElse {
|
||||
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
|
||||
span: span.with_lo(span.hi() - BytePos(1)),
|
||||
sugg,
|
||||
});
|
||||
}
|
||||
|
@ -300,14 +300,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// If `Fn`/`FnMut`, we only implement this goal if we
|
||||
// have no captures.
|
||||
let no_borrows = match args.tupled_upvars_ty().kind() {
|
||||
ty::Tuple(tys) => tys.is_empty(),
|
||||
ty::Error(_) => false,
|
||||
_ => bug!("tuple_fields called on non-tuple"),
|
||||
};
|
||||
if closure_kind != ty::ClosureKind::FnOnce && !no_borrows {
|
||||
// A coroutine-closure implements `FnOnce` *always*, since it may
|
||||
// always be called once. It additionally implements `Fn`/`FnMut`
|
||||
// only if it has no upvars referencing the closure-env lifetime,
|
||||
// and if the closure kind permits it.
|
||||
if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
|
@ -418,20 +418,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// Ambiguity if upvars haven't been constrained yet
|
||||
&& !args.tupled_upvars_ty().is_ty_var()
|
||||
{
|
||||
let no_borrows = match args.tupled_upvars_ty().kind() {
|
||||
ty::Tuple(tys) => tys.is_empty(),
|
||||
ty::Error(_) => false,
|
||||
_ => bug!("tuple_fields called on non-tuple"),
|
||||
};
|
||||
// A coroutine-closure implements `FnOnce` *always*, since it may
|
||||
// always be called once. It additionally implements `Fn`/`FnMut`
|
||||
// only if it has no upvars (therefore no borrows from the closure
|
||||
// that would need to be represented with a lifetime) and if the
|
||||
// closure kind permits it.
|
||||
// FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut`
|
||||
// if it takes all of its upvars by copy, and none by ref. This would
|
||||
// require us to record a bit more information during upvar analysis.
|
||||
if no_borrows && closure_kind.extends(kind) {
|
||||
// only if it has no upvars referencing the closure-env lifetime,
|
||||
// and if the closure kind permits it.
|
||||
if closure_kind.extends(kind) && !args.has_self_borrows() {
|
||||
candidates.vec.push(ClosureCandidate { is_const });
|
||||
} else if kind == ty::ClosureKind::FnOnce {
|
||||
candidates.vec.push(ClosureCandidate { is_const });
|
||||
|
@ -40,3 +40,15 @@ compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
|
||||
panic_immediate_abort = ["core/panic_immediate_abort"]
|
||||
# Choose algorithms that are optimized for binary size instead of runtime performance
|
||||
optimize_for_size = ["core/optimize_for_size"]
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
|
||||
# for rust-lang/rust. But for users of `-Zbuild-std` it does.
|
||||
# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
|
||||
check-cfg = [
|
||||
'cfg(bootstrap)',
|
||||
'cfg(no_global_oom_handling)',
|
||||
'cfg(no_rc)',
|
||||
'cfg(no_sync)',
|
||||
]
|
||||
|
@ -36,3 +36,16 @@ optimize_for_size = []
|
||||
# Make `RefCell` store additional debugging information, which is printed out when
|
||||
# a borrow error occurs
|
||||
debug_refcell = []
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
|
||||
# for rust-lang/rust. But for users of `-Zbuild-std` it does.
|
||||
# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
|
||||
check-cfg = [
|
||||
'cfg(bootstrap)',
|
||||
'cfg(no_fp_fmt_parse)',
|
||||
'cfg(stdarch_intel_sde)',
|
||||
# This matches `EXTRA_CHECK_CFGS` in `src/bootstrap/src/lib.rs`.
|
||||
'cfg(feature, values(any()))',
|
||||
]
|
||||
|
@ -987,7 +987,7 @@ pub const unsafe fn assume(b: bool) {
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
|
||||
pub const fn likely(b: bool) -> bool {
|
||||
b
|
||||
}
|
||||
@ -1007,7 +1007,7 @@ pub const fn likely(b: bool) -> bool {
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
|
||||
pub const fn unlikely(b: bool) -> bool {
|
||||
b
|
||||
}
|
||||
@ -2483,7 +2483,7 @@ extern "rust-intrinsic" {
|
||||
#[rustc_nounwind]
|
||||
#[rustc_do_not_const_check]
|
||||
#[inline]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
|
||||
pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
|
||||
(ptr == other) as u8
|
||||
}
|
||||
@ -2748,7 +2748,7 @@ pub const fn ub_checks() -> bool {
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
|
||||
pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 {
|
||||
// const eval overrides this function, but runtime code for now just returns null pointers.
|
||||
// See <https://github.com/rust-lang/rust/issues/93935>.
|
||||
@ -2769,7 +2769,7 @@ pub const unsafe fn const_allocate(_size: usize, _align: usize) -> *mut u8 {
|
||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_checks_ub)]
|
||||
#[cfg_attr(not(bootstrap), miri::intrinsic_fallback_is_spec)]
|
||||
pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
|
||||
// Runtime NOP
|
||||
}
|
||||
|
@ -97,3 +97,13 @@ heap_size = 0x8000000
|
||||
name = "stdbenches"
|
||||
path = "benches/lib.rs"
|
||||
test = true
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
check-cfg = [
|
||||
'cfg(bootstrap)',
|
||||
'cfg(backtrace_in_libstd)',
|
||||
'cfg(netbsd10)',
|
||||
'cfg(target_arch, values("xtensa"))',
|
||||
'cfg(feature, values("std", "as_crate"))',
|
||||
]
|
||||
|
@ -84,6 +84,9 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
|
||||
(Some(Mode::ToolRustc), "rust_analyzer", None),
|
||||
(Some(Mode::ToolStd), "rust_analyzer", None),
|
||||
(Some(Mode::Codegen), "parallel_compiler", None),
|
||||
// NOTE: consider updating `check-cfg` entries in `std/Cargo.toml` too.
|
||||
// cfg(bootstrap) remove these once the bootstrap compiler supports
|
||||
// `lints.rust.unexpected_cfgs.check-cfg`
|
||||
(Some(Mode::Std), "stdarch_intel_sde", None),
|
||||
(Some(Mode::Std), "no_fp_fmt_parse", None),
|
||||
(Some(Mode::Std), "no_global_oom_handling", None),
|
||||
|
@ -43,18 +43,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
|
||||
throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`")
|
||||
}
|
||||
let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub");
|
||||
let intrinsic_fallback_is_spec = Symbol::intern("intrinsic_fallback_is_spec");
|
||||
if this
|
||||
.tcx
|
||||
.get_attrs_by_path(
|
||||
instance.def_id(),
|
||||
&[sym::miri, intrinsic_fallback_checks_ub],
|
||||
&[sym::miri, intrinsic_fallback_is_spec],
|
||||
)
|
||||
.next()
|
||||
.is_none()
|
||||
{
|
||||
throw_unsup_format!(
|
||||
"miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that"
|
||||
"Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that"
|
||||
);
|
||||
}
|
||||
Ok(Some(ty::Instance {
|
||||
|
@ -1,14 +0,0 @@
|
||||
error: unsupported operation: miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that
|
||||
--> $DIR/intrinsic_fallback_checks_ub.rs:LL:CC
|
||||
|
|
||||
LL | ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ miri can only use intrinsic fallback bodies that check UB. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that
|
||||
|
|
||||
= help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/intrinsic_fallback_checks_ub.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -10,5 +10,5 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
|
||||
|
||||
fn main() {
|
||||
ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null());
|
||||
//~^ ERROR: can only use intrinsic fallback bodies that check UB.
|
||||
//~^ ERROR: can only use intrinsic fallback bodies that exactly reflect the specification
|
||||
}
|
14
src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr
Normal file
14
src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: unsupported operation: Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that
|
||||
--> $DIR/intrinsic_fallback_is_spec.rs:LL:CC
|
||||
|
|
||||
LL | ptr_guaranteed_cmp::<()>(std::ptr::null(), std::ptr::null());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri can only use intrinsic fallback bodies that exactly reflect the specification: they fully check for UB and are as non-deterministic as possible. After verifying that `ptr_guaranteed_cmp` does so, add the `#[miri::intrinsic_fallback_is_spec]` attribute to it; also ping @rust-lang/miri when you do that
|
||||
|
|
||||
= help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at $DIR/intrinsic_fallback_is_spec.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
23
tests/ui/async-await/async-closures/implements-fnmut.rs
Normal file
23
tests/ui/async-await/async-closures/implements-fnmut.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//@ check-pass
|
||||
//@ edition: 2021
|
||||
|
||||
// Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!)
|
||||
// if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env,
|
||||
// since it's fine to reborrow it with its original lifetime. See the doc comment on
|
||||
// `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we
|
||||
// must borrow from the closure env.
|
||||
|
||||
#![feature(async_closure)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
fn needs_fn_mut<T>(x: impl FnMut() -> T) {}
|
||||
|
||||
fn hello(x: &Ty) {
|
||||
needs_fn_mut(async || { x.hello(); });
|
||||
}
|
||||
|
||||
struct Ty;
|
||||
impl Ty {
|
||||
fn hello(&self) {}
|
||||
}
|
@ -3,8 +3,7 @@
|
||||
#![feature(explicit_tail_calls)]
|
||||
|
||||
fn a() {
|
||||
let foo = {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = {
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -22,8 +21,7 @@ fn b() {
|
||||
}
|
||||
|
||||
fn c() {
|
||||
let foo = if true {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = if true {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
@ -43,8 +41,7 @@ fn d() {
|
||||
}
|
||||
|
||||
fn e() {
|
||||
let foo = match true {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = match true {
|
||||
true => 1,
|
||||
false => 0
|
||||
} else {
|
||||
@ -53,10 +50,12 @@ fn e() {
|
||||
};
|
||||
}
|
||||
|
||||
struct X {a: i32}
|
||||
fn f() {
|
||||
let foo = X {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
struct X {
|
||||
a: i32,
|
||||
}
|
||||
|
||||
let X { a: 0 } = X {
|
||||
a: 1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -74,8 +73,7 @@ fn g() {
|
||||
}
|
||||
|
||||
fn h() {
|
||||
let foo = const {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = const {
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -84,8 +82,7 @@ fn h() {
|
||||
}
|
||||
|
||||
fn i() {
|
||||
let foo = &{
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = &{
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -94,8 +91,8 @@ fn i() {
|
||||
}
|
||||
|
||||
fn j() {
|
||||
let bar = 0;
|
||||
let foo = bar = { //~ ERROR: cannot assign twice
|
||||
let mut bar = 0;
|
||||
let foo = bar = {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
1
|
||||
} else {
|
||||
@ -105,8 +102,7 @@ fn j() {
|
||||
}
|
||||
|
||||
fn k() {
|
||||
let foo = 1 + {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = 1 + {
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -115,8 +111,8 @@ fn k() {
|
||||
}
|
||||
|
||||
fn l() {
|
||||
let foo = 1..{
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
const RANGE: std::ops::Range<u8> = 0..0;
|
||||
let RANGE = 1..{
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -125,8 +121,7 @@ fn l() {
|
||||
}
|
||||
|
||||
fn m() {
|
||||
let foo = return {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = return {
|
||||
()
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -135,8 +130,7 @@ fn m() {
|
||||
}
|
||||
|
||||
fn n() {
|
||||
let foo = -{
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = -{
|
||||
1
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -145,8 +139,7 @@ fn n() {
|
||||
}
|
||||
|
||||
fn o() -> Result<(), ()> {
|
||||
let foo = do yeet {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = do yeet {
|
||||
()
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -155,8 +148,7 @@ fn o() -> Result<(), ()> {
|
||||
}
|
||||
|
||||
fn p() {
|
||||
let foo = become {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
let 0 = become {
|
||||
()
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
@ -185,22 +177,37 @@ fn r() {
|
||||
|
||||
fn s() {
|
||||
macro_rules! a {
|
||||
() => { {} }
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
//~| WARN irrefutable `let...else` pattern
|
||||
() => {
|
||||
{ 1 }
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! b {
|
||||
(1) => {
|
||||
let x = a!() else { return; };
|
||||
let 0 = a!() else { return; };
|
||||
};
|
||||
(2) => {
|
||||
let x = a! {} else { return; };
|
||||
let 0 = a! {} else { return; };
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
};
|
||||
}
|
||||
|
||||
b!(1); b!(2);
|
||||
b!(1);
|
||||
b!(2);
|
||||
}
|
||||
|
||||
fn t() {
|
||||
macro_rules! primitive {
|
||||
(8) => { u8 };
|
||||
}
|
||||
|
||||
let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
|
||||
//~^ WARN irrefutable `let...else` pattern
|
||||
8
|
||||
} else {
|
||||
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,19 +1,18 @@
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:9:5
|
||||
--> $DIR/bad-let-else-statement.rs:8:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = ({
|
||||
LL |
|
||||
LL ~ let 0 = ({
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: `for...else` loops are not supported
|
||||
--> $DIR/bad-let-else-statement.rs:18:7
|
||||
--> $DIR/bad-let-else-statement.rs:17:7
|
||||
|
|
||||
LL | let foo = for i in 1..2 {
|
||||
| --- `else` is attached to this loop
|
||||
@ -28,22 +27,22 @@ LL | | };
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:30:5
|
||||
--> $DIR/bad-let-else-statement.rs:28:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = (if true {
|
||||
LL |
|
||||
...
|
||||
LL ~ let 0 = (if true {
|
||||
LL | 1
|
||||
LL | } else {
|
||||
LL | 0
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: `loop...else` loops are not supported
|
||||
--> $DIR/bad-let-else-statement.rs:39:7
|
||||
--> $DIR/bad-let-else-statement.rs:37:7
|
||||
|
|
||||
LL | let foo = loop {
|
||||
| ---- `else` is attached to this loop
|
||||
@ -58,36 +57,34 @@ LL | | };
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:50:5
|
||||
--> $DIR/bad-let-else-statement.rs:47:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = (match true {
|
||||
LL |
|
||||
LL ~ let 0 = (match true {
|
||||
LL | true => 1,
|
||||
LL | false => 0
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:61:5
|
||||
--> $DIR/bad-let-else-statement.rs:60:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = (X {
|
||||
LL |
|
||||
LL ~ let X { a: 0 } = (X {
|
||||
LL | a: 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: `while...else` loops are not supported
|
||||
--> $DIR/bad-let-else-statement.rs:70:7
|
||||
--> $DIR/bad-let-else-statement.rs:69:7
|
||||
|
|
||||
LL | let foo = while false {
|
||||
| ----- `else` is attached to this loop
|
||||
@ -102,35 +99,33 @@ LL | | };
|
||||
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:80:5
|
||||
--> $DIR/bad-let-else-statement.rs:78:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = (const {
|
||||
LL |
|
||||
LL ~ let 0 = (const {
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:90:5
|
||||
--> $DIR/bad-let-else-statement.rs:87:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = &({
|
||||
LL |
|
||||
LL ~ let 0 = &({
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:101:5
|
||||
--> $DIR/bad-let-else-statement.rs:98:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
@ -144,91 +139,85 @@ LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:111:5
|
||||
--> $DIR/bad-let-else-statement.rs:107:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = 1 + ({
|
||||
LL |
|
||||
LL ~ let 0 = 1 + ({
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:121:5
|
||||
--> $DIR/bad-let-else-statement.rs:117:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = 1..({
|
||||
LL |
|
||||
LL ~ let RANGE = 1..({
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:131:5
|
||||
--> $DIR/bad-let-else-statement.rs:126:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = return ({
|
||||
LL |
|
||||
LL ~ let 0 = return ({
|
||||
LL | ()
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:141:5
|
||||
--> $DIR/bad-let-else-statement.rs:135:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = -({
|
||||
LL |
|
||||
LL ~ let 0 = -({
|
||||
LL | 1
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:151:5
|
||||
--> $DIR/bad-let-else-statement.rs:144:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = do yeet ({
|
||||
LL |
|
||||
LL ~ let 0 = do yeet ({
|
||||
LL | ()
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:161:5
|
||||
--> $DIR/bad-let-else-statement.rs:153:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: wrap the expression in parentheses
|
||||
|
|
||||
LL ~ let foo = become ({
|
||||
LL |
|
||||
LL ~ let 0 = become ({
|
||||
LL | ()
|
||||
LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:171:5
|
||||
--> $DIR/bad-let-else-statement.rs:163:5
|
||||
|
|
||||
LL | } else {
|
||||
| ^
|
||||
@ -242,7 +231,7 @@ LL ~ }) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:181:31
|
||||
--> $DIR/bad-let-else-statement.rs:173:31
|
||||
|
|
||||
LL | let bad = format_args! {""} else { return; };
|
||||
| ^
|
||||
@ -253,24 +242,38 @@ LL | let bad = format_args! ("") else { return; };
|
||||
| ~ ~
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:198:25
|
||||
--> $DIR/bad-let-else-statement.rs:207:5
|
||||
|
|
||||
LL | let x = a! {} else { return; };
|
||||
LL | } else {
|
||||
| ^
|
||||
|
|
||||
help: use parentheses instead of braces for this macro
|
||||
|
|
||||
LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! (
|
||||
LL |
|
||||
LL | 8
|
||||
LL ~ ) else {
|
||||
|
|
||||
|
||||
error: right curly brace `}` before `else` in a `let...else` statement not allowed
|
||||
--> $DIR/bad-let-else-statement.rs:190:25
|
||||
|
|
||||
LL | let 0 = a! {} else { return; };
|
||||
| ^
|
||||
...
|
||||
LL | b!(1); b!(2);
|
||||
| ----- in this macro invocation
|
||||
LL | b!(2);
|
||||
| ----- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: use parentheses instead of braces for this macro
|
||||
|
|
||||
LL | let x = a! () else { return; };
|
||||
LL | let 0 = a! () else { return; };
|
||||
| ~~
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:6:5
|
||||
--> $DIR/bad-let-else-statement.rs:95:5
|
||||
|
|
||||
LL | / let foo = {
|
||||
LL | / let foo = bar = {
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
@ -281,169 +284,7 @@ LL | | } else {
|
||||
= note: `#[warn(irrefutable_let_patterns)]` on by default
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:25:5
|
||||
|
|
||||
LL | / let foo = if true {
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
LL | | 0
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:46:5
|
||||
|
|
||||
LL | / let foo = match true {
|
||||
LL | |
|
||||
LL | | true => 1,
|
||||
LL | | false => 0
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:58:5
|
||||
|
|
||||
LL | / let foo = X {
|
||||
LL | |
|
||||
LL | | a: 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:77:5
|
||||
|
|
||||
LL | / let foo = const {
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:87:5
|
||||
|
|
||||
LL | / let foo = &{
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:98:5
|
||||
|
|
||||
LL | / let foo = bar = {
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
error[E0384]: cannot assign twice to immutable variable `bar`
|
||||
--> $DIR/bad-let-else-statement.rs:98:15
|
||||
|
|
||||
LL | let bar = 0;
|
||||
| ---
|
||||
| |
|
||||
| first assignment to `bar`
|
||||
| help: consider making this binding mutable: `mut bar`
|
||||
LL | let foo = bar = {
|
||||
| _______________^
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^ cannot assign twice to immutable variable
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:108:5
|
||||
|
|
||||
LL | / let foo = 1 + {
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:118:5
|
||||
|
|
||||
LL | / let foo = 1..{
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:128:5
|
||||
|
|
||||
LL | / let foo = return {
|
||||
LL | |
|
||||
LL | | ()
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:138:5
|
||||
|
|
||||
LL | / let foo = -{
|
||||
LL | |
|
||||
LL | | 1
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:148:5
|
||||
|
|
||||
LL | / let foo = do yeet {
|
||||
LL | |
|
||||
LL | | ()
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:158:5
|
||||
|
|
||||
LL | / let foo = become {
|
||||
LL | |
|
||||
LL | | ()
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:168:5
|
||||
--> $DIR/bad-let-else-statement.rs:160:5
|
||||
|
|
||||
LL | / let foo = |x: i32| {
|
||||
LL | |
|
||||
@ -455,7 +296,7 @@ LL | | } else {
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:178:5
|
||||
--> $DIR/bad-let-else-statement.rs:170:5
|
||||
|
|
||||
LL | let ok = format_args!("") else { return; };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -464,7 +305,7 @@ LL | let ok = format_args!("") else { return; };
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:181:5
|
||||
--> $DIR/bad-let-else-statement.rs:173:5
|
||||
|
|
||||
LL | let bad = format_args! {""} else { return; };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -473,45 +314,16 @@ LL | let bad = format_args! {""} else { return; };
|
||||
= help: consider removing the `else` clause
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:188:19
|
||||
--> $DIR/bad-let-else-statement.rs:204:5
|
||||
|
|
||||
LL | () => { {} }
|
||||
| ___________________^
|
||||
LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
... |
|
||||
LL | | (1) => {
|
||||
LL | | let x = a!() else { return; };
|
||||
| |____________^
|
||||
...
|
||||
LL | b!(1); b!(2);
|
||||
| ----- in this macro invocation
|
||||
LL | | 8
|
||||
LL | | } else {
|
||||
| |_____^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
= note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> $DIR/bad-let-else-statement.rs:188:19
|
||||
|
|
||||
LL | () => { {} }
|
||||
| ___________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
... |
|
||||
LL | | (2) => {
|
||||
LL | | let x = a! {} else { return; };
|
||||
| |____________^
|
||||
...
|
||||
LL | b!(1); b!(2);
|
||||
| ----- in this macro invocation
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
= note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
error: aborting due to 20 previous errors; 5 warnings emitted
|
||||
|
||||
error: aborting due to 20 previous errors; 18 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0384`.
|
||||
|
@ -0,0 +1,10 @@
|
||||
#![feature(pattern_types, core_pattern_type)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
type Pat<const START: u32, const END: u32> =
|
||||
std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
|
||||
//~^ ERROR type and const arguments are not allowed on const parameter `START`
|
||||
//~| ERROR type arguments are not allowed on const parameter `END`
|
||||
//~| ERROR associated type bindings are not allowed here
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,38 @@
|
||||
error[E0109]: type and const arguments are not allowed on const parameter `START`
|
||||
--> $DIR/bad_const_generics_args_on_const_param.rs:5:44
|
||||
|
|
||||
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
|
||||
| ----- ^^ ^^^ ^ type and const arguments not allowed
|
||||
| |
|
||||
| not allowed on const parameter `START`
|
||||
|
|
||||
note: const parameter `START` defined here
|
||||
--> $DIR/bad_const_generics_args_on_const_param.rs:4:16
|
||||
|
|
||||
LL | type Pat<const START: u32, const END: u32> =
|
||||
| ^^^^^
|
||||
|
||||
error[E0109]: type arguments are not allowed on const parameter `END`
|
||||
--> $DIR/bad_const_generics_args_on_const_param.rs:5:64
|
||||
|
|
||||
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
|
||||
| --- ^ type argument not allowed
|
||||
| |
|
||||
| not allowed on const parameter `END`
|
||||
|
|
||||
note: const parameter `END` defined here
|
||||
--> $DIR/bad_const_generics_args_on_const_param.rs:4:34
|
||||
|
|
||||
LL | type Pat<const START: u32, const END: u32> =
|
||||
| ^^^
|
||||
|
||||
error[E0229]: associated type bindings are not allowed here
|
||||
--> $DIR/bad_const_generics_args_on_const_param.rs:5:67
|
||||
|
|
||||
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
|
||||
| ^^^^^^^^^^ associated type not allowed here
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0109, E0229.
|
||||
For more information about an error, try `rustc --explain E0109`.
|
@ -14,7 +14,7 @@ LL | type Positive2 = pattern_type!(i32 is 0..=);
|
||||
|
|
||||
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
|
||||
|
||||
error: "wildcard patterns are not permitted for pattern types"
|
||||
error: wildcard patterns are not permitted for pattern types
|
||||
--> $DIR/bad_pat.rs:11:33
|
||||
|
|
||||
LL | type Wild = pattern_type!(() is _);
|
||||
|
Loading…
Reference in New Issue
Block a user