diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index f6e9e1a87c4bb..382c903625fbd 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -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> { 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, + } +} diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 3edea0191faf1..cf492a2a3fee3 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -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 diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 168a370bba93e..9c687d3282bda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -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( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 0cd77fe774fb8..4b1c0da6ce11b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -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() diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index fc9a854c85338..40f3db89df56e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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> for HasRegionsBoundAt { + type Result = ControlFlow<()>; + fn visit_binder>>( + &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)] diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7424fbea9b053..be539d15386f9 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -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, }); } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 930ae5af811b4..6f68875e6f63f 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -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); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b9e853a067874..fd7c47ad6fb3d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -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 }); diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 2e7fcb9dbd35f..3960f71681264 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -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)', +] diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 11d33971f2563..daf2612833ddc 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -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()))', +] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 8e468a8ec3dd6..5a2a4c5ae6ebe 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -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(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 . @@ -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 } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5b36867fe2436..4b8ee4c130918 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -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"))', +] diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 698a576effa63..38de5e3800005 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -84,6 +84,9 @@ const EXTRA_CHECK_CFGS: &[(Option, &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), diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 0a7927d062146..9faaeb8d63ff6 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -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 { diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr deleted file mode 100644 index 699dda52096f3..0000000000000 --- a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.stderr +++ /dev/null @@ -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 - diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs similarity index 75% rename from src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs rename to src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs index 93c9d3d7814ca..888c548e49b5b 100644 --- a/src/tools/miri/tests/fail/intrinsic_fallback_checks_ub.rs +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.rs @@ -10,5 +10,5 @@ pub const fn ptr_guaranteed_cmp(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 } diff --git a/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr new file mode 100644 index 0000000000000..db3941a32a56a --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsic_fallback_is_spec.stderr @@ -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 + diff --git a/tests/ui/async-await/async-closures/implements-fnmut.rs b/tests/ui/async-await/async-closures/implements-fnmut.rs new file mode 100644 index 0000000000000..1ed326cd0618b --- /dev/null +++ b/tests/ui/async-await/async-closures/implements-fnmut.rs @@ -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(x: impl FnMut() -> T) {} + +fn hello(x: &Ty) { + needs_fn_mut(async || { x.hello(); }); +} + +struct Ty; +impl Ty { + fn hello(&self) {} +} diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index de41a07568fb1..ff6619cbc9864 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -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 = 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() {} diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 3f7e176b3e31f..0bf6a346dfb17 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -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,98 +242,36 @@ 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 | b!(1); b!(2); - | ----- in this macro invocation +LL | } else { + | ^ | - = 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; }; - | ~~ - -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:6: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 - = 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 { - | |_____^ +LL ~ let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! ( +LL | +LL | 8 +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 { - | |_____^ +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:190:25 | - = 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 0 = a! {} else { return; }; + | ^ +... +LL | b!(2); + | ----- in this macro invocation | -LL | / let foo = &{ -LL | | -LL | | 1 -LL | | } else { - | |_____^ + = 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 | - = note: this pattern will always match, so the `else` clause is useless - = help: consider removing the `else` clause +LL | let 0 = a! () else { return; }; + | ~~ warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:98:5 + --> $DIR/bad-let-else-statement.rs:95:5 | LL | / let foo = bar = { LL | | @@ -354,96 +281,10 @@ 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 + = note: `#[warn(irrefutable_let_patterns)]` on by default 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 - | -LL | () => { {} } - | ___________________^ -LL | | -LL | | -LL | | } -... | -LL | | (1) => { -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) - -warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:188:19 + --> $DIR/bad-let-else-statement.rs:204:5 | -LL | () => { {} } - | ___________________^ -LL | | +LL | / let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { LL | | -LL | | } -... | -LL | | (2) => { -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) -error: aborting due to 20 previous errors; 18 warnings emitted +error: aborting due to 20 previous errors; 5 warnings emitted -For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs new file mode 100644 index 0000000000000..050b7b44b4e0d --- /dev/null +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -0,0 +1,10 @@ +#![feature(pattern_types, core_pattern_type)] +#![allow(internal_features)] + +type Pat = + 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() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr new file mode 100644 index 0000000000000..40effe924da81 --- /dev/null +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -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 = + | ^^^^^ + +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 = + | ^^^ + +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`. diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index 4f0f0bc974276..2abf27100c1de 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -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 _);