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 00356ece58523..873d1e66c252c 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 8caeb85204b75..c33f771e39645 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1757,7 +1757,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) } @@ -2190,10 +2190,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_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6da5adc7a6e9b..7916366ef0898 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -373,8 +373,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(arg_ty) = self.node_ty_opt(args[idx].hir_id) else { return false; }; - let possible_rcvr_ty = expr_finder.uses.iter().find_map(|binding| { + let possible_rcvr_ty = expr_finder.uses.iter().rev().find_map(|binding| { let possible_rcvr_ty = self.node_ty_opt(binding.hir_id)?; + if possible_rcvr_ty.is_ty_var() { + return None; + } // Fudge the receiver, so we can do new inference on it. let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger); let method = self @@ -386,6 +389,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { binding, ) .ok()?; + // Make sure we select the same method that we started with... + if Some(method.def_id) + != self.typeck_results.borrow().type_dependent_def_id(call_expr.hir_id) + { + return None; + } // Unify the method signature with our incompatible arg, to // do inference in the *opposite* direction and to find out // what our ideal rcvr ty would look like. @@ -456,6 +465,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) else { continue; }; + // Make sure we select the same method that we started with... + if Some(method.def_id) + != self.typeck_results.borrow().type_dependent_def_id(parent_expr.hir_id) + { + continue; + } let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger); let ideal_method = self @@ -505,13 +520,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // blame arg, if possible. Don't do this if we're coming from // arg mismatch code, because we'll possibly suggest a mutually // incompatible fix at the original mismatch site. + // HACK(compiler-errors): We don't actually consider the implications + // of our inference guesses in `emit_type_mismatch_suggestions`, so + // only suggest things when we know our type error is precisely due to + // a type mismatch, and not via some projection or something. See #116155. if matches!(source, TypeMismatchSource::Ty(_)) && let Some(ideal_method) = ideal_method - && let ideal_arg_ty = self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) - // HACK(compiler-errors): We don't actually consider the implications - // of our inference guesses in `emit_type_mismatch_suggestions`, so - // only suggest things when we know our type error is precisely due to - // a type mismatch, and not via some projection or something. See #116155. + && Some(ideal_method.def_id) + == self + .typeck_results + .borrow() + .type_dependent_def_id(parent_expr.hir_id) + && let ideal_arg_ty = + self.resolve_vars_if_possible(ideal_method.sig.inputs()[idx + 1]) && !ideal_arg_ty.has_non_region_infer() { self.emit_type_mismatch_suggestions( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 9d16f0d48159e..e29a410e2e543 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -204,6 +204,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fake_reads: Default::default(), }; + let _ = euv::ExprUseVisitor::new( + &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id), + &mut delegate, + ) + .consume_body(body); + + // There are several curious situations with coroutine-closures where + // analysis is too aggressive with borrows when the coroutine-closure is + // marked `move`. Specifically: + // + // 1. If the coroutine-closure was inferred to be `FnOnce` during signature + // inference, then it's still possible that we try to borrow upvars from + // the coroutine-closure because they are not used by the coroutine body + // in a way that forces a move. See the test: + // `async-await/async-closures/force-move-due-to-inferred-kind.rs`. + // + // 2. If the coroutine-closure is forced to be `FnOnce` due to the way it + // uses its upvars, but not *all* upvars would force the closure to `FnOnce`. + // See the test: `async-await/async-closures/force-move-due-to-actually-fnonce.rs`. + // + // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` + // coroutine bodies can't borrow from their parent closure. To fix this, + // we force the inner coroutine to also be `move`. This only matters for + // coroutine-closures that are `move` since otherwise they themselves will + // be borrowing from the outer environment, so there's no self-borrows occuring. + // + // One *important* note is that we do a call to `process_collected_capture_information` + // to eagerly test whether the coroutine would end up `FnOnce`, but we do this + // *before* capturing all the closure args by-value below, since that would always + // cause the analysis to return `FnOnce`. + if let UpvarArgs::Coroutine(..) = args + && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = + self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") + && let parent_hir_id = + self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id)) + && let parent_ty = self.node_ty(parent_hir_id) + && let hir::CaptureBy::Value { move_kw } = + self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause + { + // (1.) Closure signature inference forced this closure to `FnOnce`. + if let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty) { + capture_clause = hir::CaptureBy::Value { move_kw }; + } + // (2.) The way that the closure uses its upvars means it's `FnOnce`. + else if let (_, ty::ClosureKind::FnOnce, _) = self + .process_collected_capture_information( + capture_clause, + &delegate.capture_information, + ) + { + capture_clause = hir::CaptureBy::Value { move_kw }; + } + } + // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode // to `ByRef` for the `async {}` block internal to async fns/closure. This means // that we would *not* be moving all of the parameters into the async block by default. @@ -253,34 +307,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let _ = euv::ExprUseVisitor::new( - &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id), - &mut delegate, - ) - .consume_body(body); - - // If a coroutine is comes from a coroutine-closure that is `move`, but - // the coroutine-closure was inferred to be `FnOnce` during signature - // inference, then it's still possible that we try to borrow upvars from - // the coroutine-closure because they are not used by the coroutine body - // in a way that forces a move. - // - // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` - // coroutine bodies can't borrow from their parent closure. To fix this, - // we force the inner coroutine to also be `move`. This only matters for - // coroutine-closures that are `move` since otherwise they themselves will - // be borrowing from the outer environment, so there's no self-borrows occuring. - if let UpvarArgs::Coroutine(..) = args - && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = - self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") - && let parent_hir_id = - self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id)) - && let parent_ty = self.node_ty(parent_hir_id) - && let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty) - { - capture_clause = self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause; - } - debug!( "For closure={:?}, capture_information={:#?}", closure_def_id, delegate.capture_information @@ -289,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.log_capture_analysis_first_pass(closure_def_id, &delegate.capture_information, span); let (capture_information, closure_kind, origin) = self - .process_collected_capture_information(capture_clause, delegate.capture_information); + .process_collected_capture_information(capture_clause, &delegate.capture_information); self.compute_min_captures(closure_def_id, capture_information, span); @@ -545,13 +571,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn process_collected_capture_information( &self, capture_clause: hir::CaptureBy, - capture_information: InferredCaptureInformation<'tcx>, + capture_information: &InferredCaptureInformation<'tcx>, ) -> (InferredCaptureInformation<'tcx>, ty::ClosureKind, Option<(Span, Place<'tcx>)>) { let mut closure_kind = ty::ClosureKind::LATTICE_BOTTOM; let mut origin: Option<(Span, Place<'tcx>)> = None; let processed = capture_information - .into_iter() + .iter() + .cloned() .map(|(place, mut capture_info)| { // Apply rules for safety before inferring closure kind let (place, capture_kind) = diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 81257f9be8823..7327db97112f1 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -103,7 +103,6 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { let mut layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_verbose_exit(verbose_entry_exit) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2d9d178449e09..b331764aefcd5 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_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index e72fddb9e9a81..6e8bb50500554 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -13,7 +13,6 @@ pub fn init_tracing() { use tracing_subscriber::Layer; let _ = tracing_tree::HierarchicalLayer::default() .with_writer(std::io::stderr) - .with_indent_lines(true) .with_ansi(true) .with_targets(true) .with_indent_amount(2) 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/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index bcd210f789bfe..b39ba4c4ac7ce 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -279,6 +279,7 @@ impl<'tcx> SearchGraph> { }; if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) { + debug!("global cache hit"); return result; } @@ -360,7 +361,7 @@ impl<'tcx> SearchGraph> { for _ in 0..FIXPOINT_STEP_LIMIT { match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) { StepResult::Done(final_entry, result) => return (final_entry, result), - StepResult::HasChanged => {} + StepResult::HasChanged => debug!("fixpoint changed provisional results"), } } 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/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d58e1dbb3e4d0..91cf3787ec484 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/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 8283fdc459be1..5989bcbcc5201 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1476,14 +1476,17 @@ mod prim_usize {} /// /// For instance, this means that unsafe code in a safe function may assume these invariants are /// ensured of arguments passed by the caller, and it may assume that these invariants are ensured -/// of return values from any safe functions it calls. In most cases, the inverse is also true: -/// unsafe code must not violate these invariants when passing arguments to safe functions or -/// returning values from safe functions; such violations may result in undefined behavior. Where -/// exceptions to this latter requirement exist, they will be called out explicitly in documentation. +/// of return values from any safe functions it calls. +/// +/// For the other direction, things are more complicated: when unsafe code passes arguments +/// to safe functions or returns values from safe functions, they generally must *at least* +/// not violate these invariants. The full requirements are stronger, as the reference generally +/// must point to data that is safe to use at type `T`. /// /// It is not decided yet whether unsafe code may violate these invariants temporarily on internal /// data. As a consequence, unsafe code which violates these invariants temporarily on internal data -/// may become unsound in future versions of Rust depending on how this question is decided. +/// may be unsound or become unsound in future versions of Rust depending on how this question is +/// decided. /// /// [allocated object]: ptr#allocated-object #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0650afb90c7ea..7f156d32655b7 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -201,7 +201,6 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); let layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_wraparound(10) 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/crashes/118185.rs b/tests/crashes/118185.rs deleted file mode 100644 index c3a29c3a3f54a..0000000000000 --- a/tests/crashes/118185.rs +++ /dev/null @@ -1,26 +0,0 @@ -//@ known-bug: #118185 - -fn main() { - let target: Target = create_target(); - target.get(0); // correct arguments work - target.get(10.0); // CRASH HERE -} - -// must be generic -fn create_target() -> T { - unimplemented!() -} - -// unimplemented trait, but contains function with the same name -pub trait RandomTrait { - fn get(&mut self); // but less arguments -} - -struct Target; - -impl Target { - // correct function with arguments - pub fn get(&self, data: i32) { - unimplemented!() - } -} diff --git a/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs new file mode 100644 index 0000000000000..ce49f55e3e304 --- /dev/null +++ b/tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs @@ -0,0 +1,27 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ check-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn consume(_: String) {} + +fn main() { + block_on::block_on(async { + let x = 1i32; + let s = String::new(); + // `consume(s)` pulls the closure's kind down to `FnOnce`, + // which means that we don't treat the borrow of `x` as a + // self-borrow (with `'env` lifetime). This leads to a lifetime + // error which is solved by forcing the inner coroutine to + // be `move` as well, so that it moves `x`. + let c = async move || { + println!("{x}"); + // This makes the closure FnOnce... + consume(s); + }; + c().await; + }); +} diff --git a/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs new file mode 100644 index 0000000000000..803c990ef93f1 --- /dev/null +++ b/tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs @@ -0,0 +1,24 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ check-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn force_fnonce(t: T) -> T { t } + +fn main() { + block_on::block_on(async { + let x = 1i32; + // `force_fnonce` pulls the closure's kind down to `FnOnce`, + // which means that we don't treat the borrow of `x` as a + // self-borrow (with `'env` lifetime). This leads to a lifetime + // error which is solved by forcing the inner coroutine to + // be `move` as well, so that it moves `x`. + let c = force_fnonce(async move || { + println!("{x}"); + }); + c().await; + }); +} 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/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 7443459b83007..d809a6948f3ea 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,7 +1,7 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 38a02c906d4fc..329086ab7dfdf 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,11 +1,11 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 59fab52b221e2..2f1dfd19c483b 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,5 +1,5 @@ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit) } error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied --> $DIR/structually-relate-aliases.rs:13:36 | diff --git a/tests/crashes/118185-2.rs b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs similarity index 85% rename from tests/crashes/118185-2.rs rename to tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs index c3a29c3a3f54a..fd41beecb0a2a 100644 --- a/tests/crashes/118185-2.rs +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs @@ -1,9 +1,8 @@ -//@ known-bug: #118185 - fn main() { let target: Target = create_target(); target.get(0); // correct arguments work - target.get(10.0); // CRASH HERE + target.get(10.0); // (used to crash here) + //~^ ERROR mismatched types } // must be generic diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr new file mode 100644 index 0000000000000..0f86916fcdae4 --- /dev/null +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:16 + | +LL | target.get(10.0); // (used to crash here) + | --- ^^^^ expected `i32`, found floating-point number + | | + | arguments to this method are incorrect + | +note: method defined here + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:22:12 + | +LL | pub fn get(&self, data: i32) { + | ^^^ --------- + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index bd0519f66c0de..6fff086a89c2e 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -9,7 +9,7 @@ LL | fn get>(self: R) -> u32 { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? + ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index 2e0566cad08e2..17da1f5247963 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -25,10 +25,10 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` --> $DIR/issue-118950-root-region.rs:19:1 | 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 _);