diff options
55 files changed, 1412 insertions, 328 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 780feb9b827..dd9ccadf6cf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; #[cfg(feature = "nightly")] use rustc_macros::HashStable_NoContext; -use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; +use rustc_type_ir::data_structures::{HashMap, HashSet}; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; @@ -336,13 +336,12 @@ where /// Creates a nested evaluation context that shares the same search graph as the /// one passed in. This is suitable for evaluation, granted that the search graph - /// has had the nested goal recorded on its stack ([`SearchGraph::with_new_goal`]), - /// but it's preferable to use other methods that call this one rather than this - /// method directly. + /// has had the nested goal recorded on its stack. This method only be used by + /// `search_graph::Delegate::compute_goal`. /// /// This function takes care of setting up the inference context, setting the anchor, /// and registering opaques from the canonicalized input. - fn enter_canonical<R>( + pub(super) fn enter_canonical<R>( cx: I, search_graph: &'a mut SearchGraph<D>, canonical_input: CanonicalInput<I>, @@ -398,56 +397,6 @@ where result } - /// The entry point of the solver. - /// - /// This function deals with (coinductive) cycles, overflow, and caching - /// and then calls [`EvalCtxt::compute_goal`] which contains the actual - /// logic of the solver. - /// - /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal] - /// if you're inside of the solver or [SolverDelegateEvalExt::evaluate_root_goal] if you're - /// outside of it. - #[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)] - fn evaluate_canonical_goal( - cx: I, - search_graph: &'a mut SearchGraph<D>, - canonical_input: CanonicalInput<I>, - step_kind_from_parent: PathKind, - goal_evaluation: &mut ProofTreeBuilder<D>, - ) -> QueryResult<I> { - let mut canonical_goal_evaluation = - goal_evaluation.new_canonical_goal_evaluation(canonical_input); - - // Deal with overflow, caching, and coinduction. - // - // The actual solver logic happens in `ecx.compute_goal`. - let result = ensure_sufficient_stack(|| { - search_graph.with_new_goal( - cx, - canonical_input, - step_kind_from_parent, - &mut canonical_goal_evaluation, - |search_graph, cx, canonical_input, canonical_goal_evaluation| { - EvalCtxt::enter_canonical( - cx, - search_graph, - canonical_input, - canonical_goal_evaluation, - |ecx, goal| { - let result = ecx.compute_goal(goal); - ecx.inspect.query_result(result); - result - }, - ) - }, - ) - }); - - canonical_goal_evaluation.query_result(result); - goal_evaluation.canonical_goal_evaluation(canonical_goal_evaluation); - result - } - /// Recursively evaluates `goal`, returning whether any inference vars have /// been constrained and the certainty of the result. fn evaluate_goal( @@ -501,18 +450,16 @@ where let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); - let canonical_response = EvalCtxt::evaluate_canonical_goal( + let canonical_result = self.search_graph.evaluate_goal( self.cx(), - self.search_graph, canonical_goal, self.step_kind_for_source(source), &mut goal_evaluation, ); - let response = match canonical_response { - Err(e) => { - self.inspect.goal_evaluation(goal_evaluation); - return Err(e); - } + goal_evaluation.query_result(canonical_result); + self.inspect.goal_evaluation(goal_evaluation); + let response = match canonical_result { + Err(e) => return Err(e), Ok(response) => response, }; @@ -521,7 +468,6 @@ where let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response); - self.inspect.goal_evaluation(goal_evaluation); // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. @@ -582,7 +528,7 @@ where Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on })) } - fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> { + pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); if let Some(kind) = kind.no_bound_vars() { diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index f22b275bc44..c8521624ebb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -13,8 +13,7 @@ use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; use crate::solve::eval_ctxt::canonical; use crate::solve::{ - CanonicalInput, Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, - QueryResult, inspect, + Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryResult, inspect, }; /// The core data structure when building proof trees. @@ -54,7 +53,6 @@ where enum DebugSolver<I: Interner> { Root, GoalEvaluation(WipGoalEvaluation<I>), - CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<I>), CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep<I>), } @@ -64,12 +62,6 @@ impl<I: Interner> From<WipGoalEvaluation<I>> for DebugSolver<I> { } } -impl<I: Interner> From<WipCanonicalGoalEvaluation<I>> for DebugSolver<I> { - fn from(g: WipCanonicalGoalEvaluation<I>) -> DebugSolver<I> { - DebugSolver::CanonicalGoalEvaluation(g) - } -} - impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> { fn from(g: WipCanonicalGoalEvaluationStep<I>) -> DebugSolver<I> { DebugSolver::CanonicalGoalEvaluationStep(g) @@ -80,7 +72,10 @@ impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> { struct WipGoalEvaluation<I: Interner> { pub uncanonicalized_goal: Goal<I, I::Predicate>, pub orig_values: Vec<I::GenericArg>, - pub evaluation: Option<WipCanonicalGoalEvaluation<I>>, + pub encountered_overflow: bool, + /// After we finished evaluating this is moved into `kind`. + pub final_revision: Option<WipCanonicalGoalEvaluationStep<I>>, + pub result: Option<QueryResult<I>>, } impl<I: Interner> WipGoalEvaluation<I> { @@ -88,31 +83,12 @@ impl<I: Interner> WipGoalEvaluation<I> { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, orig_values: self.orig_values, - evaluation: self.evaluation.unwrap().finalize(), - } - } -} - -#[derive_where(PartialEq, Eq, Debug; I: Interner)] -struct WipCanonicalGoalEvaluation<I: Interner> { - goal: CanonicalInput<I>, - encountered_overflow: bool, - /// Only used for uncached goals. After we finished evaluating - /// the goal, this is interned and moved into `kind`. - final_revision: Option<WipCanonicalGoalEvaluationStep<I>>, - result: Option<QueryResult<I>>, -} - -impl<I: Interner> WipCanonicalGoalEvaluation<I> { - fn finalize(self) -> inspect::CanonicalGoalEvaluation<I> { - inspect::CanonicalGoalEvaluation { - goal: self.goal, kind: if self.encountered_overflow { assert!(self.final_revision.is_none()); - inspect::CanonicalGoalEvaluationKind::Overflow + inspect::GoalEvaluationKind::Overflow } else { let final_revision = self.final_revision.unwrap().finalize(); - inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } + inspect::GoalEvaluationKind::Evaluation { final_revision } }, result: self.result.unwrap(), } @@ -256,55 +232,27 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { pub(in crate::solve) fn new_goal_evaluation( &mut self, - goal: Goal<I, I::Predicate>, + uncanonicalized_goal: Goal<I, I::Predicate>, orig_values: &[I::GenericArg], kind: GoalEvaluationKind, ) -> ProofTreeBuilder<D> { self.opt_nested(|| match kind { GoalEvaluationKind::Root => Some(WipGoalEvaluation { - uncanonicalized_goal: goal, + uncanonicalized_goal, orig_values: orig_values.to_vec(), - evaluation: None, + encountered_overflow: false, + final_revision: None, + result: None, }), GoalEvaluationKind::Nested => None, }) } - pub(crate) fn new_canonical_goal_evaluation( - &mut self, - goal: CanonicalInput<I>, - ) -> ProofTreeBuilder<D> { - self.nested(|| WipCanonicalGoalEvaluation { - goal, - encountered_overflow: false, - final_revision: None, - result: None, - }) - } - - pub(crate) fn canonical_goal_evaluation( - &mut self, - canonical_goal_evaluation: ProofTreeBuilder<D>, - ) { - if let Some(this) = self.as_mut() { - match (this, *canonical_goal_evaluation.state.unwrap()) { - ( - DebugSolver::GoalEvaluation(goal_evaluation), - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation), - ) => { - let prev = goal_evaluation.evaluation.replace(canonical_goal_evaluation); - assert_eq!(prev, None); - } - _ => unreachable!(), - } - } - } - pub(crate) fn canonical_goal_evaluation_overflow(&mut self) { if let Some(this) = self.as_mut() { match this { - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { - canonical_goal_evaluation.encountered_overflow = true; + DebugSolver::GoalEvaluation(goal_evaluation) => { + goal_evaluation.encountered_overflow = true; } _ => unreachable!(), }; @@ -343,10 +291,10 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { if let Some(this) = self.as_mut() { match (this, *goal_evaluation_step.state.unwrap()) { ( - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), + DebugSolver::GoalEvaluation(goal_evaluation), DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), ) => { - canonical_goal_evaluations.final_revision = Some(goal_evaluation_step); + goal_evaluation.final_revision = Some(goal_evaluation_step); } _ => unreachable!(), } @@ -489,8 +437,8 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { pub(crate) fn query_result(&mut self, result: QueryResult<I>) { if let Some(this) = self.as_mut() { match this { - DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { - assert_eq!(canonical_goal_evaluation.result.replace(result), None); + DebugSolver::GoalEvaluation(goal_evaluation) => { + assert_eq!(goal_evaluation.result.replace(result), None); } DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { assert_eq!( diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index ecffbbff7a2..12cbc7e8f91 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -1,13 +1,14 @@ use std::convert::Infallible; use std::marker::PhantomData; +use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::search_graph::{self, PathKind}; use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult}; use rustc_type_ir::{Interner, TypingMode}; -use super::inspect::ProofTreeBuilder; -use super::{FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints}; use crate::delegate::SolverDelegate; +use crate::solve::inspect::ProofTreeBuilder; +use crate::solve::{EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints}; /// This type is never constructed. We only use it to implement `search_graph::Delegate` /// for all types which impl `SolverDelegate` and doing it directly fails in coherence. @@ -80,8 +81,8 @@ where fn on_stack_overflow( cx: I, - inspect: &mut ProofTreeBuilder<D>, input: CanonicalInput<I>, + inspect: &mut ProofTreeBuilder<D>, ) -> QueryResult<I> { inspect.canonical_goal_evaluation_overflow(); response_no_constraints(cx, input, Certainty::overflow(true)) @@ -106,6 +107,21 @@ where let certainty = from_result.unwrap().value.certainty; response_no_constraints(cx, for_input, certainty) } + + fn compute_goal( + search_graph: &mut SearchGraph<D>, + cx: I, + input: CanonicalInput<I>, + inspect: &mut Self::ProofTreeBuilder, + ) -> QueryResult<I> { + ensure_sufficient_stack(|| { + EvalCtxt::enter_canonical(cx, search_graph, input, inspect, |ecx, goal| { + let result = ecx.compute_goal(goal); + ecx.inspect.query_result(result); + result + }) + }) + } } fn response_no_constraints<I: Interner>( diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 80df0fab2d8..308486811e6 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -37,7 +37,7 @@ pub struct InspectGoal<'a, 'tcx> { orig_values: Vec<ty::GenericArg<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>, result: Result<Certainty, NoSolution>, - evaluation_kind: inspect::CanonicalGoalEvaluationKind<TyCtxt<'tcx>>, + evaluation_kind: inspect::GoalEvaluationKind<TyCtxt<'tcx>>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, source: GoalSource, } @@ -393,8 +393,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { let mut candidates = vec![]; let last_eval_step = match &self.evaluation_kind { // An annoying edge case in case the recursion limit is 0. - inspect::CanonicalGoalEvaluationKind::Overflow => return vec![], - inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision, + inspect::GoalEvaluationKind::Overflow => return vec![], + inspect::GoalEvaluationKind::Evaluation { final_revision } => final_revision, }; let mut nested_goals = vec![]; @@ -426,10 +426,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { ) -> Self { let infcx = <&SolverDelegate<'tcx>>::from(infcx); - let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root; + let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, kind, result } = root; // If there's a normalizes-to goal, AND the evaluation result with the result of // constraining the normalizes-to RHS and computing the nested goals. - let result = evaluation.result.and_then(|ok| { + let result = result.and_then(|ok| { let nested_goals_certainty = term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?; Ok(ok.value.certainty.and(nested_goals_certainty)) @@ -441,7 +441,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { orig_values, goal: eager_resolve_vars(infcx, uncanonicalized_goal), result, - evaluation_kind: evaluation.kind, + evaluation_kind: kind, normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n), source, } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index a857da2fcd5..8941360d2d0 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -21,7 +21,7 @@ use std::marker::PhantomData; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; -use tracing::debug; +use tracing::{debug, instrument}; use crate::data_structures::HashMap; @@ -56,7 +56,7 @@ pub trait Cx: Copy { fn evaluation_is_concurrent(&self) -> bool; } -pub trait Delegate { +pub trait Delegate: Sized { type Cx: Cx; /// Whether to use the provisional cache. Set to `false` by a fuzzer when /// validating the search graph. @@ -94,8 +94,8 @@ pub trait Delegate { ) -> bool; fn on_stack_overflow( cx: Self::Cx, - inspect: &mut Self::ProofTreeBuilder, input: <Self::Cx as Cx>::Input, + inspect: &mut Self::ProofTreeBuilder, ) -> <Self::Cx as Cx>::Result; fn on_fixpoint_overflow( cx: Self::Cx, @@ -108,6 +108,13 @@ pub trait Delegate { for_input: <Self::Cx as Cx>::Input, from_result: <Self::Cx as Cx>::Result, ) -> <Self::Cx as Cx>::Result; + + fn compute_goal( + search_graph: &mut SearchGraph<Self>, + cx: Self::Cx, + input: <Self::Cx as Cx>::Input, + inspect: &mut Self::ProofTreeBuilder, + ) -> <Self::Cx as Cx>::Result; } /// In the initial iteration of a cycle, we do not yet have a provisional @@ -589,15 +596,15 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { /// Probably the most involved method of the whole solver. /// - /// Given some goal which is proven via the `prove_goal` closure, this - /// handles caching, overflow, and coinductive cycles. - pub fn with_new_goal( + /// While goals get computed via `D::compute_goal`, this function handles + /// caching, overflow, and cycles. + #[instrument(level = "debug", skip(self, cx, inspect), ret)] + pub fn evaluate_goal( &mut self, cx: X, input: X::Input, step_kind_from_parent: PathKind, inspect: &mut D::ProofTreeBuilder, - evaluate_goal: impl Fn(&mut Self, X, X::Input, &mut D::ProofTreeBuilder) -> X::Result + Copy, ) -> X::Result { let Some(available_depth) = AvailableDepth::allowed_depth_for_nested::<D>(self.root_depth, &self.stack) @@ -666,7 +673,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { // must not be added to the global cache. Notably, this is the case for // trait solver cycles participants. let (evaluation_result, dep_node) = - cx.with_cached_task(|| self.evaluate_goal_in_task(cx, input, inspect, evaluate_goal)); + cx.with_cached_task(|| self.evaluate_goal_in_task(cx, input, inspect)); // We've finished computing the goal and have popped it from the stack, // lazily update its parent goal. @@ -736,7 +743,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { } debug!("encountered stack overflow"); - D::on_stack_overflow(cx, inspect, input) + D::on_stack_overflow(cx, input, inspect) } /// When reevaluating a goal with a changed provisional result, all provisional cache entry @@ -1064,7 +1071,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { cx: X, input: X::Input, inspect: &mut D::ProofTreeBuilder, - evaluate_goal: impl Fn(&mut Self, X, X::Input, &mut D::ProofTreeBuilder) -> X::Result + Copy, ) -> EvaluationResult<X> { // We reset `encountered_overflow` each time we rerun this goal // but need to make sure we currently propagate it to the global @@ -1073,7 +1079,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { let mut encountered_overflow = false; let mut i = 0; loop { - let result = evaluate_goal(self, cx, input, inspect); + let result = D::compute_goal(self, cx, input, inspect); let stack_entry = self.stack.pop(); encountered_overflow |= stack_entry.encountered_overflow; debug_assert_eq!(stack_entry.input, input); diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index b10641b287d..089695d0475 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -23,7 +23,7 @@ use std::hash::Hash; use derive_where::derive_where; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::solve::{CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryResult}; +use crate::solve::{CandidateSource, Certainty, Goal, GoalSource, QueryResult}; use crate::{Canonical, CanonicalVarValues, Interner}; /// Some `data` together with information about how they relate to the input @@ -54,18 +54,12 @@ pub type CanonicalState<I, T> = Canonical<I, State<I, T>>; pub struct GoalEvaluation<I: Interner> { pub uncanonicalized_goal: Goal<I, I::Predicate>, pub orig_values: Vec<I::GenericArg>, - pub evaluation: CanonicalGoalEvaluation<I>, -} - -#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] -pub struct CanonicalGoalEvaluation<I: Interner> { - pub goal: CanonicalInput<I>, - pub kind: CanonicalGoalEvaluationKind<I>, + pub kind: GoalEvaluationKind<I>, pub result: QueryResult<I>, } #[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] -pub enum CanonicalGoalEvaluationKind<I: Interner> { +pub enum GoalEvaluationKind<I: Interner> { Overflow, Evaluation { /// This is always `ProbeKind::Root`. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index a2c1ba835f3..7ce03e3d831 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display}; use crate::marker::{PhantomData, PointerLike, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; +use crate::panic::const_panic; use crate::pin::PinCoerceUnsized; use crate::ptr::{self, NonNull}; @@ -781,16 +782,24 @@ impl Display for BorrowMutError { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] -fn panic_already_borrowed(err: BorrowMutError) -> ! { - panic!("{err}") +const fn panic_already_borrowed(err: BorrowMutError) -> ! { + const_panic!( + "RefCell already borrowed", + "{err}", + err: BorrowMutError = err, + ) } // This ensures the panicking code is outlined from `borrow` for `RefCell`. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[cold] -fn panic_already_mutably_borrowed(err: BorrowError) -> ! { - panic!("{err}") +const fn panic_already_mutably_borrowed(err: BorrowError) -> ! { + const_panic!( + "RefCell already mutably borrowed", + "{err}", + err: BorrowError = err, + ) } // Positive values represent the number of `Ref` active. Negative values @@ -810,12 +819,12 @@ type BorrowCounter = isize; const UNUSED: BorrowCounter = 0; #[inline(always)] -fn is_writing(x: BorrowCounter) -> bool { +const fn is_writing(x: BorrowCounter) -> bool { x < UNUSED } #[inline(always)] -fn is_reading(x: BorrowCounter) -> bool { +const fn is_reading(x: BorrowCounter) -> bool { x > UNUSED } @@ -884,8 +893,9 @@ impl<T> RefCell<T> { #[stable(feature = "refcell_replace", since = "1.24.0")] #[track_caller] #[rustc_confusables("swap")] - pub fn replace(&self, t: T) -> T { - mem::replace(&mut *self.borrow_mut(), t) + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn replace(&self, t: T) -> T { + mem::replace(&mut self.borrow_mut(), t) } /// Replaces the wrapped value with a new one computed from `f`, returning @@ -935,7 +945,8 @@ impl<T> RefCell<T> { /// ``` #[inline] #[stable(feature = "refcell_swap", since = "1.24.0")] - pub fn swap(&self, other: &Self) { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn swap(&self, other: &Self) { mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) } } @@ -975,7 +986,8 @@ impl<T: ?Sized> RefCell<T> { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] - pub fn borrow(&self) -> Ref<'_, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn borrow(&self) -> Ref<'_, T> { match self.try_borrow() { Ok(b) => b, Err(err) => panic_already_mutably_borrowed(err), @@ -1010,14 +1022,15 @@ impl<T: ?Sized> RefCell<T> { #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] - pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> { match BorrowRef::new(&self.borrow) { Some(b) => { #[cfg(feature = "debug_refcell")] { // `borrowed_at` is always the *first* active borrow if b.borrow.get() == 1 { - self.borrowed_at.set(Some(crate::panic::Location::caller())); + self.borrowed_at.replace(Some(crate::panic::Location::caller())); } } @@ -1071,7 +1084,8 @@ impl<T: ?Sized> RefCell<T> { #[stable(feature = "rust1", since = "1.0.0")] #[inline] #[track_caller] - pub fn borrow_mut(&self) -> RefMut<'_, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn borrow_mut(&self) -> RefMut<'_, T> { match self.try_borrow_mut() { Ok(b) => b, Err(err) => panic_already_borrowed(err), @@ -1103,12 +1117,13 @@ impl<T: ?Sized> RefCell<T> { #[stable(feature = "try_borrow", since = "1.13.0")] #[inline] #[cfg_attr(feature = "debug_refcell", track_caller)] - pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { Some(b) => { #[cfg(feature = "debug_refcell")] { - self.borrowed_at.set(Some(crate::panic::Location::caller())); + self.borrowed_at.replace(Some(crate::panic::Location::caller())); } // SAFETY: `BorrowRefMut` guarantees unique access. @@ -1139,7 +1154,8 @@ impl<T: ?Sized> RefCell<T> { #[stable(feature = "cell_as_ptr", since = "1.12.0")] #[rustc_as_ptr] #[rustc_never_returns_null_ptr] - pub fn as_ptr(&self) -> *mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn as_ptr(&self) -> *mut T { self.value.get() } @@ -1176,7 +1192,8 @@ impl<T: ?Sized> RefCell<T> { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -1202,7 +1219,8 @@ impl<T: ?Sized> RefCell<T> { /// assert!(c.try_borrow().is_ok()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn undo_leak(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn undo_leak(&mut self) -> &mut T { *self.borrow.get_mut() = UNUSED; self.get_mut() } @@ -1236,7 +1254,8 @@ impl<T: ?Sized> RefCell<T> { /// ``` #[stable(feature = "borrow_state", since = "1.37.0")] #[inline] - pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { if !is_writing(self.borrow.get()) { // SAFETY: We check that nobody is actively writing now, but it is // the caller's responsibility to ensure that nobody writes until @@ -1400,7 +1419,7 @@ struct BorrowRef<'b> { impl<'b> BorrowRef<'b> { #[inline] - fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> { + const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> { let b = borrow.get().wrapping_add(1); if !is_reading(b) { // Incrementing borrow can result in a non-reading value (<= 0) in these cases: @@ -1417,22 +1436,24 @@ impl<'b> BorrowRef<'b> { // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize // is large enough to represent having one more read borrow - borrow.set(b); + borrow.replace(b); Some(BorrowRef { borrow }) } } } -impl Drop for BorrowRef<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Drop for BorrowRef<'_> { #[inline] fn drop(&mut self) { let borrow = self.borrow.get(); debug_assert!(is_reading(borrow)); - self.borrow.set(borrow - 1); + self.borrow.replace(borrow - 1); } } -impl Clone for BorrowRef<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Clone for BorrowRef<'_> { #[inline] fn clone(&self) -> Self { // Since this Ref exists, we know the borrow flag @@ -1442,7 +1463,7 @@ impl Clone for BorrowRef<'_> { // Prevent the borrow counter from overflowing into // a writing borrow. assert!(borrow != BorrowCounter::MAX); - self.borrow.set(borrow + 1); + self.borrow.replace(borrow + 1); BorrowRef { borrow: self.borrow } } } @@ -1463,7 +1484,8 @@ pub struct Ref<'b, T: ?Sized + 'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> Deref for Ref<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl<T: ?Sized> const Deref for Ref<'_, T> { type Target = T; #[inline] @@ -1488,7 +1510,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { #[stable(feature = "cell_extras", since = "1.15.0")] #[must_use] #[inline] - pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { Ref { value: orig.value, borrow: orig.borrow.clone() } } @@ -1610,7 +1633,8 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// assert!(cell.try_borrow_mut().is_err()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn leak(orig: Ref<'b, T>) -> &'b T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn leak(orig: Ref<'b, T>) -> &'b T { // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a // unique reference to the borrowed RefCell. No further mutable references can be created @@ -1776,7 +1800,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// assert!(cell.try_borrow_mut().is_err()); /// ``` #[unstable(feature = "cell_leak", issue = "69099")] - pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { + #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] + pub const fn leak(mut orig: RefMut<'b, T>) -> &'b mut T { // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would // require a unique reference to the borrowed RefCell. No further references can be created @@ -1792,25 +1817,26 @@ struct BorrowRefMut<'b> { borrow: &'b Cell<BorrowCounter>, } -impl Drop for BorrowRefMut<'_> { +#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")] +impl const Drop for BorrowRefMut<'_> { #[inline] fn drop(&mut self) { let borrow = self.borrow.get(); debug_assert!(is_writing(borrow)); - self.borrow.set(borrow + 1); + self.borrow.replace(borrow + 1); } } impl<'b> BorrowRefMut<'b> { #[inline] - fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> { + const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> { // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial // mutable reference, and so there must currently be no existing // references. Thus, while clone increments the mutable refcount, here // we explicitly only allow going from UNUSED to UNUSED - 1. match borrow.get() { UNUSED => { - borrow.set(UNUSED - 1); + borrow.replace(UNUSED - 1); Some(BorrowRefMut { borrow }) } _ => None, @@ -1849,7 +1875,8 @@ pub struct RefMut<'b, T: ?Sized + 'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> Deref for RefMut<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl<T: ?Sized> const Deref for RefMut<'_, T> { type Target = T; #[inline] @@ -1860,7 +1887,8 @@ impl<T: ?Sized> Deref for RefMut<'_, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: ?Sized> DerefMut for RefMut<'_, T> { +#[rustc_const_unstable(feature = "const_deref", issue = "88955")] +impl<T: ?Sized> const DerefMut for RefMut<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut T { // SAFETY: the value is accessible as long as we hold our borrow. diff --git a/library/coretests/tests/cell.rs b/library/coretests/tests/cell.rs index 781a46c3744..c0ac66e5d2b 100644 --- a/library/coretests/tests/cell.rs +++ b/library/coretests/tests/cell.rs @@ -1,4 +1,5 @@ use core::cell::*; +use core::mem::forget; #[test] fn smoketest_unsafe_cell() { @@ -477,3 +478,74 @@ fn const_cells() { const _: i32 = CELL.into_inner(); */ } + +#[test] +fn refcell_borrow() { + // Check that `borrow` is usable at compile-time + const { + let a = RefCell::new(0); + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_ok()); + let a_ref = a.borrow(); + assert!(*a_ref == 0); + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_err()); + } +} + +#[test] +fn refcell_borrow_mut() { + // Check that `borrow_mut` is usable at compile-time + const { + let mut a = RefCell::new(0); + { + assert!(a.try_borrow().is_ok()); + assert!(a.try_borrow_mut().is_ok()); + let mut a_ref = a.borrow_mut(); + assert!(*a_ref == 0); + *a_ref = 10; + assert!(*a_ref == 10); + assert!(a.try_borrow().is_err()); + assert!(a.try_borrow_mut().is_err()); + } + assert!(*a.get_mut() == 10); + }; +} +struct NeverDrop; +impl Drop for NeverDrop { + fn drop(&mut self) { + panic!("should never be called"); + } +} + +#[test] +fn refcell_replace() { + // Check that `replace` is usable at compile-time + const { + let a = RefCell::new(0); + assert!(a.replace(10) == 0); + let a = a.into_inner(); + assert!(a == 10); + + let b = RefCell::new(NeverDrop); + forget(b.replace(NeverDrop)); + forget(b) + }; +} + +#[test] +fn refcell_swap() { + // Check that `swap` is usable at compile-time + const { + let (a, b) = (RefCell::new(31), RefCell::new(41)); + a.swap(&b); + let (a, b) = (a.into_inner(), b.into_inner()); + assert!(a == 41); + assert!(b == 31); + + let c = RefCell::new(NeverDrop); + let d = RefCell::new(NeverDrop); + c.swap(&d); + forget((c, d)); + }; +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 5449132413b..b6298883784 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,8 +15,11 @@ #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_max_len)] #![feature(clone_to_uninit)] +#![feature(const_deref)] +#![feature(const_destruct)] #![feature(const_eval_select)] #![feature(const_float_round_methods)] +#![feature(const_ref_cell)] #![feature(const_trait_impl)] #![feature(core_float_math)] #![feature(core_intrinsics)] diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs index f115896a473..736555b31bb 100644 --- a/tests/ui/coroutine/auto-trait-regions.rs +++ b/tests/ui/coroutine/auto-trait-regions.rs @@ -23,31 +23,31 @@ fn assert_foo<T: Foo>(f: T) {} fn main() { // Make sure 'static is erased for coroutine interiors so we can't match it in trait selection let x: &'static _ = &OnlyFooIfStaticRef(No); - let gen = #[coroutine] move || { + let generator = #[coroutine] move || { let x = x; yield; assert_foo(x); }; - assert_foo(gen); + assert_foo(generator); //~^ ERROR implementation of `Foo` is not general enough // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); - let gen = #[coroutine] move || { + let generator = #[coroutine] move || { let x = x; yield; assert_foo(x); }; - assert_foo(gen); // ok + assert_foo(generator); // ok // Disallow impls which relates lifetimes in the coroutine interior - let gen = #[coroutine] move || { + let generator = #[coroutine] move || { let a = A(&mut true, &mut true, No); //~^ ERROR borrow may still be in use when coroutine yields //~| ERROR borrow may still be in use when coroutine yields yield; assert_foo(a); }; - assert_foo(gen); + assert_foo(generator); //~^ ERROR not general enough } diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 77b5f3ce57c..beb689d868d 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -1,8 +1,8 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/auto-trait-regions.rs:45:19 | -LL | let gen = #[coroutine] move || { - | ------- within this coroutine +LL | let generator = #[coroutine] move || { + | ------- within this coroutine LL | let a = A(&mut true, &mut true, No); | ^^^^^^^^^ ... @@ -11,14 +11,14 @@ LL | yield; | help: add `static` to mark this coroutine as unmovable | -LL | let gen = #[coroutine] static move || { - | ++++++ +LL | let generator = #[coroutine] static move || { + | ++++++ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/auto-trait-regions.rs:45:30 | -LL | let gen = #[coroutine] move || { - | ------- within this coroutine +LL | let generator = #[coroutine] move || { + | ------- within this coroutine LL | let a = A(&mut true, &mut true, No); | ^^^^^^^^^ ... @@ -27,14 +27,14 @@ LL | yield; | help: add `static` to mark this coroutine as unmovable | -LL | let gen = #[coroutine] static move || { - | ++++++ +LL | let generator = #[coroutine] static move || { + | ++++++ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | assert_foo(generator); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` @@ -42,8 +42,8 @@ LL | assert_foo(gen); error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:51:5 | -LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough +LL | assert_foo(generator); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough | = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` diff --git a/tests/ui/coroutine/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs index f6fadff7faf..2f941d65591 100644 --- a/tests/ui/coroutine/clone-impl-static.rs +++ b/tests/ui/coroutine/clone-impl-static.rs @@ -7,13 +7,13 @@ #![feature(coroutines, coroutine_clone, stmt_expr_attributes)] fn main() { - let gen = #[coroutine] + let generator = #[coroutine] static move || { yield; }; - check_copy(&gen); + check_copy(&generator); //~^ ERROR Copy` is not satisfied - check_clone(&gen); + check_clone(&generator); //~^ ERROR Clone` is not satisfied } diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index db1d2770346..9fb71fd5fd0 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied --> $DIR/clone-impl-static.rs:14:16 | -LL | check_copy(&gen); - | ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` +LL | check_copy(&generator); + | ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | | | required by a bound introduced by this call | @@ -15,8 +15,8 @@ LL | fn check_copy<T: Copy>(_x: &T) {} error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied --> $DIR/clone-impl-static.rs:16:17 | -LL | check_clone(&gen); - | ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` +LL | check_clone(&generator); + | ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}` | | | required by a bound introduced by this call | diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr index 7e34f4d35b4..0835f766a82 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr @@ -1,5 +1,5 @@ error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:1:10 + --> $DIR/bad-assoc-ty.rs:5:10 | LL | type A = [u8; 4]::AssocTy; | ^^^^^^^ @@ -10,7 +10,7 @@ LL | type A = <[u8; 4]>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:5:10 + --> $DIR/bad-assoc-ty.rs:9:10 | LL | type B = [u8]::AssocTy; | ^^^^ @@ -21,7 +21,7 @@ LL | type B = <[u8]>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:9:10 + --> $DIR/bad-assoc-ty.rs:13:10 | LL | type C = (u8)::AssocTy; | ^^^^ @@ -32,7 +32,7 @@ LL | type C = <(u8)>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:13:10 + --> $DIR/bad-assoc-ty.rs:17:10 | LL | type D = (u8, u8)::AssocTy; | ^^^^^^^^ @@ -43,7 +43,7 @@ LL | type D = <(u8, u8)>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:17:10 + --> $DIR/bad-assoc-ty.rs:21:10 | LL | type E = _::AssocTy; | ^ @@ -54,7 +54,7 @@ LL | type E = <_>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:21:19 + --> $DIR/bad-assoc-ty.rs:25:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^ @@ -65,7 +65,7 @@ LL | type F = &'static <(u8)>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:27:10 + --> $DIR/bad-assoc-ty.rs:31:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | type G = <dyn 'static + (Send)>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:46:10 + --> $DIR/bad-assoc-ty.rs:51:10 | LL | type I = ty!()::AssocTy; | ^^^^^ @@ -87,7 +87,7 @@ LL | type I = <ty!()>::AssocTy; | + + error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:39:19 + --> $DIR/bad-assoc-ty.rs:44:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^ @@ -102,7 +102,7 @@ LL | ($ty: ty) => (<$ty>::AssocTy); | + + error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:1:10 + --> $DIR/bad-assoc-ty.rs:5:10 | LL | type A = [u8; 4]::AssocTy; | ^^^^^^^^^^^^^^^^ @@ -114,7 +114,7 @@ LL + type A = <[u8; 4] as Example>::AssocTy; | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:5:10 + --> $DIR/bad-assoc-ty.rs:9:10 | LL | type B = [u8]::AssocTy; | ^^^^^^^^^^^^^ @@ -126,7 +126,7 @@ LL + type B = <[u8] as Example>::AssocTy; | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:9:10 + --> $DIR/bad-assoc-ty.rs:13:10 | LL | type C = (u8)::AssocTy; | ^^^^^^^^^^^^^ @@ -138,7 +138,7 @@ LL + type C = <u8 as Example>::AssocTy; | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:13:10 + --> $DIR/bad-assoc-ty.rs:17:10 | LL | type D = (u8, u8)::AssocTy; | ^^^^^^^^^^^^^^^^^ @@ -150,13 +150,13 @@ LL + type D = <(u8, u8) as Example>::AssocTy; | error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases - --> $DIR/bad-assoc-ty.rs:17:10 + --> $DIR/bad-assoc-ty.rs:21:10 | LL | type E = _::AssocTy; | ^ not allowed in type signatures error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:21:19 + --> $DIR/bad-assoc-ty.rs:25:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ @@ -168,7 +168,7 @@ LL + type F = &'static <u8 as Example>::AssocTy; | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:27:10 + --> $DIR/bad-assoc-ty.rs:31:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -180,7 +180,7 @@ LL + type G = <(dyn Send + 'static) as Example>::AssocTy; | warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/bad-assoc-ty.rs:33:10 + --> $DIR/bad-assoc-ty.rs:37:10 | LL | type H = Fn(u8) -> (u8)::Output; | ^^^^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | type H = <dyn Fn(u8) -> (u8)>::Output; | ++++ + error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:33:10 + --> $DIR/bad-assoc-ty.rs:37:10 | LL | type H = Fn(u8) -> (u8)::Output; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +209,7 @@ LL + type H = <(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output; | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:39:19 + --> $DIR/bad-assoc-ty.rs:44:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + ($ty: ty) => (<u8 as Example>::AssocTy); | error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:46:10 + --> $DIR/bad-assoc-ty.rs:51:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + type I = <u8 as Example>::AssocTy; | error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/bad-assoc-ty.rs:51:13 + --> $DIR/bad-assoc-ty.rs:56:13 | LL | fn foo<X: K<_, _>>(x: X) {} | ^ ^ not allowed in type signatures @@ -245,7 +245,7 @@ LL | fn foo<X: K<_, _>>(x: X) {} | not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/bad-assoc-ty.rs:54:34 + --> $DIR/bad-assoc-ty.rs:59:34 | LL | fn bar<F>(_: F) where F: Fn() -> _ {} | ^ not allowed in type signatures @@ -257,7 +257,7 @@ LL + fn bar<F, T>(_: F) where F: Fn() -> T {} | error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/bad-assoc-ty.rs:57:19 + --> $DIR/bad-assoc-ty.rs:62:19 | LL | fn baz<F: Fn() -> _>(_: F) {} | ^ not allowed in type signatures @@ -269,7 +269,7 @@ LL + fn baz<F: Fn() -> T, T>(_: F) {} | error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/bad-assoc-ty.rs:60:33 + --> $DIR/bad-assoc-ty.rs:65:33 | LL | struct L<F>(F) where F: Fn() -> _; | ^ not allowed in type signatures @@ -281,7 +281,7 @@ LL + struct L<F, T>(F) where F: Fn() -> T; | error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/bad-assoc-ty.rs:82:38 + --> $DIR/bad-assoc-ty.rs:87:38 | LL | fn foo<F>(_: F) where F: Fn() -> _ {} | ^ not allowed in type signatures @@ -293,7 +293,7 @@ LL + fn foo<F, T>(_: F) where F: Fn() -> T {} | error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/bad-assoc-ty.rs:62:30 + --> $DIR/bad-assoc-ty.rs:67:30 | LL | struct M<F> where F: Fn() -> _ { | ^ not allowed in type signatures @@ -305,7 +305,7 @@ LL + struct M<F, T> where F: Fn() -> T { | error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums - --> $DIR/bad-assoc-ty.rs:66:28 + --> $DIR/bad-assoc-ty.rs:71:28 | LL | enum N<F> where F: Fn() -> _ { | ^ not allowed in type signatures @@ -317,7 +317,7 @@ LL + enum N<F, T> where F: Fn() -> T { | error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions - --> $DIR/bad-assoc-ty.rs:71:29 + --> $DIR/bad-assoc-ty.rs:76:29 | LL | union O<F> where F: Fn() -> _ { | ^ not allowed in type signatures @@ -329,7 +329,7 @@ LL + union O<F, T> where F: Fn() -> T { | error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union - --> $DIR/bad-assoc-ty.rs:73:5 + --> $DIR/bad-assoc-ty.rs:78:5 | LL | foo: F, | ^^^^^^ @@ -341,7 +341,7 @@ LL | foo: std::mem::ManuallyDrop<F>, | +++++++++++++++++++++++ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits - --> $DIR/bad-assoc-ty.rs:77:29 + --> $DIR/bad-assoc-ty.rs:82:29 | LL | trait P<F> where F: Fn() -> _ { | ^ not allowed in type signatures diff --git a/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr new file mode 100644 index 00000000000..3cc403f9ac4 --- /dev/null +++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr @@ -0,0 +1,340 @@ +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:5:10 + | +LL | type A = [u8; 4]::AssocTy; + | ^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type A = <[u8; 4]>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:9:10 + | +LL | type B = [u8]::AssocTy; + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type B = <[u8]>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:13:10 + | +LL | type C = (u8)::AssocTy; + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type C = <(u8)>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:17:10 + | +LL | type D = (u8, u8)::AssocTy; + | ^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type D = <(u8, u8)>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:21:10 + | +LL | type E = _::AssocTy; + | ^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type E = <_>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:25:19 + | +LL | type F = &'static (u8)::AssocTy; + | ^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type F = &'static <(u8)>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:31:10 + | +LL | type G = dyn 'static + (Send)::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type G = <dyn 'static + (Send)>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:51:10 + | +LL | type I = ty!()::AssocTy; + | ^^^^^ + | +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | type I = <ty!()>::AssocTy; + | + + + +error: missing angle brackets in associated item path + --> $DIR/bad-assoc-ty.rs:44:19 + | +LL | ($ty: ty) => ($ty::AssocTy); + | ^^^ +... +LL | type J = ty!(u8); + | ------- in this macro invocation + | + = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths + | +LL | ($ty: ty) => (<$ty>::AssocTy); + | + + + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:5:10 + | +LL | type A = [u8; 4]::AssocTy; + | ^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path + | +LL - type A = [u8; 4]::AssocTy; +LL + type A = <[u8; 4] as Example>::AssocTy; + | + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:9:10 + | +LL | type B = [u8]::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path + | +LL - type B = [u8]::AssocTy; +LL + type B = <[u8] as Example>::AssocTy; + | + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:13:10 + | +LL | type C = (u8)::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL - type C = (u8)::AssocTy; +LL + type C = <u8 as Example>::AssocTy; + | + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:17:10 + | +LL | type D = (u8, u8)::AssocTy; + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path + | +LL - type D = (u8, u8)::AssocTy; +LL + type D = <(u8, u8) as Example>::AssocTy; + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/bad-assoc-ty.rs:21:10 + | +LL | type E = _::AssocTy; + | ^ not allowed in type signatures + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:25:19 + | +LL | type F = &'static (u8)::AssocTy; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL - type F = &'static (u8)::AssocTy; +LL + type F = &'static <u8 as Example>::AssocTy; + | + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:31:10 + | +LL | type G = dyn 'static + (Send)::AssocTy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path + | +LL - type G = dyn 'static + (Send)::AssocTy; +LL + type G = <(dyn Send + 'static) as Example>::AssocTy; + | + +error[E0782]: expected a type, found a trait + --> $DIR/bad-assoc-ty.rs:37:10 + | +LL | type H = Fn(u8) -> (u8)::Output; + | ^^^^^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | type H = <dyn Fn(u8) -> (u8)>::Output; + | ++++ + + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:44:19 + | +LL | ($ty: ty) => ($ty::AssocTy); + | ^^^^^^^^^^^^ +... +LL | type J = ty!(u8); + | ------- in this macro invocation + | + = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL - ($ty: ty) => ($ty::AssocTy); +LL + ($ty: ty) => (<u8 as Example>::AssocTy); + | + +error[E0223]: ambiguous associated type + --> $DIR/bad-assoc-ty.rs:51:10 + | +LL | type I = ty!()::AssocTy; + | ^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path + | +LL - type I = ty!()::AssocTy; +LL + type I = <u8 as Example>::AssocTy; + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:56:13 + | +LL | fn foo<X: K<_, _>>(x: X) {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:59:34 + | +LL | fn bar<F>(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - fn bar<F>(_: F) where F: Fn() -> _ {} +LL + fn bar<F, T>(_: F) where F: Fn() -> T {} + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:62:19 + | +LL | fn baz<F: Fn() -> _>(_: F) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - fn baz<F: Fn() -> _>(_: F) {} +LL + fn baz<F: Fn() -> T, T>(_: F) {} + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/bad-assoc-ty.rs:65:33 + | +LL | struct L<F>(F) where F: Fn() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - struct L<F>(F) where F: Fn() -> _; +LL + struct L<F, T>(F) where F: Fn() -> T; + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/bad-assoc-ty.rs:87:38 + | +LL | fn foo<F>(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - fn foo<F>(_: F) where F: Fn() -> _ {} +LL + fn foo<F, T>(_: F) where F: Fn() -> T {} + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/bad-assoc-ty.rs:67:30 + | +LL | struct M<F> where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - struct M<F> where F: Fn() -> _ { +LL + struct M<F, T> where F: Fn() -> T { + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums + --> $DIR/bad-assoc-ty.rs:71:28 + | +LL | enum N<F> where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - enum N<F> where F: Fn() -> _ { +LL + enum N<F, T> where F: Fn() -> T { + | + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions + --> $DIR/bad-assoc-ty.rs:76:29 + | +LL | union O<F> where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - union O<F> where F: Fn() -> _ { +LL + union O<F, T> where F: Fn() -> T { + | + +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + --> $DIR/bad-assoc-ty.rs:78:5 + | +LL | foo: F, + | ^^^^^^ + | + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` + | +LL | foo: std::mem::ManuallyDrop<F>, + | +++++++++++++++++++++++ + + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits + --> $DIR/bad-assoc-ty.rs:82:29 + | +LL | trait P<F> where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - trait P<F> where F: Fn() -> _ { +LL + trait P<F, T> where F: Fn() -> T { + | + +error: aborting due to 29 previous errors + +Some errors have detailed explanations: E0121, E0223, E0740, E0782. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/did_you_mean/bad-assoc-ty.rs b/tests/ui/did_you_mean/bad-assoc-ty.rs index 5a559b01ea2..6e56cba24e1 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.rs +++ b/tests/ui/did_you_mean/bad-assoc-ty.rs @@ -1,3 +1,7 @@ +//@revisions: edition2015 edition2021 +//@[edition2015] edition:2015 +//@[edition2021] edition:2021 + type A = [u8; 4]::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR ambiguous associated type @@ -31,9 +35,10 @@ type G = dyn 'static + (Send)::AssocTy; // This is actually a legal path with fn-like generic arguments in the middle! // Recovery should not apply in this context. type H = Fn(u8) -> (u8)::Output; -//~^ ERROR ambiguous associated type -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition +//[edition2015]~^ ERROR ambiguous associated type +//[edition2015]~| WARN trait objects without an explicit `dyn` are deprecated +//[edition2015]~| WARN this is accepted in the current edition +//[edition2021]~^^^^ ERROR expected a type, found a trait macro_rules! ty { ($ty: ty) => ($ty::AssocTy); diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2015.stderr index 30f95851768..ac2d1ffa868 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2015.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-unsized_fn_params.rs:17:11 + --> $DIR/feature-gate-unsized_fn_params.rs:20:11 | LL | fn foo(x: dyn Foo) { | ^^^^^^^ doesn't have a size known at compile-time @@ -17,7 +17,7 @@ LL | fn foo(x: &dyn Foo) { | + error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-unsized_fn_params.rs:21:11 + --> $DIR/feature-gate-unsized_fn_params.rs:24:11 | LL | fn bar(x: Foo) { | ^^^ doesn't have a size known at compile-time @@ -34,7 +34,7 @@ LL | fn bar(x: &dyn Foo) { | ++++ error[E0277]: the size for values of type `[()]` cannot be known at compilation time - --> $DIR/feature-gate-unsized_fn_params.rs:25:11 + --> $DIR/feature-gate-unsized_fn_params.rs:30:11 | LL | fn qux(_: [()]) {} | ^^^^ doesn't have a size known at compile-time @@ -47,7 +47,7 @@ LL | fn qux(_: &[()]) {} | + error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-unsized_fn_params.rs:29:9 + --> $DIR/feature-gate-unsized_fn_params.rs:34:9 | LL | foo(*x); | ^^ doesn't have a size known at compile-time diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr new file mode 100644 index 00000000000..12411f695f4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr @@ -0,0 +1,65 @@ +error[E0782]: expected a type, found a trait + --> $DIR/feature-gate-unsized_fn_params.rs:24:11 + | +LL | fn bar(x: Foo) { + | ^^^ + | +help: use a new generic type parameter, constrained by `Foo` + | +LL - fn bar(x: Foo) { +LL + fn bar<T: Foo>(x: T) { + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bar(x: impl Foo) { + | ++++ +help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bar(x: &dyn Foo) { + | ++++ + +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:20:11 + | +LL | fn foo(x: dyn Foo) { + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = help: unsized fn params are gated as an unstable feature +help: you can use `impl Trait` as the argument type + | +LL - fn foo(x: dyn Foo) { +LL + fn foo(x: impl Foo) { + | +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn foo(x: &dyn Foo) { + | + + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:30:11 + | +LL | fn qux(_: [()]) {} + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed slices always have a known size + | +LL | fn qux(_: &[()]) {} + | + + +error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time + --> $DIR/feature-gate-unsized_fn_params.rs:34:9 + | +LL | foo(*x); + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` + = note: all function arguments must have a statically known size + = help: unsized fn params are gated as an unstable feature + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0782. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs index c04e57843d4..3c5f932e891 100644 --- a/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs +++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2021 +//@[edition2015] edition:2015 +//@[edition2021] edition:2021 #![allow(unused, bare_trait_objects)] #[repr(align(256))] struct A { @@ -18,7 +21,9 @@ fn foo(x: dyn Foo) { //~ ERROR [E0277] x.foo() } -fn bar(x: Foo) { //~ ERROR [E0277] +fn bar(x: Foo) { +//[edition2015]~^ ERROR [E0277] +//[edition2021]~^^ ERROR expected a type, found a trait x.foo() } diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2015.stderr index a2d00edbb6d..68b4e2ed39f 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds - --> $DIR/rpit-hidden-erased-unsoundness.rs:16:5 + --> $DIR/rpit-hidden-erased-unsoundness.rs:19:5 | LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a { | -- --------------- opaque type defined here diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr new file mode 100644 index 00000000000..6c0c1789582 --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/rpit-hidden-erased-unsoundness.rs:24:5 + | +LL | fn step3<'a, 'b: 'a>() -> impl Send + 'a { + | -- lifetime `'b` defined here +LL | step2::<'a, 'b>() + | ^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs index 6863a3c73ba..3338063d8c6 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 // This test should never pass! #![feature(type_alias_impl_trait)] @@ -14,11 +17,12 @@ fn step1<'a, 'b: 'a>() -> impl Sized + Captures<'b> + 'a { fn step2<'a, 'b: 'a>() -> impl Sized + 'a { step1::<'a, 'b>() - //~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds + //[edition2015]~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds } fn step3<'a, 'b: 'a>() -> impl Send + 'a { step2::<'a, 'b>() + //[edition2024]~^ ERROR lifetime may not live long enough // This should not be Send unless `'b: 'static` } diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2015.stderr index a1e92e53384..769a878a45c 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds - --> $DIR/rpit-hide-lifetime-for-swap.rs:17:5 + --> $DIR/rpit-hide-lifetime-for-swap.rs:20:5 | LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { | -- -------------- opaque type defined here diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr new file mode 100644 index 00000000000..6109184250b --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr @@ -0,0 +1,17 @@ +error[E0597]: `x` does not live long enough + --> $DIR/rpit-hide-lifetime-for-swap.rs:27:38 + | +LL | let x = [1, 2, 3]; + | - binding `x` declared here +LL | let short = Rc::new(RefCell::new(&x)); + | ^^ borrowed value does not live long enough +... +LL | let res: &'static [i32; 3] = *long.borrow(); + | ----------------- type annotation requires that `x` is borrowed for `'static` +LL | res +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs index 4de2ffbb808..c4eaec478b8 100644 --- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 // This test should never pass! use std::cell::RefCell; @@ -15,13 +18,14 @@ impl<T> Swap for Rc<RefCell<T>> { fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { x - //~^ ERROR hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds + //[edition2015]~^ ERROR hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds } fn dangle() -> &'static [i32; 3] { let long = Rc::new(RefCell::new(&[4, 5, 6])); let x = [1, 2, 3]; let short = Rc::new(RefCell::new(&x)); + //[edition2024]~^ ERROR `x` does not live long enough hide(long.clone()).swap(hide(short)); let res: &'static [i32; 3] = *long.borrow(); res diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2015.stderr index 304d7d43b78..64f0b201ca2 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2015.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13 | LL | fn fuz() -> (usize, Trait) { (42, Struct) } | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,7 +9,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) } = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 | LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -19,7 +19,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } = note: the return type of a function must have a statically known size error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 | LL | fn bap() -> Trait { Struct } | ^^^^^ doesn't have a size known at compile-time @@ -34,7 +34,7 @@ LL | fn bap() -> Box<dyn Trait> { Box::new(Struct) } | +++++++ + +++++++++ + error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:22:13 | LL | fn ban() -> dyn Trait { Struct } | ^^^^^^^^^ doesn't have a size known at compile-time @@ -50,7 +50,7 @@ LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) } | ++++ + +++++++++ + error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:24:13 | LL | fn bak() -> dyn Trait { unimplemented!() } | ^^^^^^^^^ doesn't have a size known at compile-time @@ -66,7 +66,7 @@ LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) } | ++++ + +++++++++ + error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:21:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:26:13 | LL | fn bal() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -86,7 +86,7 @@ LL ~ Box::new(42) | error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:32:13 | LL | fn bax() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -106,7 +106,7 @@ LL ~ Box::new(42) | error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:67:13 | LL | fn bat() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -126,7 +126,7 @@ LL ~ Box::new(42) | error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:68:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:73:13 | LL | fn bay() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -146,7 +146,7 @@ LL ~ Box::new(42) | error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:35 | LL | fn fuz() -> (usize, Trait) { (42, Struct) } | ^^^^^^ expected `dyn Trait`, found `Struct` @@ -156,7 +156,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) } = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:30 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:30 | LL | fn fuz() -> (usize, Trait) { (42, Struct) } | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -166,7 +166,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) } = note: tuples must have a statically known size to be initialized error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:39 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:39 | LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } | ^^^^^^ expected `dyn Trait`, found `Struct` @@ -176,7 +176,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:34 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:34 | LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } | ^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -186,7 +186,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } = note: tuples must have a statically known size to be initialized error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:16 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:16 | LL | fn bam() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -203,7 +203,7 @@ LL | return Box::new(Struct); | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:38:5 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:43:5 | LL | fn bam() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -220,7 +220,7 @@ LL | Box::new(42) | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:16 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:47:16 | LL | fn baq() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -237,7 +237,7 @@ LL | return Box::new(0); | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:44:5 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:49:5 | LL | fn baq() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -254,7 +254,7 @@ LL | Box::new(42) | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9 | LL | fn baz() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -271,7 +271,7 @@ LL | Box::new(Struct) | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:50:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 | LL | fn baz() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -288,7 +288,7 @@ LL | Box::new(42) | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:9 | LL | fn baw() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type @@ -305,7 +305,7 @@ LL | Box::new(0) | +++++++++ + error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:57:9 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:9 | LL | fn baw() -> Box<dyn Trait> { | -------------- expected `Box<(dyn Trait + 'static)>` because of return type diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr new file mode 100644 index 00000000000..5811431b494 --- /dev/null +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr @@ -0,0 +1,308 @@ +error[E0782]: expected a type, found a trait + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:21 + | +LL | fn fuz() -> (usize, Trait) { (42, Struct) } + | ^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | fn fuz() -> (usize, dyn Trait) { (42, Struct) } + | +++ + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: the return type of a function must have a statically known size + +error[E0782]: expected a type, found a trait + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 + | +LL | fn bap() -> Trait { Struct } + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn bap() -> impl Trait { Struct } + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn bap() -> Box<dyn Trait> { Struct } + | +++++++ + + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:22:13 + | +LL | fn ban() -> dyn Trait { Struct } + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn ban() -> dyn Trait { Struct } +LL + fn ban() -> impl Trait { Struct } + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) } + | ++++ + +++++++++ + + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:24:13 + | +LL | fn bak() -> dyn Trait { unimplemented!() } + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn bak() -> dyn Trait { unimplemented!() } +LL + fn bak() -> impl Trait { unimplemented!() } + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) } + | ++++ + +++++++++ + + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:26:13 + | +LL | fn bal() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn bal() -> dyn Trait { +LL + fn bal() -> impl Trait { + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn bal() -> Box<dyn Trait> { +LL | if true { +LL ~ return Box::new(Struct); +LL | } +LL ~ Box::new(42) + | + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:32:13 + | +LL | fn bax() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn bax() -> dyn Trait { +LL + fn bax() -> impl Trait { + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn bax() -> Box<dyn Trait> { +LL | if true { +LL ~ Box::new(Struct) +LL | } else { +LL ~ Box::new(42) + | + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:67:13 + | +LL | fn bat() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn bat() -> dyn Trait { +LL + fn bat() -> impl Trait { + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn bat() -> Box<dyn Trait> { +LL | if true { +LL ~ return Box::new(0); +LL | } +LL ~ Box::new(42) + | + +error[E0746]: return type cannot be a trait object without pointer indirection + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:73:13 + | +LL | fn bay() -> dyn Trait { + | ^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL - fn bay() -> dyn Trait { +LL + fn bay() -> impl Trait { + | +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn bay() -> Box<dyn Trait> { +LL | if true { +LL ~ Box::new(0) +LL | } else { +LL ~ Box::new(42) + | + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:39 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^ expected `dyn Trait`, found `Struct` + | + = note: expected trait object `(dyn Trait + 'static)` + found struct `Struct` + = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:34 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: tuples must have a statically known size to be initialized + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:16 + | +LL | fn bam() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return Struct; + | ^^^^^^ expected `Box<dyn Trait>`, found `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(Struct); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:43:5 + | +LL | fn bam() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:47:16 + | +LL | fn baq() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return 0; + | ^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(0); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:49:5 + | +LL | fn baq() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9 + | +LL | fn baz() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | Struct + | ^^^^^^ expected `Box<dyn Trait>`, found `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(Struct) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 + | +LL | fn baz() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:9 + | +LL | fn baw() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | 0 + | ^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(0) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:9 + | +LL | fn baw() -> Box<dyn Trait> { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box<dyn Trait>`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0277, E0308, E0746, E0782. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs index ccf0a1ad3d4..aa1f871d8ea 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2021 +//@[edition2015] edition:2015 +//@[edition2021] edition:2021 #![allow(bare_trait_objects)] struct Struct; trait Trait {} @@ -5,15 +8,17 @@ impl Trait for Struct {} impl Trait for u32 {} fn fuz() -> (usize, Trait) { (42, Struct) } -//~^ ERROR E0277 -//~| ERROR E0277 -//~| ERROR E0308 +//[edition2015]~^ ERROR E0277 +//[edition2015]~| ERROR E0277 +//[edition2015]~| ERROR E0308 +//[edition2021]~^^^^ ERROR expected a type, found a trait fn bar() -> (usize, dyn Trait) { (42, Struct) } //~^ ERROR E0277 //~| ERROR E0277 //~| ERROR E0308 fn bap() -> Trait { Struct } -//~^ ERROR E0746 +//[edition2015]~^ ERROR E0746 +//[edition2021]~^^ ERROR expected a type, found a trait fn ban() -> dyn Trait { Struct } //~^ ERROR E0746 fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0746 diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.edition2015.stderr index 70d8c816ecb..b63115f7658 100644 --- a/tests/ui/impl-trait/hidden-lifetimes.stderr +++ b/tests/ui/impl-trait/hidden-lifetimes.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds - --> $DIR/hidden-lifetimes.rs:29:5 + --> $DIR/hidden-lifetimes.rs:33:5 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | -- -------------- opaque type defined here @@ -14,7 +14,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + use<' | ++++++++++++++++ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds - --> $DIR/hidden-lifetimes.rs:46:5 + --> $DIR/hidden-lifetimes.rs:50:5 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { | -- -------------- opaque type defined here diff --git a/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr b/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr new file mode 100644 index 00000000000..d585bb50b13 --- /dev/null +++ b/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr @@ -0,0 +1,26 @@ +error[E0515]: cannot return value referencing local variable `x` + --> $DIR/hidden-lifetimes.rs:41:5 + | +LL | hide_ref(&mut res).swap(hide_ref(&mut &x)); + | -- `x` is borrowed here +LL | res + | ^^^ returns a value referencing data owned by the current function + +error[E0597]: `x` does not live long enough + --> $DIR/hidden-lifetimes.rs:57:38 + | +LL | let x = [1, 2, 3]; + | - binding `x` declared here +LL | let short = Rc::new(RefCell::new(&x)); + | ^^ borrowed value does not live long enough +LL | hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short)); +LL | let res: &'static [i32; 3] = *long.borrow(); + | ----------------- type annotation requires that `x` is borrowed for `'static` +LL | res +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0515, E0597. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/impl-trait/hidden-lifetimes.rs b/tests/ui/impl-trait/hidden-lifetimes.rs index ae07c892768..b50c43bd3fa 100644 --- a/tests/ui/impl-trait/hidden-lifetimes.rs +++ b/tests/ui/impl-trait/hidden-lifetimes.rs @@ -1,3 +1,7 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 + // Test to show what happens if we were not careful and allowed invariant // lifetimes to escape though an impl trait. // @@ -27,14 +31,14 @@ impl<T> Swap for Rc<RefCell<T>> { // `&'a mut &'l T` are the same type. fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { x - //~^ ERROR hidden type + //[edition2015]~^ ERROR hidden type } fn dangle_ref() -> &'static [i32; 3] { let mut res = &[4, 5, 6]; let x = [1, 2, 3]; hide_ref(&mut res).swap(hide_ref(&mut &x)); - res + res //[edition2024]~ ERROR cannot return value referencing local variable `x` } // Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>` @@ -44,13 +48,13 @@ fn dangle_ref() -> &'static [i32; 3] { // only has a single lifetime. fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a { x - //~^ ERROR hidden type + //[edition2015]~^ ERROR hidden type } fn dangle_rc_refcell() -> &'static [i32; 3] { let long = Rc::new(RefCell::new(&[4, 5, 6])); let x = [1, 2, 3]; - let short = Rc::new(RefCell::new(&x)); + let short = Rc::new(RefCell::new(&x)); //[edition2024]~ ERROR `x` does not live long enough hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short)); let res: &'static [i32; 3] = *long.borrow(); res diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2015.stderr index 4e453c108d4..4ba59826231 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds - --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 + --> $DIR/impl-fn-hrtb-bounds-2.rs:8:9 | LL | fn a() -> impl Fn(&u8) -> impl Debug { | ---------- opaque type defined here diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr new file mode 100644 index 00000000000..c7aedfe96bb --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr @@ -0,0 +1,15 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/impl-fn-hrtb-bounds-2.rs:7:27 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug { + | ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/impl-fn-hrtb-bounds-2.rs:7:19 + | +LL | fn a() -> impl Fn(&u8) -> impl Debug { + | ^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs index b0aeded0ef7..f4bfbdeb9f3 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs @@ -1,8 +1,11 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 #![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; -fn a() -> impl Fn(&u8) -> impl Debug { - |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds +fn a() -> impl Fn(&u8) -> impl Debug { //[edition2024]~ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + |x| x //[edition2015]~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds } fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr index 6064b09ef09..94476bcfbe8 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:5:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:8:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr new file mode 100644 index 00000000000..2f1eacb0c34 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr @@ -0,0 +1,11 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/impl-fn-predefined-lifetimes.rs:8:9 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | -- this generic parameter must be used with a generic lifetime parameter +LL | |x| x + | ^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 199cbbf4fcc..b2963cc10fa 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 #![feature(impl_trait_in_fn_trait_return)] use std::fmt::Debug; diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.edition2015.stderr index 64b425328e3..27a3c6c8b7c 100644 --- a/tests/ui/impl-trait/issues/issue-54895.stderr +++ b/tests/ui/impl-trait/issues/issue-54895.edition2015.stderr @@ -1,11 +1,11 @@ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` - --> $DIR/issue-54895.rs:15:53 + --> $DIR/issue-54895.rs:18:53 | LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { | ^^ | note: lifetime declared here - --> $DIR/issue-54895.rs:15:20 + --> $DIR/issue-54895.rs:18:20 | LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { | ^^ diff --git a/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr b/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr new file mode 100644 index 00000000000..54aa29e62d8 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr @@ -0,0 +1,27 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/issue-54895.rs:18:40 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/issue-54895.rs:18:20 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^ + +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/issue-54895.rs:18:53 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^ + | +note: lifetime declared here + --> $DIR/issue-54895.rs:18:20 + | +LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs index 13c0038ce43..bc1841209e1 100644 --- a/tests/ui/impl-trait/issues/issue-54895.rs +++ b/tests/ui/impl-trait/issues/issue-54895.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 trait Trait<'a> { type Out; fn call(&'a self) -> Self::Out; @@ -14,6 +17,7 @@ impl<'a> Trait<'a> for X { fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + //[edition2024]~^^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` X(()) } diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.edition2015.stderr index d7c0c494454..ee1a479310d 100644 --- a/tests/ui/impl-trait/issues/issue-79099.stderr +++ b/tests/ui/impl-trait/issues/issue-79099.edition2015.stderr @@ -1,5 +1,5 @@ error: expected identifier, found `1` - --> $DIR/issue-79099.rs:3:65 + --> $DIR/issue-79099.rs:6:65 | LL | let f: impl core::future::Future<Output = u8> = async { 1 }; | ----- ^ expected identifier @@ -10,7 +10,7 @@ LL | let f: impl core::future::Future<Output = u8> = async { 1 }; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/issue-79099.rs:3:16 + --> $DIR/issue-79099.rs:6:16 | LL | let f: impl core::future::Future<Output = u8> = async { 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr b/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr new file mode 100644 index 00000000000..3e422e25136 --- /dev/null +++ b/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr @@ -0,0 +1,14 @@ +error[E0562]: `impl Trait` is not allowed in the type of variable bindings + --> $DIR/issue-79099.rs:6:16 + | +LL | let f: impl core::future::Future<Output = u8> = async { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `impl Trait` is only allowed in arguments and return types of functions and methods + = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information + = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0562`. diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs index c2bad59045b..8426298620f 100644 --- a/tests/ui/impl-trait/issues/issue-79099.rs +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -1,8 +1,11 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 struct Bug { V1: [(); { let f: impl core::future::Future<Output = u8> = async { 1 }; //~^ ERROR `impl Trait` is not allowed in the type of variable bindings - //~| ERROR expected identifier + //[edition2015]~| ERROR expected identifier 1 }], } diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2015.stderr index d8903fc4129..9951e9e0965 100644 --- a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr +++ b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2015.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use` - --> $DIR/dyn-use.rs:1:26 + --> $DIR/dyn-use.rs:4:26 | LL | fn dyn() -> &'static dyn use<> { &() } | ^^^ expected one of `!`, `(`, `::`, `<`, `where`, or `{` diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr new file mode 100644 index 00000000000..cb3fe4cb583 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr @@ -0,0 +1,26 @@ +error: expected identifier, found keyword `dyn` + --> $DIR/dyn-use.rs:4:4 + | +LL | fn dyn() -> &'static dyn use<> { &() } + | ^^^ expected identifier, found keyword + | +help: escape `dyn` to use it as an identifier + | +LL | fn r#dyn() -> &'static dyn use<> { &() } + | ++ + +error: `use<...>` precise capturing syntax not allowed in `dyn` trait object bounds + --> $DIR/dyn-use.rs:4:26 + | +LL | fn dyn() -> &'static dyn use<> { &() } + | ^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/dyn-use.rs:4:22 + | +LL | fn dyn() -> &'static dyn use<> { &() } + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.rs b/tests/ui/impl-trait/precise-capturing/dyn-use.rs index fb2f83e2d21..0b6a9467ff7 100644 --- a/tests/ui/impl-trait/precise-capturing/dyn-use.rs +++ b/tests/ui/impl-trait/precise-capturing/dyn-use.rs @@ -1,2 +1,10 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 fn dyn() -> &'static dyn use<> { &() } -//~^ ERROR expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use` +//[edition2015]~^ ERROR expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use` +//[edition2024]~^^ ERROR expected identifier, found keyword `dyn` +//[edition2024]~| ERROR `use<...>` precise capturing syntax not allowed in `dyn` trait object bounds +//[edition2024]~| ERROR at least one trait is required for an object type + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2015.stderr index 0d8fa650df4..c16722bb80f 100644 --- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr +++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:3:5 + --> $DIR/hidden-type-suggestion.rs:6:5 | LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> { | -- -------------------- opaque type defined here @@ -15,7 +15,7 @@ LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b, 'a> { | ++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:9:5 + --> $DIR/hidden-type-suggestion.rs:12:5 | LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<T> { | -- ------------------- opaque type defined here @@ -31,7 +31,7 @@ LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<'a, T> { | +++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:15:5 + --> $DIR/hidden-type-suggestion.rs:18:5 | LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<> { | -- ------------------ opaque type defined here @@ -47,7 +47,7 @@ LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<'a> { | ++ error[E0700]: hidden type for `impl Captures<'captured>` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:24:5 + --> $DIR/hidden-type-suggestion.rs:27:5 | LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> { | -- ------------------------ opaque type defined here @@ -63,7 +63,7 @@ LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captu | ++++++++++++++++++++++++++++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:30:5 + --> $DIR/hidden-type-suggestion.rs:33:5 | LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized { | --- ---------- opaque type defined here @@ -74,7 +74,7 @@ LL | y | ^ | note: you could use a `use<...>` bound to explicitly capture `'_`, but argument-position `impl Trait`s are not nameable - --> $DIR/hidden-type-suggestion.rs:28:21 + --> $DIR/hidden-type-suggestion.rs:31:21 | LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized { | ^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + fn no_params_yet<T: Sized>(_: T, y: &()) -> impl Sized + use<'_, T> { | error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds - --> $DIR/hidden-type-suggestion.rs:36:5 + --> $DIR/hidden-type-suggestion.rs:39:5 | LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized { | -- ---------- opaque type defined here @@ -96,7 +96,7 @@ LL | y | ^ | note: you could use a `use<...>` bound to explicitly capture `'a`, but argument-position `impl Trait`s are not nameable - --> $DIR/hidden-type-suggestion.rs:34:29 + --> $DIR/hidden-type-suggestion.rs:37:29 | LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized { | ^^^^^^^^^^ diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr new file mode 100644 index 00000000000..308dc9b00fc --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr @@ -0,0 +1,51 @@ +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/hidden-type-suggestion.rs:6:5 + | +LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> { + | -- -------------------- opaque type defined here + | | + | hidden type `&'a ()` captures the lifetime `'a` as defined here +LL | +LL | x + | ^ + | +help: add `'a` to the `use<...>` bound to explicitly capture it + | +LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b, 'a> { + | ++++ + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/hidden-type-suggestion.rs:12:5 + | +LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<T> { + | -- ------------------- opaque type defined here + | | + | hidden type `&'a ()` captures the lifetime `'a` as defined here +LL | +LL | x + | ^ + | +help: add `'a` to the `use<...>` bound to explicitly capture it + | +LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<'a, T> { + | +++ + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/hidden-type-suggestion.rs:18:5 + | +LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<> { + | -- ------------------ opaque type defined here + | | + | hidden type `&'a ()` captures the lifetime `'a` as defined here +LL | +LL | x + | ^ + | +help: add `'a` to the `use<...>` bound to explicitly capture it + | +LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<'a> { + | ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs index d34c6135596..9712eac859a 100644 --- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs +++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> { //~^ HELP add `'a` to the `use<...>` bound x @@ -20,21 +23,21 @@ trait Captures<'a> {} impl<T> Captures<'_> for T {} fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> { -//~^ HELP add a `use<...>` bound +//[edition2015]~^ HELP add a `use<...>` bound x -//~^ ERROR hidden type for +//[edition2015]~^ ERROR hidden type for } fn no_params_yet(_: impl Sized, y: &()) -> impl Sized { -//~^ HELP add a `use<...>` bound +//[edition2015]~^ HELP add a `use<...>` bound y -//~^ ERROR hidden type for +//[edition2015]~^ ERROR hidden type for } fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized { -//~^ HELP add a `use<...>` bound +//[edition2015]~^ HELP add a `use<...>` bound y -//~^ ERROR hidden type for +//[edition2015]~^ ERROR hidden type for } fn main() {} diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.edition2015.stderr index 9fe2bdbcfa2..cd1a9581d30 100644 --- a/tests/ui/imports/import-from-missing-star-2.stderr +++ b/tests/ui/imports/import-from-missing-star-2.edition2015.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `spam` - --> $DIR/import-from-missing-star-2.rs:2:9 + --> $DIR/import-from-missing-star-2.rs:6:9 | LL | use spam::*; | ^^^^ use of unresolved module or unlinked crate `spam` diff --git a/tests/ui/imports/import-from-missing-star-2.edition2024.stderr b/tests/ui/imports/import-from-missing-star-2.edition2024.stderr new file mode 100644 index 00000000000..086b7a576b2 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-2.edition2024.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `spam` + --> $DIR/import-from-missing-star-2.rs:6:9 + | +LL | use spam::*; + | ^^^^ use of unresolved module or unlinked crate `spam` + | + = help: you might be missing a crate named `spam` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/import-from-missing-star-2.rs b/tests/ui/imports/import-from-missing-star-2.rs index cb341b0b0ca..9dad2d4886b 100644 --- a/tests/ui/imports/import-from-missing-star-2.rs +++ b/tests/ui/imports/import-from-missing-star-2.rs @@ -1,5 +1,10 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 mod foo { +//[edition2015]~^ HELP you might be missing a crate named `spam`, add it to your project and import it in your code use spam::*; //~ ERROR unresolved import `spam` [E0432] + //[edition2024]~^ HELP you might be missing a crate named `spam` } fn main() { diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2015.stderr index 0bf9dccfad8..4f1e769bc6c 100644 --- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2015.stderr @@ -1,5 +1,5 @@ error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds - --> $DIR/imply_bounds_from_bounds_param.rs:26:5 + --> $DIR/imply_bounds_from_bounds_param.rs:29:5 | LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne { | -- ------------ opaque type defined here diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr new file mode 100644 index 00000000000..a7135e8f05f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr @@ -0,0 +1,91 @@ +error[E0499]: cannot borrow `z` as mutable more than once at a time + --> $DIR/imply_bounds_from_bounds_param.rs:36:27 + | +LL | let mut thing = test(&mut z); + | ------ first mutable borrow occurs here +LL | let mut thing2 = test(&mut z); + | ^^^^^^ second mutable borrow occurs here +LL | thing.plus_one(); + | ----- first borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/imply_bounds_from_bounds_param.rs:35:21 + | +LL | let mut thing = test(&mut z); + | ^^^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> { + | +++++++ + +error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable + --> $DIR/imply_bounds_from_bounds_param.rs:38:5 + | +LL | let mut thing = test(&mut z); + | ------ mutable borrow occurs here +... +LL | assert_eq!(z, 43); + | ^^^^^^^^^^^^^^^^^ immutable borrow occurs here +... +LL | thing.plus_one(); + | ----- mutable borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/imply_bounds_from_bounds_param.rs:35:21 + | +LL | let mut thing = test(&mut z); + | ^^^^^^^^^^^^ + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> { + | +++++++ + +error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable + --> $DIR/imply_bounds_from_bounds_param.rs:40:5 + | +LL | let mut thing = test(&mut z); + | ------ mutable borrow occurs here +... +LL | assert_eq!(z, 44); + | ^^^^^^^^^^^^^^^^^ immutable borrow occurs here +LL | thing.plus_one(); + | ----- mutable borrow later used here + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/imply_bounds_from_bounds_param.rs:35:21 + | +LL | let mut thing = test(&mut z); + | ^^^^^^^^^^^^ + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> { + | +++++++ + +error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable + --> $DIR/imply_bounds_from_bounds_param.rs:42:5 + | +LL | let mut thing = test(&mut z); + | ------ mutable borrow occurs here +... +LL | assert_eq!(z, 45); + | ^^^^^^^^^^^^^^^^^ immutable borrow occurs here +LL | } + | - mutable borrow might be used here, when `thing` is dropped and runs the destructor for type `impl PlusOne` + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/imply_bounds_from_bounds_param.rs:35:21 + | +LL | let mut thing = test(&mut z); + | ^^^^^^^^^^^^ + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> { + | +++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs index 5d5645077c2..672019ba73a 100644 --- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs +++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs @@ -1,3 +1,6 @@ +//@revisions: edition2015 edition2024 +//@[edition2015] edition:2015 +//@[edition2024] edition:2024 #![feature(impl_trait_in_assoc_type)] trait Callable { @@ -24,17 +27,17 @@ impl<T: PlusOne> Callable for T { fn test<'a>(y: &'a mut i32) -> impl PlusOne { <&'a mut i32 as Callable>::call(y) - //~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds + //[edition2015]~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds } fn main() { let mut z = 42; let mut thing = test(&mut z); - let mut thing2 = test(&mut z); + let mut thing2 = test(&mut z); //[edition2024]~ ERROR cannot borrow `z` as mutable more than once thing.plus_one(); - assert_eq!(z, 43); + assert_eq!(z, 43); //[edition2024]~ ERROR cannot borrow `z` as immutable thing2.plus_one(); - assert_eq!(z, 44); + assert_eq!(z, 44); //[edition2024]~ ERROR cannot borrow `z` as immutable thing.plus_one(); - assert_eq!(z, 45); + assert_eq!(z, 45); //[edition2024]~ ERROR cannot borrow `z` as immutable } |
