diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3b7367d1ee209..100f664a89fd9 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -527,13 +527,13 @@ impl TokenKind { /// Returns tokens that are likely to be typed accidentally instead of the current token. /// Enables better error recovery when the wrong token is found. - pub fn similar_tokens(&self) -> Option> { - match *self { - Comma => Some(vec![Dot, Lt, Semi]), - Semi => Some(vec![Colon, Comma]), - Colon => Some(vec![Semi]), - FatArrow => Some(vec![Eq, RArrow, Ge, Gt]), - _ => None, + pub fn similar_tokens(&self) -> &[TokenKind] { + match self { + Comma => &[Dot, Lt, Semi], + Semi => &[Colon, Comma], + Colon => &[Semi], + FatArrow => &[Eq, RArrow, Ge, Gt], + _ => &[], } } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index a0ab6375a666b..7c746bd719f31 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -101,15 +101,14 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, match p.expect(exp!(Comma)) { Err(err) => { - match token::TokenKind::Comma.similar_tokens() { - Some(tks) if tks.contains(&p.token.kind) => { - // If a similar token is found, then it may be a typo. We - // consider it as a comma, and continue parsing. - err.emit(); - p.bump(); - } + if token::TokenKind::Comma.similar_tokens().contains(&p.token.kind) { + // If a similar token is found, then it may be a typo. We + // consider it as a comma, and continue parsing. + err.emit(); + p.bump(); + } else { // Otherwise stop the parsing and return the error. - _ => return Err(err), + return Err(err); } } Ok(Recovered::Yes(_)) => (), diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 0aa2f1110fb3d..c947ecde65605 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -243,8 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn downgrade_mut_inside_shared(&self) -> bool { // NB: RFC 3627 proposes stabilizing Rule 3 in all editions. If we adopt the same behavior // across all editions, this may be removed. - self.tcx.features().ref_pat_eat_one_layer_2024() - || self.tcx.features().ref_pat_eat_one_layer_2024_structural() + self.tcx.features().ref_pat_eat_one_layer_2024_structural() } /// Experimental pattern feature: when do reference patterns match against inherited references? @@ -435,7 +434,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { #[cfg(debug_assertions)] - if def_br == ByRef::Yes(Mutability::Mut) && max_ref_mutbl != MutblCap::Mut { + if def_br == ByRef::Yes(Mutability::Mut) + && max_ref_mutbl != MutblCap::Mut + && self.downgrade_mut_inside_shared() + { span_bug!(pat.span, "Pattern mutability cap violated!"); } match adjust_mode { @@ -2328,22 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E // but not Rule 5, we'll need to check that here. debug_assert!(ref_pat_matches_mut_ref); - let err_msg = "mismatched types"; - let err = if let Some(span) = pat_prefix_span { - let mut err = self.dcx().struct_span_err(span, err_msg); - err.code(E0308); - err.note("cannot match inherited `&` with `&mut` pattern"); - err.span_suggestion_verbose( - span, - "replace this `&mut` pattern with `&`", - "&", - Applicability::MachineApplicable, - ); - err - } else { - self.dcx().struct_span_err(pat.span, err_msg) - }; - err.emit(); + self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span); } pat_info.binding_mode = ByRef::No; @@ -2352,28 +2339,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } InheritedRefMatchRule::EatInner => { - if let ty::Ref(_, _, r_mutbl) = *expected.kind() { + if let ty::Ref(_, _, r_mutbl) = *expected.kind() + && pat_mutbl <= r_mutbl + { // Match against the reference type; don't consume the inherited ref. - pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl); + // NB: The check for compatible pattern and ref type mutability assumes that + // `&` patterns can match against mutable references (RFC 3627, Rule 5). If + // we implement a pattern typing ruleset with Rule 4 (including the fallback + // to matching the inherited ref when the inner ref can't match) but not + // Rule 5, we'll need to check that here. + debug_assert!(ref_pat_matches_mut_ref); + // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref + // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing + // ruleset with Rule 4 but not Rule 3, we'll need to check that here. + debug_assert!(self.downgrade_mut_inside_shared()); + let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl()); + pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap); } else { - // The expected type isn't a reference, so match against the inherited ref. + // The reference pattern can't match against the expected type, so try + // matching against the inherited ref instead. if pat_mutbl > inh_mut { - // We can't match an inherited shared reference with `&mut`. This will - // be a type error later, since we're matching a reference pattern - // against a non-reference type. + // We can't match an inherited shared reference with `&mut`. // NB: This assumes that `&` patterns can match against mutable // references (RFC 3627, Rule 5). If we implement a pattern typing // ruleset with Rule 4 but not Rule 5, we'll need to check that here. debug_assert!(ref_pat_matches_mut_ref); - } else { - pat_info.binding_mode = ByRef::No; - self.typeck_results - .borrow_mut() - .skipped_ref_pats_mut() - .insert(pat.hir_id); - self.check_pat(inner, expected, pat_info); - return expected; + self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span); } + + pat_info.binding_mode = ByRef::No; + self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; } } InheritedRefMatchRule::EatBoth => { @@ -2447,6 +2444,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_ref(self.tcx, region, ty, mutbl) } + fn error_inherited_ref_mutability_mismatch( + &self, + pat: &'tcx Pat<'tcx>, + pat_prefix_span: Option, + ) -> ErrorGuaranteed { + let err_msg = "mismatched types"; + let err = if let Some(span) = pat_prefix_span { + let mut err = self.dcx().struct_span_err(span, err_msg); + err.code(E0308); + err.note("cannot match inherited `&` with `&mut` pattern"); + err.span_suggestion_verbose( + span, + "replace this `&mut` pattern with `&`", + "&", + Applicability::MachineApplicable, + ); + err + } else { + self.dcx().struct_span_err(pat.span, err_msg) + }; + err.emit() + } + fn try_resolve_slice_ty_to_array_ty( &self, before: &'tcx [Pat<'tcx>], diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0d41a1d7dbfba..b212992bd2dd7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -504,6 +504,9 @@ impl<'tcx> SizeSkeleton<'tcx> { } } + // Pattern types are always the same size as their base. + ty::Pat(base, _) => SizeSkeleton::compute(base, tcx, typing_env), + _ => Err(err), } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a5b73ce4098ed..ffd46f20767e3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3114,9 +3114,8 @@ impl<'a> Parser<'a> { let span_before_body = this.prev_token.span; let arm_body; let is_fat_arrow = this.check(exp!(FatArrow)); - let is_almost_fat_arrow = TokenKind::FatArrow - .similar_tokens() - .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)); + let is_almost_fat_arrow = + TokenKind::FatArrow.similar_tokens().contains(&this.token.kind); // this avoids the compiler saying that a `,` or `}` was expected even though // the pattern isn't a never pattern (and thus an arm body is required) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 714a60cb179e4..faebb5a40bb15 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -924,10 +924,8 @@ impl<'a> Parser<'a> { _ => { // Attempt to keep parsing if it was a similar separator. - if let Some(tokens) = exp.tok.similar_tokens() { - if tokens.contains(&self.token.kind) { - self.bump(); - } + if exp.tok.similar_tokens().contains(&self.token.kind) { + self.bump(); } } } diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 09c88e7f83bb6..d021ea107ed28 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -363,12 +363,7 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err, S2: Into>( - &mut self, - description: S1, - label: S2, - span: InnerSpan, - ) { + fn err(&mut self, description: impl Into, label: impl Into, span: InnerSpan) { self.errors.push(ParseError { description: description.into(), note: None, @@ -382,11 +377,11 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err_with_note, S2: Into, S3: Into>( + fn err_with_note( &mut self, - description: S1, - label: S2, - note: S3, + description: impl Into, + label: impl Into, + note: impl Into, span: InnerSpan, ) { self.errors.push(ParseError { diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index acd00d9f74f56..abb794934324e 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::{ Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues, @@ -98,9 +98,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< param_env: ty::ParamEnv<'tcx>, arg: ty::GenericArg<'tcx>, ) -> Option>>> { - crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg).map(|obligations| { - obligations.into_iter().map(|obligation| obligation.into()).collect() - }) + crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .map(|obligations| { + obligations.into_iter().map(|obligation| obligation.into()).collect() + }) } fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 2b7da4bc5ff07..0db44eda8470e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,25 +1,21 @@ use std::marker::PhantomData; use std::mem; -use std::ops::ControlFlow; use rustc_data_structures::thinvec::ExtractIf; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, PredicateObligation, PredicateObligations, SelectionError, TraitEngine, + FromSolverError, PredicateObligation, PredicateObligations, TraitEngine, }; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; -use tracing::{instrument, trace}; +use tracing::instrument; +use self::derive_errors::*; use super::Certainty; use super::delegate::SolverDelegate; -use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError}; +use crate::traits::{FulfillmentError, ScrubbedTraitError}; + +mod derive_errors; /// A trait engine using the new trait solver. /// @@ -244,483 +240,3 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError<' } } } - -fn fulfillment_error_for_no_solution<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - let obligation = find_best_leaf_obligation(infcx, &root_obligation, false); - - let code = match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::Project( - // FIXME: This could be a `Sorts` if the term is a type - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { - let ct_ty = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { - infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) - } - ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), - ty::ConstKind::Value(ty, _) => ty, - kind => span_bug!( - obligation.cause.span, - "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}" - ), - }; - FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType { - ct, - ct_ty, - expected_ty, - }) - } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(a, b); - FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) - } - ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(b, a); - FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) - } - ty::PredicateKind::Clause(_) - | ty::PredicateKind::DynCompatible(_) - | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::Select(SelectionError::Unimplemented) - } - ty::PredicateKind::ConstEquate(..) => { - bug!("unexpected goal: {obligation:?}") - } - }; - - FulfillmentError { obligation, code, root_obligation } -} - -fn fulfillment_error_for_stalled<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - let (code, refine_obligation) = infcx.probe(|_| { - match <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No) - .0 - { - Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { - (FulfillmentErrorCode::Ambiguity { overflow: None }, true) - } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( - FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, - // Don't look into overflows because we treat overflows weirdly anyways. - // We discard the inference constraints from overflowing goals, so - // recomputing the goal again during `find_best_leaf_obligation` may apply - // inference guidance that makes other goals go from ambig -> pass, for example. - // - // FIXME: We should probably just look into overflows here. - false, - ), - Ok((_, Certainty::Yes)) => { - bug!("did not expect successful goal when collecting ambiguity errors") - } - Err(_) => { - bug!("did not expect selection error when collecting ambiguity errors") - } - } - }); - - FulfillmentError { - obligation: if refine_obligation { - find_best_leaf_obligation(infcx, &root_obligation, true) - } else { - root_obligation.clone() - }, - code, - root_obligation, - } -} - -fn fulfillment_error_for_overflow<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &root_obligation, true), - code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - root_obligation, - } -} - -fn find_best_leaf_obligation<'tcx>( - infcx: &InferCtxt<'tcx>, - obligation: &PredicateObligation<'tcx>, - consider_ambiguities: bool, -) -> PredicateObligation<'tcx> { - let obligation = infcx.resolve_vars_if_possible(obligation.clone()); - // FIXME: we use a probe here as the `BestObligation` visitor does not - // check whether it uses candidates which get shadowed by where-bounds. - // - // We should probably fix the visitor to not do so instead, as this also - // means the leaf obligation may be incorrect. - infcx - .fudge_inference_if_ok(|| { - infcx - .visit_proof_tree(obligation.clone().into(), &mut BestObligation { - obligation: obligation.clone(), - consider_ambiguities, - }) - .break_value() - .ok_or(()) - }) - .unwrap_or(obligation) -} - -struct BestObligation<'tcx> { - obligation: PredicateObligation<'tcx>, - consider_ambiguities: bool, -} - -impl<'tcx> BestObligation<'tcx> { - fn with_derived_obligation( - &mut self, - derived_obligation: PredicateObligation<'tcx>, - and_then: impl FnOnce(&mut Self) -> >::Result, - ) -> >::Result { - let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); - let res = and_then(self); - self.obligation = old_obligation; - res - } - - /// Filter out the candidates that aren't interesting to visit for the - /// purposes of reporting errors. For ambiguities, we only consider - /// candidates that may hold. For errors, we only consider candidates that - /// *don't* hold and which have impl-where clauses that also don't hold. - fn non_trivial_candidates<'a>( - &self, - goal: &'a inspect::InspectGoal<'a, 'tcx>, - ) -> Vec> { - let mut candidates = goal.candidates(); - match self.consider_ambiguities { - true => { - // If we have an ambiguous obligation, we must consider *all* candidates - // that hold, or else we may guide inference causing other goals to go - // from ambig -> pass/fail. - candidates.retain(|candidate| candidate.result().is_ok()); - } - false => { - // If we have >1 candidate, one may still be due to "boring" reasons, like - // an alias-relate that failed to hold when deeply evaluated. We really - // don't care about reasons like this. - if candidates.len() > 1 { - candidates.retain(|candidate| { - goal.infcx().probe(|_| { - candidate.instantiate_nested_goals(self.span()).iter().any( - |nested_goal| { - matches!( - nested_goal.source(), - GoalSource::ImplWhereBound - | GoalSource::AliasBoundConstCondition - | GoalSource::InstantiateHigherRanked - | GoalSource::AliasWellFormed - ) && match self.consider_ambiguities { - true => { - matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) - } - false => matches!(nested_goal.result(), Err(_)), - } - }, - ) - }) - }); - } - - // Prefer a non-rigid candidate if there is one. - if candidates.len() > 1 { - candidates.retain(|candidate| { - !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. }) - }); - } - } - } - - candidates - } -} - -impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { - type Result = ControlFlow>; - - fn span(&self) -> rustc_span::Span { - self.obligation.cause.span - } - - #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))] - fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { - let candidates = self.non_trivial_candidates(goal); - trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::>()); - - let [candidate] = candidates.as_slice() else { - return ControlFlow::Break(self.obligation.clone()); - }; - - // Don't walk into impls that have `do_not_recommend`. - if let inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } = candidate.kind() - && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) - { - return ControlFlow::Break(self.obligation.clone()); - } - - let tcx = goal.infcx().tcx; - // FIXME: Also, what about considering >1 layer up the stack? May be necessary - // for normalizes-to. - let pred_kind = goal.goal().predicate.kind(); - let child_mode = match pred_kind.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - ChildMode::Trait(pred_kind.rebind(pred)) - } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { - ChildMode::Host(pred_kind.rebind(pred)) - } - ty::PredicateKind::NormalizesTo(normalizes_to) - if matches!( - normalizes_to.alias.kind(tcx), - ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst - ) => - { - ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { - trait_ref: normalizes_to.alias.trait_ref(tcx), - polarity: ty::PredicatePolarity::Positive, - })) - } - _ => ChildMode::PassThrough, - }; - - let nested_goals = candidate.instantiate_nested_goals(self.span()); - - // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as - // an actual candidate, instead we should treat them as if the impl was never considered to - // have potentially applied. As if `impl Trait for for<..> fn(..A) -> R` was written - // instead of `impl Trait for T`. - // - // We do this as a separate loop so that we do not choose to tell the user about some nested - // goal before we encounter a `T: FnPtr` nested goal. - for nested_goal in &nested_goals { - if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait() - && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause() - && poly_trait_pred.def_id() == fn_ptr_trait - && let Err(NoSolution) = nested_goal.result() - { - return ControlFlow::Break(self.obligation.clone()); - } - } - - let mut impl_where_bound_count = 0; - for nested_goal in nested_goals { - trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); - - let make_obligation = |cause| Obligation { - cause, - param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, - recursion_depth: self.obligation.recursion_depth + 1, - }; - - let obligation; - match (child_mode, nested_goal.source()) { - (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => { - continue; - } - (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { - obligation = make_obligation(derive_cause( - tcx, - candidate.kind(), - self.obligation.cause.clone(), - impl_where_bound_count, - parent_trait_pred, - )); - impl_where_bound_count += 1; - } - ( - ChildMode::Host(parent_host_pred), - GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, - ) => { - obligation = make_obligation(derive_host_cause( - tcx, - candidate.kind(), - self.obligation.cause.clone(), - impl_where_bound_count, - parent_host_pred, - )); - impl_where_bound_count += 1; - } - // Skip over a higher-ranked predicate. - (_, GoalSource::InstantiateHigherRanked) => { - obligation = self.obligation.clone(); - } - (ChildMode::PassThrough, _) - | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { - obligation = make_obligation(self.obligation.cause.clone()); - } - } - - // Skip nested goals that aren't the *reason* for our goal's failure. - match self.consider_ambiguities { - true if matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) => {} - false if matches!(nested_goal.result(), Err(_)) => {} - _ => continue, - } - - self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; - } - - // alias-relate may fail because the lhs or rhs can't be normalized, - // and therefore is treated as rigid. - if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { - if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } else if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } - } - - ControlFlow::Break(self.obligation.clone()) - } -} - -#[derive(Debug, Copy, Clone)] -enum ChildMode<'tcx> { - // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, - // and skip all `GoalSource::Misc`, which represent useless obligations - // such as alias-eq which may not hold. - Trait(ty::PolyTraitPredicate<'tcx>), - // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, - // and skip all `GoalSource::Misc`, which represent useless obligations - // such as alias-eq which may not hold. - Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>), - // Skip trying to derive an `ObligationCause` from this obligation, and - // report *all* sub-obligations as if they came directly from the parent - // obligation. - PassThrough, -} - -fn derive_cause<'tcx>( - tcx: TyCtxt<'tcx>, - candidate_kind: inspect::ProbeKind>, - mut cause: ObligationCause<'tcx>, - idx: usize, - parent_trait_pred: ty::PolyTraitPredicate<'tcx>, -) -> ObligationCause<'tcx> { - match candidate_kind { - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } => { - if let Some((_, span)) = - tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) - { - cause = cause.derived_cause(parent_trait_pred, |derived| { - ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause { - derived, - impl_or_alias_def_id: impl_def_id, - impl_def_predicate_index: Some(idx), - span, - })) - }) - } - } - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(..), - result: _, - } => { - cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived); - } - _ => {} - }; - cause -} - -fn derive_host_cause<'tcx>( - tcx: TyCtxt<'tcx>, - candidate_kind: inspect::ProbeKind>, - mut cause: ObligationCause<'tcx>, - idx: usize, - parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, -) -> ObligationCause<'tcx> { - match candidate_kind { - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } => { - if let Some((_, span)) = tcx - .predicates_of(impl_def_id) - .instantiate_identity(tcx) - .into_iter() - .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map( - |(trait_ref, span)| { - ( - trait_ref.to_host_effect_clause( - tcx, - parent_host_pred.skip_binder().constness, - ), - span, - ) - }, - )) - .nth(idx) - { - cause = - cause.derived_host_cause(parent_host_pred, |derived| { - ObligationCauseCode::ImplDerivedHost(Box::new( - traits::ImplDerivedHostCause { derived, impl_def_id, span }, - )) - }) - } - } - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(..), - result: _, - } => { - cause = - cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost); - } - _ => {} - }; - cause -} diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs new file mode 100644 index 0000000000000..d13e5a1669421 --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -0,0 +1,527 @@ +use std::ops::ControlFlow; + +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; +use rustc_infer::traits::{ + self, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, + PredicateObligation, SelectionError, +}; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{bug, span_bug}; +use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; +use rustc_type_ir::solve::{Goal, NoSolution}; +use tracing::{instrument, trace}; + +use crate::solve::Certainty; +use crate::solve::delegate::SolverDelegate; +use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; + +pub(super) fn fulfillment_error_for_no_solution<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + let obligation = find_best_leaf_obligation(infcx, &root_obligation, false); + + let code = match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + FulfillmentErrorCode::Project( + // FIXME: This could be a `Sorts` if the term is a type + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { + let ct_ty = match ct.kind() { + ty::ConstKind::Unevaluated(uv) => { + infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) + } + ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), + ty::ConstKind::Value(ty, _) => ty, + kind => span_bug!( + obligation.cause.span, + "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}" + ), + }; + FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType { + ct, + ct_ty, + expected_ty, + }) + } + ty::PredicateKind::NormalizesTo(..) => { + FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) + } + ty::PredicateKind::AliasRelate(_, _, _) => { + FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) + } + ty::PredicateKind::Subtype(pred) => { + let (a, b) = infcx.enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(a, b); + FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) + } + ty::PredicateKind::Coerce(pred) => { + let (a, b) = infcx.enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(b, a); + FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) + } + ty::PredicateKind::Clause(_) + | ty::PredicateKind::DynCompatible(_) + | ty::PredicateKind::Ambiguous => { + FulfillmentErrorCode::Select(SelectionError::Unimplemented) + } + ty::PredicateKind::ConstEquate(..) => { + bug!("unexpected goal: {obligation:?}") + } + }; + + FulfillmentError { obligation, code, root_obligation } +} + +pub(super) fn fulfillment_error_for_stalled<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + let (code, refine_obligation) = infcx.probe(|_| { + match <&SolverDelegate<'tcx>>::from(infcx) + .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No) + .0 + { + Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { + (FulfillmentErrorCode::Ambiguity { overflow: None }, true) + } + Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, + // Don't look into overflows because we treat overflows weirdly anyways. + // We discard the inference constraints from overflowing goals, so + // recomputing the goal again during `find_best_leaf_obligation` may apply + // inference guidance that makes other goals go from ambig -> pass, for example. + // + // FIXME: We should probably just look into overflows here. + false, + ), + Ok((_, Certainty::Yes)) => { + bug!("did not expect successful goal when collecting ambiguity errors") + } + Err(_) => { + bug!("did not expect selection error when collecting ambiguity errors") + } + } + }); + + FulfillmentError { + obligation: if refine_obligation { + find_best_leaf_obligation(infcx, &root_obligation, true) + } else { + root_obligation.clone() + }, + code, + root_obligation, + } +} + +pub(super) fn fulfillment_error_for_overflow<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &root_obligation, true), + code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, + root_obligation, + } +} + +fn find_best_leaf_obligation<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, + consider_ambiguities: bool, +) -> PredicateObligation<'tcx> { + let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + // FIXME: we use a probe here as the `BestObligation` visitor does not + // check whether it uses candidates which get shadowed by where-bounds. + // + // We should probably fix the visitor to not do so instead, as this also + // means the leaf obligation may be incorrect. + infcx + .fudge_inference_if_ok(|| { + infcx + .visit_proof_tree(obligation.clone().into(), &mut BestObligation { + obligation: obligation.clone(), + consider_ambiguities, + }) + .break_value() + .ok_or(()) + }) + .unwrap_or(obligation) +} + +struct BestObligation<'tcx> { + obligation: PredicateObligation<'tcx>, + consider_ambiguities: bool, +} + +impl<'tcx> BestObligation<'tcx> { + fn with_derived_obligation( + &mut self, + derived_obligation: PredicateObligation<'tcx>, + and_then: impl FnOnce(&mut Self) -> >::Result, + ) -> >::Result { + let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); + let res = and_then(self); + self.obligation = old_obligation; + res + } + + /// Filter out the candidates that aren't interesting to visit for the + /// purposes of reporting errors. For ambiguities, we only consider + /// candidates that may hold. For errors, we only consider candidates that + /// *don't* hold and which have impl-where clauses that also don't hold. + fn non_trivial_candidates<'a>( + &self, + goal: &'a inspect::InspectGoal<'a, 'tcx>, + ) -> Vec> { + let mut candidates = goal.candidates(); + match self.consider_ambiguities { + true => { + // If we have an ambiguous obligation, we must consider *all* candidates + // that hold, or else we may guide inference causing other goals to go + // from ambig -> pass/fail. + candidates.retain(|candidate| candidate.result().is_ok()); + } + false => { + // If we have >1 candidate, one may still be due to "boring" reasons, like + // an alias-relate that failed to hold when deeply evaluated. We really + // don't care about reasons like this. + if candidates.len() > 1 { + candidates.retain(|candidate| { + goal.infcx().probe(|_| { + candidate.instantiate_nested_goals(self.span()).iter().any( + |nested_goal| { + matches!( + nested_goal.source(), + GoalSource::ImplWhereBound + | GoalSource::AliasBoundConstCondition + | GoalSource::InstantiateHigherRanked + | GoalSource::AliasWellFormed + ) && match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) + | (false, Err(_)) => true, + _ => false, + } + }, + ) + }) + }); + } + + // Prefer a non-rigid candidate if there is one. + if candidates.len() > 1 { + candidates.retain(|candidate| { + !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. }) + }); + } + } + } + + candidates + } + + /// HACK: We walk the nested obligations for a well-formed arg manually, + /// since there's nontrivial logic in `wf.rs` to set up an obligation cause. + /// Ideally we'd be able to track this better. + fn visit_well_formed_goal( + &mut self, + candidate: &inspect::InspectCandidate<'_, 'tcx>, + arg: ty::GenericArg<'tcx>, + ) -> ControlFlow> { + let infcx = candidate.goal().infcx(); + let param_env = candidate.goal().goal().param_env; + let body_id = self.obligation.cause.body_id; + + for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id) + .into_iter() + .flatten() + { + let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( + GoalSource::Misc, + Goal::new(infcx.tcx, obligation.param_env, obligation.predicate), + self.span(), + ); + // Skip nested goals that aren't the *reason* for our goal's failure. + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} + _ => continue, + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + ControlFlow::Break(self.obligation.clone()) + } +} + +impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { + type Result = ControlFlow>; + + fn span(&self) -> rustc_span::Span { + self.obligation.cause.span + } + + #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))] + fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + let candidates = self.non_trivial_candidates(goal); + trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::>()); + + let [candidate] = candidates.as_slice() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + // Don't walk into impls that have `do_not_recommend`. + if let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } = candidate.kind() + && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) + { + return ControlFlow::Break(self.obligation.clone()); + } + + let tcx = goal.infcx().tcx; + // FIXME: Also, what about considering >1 layer up the stack? May be necessary + // for normalizes-to. + let pred_kind = goal.goal().predicate.kind(); + let child_mode = match pred_kind.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ChildMode::Trait(pred_kind.rebind(pred)) + } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { + ChildMode::Host(pred_kind.rebind(pred)) + } + ty::PredicateKind::NormalizesTo(normalizes_to) + if matches!( + normalizes_to.alias.kind(tcx), + ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst + ) => + { + ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { + trait_ref: normalizes_to.alias.trait_ref(tcx), + polarity: ty::PredicatePolarity::Positive, + })) + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + return self.visit_well_formed_goal(candidate, arg); + } + _ => ChildMode::PassThrough, + }; + + let nested_goals = candidate.instantiate_nested_goals(self.span()); + + // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as + // an actual candidate, instead we should treat them as if the impl was never considered to + // have potentially applied. As if `impl Trait for for<..> fn(..A) -> R` was written + // instead of `impl Trait for T`. + // + // We do this as a separate loop so that we do not choose to tell the user about some nested + // goal before we encounter a `T: FnPtr` nested goal. + for nested_goal in &nested_goals { + if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait() + && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause() + && poly_trait_pred.def_id() == fn_ptr_trait + && let Err(NoSolution) = nested_goal.result() + { + return ControlFlow::Break(self.obligation.clone()); + } + } + + let mut impl_where_bound_count = 0; + for nested_goal in nested_goals { + trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); + + let make_obligation = |cause| Obligation { + cause, + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + + let obligation; + match (child_mode, nested_goal.source()) { + (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => { + continue; + } + (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { + obligation = make_obligation(derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + )); + impl_where_bound_count += 1; + } + ( + ChildMode::Host(parent_host_pred), + GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, + ) => { + obligation = make_obligation(derive_host_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_host_pred, + )); + impl_where_bound_count += 1; + } + // Skip over a higher-ranked predicate. + (_, GoalSource::InstantiateHigherRanked) => { + obligation = self.obligation.clone(); + } + (ChildMode::PassThrough, _) + | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { + obligation = make_obligation(self.obligation.cause.clone()); + } + } + + // Skip nested goals that aren't the *reason* for our goal's failure. + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} + _ => continue, + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + // alias-relate may fail because the lhs or rhs can't be normalized, + // and therefore is treated as rigid. + if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { + if let Some(obligation) = goal + .infcx() + .visit_proof_tree_at_depth( + goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())), + goal.depth() + 1, + self, + ) + .break_value() + { + return ControlFlow::Break(obligation); + } else if let Some(obligation) = goal + .infcx() + .visit_proof_tree_at_depth( + goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())), + goal.depth() + 1, + self, + ) + .break_value() + { + return ControlFlow::Break(obligation); + } + } + + ControlFlow::Break(self.obligation.clone()) + } +} + +#[derive(Debug, Copy, Clone)] +enum ChildMode<'tcx> { + // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, + // and skip all `GoalSource::Misc`, which represent useless obligations + // such as alias-eq which may not hold. + Trait(ty::PolyTraitPredicate<'tcx>), + // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, + // and skip all `GoalSource::Misc`, which represent useless obligations + // such as alias-eq which may not hold. + Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>), + // Skip trying to derive an `ObligationCause` from this obligation, and + // report *all* sub-obligations as if they came directly from the parent + // obligation. + PassThrough, +} + +fn derive_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: inspect::ProbeKind>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, +) -> ObligationCause<'tcx> { + match candidate_kind { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } => { + if let Some((_, span)) = + tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) + { + cause = cause.derived_cause(parent_trait_pred, |derived| { + ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause { + derived, + impl_or_alias_def_id: impl_def_id, + impl_def_predicate_index: Some(idx), + span, + })) + }) + } + } + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::BuiltinImpl(..), + result: _, + } => { + cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived); + } + _ => {} + }; + cause +} + +fn derive_host_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: inspect::ProbeKind>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, +) -> ObligationCause<'tcx> { + match candidate_kind { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } => { + if let Some((_, span)) = tcx + .predicates_of(impl_def_id) + .instantiate_identity(tcx) + .into_iter() + .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map( + |(trait_ref, span)| { + ( + trait_ref.to_host_effect_clause( + tcx, + parent_host_pred.skip_binder().constness, + ), + span, + ) + }, + )) + .nth(idx) + { + cause = + cause.derived_host_cause(parent_host_pred, |derived| { + ObligationCauseCode::ImplDerivedHost(Box::new( + traits::ImplDerivedHostCause { derived, impl_def_id, span }, + )) + }) + } + } + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::BuiltinImpl(..), + result: _, + } => { + cause = + cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost); + } + _ => {} + }; + cause +} diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index e735020a63e66..9ba48cd588fa1 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -194,47 +194,57 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let goals = instantiated_goals .into_iter() - .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.unpack() { - ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(_) => infcx.next_const_var(span).into(), - }; - let goal = - goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); - // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the - // expected term. This means that candidates which only fail due to nested goals - // and which normalize to a different term then the final result could ICE: when - // building their proof tree, the expected term was unconstrained, but when - // instantiating the candidate it is already constrained to the result of another - // candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); - InspectGoal::new( - infcx, - self.goal.depth + 1, - proof_tree.unwrap(), - Some(NormalizesToTermHack { term, unconstrained_term }), - source, - ) - } - _ => { - // We're using a probe here as evaluating a goal could constrain - // inference variables by choosing one candidate. If we then recurse - // into another candidate who ends up with different inference - // constraints, we get an ICE if we already applied the constraints - // from the chosen candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) - .unwrap(); - InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) - } - }) + .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span)) .collect(); (goals, opt_impl_args) } + pub fn instantiate_proof_tree_for_nested_goal( + &self, + source: GoalSource, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + span: Span, + ) -> InspectGoal<'a, 'tcx> { + let infcx = self.goal.infcx; + match goal.predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { + let unconstrained_term = match term.unpack() { + ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), + ty::TermKind::Const(_) => infcx.next_const_var(span).into(), + }; + let goal = + goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); + // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the + // expected term. This means that candidates which only fail due to nested goals + // and which normalize to a different term then the final result could ICE: when + // building their proof tree, the expected term was unconstrained, but when + // instantiating the candidate it is already constrained to the result of another + // candidate. + let proof_tree = + infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); + InspectGoal::new( + infcx, + self.goal.depth + 1, + proof_tree.unwrap(), + Some(NormalizesToTermHack { term, unconstrained_term }), + source, + ) + } + _ => { + // We're using a probe here as evaluating a goal could constrain + // inference variables by choosing one candidate. If we then recurse + // into another candidate who ends up with different inference + // constraints, we get an ICE if we already applied the constraints + // from the chosen candidate. + let proof_tree = infcx + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) + .unwrap(); + InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) + } + } + } + /// Visit all nested goals of this candidate, rolling back /// all inference constraints. pub fn visit_nested_in_probe>(&self, visitor: &mut V) -> V::Result { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fe5ad003a7e43..b9d03c4265596 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -76,6 +76,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::regions::InferCtxtRegionExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +#[derive(Debug)] pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, @@ -107,12 +108,6 @@ impl<'tcx> FulfillmentError<'tcx> { } } -impl<'tcx> Debug for FulfillmentError<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code) - } -} - #[derive(Clone)] pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 1339739ce7f5e..ec0b790339691 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -5,8 +5,8 @@ use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; -use rustc_span::Span; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::{DUMMY_SP, Span}; use rustc_type_ir::outlives::{Component, push_outlives_components}; use smallvec::{SmallVec, smallvec}; use tracing::debug; @@ -92,7 +92,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // From the full set of obligations, just filter down to the region relationships. for obligation in - wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten() + wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .into_iter() + .flatten() { assert!(!obligation.has_escaping_bound_vars()); let Some(pred) = obligation.predicate.kind().no_bound_vars() else { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 20b675bcb76b7..37d49cc2f555f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -8,8 +8,8 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; +use rustc_span::def_id::{DefId, LocalDefId}; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -89,6 +89,8 @@ pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, + span: Span, + body_id: LocalDefId, ) -> Option> { debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); @@ -106,8 +108,8 @@ pub fn unnormalized_obligations<'tcx>( let mut wf = WfPredicates { infcx, param_env, - body_id: CRATE_DEF_ID, - span: DUMMY_SP, + body_id, + span, out: PredicateObligations::new(), recursion_depth: 0, item: None, diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh index 4a7dad0090b2e..fe7a3b2dc2fc6 100755 --- a/src/ci/scripts/free-disk-space.sh +++ b/src/ci/scripts/free-disk-space.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail # Free disk space on Linux GitHub action runners # Script inspired by https://github.com/jlumbroso/free-disk-space @@ -14,11 +15,15 @@ printSeparationLine() { # compute available space # REF: https://unix.stackexchange.com/a/42049/60849 # REF: https://stackoverflow.com/a/450821/408734 -getAvailableSpace() { echo $(df -a | awk 'NR > 1 {avail+=$4} END {print avail}'); } +getAvailableSpace() { + df -a | awk 'NR > 1 {avail+=$4} END {print avail}' +} # make Kb human readable (assume the input is Kb) # REF: https://unix.stackexchange.com/a/44087/60849 -formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); } +formatByteCount() { + numfmt --to=iec-i --suffix=B --padding=7 "$1"'000' +} # macro to output saved space printSavedSpace() { @@ -58,11 +63,27 @@ removeDir() { dir=${1} local before - before=$(getAvailableSpace) + if [ ! -d "$dir" ]; then + echo "::warning::Directory $dir does not exist, skipping." + else + before=$(getAvailableSpace) + sudo rm -rf "$dir" + printSavedSpace "$before" "Removed $dir" + fi +} - sudo rm -rf "$dir" || true +removeUnusedDirectories() { + local dirs_to_remove=( + "/usr/local/lib/android" + "/usr/share/dotnet" - printSavedSpace "$before" "$dir" + # Haskell runtime + "/usr/local/.ghcup" + ) + + for dir in "${dirs_to_remove[@]}"; do + removeDir "$dir" + done } execAndMeasureSpaceChange() { @@ -101,9 +122,9 @@ cleanPackages() { # Remove Docker images cleanDocker() { - echo "Removing the following docker images:" + echo "=> Removing the following docker images:" sudo docker image ls - echo "Removing docker images..." + echo "=> Removing docker images..." sudo docker image prune --all --force || true } @@ -121,17 +142,12 @@ AVAILABLE_INITIAL=$(getAvailableSpace) printDF "BEFORE CLEAN-UP:" echo "" -removeDir /usr/local/lib/android -removeDir /usr/share/dotnet - -# Haskell runtime -removeDir /opt/ghc -removeDir /usr/local/.ghcup - -execAndMeasureSpaceChange cleanPackages "Large misc. packages" +execAndMeasureSpaceChange cleanPackages "Unused packages" execAndMeasureSpaceChange cleanDocker "Docker images" execAndMeasureSpaceChange cleanSwap "Swap storage" +removeUnusedDirectories + # Output saved space statistic echo "" printDF "AFTER CLEAN-UP:" diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md new file mode 100644 index 0000000000000..bc58768611175 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md @@ -0,0 +1,19 @@ +# `ref_pat_eat_one_layer_2024_structural` + +The tracking issue for this feature is: [#123076] + +[#123076]: https://github.com/rust-lang/rust/issues/123076 + +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust. +For more information, see the corresponding typing rules for [Editions 2024 and later]. +On earlier Editions, the current behavior is unspecified. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md). + +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md new file mode 100644 index 0000000000000..43de1849a5ebb --- /dev/null +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md @@ -0,0 +1,19 @@ +# `ref_pat_eat_one_layer_2024` + +The tracking issue for this feature is: [#123076] + +[#123076]: https://github.com/rust-lang/rust/issues/123076 + +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust. +For more information, see the corresponding typing rules for [Editions 2024 and later]. +On earlier Editions, the current behavior is unspecified. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md). + +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index acdb3cbdd4590..71496444660f5 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -177,6 +177,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-bpf", "only-cdb", "only-dist", + "only-emscripten", "only-gnu", "only-i686-pc-windows-gnu", "only-i686-pc-windows-msvc", diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs index 514d35433e12d..562a8e6c9e9ba 100644 --- a/tests/codegen/float/f128.rs +++ b/tests/codegen/float/f128.rs @@ -1,11 +1,15 @@ // 32-bit x86 returns float types differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: x86 bit32 bit64 +// Emscripten aligns f128 to 8 bytes, not 16. +//@ revisions: x86 bit32 bit64 emscripten //@[x86] only-x86 //@[bit32] ignore-x86 +//@[bit32] ignore-emscripten //@[bit32] only-32bit //@[bit64] ignore-x86 +//@[bit64] ignore-emscripten //@[bit64] only-64bit +//@[emscripten] only-emscripten // Verify that our intrinsics generate the correct LLVM calls for f128 @@ -59,6 +63,7 @@ pub fn f128_le(a: f128, b: f128) -> bool { // x86-LABEL: void @f128_neg({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_neg({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_neg( +// emscripten-LABEL: void @f128_neg({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_neg(a: f128) -> f128 { // CHECK: fneg fp128 @@ -68,6 +73,7 @@ pub fn f128_neg(a: f128) -> f128 { // x86-LABEL: void @f128_add({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_add({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_add( +// emscripten-LABEL: void @f128_add({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_add(a: f128, b: f128) -> f128 { // CHECK: fadd fp128 %{{.+}}, %{{.+}} @@ -77,6 +83,7 @@ pub fn f128_add(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_sub({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_sub({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_sub( +// emscripten-LABEL: void @f128_sub({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_sub(a: f128, b: f128) -> f128 { // CHECK: fsub fp128 %{{.+}}, %{{.+}} @@ -86,6 +93,7 @@ pub fn f128_sub(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_mul({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_mul({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_mul( +// emscripten-LABEL: void @f128_mul({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_mul(a: f128, b: f128) -> f128 { // CHECK: fmul fp128 %{{.+}}, %{{.+}} @@ -95,6 +103,7 @@ pub fn f128_mul(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_div({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_div({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_div( +// emscripten-LABEL: void @f128_div({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_div(a: f128, b: f128) -> f128 { // CHECK: fdiv fp128 %{{.+}}, %{{.+}} @@ -104,6 +113,7 @@ pub fn f128_div(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_rem({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_rem({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_rem( +// emscripten-LABEL: void @f128_rem({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_rem(a: f128, b: f128) -> f128 { // CHECK: frem fp128 %{{.+}}, %{{.+}} @@ -164,6 +174,7 @@ pub fn f128_as_f16(a: f128) -> f16 { // x86-LABEL: i32 @f128_as_f32( // bit32-LABEL: float @f128_as_f32( // bit64-LABEL: float @f128_as_f32( +// emscripten-LABEL: float @f128_as_f32( #[no_mangle] pub fn f128_as_f32(a: f128) -> f32 { // CHECK: fptrunc fp128 %{{.+}} to float @@ -173,6 +184,7 @@ pub fn f128_as_f32(a: f128) -> f32 { // x86-LABEL: void @f128_as_f64( // bit32-LABEL: double @f128_as_f64( // bit64-LABEL: double @f128_as_f64( +// emscripten-LABEL: double @f128_as_f64( #[no_mangle] pub fn f128_as_f64(a: f128) -> f64 { // CHECK: fptrunc fp128 %{{.+}} to double @@ -182,17 +194,20 @@ pub fn f128_as_f64(a: f128) -> f64 { // x86-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_as_self( +// emscripten-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_self(a: f128) -> f128 { // x86: store fp128 %a, ptr %_0, align 16 // bit32: store fp128 %a, ptr %_0, align 16 // bit64: ret fp128 %{{.+}} + // emscripten: store fp128 %a, ptr %_0, align 8 a as f128 } // x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f16_as_f128( +// emscripten-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f16_as_f128(a: f16) -> f128 { // CHECK: fpext half %{{.+}} to fp128 @@ -202,6 +217,7 @@ pub fn f16_as_f128(a: f16) -> f128 { // x86-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f32_as_f128( +// emscripten-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f32_as_f128(a: f32) -> f128 { // CHECK: fpext float %{{.+}} to fp128 @@ -211,6 +227,7 @@ pub fn f32_as_f128(a: f32) -> f128 { // x86-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f64_as_f128( +// emscripten-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f64_as_f128(a: f64) -> f128 { // CHECK: fpext double %{{.+}} to fp128 @@ -249,6 +266,7 @@ pub fn f128_as_u64(a: f128) -> u64 { // x86-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_u128( +// emscripten-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_u128(a: f128) -> u128 { // CHECK: call i128 @llvm.fptoui.sat.i128.f128(fp128 %{{.+}}) @@ -285,6 +303,7 @@ pub fn f128_as_i64(a: f128) -> i64 { // x86-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_i128( +// emscripten-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_i128(a: f128) -> i128 { // CHECK: call i128 @llvm.fptosi.sat.i128.f128(fp128 %{{.+}}) @@ -296,6 +315,7 @@ pub fn f128_as_i128(a: f128) -> i128 { // x86-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u8_as_f128( +// emscripten-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u8_as_f128(a: u8) -> f128 { // CHECK: uitofp i8 %{{.+}} to fp128 @@ -305,6 +325,7 @@ pub fn u8_as_f128(a: u8) -> f128 { // x86-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u16_as_f128( +// emscripten-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u16_as_f128(a: u16) -> f128 { // CHECK: uitofp i16 %{{.+}} to fp128 @@ -314,6 +335,7 @@ pub fn u16_as_f128(a: u16) -> f128 { // x86-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u32_as_f128( +// emscripten-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u32_as_f128(a: u32) -> f128 { // CHECK: uitofp i32 %{{.+}} to fp128 @@ -323,6 +345,7 @@ pub fn u32_as_f128(a: u32) -> f128 { // x86-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u64_as_f128( +// emscripten-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u64_as_f128(a: u64) -> f128 { // CHECK: uitofp i64 %{{.+}} to fp128 @@ -332,6 +355,7 @@ pub fn u64_as_f128(a: u64) -> f128 { // x86-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u128_as_f128( +// emscripten-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u128_as_f128(a: u128) -> f128 { // CHECK: uitofp i128 %{{.+}} to fp128 @@ -341,6 +365,7 @@ pub fn u128_as_f128(a: u128) -> f128 { // x86-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i8_as_f128( +// emscripten-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i8_as_f128(a: i8) -> f128 { // CHECK: sitofp i8 %{{.+}} to fp128 @@ -350,6 +375,7 @@ pub fn i8_as_f128(a: i8) -> f128 { // x86-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i16_as_f128( +// emscripten-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i16_as_f128(a: i16) -> f128 { // CHECK: sitofp i16 %{{.+}} to fp128 @@ -359,6 +385,7 @@ pub fn i16_as_f128(a: i16) -> f128 { // x86-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i32_as_f128( +// emscripten-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i32_as_f128(a: i32) -> f128 { // CHECK: sitofp i32 %{{.+}} to fp128 @@ -368,6 +395,7 @@ pub fn i32_as_f128(a: i32) -> f128 { // x86-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i64_as_f128( +// emscripten-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i64_as_f128(a: i64) -> f128 { // CHECK: sitofp i64 %{{.+}} to fp128 @@ -377,6 +405,7 @@ pub fn i64_as_f128(a: i64) -> f128 { // x86-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i128_as_f128( +// emscripten-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i128_as_f128(a: i128) -> f128 { // CHECK: sitofp i128 %{{.+}} to fp128 diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs index 719499dd8eade..07b8ae6e9d7e5 100644 --- a/tests/codegen/wasm_exceptions.rs +++ b/tests/codegen/wasm_exceptions.rs @@ -1,5 +1,5 @@ //@ only-wasm32 -//@ compile-flags: -C panic=unwind +//@ compile-flags: -C panic=unwind -Z emscripten-wasm-eh #![crate_type = "lib"] #![feature(core_intrinsics)] diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr index bf53089675d5b..81ace4ebb6daf 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr @@ -5,6 +5,8 @@ LL | fn main() -> Foo::Bar::> {} | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u32]` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index f219c90849a26..c497f1b6d0bdb 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -6,35 +6,29 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:19:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:21:5 | -LL | impl const ConstName for &T - | ^^ cannot normalize `<&T as ConstName>::{constant#0}` +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` | -note: required for `&T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:19:35 +note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:10 | -LL | impl const ConstName for &T - | ^^^^^^^^^ ^^ -LL | where LL | [(); name_len::()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` -error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:26:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:28:5 | -LL | impl const ConstName for &mut T - | ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}` +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` | -note: required for `&mut T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:26:35 +note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:10 | -LL | impl const ConstName for &mut T - | ^^^^^^^^^ ^^^^^^ -LL | where LL | [(); name_len::()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` error: aborting due to 3 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 1b76669ccb0d7..4f685c508c721 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -16,23 +16,13 @@ LL | where LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error[E0277]: the trait bound `&str: AsExpression` is not satisfied - --> $DIR/as_expression.rs:55:15 - | -LL | SelectInt.check("bar"); - | ^^^^^ the trait `AsExpression` is not implemented for `&str` - | - = help: the trait `AsExpression` is not implemented for `&str` - but trait `AsExpression` is implemented for it - = help: for that trait implementation, expected `Text`, found `Integer` - error[E0271]: type mismatch resolving `::SqlType == Text` --> $DIR/as_expression.rs:55:5 | LL | SelectInt.check("bar"); | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 583b3c4675a87..48c1ed2b02d71 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -53,7 +53,7 @@ impl Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //~^ ERROR the trait bound `&str: AsExpression` is not satisfied - //[next]~| the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[current]~^ ERROR the trait bound `&str: AsExpression` is not satisfied + //[next]~^^ the trait bound `&str: AsExpression<::SqlType>` is not satisfied //[next]~| type mismatch } diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 1cfc2a6d94495..a95670ced8678 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -18,6 +18,11 @@ help: this trait has no implementations, consider adding one | LL | trait Foo {} | ^^^^^^^^^ +note: required by a bound in `A` + --> $DIR/alias-bounds-when-not-wf.rs:8:11 + | +LL | type A = T; + | ^^^ required by this bound in `A` error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:10 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr new file mode 100644 index 0000000000000..331b86736a0ba --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr @@ -0,0 +1,79 @@ +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:13:16 + | +LL | let [&x] = &[&mut 0]; + | - ^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &[&mut 0]; + | +++ + +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:19:16 + | +LL | let [&x] = &mut [&mut 0]; + | - ^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &mut [&mut 0]; + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-errors.rs:27:29 + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | - ^^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { +LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { + | + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:10 + | +LL | let &ref mut x = &0; + | ^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:35:23 + | +LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:40:11 + | +LL | let &[x] = &&mut [0]; + | ^ cannot borrow as mutable + +error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:44:20 + | +LL | let [&mut x] = &mut [&mut 0]; + | - ^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&mut ref x] = &mut [&mut 0]; + | +++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0507, E0508, E0596. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index a01e9ca265760..3f5d9c8db5d87 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -1,9 +1,27 @@ -//@ edition: 2024 -//@ revisions: classic structural +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 //! Tests for pattern errors not handled by the pattern typing rules, but by borrowck. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] + +/// These patterns additionally use `&` to match a `&mut` reference type, which causes compilation +/// to fail in HIR typeck on stable. As such, they need to be separate from the other tests. +fn errors_caught_in_hir_typeck_on_stable() { + let [&x] = &[&mut 0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + //[classic2024]~^^^ ERROR: cannot move out of type + let _: &u32 = x; + + let [&x] = &mut [&mut 0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + //[classic2024]~^^^ ERROR: cannot move out of type + let _: &u32 = x; +} pub fn main() { if let Some(&Some(x)) = Some(&Some(&mut 0)) { @@ -13,4 +31,18 @@ pub fn main() { let &ref mut x = &0; //~^ cannot borrow data in a `&` reference as mutable [E0596] + + if let &Some(Some(x)) = &Some(&mut Some(0)) { + //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable + let _: &u32 = x; + } + + let &[x] = &&mut [0]; + //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable + let _: &u32 = x; + + let [&mut x] = &mut [&mut 0]; + //[classic2024]~^ ERROR: cannot move out of type + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr new file mode 100644 index 0000000000000..65c98e2da9c38 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr @@ -0,0 +1,69 @@ +error[E0308]: mismatched types + --> $DIR/borrowck-errors.rs:13:10 + | +LL | let [&x] = &[&mut 0]; + | ^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&x] = &[&mut 0]; +LL + let [x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/borrowck-errors.rs:19:10 + | +LL | let [&x] = &mut [&mut 0]; + | ^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&x] = &mut [&mut 0]; +LL + let [x] = &mut [&mut 0]; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-errors.rs:27:29 + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | - ^^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { +LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { + | + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:10 + | +LL | let &ref mut x = &0; + | ^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:35:23 + | +LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:40:11 + | +LL | let &[x] = &&mut [0]; + | ^ cannot borrow as mutable + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0507, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr deleted file mode 100644 index c62461140750b..0000000000000 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:9:29 - | -LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ - | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | - -error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:14:10 - | -LL | let &ref mut x = &0; - | ^^^^^^^^^ cannot borrow as mutable - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0507, E0596. -For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr similarity index 91% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr index c62461140750b..30d2f9f3d702f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:9:29 + --> $DIR/borrowck-errors.rs:27:29 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { | error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:14:10 + --> $DIR/borrowck-errors.rs:32:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ cannot borrow as mutable diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs index e22bd1f8f6c99..a493b672c929f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs @@ -1,9 +1,9 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Test that `&mut` patterns don't match shared reference types under new typing rules in Rust 2024 #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { let &mut _ = &&0; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr similarity index 60% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr index 43560a1803026..afaa925a75779 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr @@ -1,5 +1,5 @@ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:11:13 + --> $DIR/mut-ref-mut.rs:14:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -9,7 +9,7 @@ LL | let Foo(mut a) = &Foo(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:15:13 + --> $DIR/mut-ref-mut.rs:19:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ @@ -18,6 +18,19 @@ LL | let Foo(mut a) = &mut Foo(0); = help: add `#![feature(mut_ref)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/mut-ref-mut.rs:24:10 + | +LL | let [&mut mut x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&mut x] = &[&mut 0]; + | ~ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs index 786587984ba41..fbd6514df73d6 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs @@ -1,18 +1,29 @@ -//@ edition: 2024 -//@ revisions: classic structural +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[stable2021] run-pass //! Test diagnostics for binding with `mut` when the default binding mode is by-ref. -#![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![allow(incomplete_features, unused_assignments, unused_variables)] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { struct Foo(u8); let Foo(mut a) = &Foo(0); - //~^ ERROR: binding cannot be both mutable and by-reference - a = &42; + //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] { a = 42 } + #[cfg(any(classic2024, structural2024))] { a = &42 } let Foo(mut a) = &mut Foo(0); - //~^ ERROR: binding cannot be both mutable and by-reference - a = &mut 42; + //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] { a = 42 } + #[cfg(any(classic2024, structural2024))] { a = &mut 42 } + + let [&mut mut x] = &[&mut 0]; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^^^ binding cannot be both mutable and by-reference + #[cfg(stable2021)] { x = 0 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr similarity index 61% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr index 43560a1803026..fd82da70a18de 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr @@ -1,5 +1,5 @@ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:11:13 + --> $DIR/mut-ref-mut.rs:14:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -9,7 +9,7 @@ LL | let Foo(mut a) = &Foo(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:15:13 + --> $DIR/mut-ref-mut.rs:19:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ @@ -18,6 +18,16 @@ LL | let Foo(mut a) = &mut Foo(0); = help: add `#![feature(mut_ref)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/mut-ref-mut.rs:24:15 + | +LL | let [&mut mut x] = &[&mut 0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` 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 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr similarity index 70% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr index 2bc3ecb7636d0..3a124dcead52a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:15:17 + --> $DIR/pattern-errors.rs:12:17 | LL | if let Some(&mut x) = &Some(&mut 0) { | ^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(&x) = &Some(&mut 0) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:19:17 + --> $DIR/pattern-errors.rs:18:17 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:23:22 + --> $DIR/pattern-errors.rs:24:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:28:17 + --> $DIR/pattern-errors.rs:31:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -47,65 +47,77 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:31:23 + --> $DIR/pattern-errors.rs:41:23 | -LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { +LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 + --> $DIR/pattern-errors.rs:51:17 | -LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - | ^^^^^ +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { - | ~ +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:37:29 + --> $DIR/pattern-errors.rs:147:10 | -LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^ +LL | let [&mut x] = &[&mut 0]; + | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { - | ~ +LL | let [&x] = &[&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:40:17 + --> $DIR/pattern-errors.rs:153:10 | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^ +LL | let [&mut &x] = &[&mut 0]; + | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(x)) = &Some(Some(0)) { - | ~ +LL | let [&&x] = &[&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:43:17 + --> $DIR/pattern-errors.rs:159:10 | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^ +LL | let [&mut &ref x] = &[&mut 0]; + | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(x)) = &Some(Some(0)) { - | ~ +LL | let [&&ref x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:165:10 + | +LL | let [&mut &(mut x)] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&(mut x)] = &[&mut 0]; + | ~ -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 3535ba9c7019a..c07c2972cd055 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -1,46 +1,170 @@ -//@ edition: 2024 -//@ revisions: classic structural +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 //! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must //! be separate from cases caught by MIR borrowck or the latter errors may not be emitted. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { - if let Some(&mut x) = &mut Some(&0) { - //[structural]~^ ERROR: mismatched types - let _: &u32 = x; - } - if let Some(&mut x) = &Some(&mut 0) { - //[classic]~^ ERROR: mismatched types - let _: &u32 = x; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; } if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { - //[classic]~^ ERROR: mismatched types + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { - //[classic]~^ ERROR: mismatched types - let _: &u32 = x; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; } if let Some(&mut Some(&_)) = &Some(&Some(0)) { //~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } - if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //~^ ERROR: mismatched types - } - if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: mismatched types + if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` + //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&mut _` + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } } + +fn structural_errors_0() { + let &[&mut x] = &&mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let &[&mut x] = &mut &mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let &[&mut ref x] = &&mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let &[&mut ref x] = &mut &mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let &[&mut mut x] = &&mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let &[&mut mut x] = &mut &mut [0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; +} + +fn structural_errors_1() { + let [&(mut x)] = &[&0]; + //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] let _: u32 = x; + #[cfg(classic2024)] let _: &u32 = x; + + let [&(mut x)] = &mut [&0]; + //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] let _: u32 = x; + #[cfg(classic2024)] let _: &u32 = x; +} + +fn structural_errors_2() { + let [&&mut x] = &[&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let [&&mut x] = &mut [&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let [&&mut ref x] = &[&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let [&&mut ref x] = &mut [&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let [&&mut mut x] = &[&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let [&&mut mut x] = &mut [&mut 0]; + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; +} + +fn classic_errors_0() { + let [&mut x] = &[&mut 0]; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; + + let [&mut &x] = &[&mut 0]; + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let [&mut &ref x] = &[&mut 0]; + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let [&mut &(mut x)] = &[&mut 0]; + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr new file mode 100644 index 0000000000000..e7eb1813846e6 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr @@ -0,0 +1,283 @@ +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:18:27 + | +LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { + | ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:31:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected reference `&Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:36:17 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:41:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:46:17 + | +LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { + | ^^^^^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected `Option<&mut Option<{integer}>>`, found `&_` + | + = note: expected enum `Option<&mut Option<{integer}>>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:51:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:59:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:59:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut x] = &&mut [0]; +LL + let &[x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:65:9 + | +LL | let &[&mut x] = &mut &mut [0]; + | ^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:71:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:71:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut ref x] = &&mut [0]; +LL + let &[ref x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:77:9 + | +LL | let &[&mut ref x] = &mut &mut [0]; + | ^^^^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:83:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:83:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut mut x] = &&mut [0]; +LL + let &[mut x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:89:9 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:109:10 + | +LL | let [&&mut x] = &[&mut 0]; + | ^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:115:10 + | +LL | let [&&mut x] = &mut [&mut 0]; + | ^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:121:10 + | +LL | let [&&mut ref x] = &[&mut 0]; + | ^^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:127:10 + | +LL | let [&&mut ref x] = &mut [&mut 0]; + | ^^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:133:10 + | +LL | let [&&mut mut x] = &[&mut 0]; + | ^^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:139:10 + | +LL | let [&&mut mut x] = &mut [&mut 0]; + | ^^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:153:15 + | +LL | let [&mut &x] = &[&mut 0]; + | ^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &x] = &[&mut 0]; +LL + let [&mut x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:159:15 + | +LL | let [&mut &ref x] = &[&mut 0]; + | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &ref x] = &[&mut 0]; +LL + let [&mut ref x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:165:15 + | +LL | let [&mut &(mut x)] = &[&mut 0]; + | ^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &(mut x)] = &[&mut 0]; +LL + let [&mut mut x)] = &[&mut 0]; + | + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr deleted file mode 100644 index 59d65553fae8f..0000000000000 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:10:17 - | -LL | if let Some(&mut x) = &mut Some(&0) { - | ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:10:17 - | -LL | if let Some(&mut x) = &mut Some(&0) { - | ^^^^^^ -help: consider removing `&mut` from the pattern - | -LL | if let Some(x) = &mut Some(&0) { - | ~ - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:28:17 - | -LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { - | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` - | | - | types differ in mutability - | - = note: expected reference `&Option<{integer}>` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:31:23 - | -LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 - | -LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:37:29 - | -LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^^ ------------------------- this expression has type `&Option>>` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:40:17 - | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` - | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:43:17 - | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` - | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr new file mode 100644 index 0000000000000..861ed2216cd9b --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr @@ -0,0 +1,228 @@ +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:31:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:36:23 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:41:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:46:28 + | +LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:51:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:59:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&x] = &&mut [0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:65:11 + | +LL | let &[&mut x] = &mut &mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&x] = &mut &mut [0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:71:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&ref x] = &&mut [0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:77:11 + | +LL | let &[&mut ref x] = &mut &mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&ref x] = &mut &mut [0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:83:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&mut x] = &&mut [0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:89:11 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let &[&mut x] = &mut &mut [0]; + | ~ + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:97:12 + | +LL | let [&(mut x)] = &[&0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:102:12 + | +LL | let [&(mut x)] = &mut [&0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` 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[E0308]: mismatched types + --> $DIR/pattern-errors.rs:109:11 + | +LL | let [&&mut x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:115:11 + | +LL | let [&&mut x] = &mut [&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&x] = &mut [&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:121:11 + | +LL | let [&&mut ref x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&ref x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:127:11 + | +LL | let [&&mut ref x] = &mut [&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&ref x] = &mut [&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:133:11 + | +LL | let [&&mut mut x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&mut x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:139:11 + | +LL | let [&&mut mut x] = &mut [&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&mut x] = &mut [&mut 0]; + | ~ + +error: aborting due to 19 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr new file mode 100644 index 0000000000000..70cdcbd62eb07 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -0,0 +1,70 @@ +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:60:10 + | +LL | let [&mut ref x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&ref x] = &[&mut 0]; + | ~ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref mut x] = &[0]; + | + + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 + | +LL | let [ref x] = &[0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref x] = &[0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 + | +LL | let [ref x] = &mut [0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref x] = &mut [0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref mut x] = &mut [0]; + | ++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs new file mode 100644 index 0000000000000..4c88c0c63ae54 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -0,0 +1,97 @@ +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//! Tests for errors from binding with `ref x` under a by-ref default binding mode in edition 2024. +//! These can't be in the same body as tests for other errors, since they're emitted during THIR +//! construction. The errors on stable edition 2021 Rust are unrelated. +#![allow(incomplete_features)] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] + +/// These only fail on the eat-inner variant of the new edition 2024 pattern typing rules. +/// The eat-outer variant eats the inherited reference, so binding with `ref` isn't a problem. +fn errors_from_eating_the_real_reference() { + let [&ref x] = &[&0]; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + #[cfg(classic2024)] let _: &&u32 = x; + + let [&ref x] = &mut [&0]; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + #[cfg(classic2024)] let _: &&u32 = x; + + let [&mut ref x] = &mut [&mut 0]; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + #[cfg(classic2024)] let _: &&mut u32 = x; + + let [&mut ref mut x] = &mut [&mut 0]; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &mut u32 = x; + #[cfg(classic2024)] let _: &mut &mut u32 = x; +} + +/// To make absolutely sure binding with `ref` ignores inherited references on stable, let's +/// quarantine these typeck errors (from using a `&` pattern to match a `&mut` reference type). +fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() { + let [&ref x] = &[&mut 0]; + //[stable2021]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; + + let [&ref x] = &mut [&mut 0]; + //[stable2021]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; +} + +/// This one also needs to be quarantined for a typeck error on `classic2024` (eat-outer). +fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() { + let [&mut ref x] = &[&mut 0]; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; +} + +/// These should be errors in all editions. In edition 2024, they should be caught by the pattern +/// typing rules disallowing `ref` when there's an inherited reference. In old editions where that +/// resets the binding mode, they're borrowck errors due to binding with `ref mut`. +/// As a quirk of how the edition 2024 error is emitted during THIR construction, it ends up going +/// through borrowck as well, using the old `ref` behavior as a fallback, so we get that error too. +fn borrowck_errors_in_old_editions() { + let [ref mut x] = &[0]; + //~^ ERROR: cannot borrow data in a `&` reference as mutable + //[classic2024,structural2024]~| ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default +} + +/// The remaining tests are purely for testing `ref` bindings in the presence of an inherited +/// reference. These should always fail on edition 2024 and succeed on edition 2021. +pub fn main() { + let [ref x] = &[0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + + let [ref x] = &mut [0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + + let [ref mut x] = &mut [0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &mut u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr new file mode 100644 index 0000000000000..a21e4bb5b8f8f --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:43:10 + | +LL | let [&ref x] = &[&mut 0]; + | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&ref x] = &[&mut 0]; +LL + let [ref x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:50:10 + | +LL | let [&ref x] = &mut [&mut 0]; + | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&ref x] = &mut [&mut 0]; +LL + let [ref x] = &mut [&mut 0]; + | + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr new file mode 100644 index 0000000000000..ee2c831bfcc80 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -0,0 +1,141 @@ +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 + | +LL | let [&ref x] = &[&0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&ref x] = &[&0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11 + | +LL | let [&ref x] = &mut [&0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&ref x] = &mut [&0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15 + | +LL | let [&mut ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&mut ref x] = &mut [&mut 0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:33:15 + | +LL | let [&mut ref mut x] = &mut [&mut 0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&mut ref mut x] = &mut [&mut 0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:43:11 + | +LL | let [&ref x] = &[&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&ref x] = &[&mut 0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:50:11 + | +LL | let [&ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&ref x] = &mut [&mut 0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:60:15 + | +LL | let [&mut ref x] = &[&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&mut ref x] = &[&mut 0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref mut x] = &[0]; + | + + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 + | +LL | let [ref x] = &[0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref x] = &[0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 + | +LL | let [ref x] = &mut [0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref x] = &mut [0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref mut x] = &mut [0]; + | ++++ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed deleted file mode 100644 index 4f4941975d804..0000000000000 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed +++ /dev/null @@ -1,33 +0,0 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic structural -//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts -//! to bind by mutable reference. -#![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] - -pub fn main() { - if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - } - - if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - } - - macro_rules! pat { - ($var:ident) => { ref mut $var }; - } - let &mut pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - - let &mut (ref mut a, ref mut b) = &mut (true, false); - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - //~| ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut bool = a; - let _: &mut bool = b; -} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed new file mode 100644 index 0000000000000..c01784d5076b7 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed @@ -0,0 +1,45 @@ +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix +//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts +//! to bind by mutable reference. +#![allow(incomplete_features)] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] + +pub fn main() { + if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) { + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + macro_rules! pat { + ($var:ident) => { ref mut $var }; + } + let &mut pat!(x) = &mut 0; + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + + let &mut (ref mut a, ref mut b) = &mut (true, false); + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut bool = a; + let _: &mut bool = b; + + let &mut [x] = &mut &mut [0]; + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr similarity index 69% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr index 6c384a51fac14..5e98b77be40cd 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31 | LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -7,7 +7,7 @@ LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31 | LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -15,7 +15,7 @@ LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:24:15 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15 | LL | let &pat!(x) = &mut 0; | - ^ @@ -23,7 +23,7 @@ LL | let &pat!(x) = &mut 0; | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ @@ -31,13 +31,21 @@ LL | let &(ref mut a, ref mut b) = &mut (true, false); | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:30 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | | help: replace this `&` with `&mut`: `&mut` -error: aborting due to 5 previous errors +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:11 + | +LL | let &[x] = &mut &mut [0]; + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs index b29bff7603f7a..fe40dabb55394 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs @@ -1,20 +1,25 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic structural +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; } if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; } @@ -22,12 +27,19 @@ pub fn main() { ($var:ident) => { ref mut $var }; } let &pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; let &(ref mut a, ref mut b) = &mut (true, false); - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - //~| ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; + + let &[x] = &mut &mut [0]; + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr new file mode 100644 index 0000000000000..72c6c05e18443 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr @@ -0,0 +1,58 @@ +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:17 + | +LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { + | ^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:12 + | +LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { + | ^^^^^^^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:9 + | +LL | let &pat!(x) = &mut 0; + | ^^^^^^^^ ------ this expression has type `&mut {integer}` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:9 + | +LL | let &(ref mut a, ref mut b) = &mut (true, false); + | ^^^^^^^^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut (bool, bool)` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut (bool, bool)` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:9 + | +LL | let &[x] = &mut &mut [0]; + | ^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed deleted file mode 100644 index 4f4941975d804..0000000000000 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed +++ /dev/null @@ -1,33 +0,0 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic structural -//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts -//! to bind by mutable reference. -#![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] - -pub fn main() { - if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - } - - if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - } - - macro_rules! pat { - ($var:ident) => { ref mut $var }; - } - let &mut pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut u8 = x; - - let &mut (ref mut a, ref mut b) = &mut (true, false); - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - //~| ERROR: cannot borrow as mutable inside an `&` pattern - let _: &mut bool = a; - let _: &mut bool = b; -} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed new file mode 100644 index 0000000000000..4ee849b38c53b --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed @@ -0,0 +1,45 @@ +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix +//! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts +//! to bind by mutable reference. +#![allow(incomplete_features)] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] + +pub fn main() { + if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) { + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + macro_rules! pat { + ($var:ident) => { ref mut $var }; + } + let &mut pat!(x) = &mut 0; + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + + let &mut (ref mut a, ref mut b) = &mut (true, false); + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut bool = a; + let _: &mut bool = b; + + let &[x] = &mut &mut [0]; + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr similarity index 83% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr index 6c384a51fac14..69cb6c438b6ed 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31 | LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -7,7 +7,7 @@ LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31 | LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -15,7 +15,7 @@ LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:24:15 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15 | LL | let &pat!(x) = &mut 0; | - ^ @@ -23,7 +23,7 @@ LL | let &pat!(x) = &mut 0; | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ @@ -31,7 +31,7 @@ LL | let &(ref mut a, ref mut b) = &mut (true, false); | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:30 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs index 9372049a2b283..ab3264704acc0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs @@ -6,9 +6,11 @@ #![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { + #[cfg(structural)] if let &Some(Some(x)) = &Some(&mut Some(0)) { let _: &u32 = x; } + if let Some(&x) = Some(&mut 0) { let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 077b52d8f274e..3114b9d3bf8cb 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -1,59 +1,127 @@ -//@ edition: 2024 -//@ revisions: classic structural -//@ run-pass +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-pass +//@[structural2024] run-pass //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests. -#![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![allow(incomplete_features, unused_mut)] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { - if let Some(Some(&x)) = &Some(&Some(0)) { - let _: u32 = x; - } - if let Some(Some(&x)) = &Some(Some(&0)) { + // Tests not using match ergonomics. These should always succeed with the same bindings. + if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { let _: &u32 = x; } - if let Some(Some(&&x)) = &Some(Some(&0)) { - let _: u32 = x; + + // Tests for differences in how many layers of reference are eaten by reference patterns + if let Some(Some(&x)) = &Some(Some(&0)) { + #[cfg(stable2021)] let _: u32 = x; + #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } - if let Some(&Some(x)) = &Some(Some(0)) { - let _: u32 = x; + if let Some(&Some(x)) = &mut Some(&Some(0)) { + // This additionally tests that `&` patterns can eat inherited `&mut` refs. + // This is possible on stable when the real reference being eaten is of a `&` type. + #[cfg(stable2021)] let _: u32 = x; + #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } - if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + if let Some(Some(&&x)) = &Some(Some(&0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } + + // Tests for eating a lone inherited reference if let Some(Some(&x)) = &Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } - if let Some(&Some(&x)) = &mut Some(&Some(0)) { + if let Some(&Some(x)) = &Some(Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&_` let _: u32 = x; } - if let Some(&Some(x)) = &mut Some(&Some(0)) { - let _: &u32 = x; - } - if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { - let _: &u32 = x; - } - if let &Some(Some(x)) = &Some(&mut Some(0)) { - let _: &u32 = x; + if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&mut _` + let _: u32 = x; } - if let Some(&Some(&x)) = &Some(&mut Some(0)) { + + // Tests for `&` patterns matching real `&mut` reference types + if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; } + + // Tests for eating only one layer and also eating a lone inherited reference if let Some(&Some(&x)) = &Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } - if let Some(&Some(&x)) = &Some(&mut Some(0)) { + + // Tests for `&` matching a lone inherited possibly-`&mut` reference + if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` let _: u32 = x; } - if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { + if let Some(&Some(x)) = &mut Some(Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&_` let _: u32 = x; } - if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + + // Tests eating one layer, eating a lone inherited ref, and `&` eating `&mut` (realness varies) + if let Some(&Some(&x)) = &Some(&mut Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; } - if let Some(&Some(x)) = &mut Some(Some(0)) { + if let Some(&Some(&x)) = &mut Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } + + // Tests for eat-inner rulesets matching on the outer reference if matching on the inner + // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`: + let [&mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: &u32 = x; + + let [&mut ref x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: &&u32 = x; + + let [&mut ref mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: &mut &u32 = x; + + let [&mut mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: &u32 = x; + + let [&mut &x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: u32 = x; + + let [&mut &ref x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: &u32 = x; + + let [&mut &(mut x)] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr new file mode 100644 index 0000000000000..e9c338de24312 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr @@ -0,0 +1,260 @@ +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:30:23 + | +LL | if let Some(Some(&&x)) = &Some(Some(&0)) { + | ^^ --------------- this expression has type `&Option>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let Some(Some(&&x)) = &Some(Some(&0)) { +LL + if let Some(Some(&x)) = &Some(Some(&0)) { + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:37:22 + | +LL | if let Some(Some(&x)) = &Some(&Some(0)) { + | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(Some(x)) = &Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:42:17 + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:47:22 + | +LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:47:22 + | +LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:54:23 + | +LL | if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + | ^^ ------------------- this expression has type `Option<&Option<&mut {integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:61:23 + | +LL | if let Some(&Some(&x)) = &Some(&Some(0)) { + | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = &Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:68:17 + | +LL | if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { + | ^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected `Option<&mut Option<{integer}>>`, found `&_` + | + = note: expected enum `Option<&mut Option<{integer}>>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:73:17 + | +LL | if let Some(&Some(x)) = &mut Some(Some(0)) { + | ^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:80:17 + | +LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { + | ^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:85:23 + | +LL | if let Some(&Some(&x)) = &mut Some(&Some(0)) { + | ^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = &mut Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:93:10 + | +LL | let [&mut x] = &mut [&0]; + | ^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:93:10 + | +LL | let [&mut x] = &mut [&0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut x] = &mut [&0]; +LL + let [x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:98:10 + | +LL | let [&mut ref x] = &mut [&0]; + | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:98:10 + | +LL | let [&mut ref x] = &mut [&0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref x] = &mut [&0]; +LL + let [ref x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:103:10 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:103:10 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref mut x] = &mut [&0]; +LL + let [ref mut x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:108:10 + | +LL | let [&mut mut x] = &mut [&0]; + | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:108:10 + | +LL | let [&mut mut x] = &mut [&0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut mut x] = &mut [&0]; +LL + let [mut x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:113:10 + | +LL | let [&mut &x] = &mut [&0]; + | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:118:10 + | +LL | let [&mut &ref x] = &mut [&0]; + | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:123:10 + | +LL | let [&mut &(mut x)] = &mut [&0]; + | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/privacy/sysroot-private.default.stderr b/tests/ui/privacy/sysroot-private.default.stderr index 845d4558d13a0..fef88d107e635 100644 --- a/tests/ui/privacy/sysroot-private.default.stderr +++ b/tests/ui/privacy/sysroot-private.default.stderr @@ -1,11 +1,11 @@ error[E0405]: cannot find trait `Equivalent` in this scope - --> $DIR/sysroot-private.rs:26:18 + --> $DIR/sysroot-private.rs:27:18 | LL | trait Trait2: Equivalent {} | ^^^^^^^^^^ not found in this scope error[E0412]: cannot find type `K` in this scope - --> $DIR/sysroot-private.rs:31:35 + --> $DIR/sysroot-private.rs:32:35 | LL | fn trait_member(val: &T, key: &K) -> bool { | - ^ @@ -22,13 +22,13 @@ LL | fn trait_member(val: &T, key: &K) -> bool { | +++ error[E0220]: associated type `ExpressionStack` not found for `Trait` - --> $DIR/sysroot-private.rs:21:31 + --> $DIR/sysroot-private.rs:22:31 | LL | type AssociatedTy = dyn Trait; | ^^^^^^^^^^^^^^^ help: `Trait` has the following associated type: `Bar` error[E0425]: cannot find function `memchr2` in this scope - --> $DIR/sysroot-private.rs:39:5 + --> $DIR/sysroot-private.rs:40:5 | LL | memchr2(b'a', b'b', buf) | ^^^^^^^ not found in this scope diff --git a/tests/ui/privacy/sysroot-private.rs b/tests/ui/privacy/sysroot-private.rs index 67ab67c7f5c53..8681857459273 100644 --- a/tests/ui/privacy/sysroot-private.rs +++ b/tests/ui/privacy/sysroot-private.rs @@ -7,6 +7,7 @@ //! of `std`'s dependencies, but may not be robust against dependency upgrades/changes. //@ only-unix Windows sysroots seem to not expose this dependency +//@ ignore-emscripten neither does Emscripten //@ revisions: default rustc_private_enabled // Enabling `rustc_private` should `std`'s dependencies accessible, so they should show up diff --git a/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr index 98e6922428a90..4b54b59714aa6 100644 --- a/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr +++ b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr @@ -1,11 +1,11 @@ error[E0405]: cannot find trait `Equivalent` in this scope - --> $DIR/sysroot-private.rs:26:18 + --> $DIR/sysroot-private.rs:27:18 | LL | trait Trait2: Equivalent {} | ^^^^^^^^^^ not found in this scope error[E0412]: cannot find type `K` in this scope - --> $DIR/sysroot-private.rs:31:35 + --> $DIR/sysroot-private.rs:32:35 | LL | fn trait_member(val: &T, key: &K) -> bool { | - ^ @@ -22,13 +22,13 @@ LL | fn trait_member(val: &T, key: &K) -> bool { | +++ error[E0220]: associated type `ExpressionStack` not found for `Trait` - --> $DIR/sysroot-private.rs:21:31 + --> $DIR/sysroot-private.rs:22:31 | LL | type AssociatedTy = dyn Trait; | ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` error[E0425]: cannot find function `memchr2` in this scope - --> $DIR/sysroot-private.rs:39:5 + --> $DIR/sysroot-private.rs:40:5 | LL | memchr2(b'a', b'b', buf) | ^^^^^^^ not found in this scope diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 377dfc8b52916..425f2d59222e0 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` +error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index b96bfab927d2d..2d0c503bc958d 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -10,11 +10,11 @@ LL | #![feature(specialization)] error: cannot normalize `::Id: '_` -error[E0284]: type annotations needed: cannot normalize `::Id` +error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot normalize `::Id` + | ^^^^^^^^^ cannot infer type for reference `&::Id` error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to T` --> $DIR/specialization-transmute.rs:17:9 @@ -36,4 +36,5 @@ LL | fn transmute, U: Copy>(t: T) -> U { error: aborting due to 4 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/type/pattern_types/transmute.rs b/tests/ui/type/pattern_types/transmute.rs new file mode 100644 index 0000000000000..cb76b2b938dc6 --- /dev/null +++ b/tests/ui/type/pattern_types/transmute.rs @@ -0,0 +1,32 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +// ok +fn create(x: u32) -> pattern_type!(u32 is S..=E) { + unsafe { std::mem::transmute(x) } +} + +// ok +fn unwrap(x: pattern_type!(u32 is S..=E)) -> u32 { + unsafe { std::mem::transmute(x) } +} + +// bad, only when S != u32::MIN or E != u32::MAX will this ok +fn non_base_ty_transmute( + x: Option, +) -> u32 { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +// bad, only when S = u32::MIN and E = u32::MAX will this ok +fn wrapped_transmute( + x: Option, +) -> Option { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +fn main() {} diff --git a/tests/ui/type/pattern_types/transmute.stderr b/tests/ui/type/pattern_types/transmute.stderr new file mode 100644 index 0000000000000..578549b515c10 --- /dev/null +++ b/tests/ui/type/pattern_types/transmute.stderr @@ -0,0 +1,21 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:20:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<(u32) is S..=E>` (size can vary because of u32) + = note: target type: `u32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:28:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<(u32) is S..=E>` (size can vary because of u32) + = note: target type: `Option` (64 bits) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/union/union-derive-eq.next.stderr b/tests/ui/union/union-derive-eq.next.stderr index 3952b1f12840f..151ceebe1ba67 100644 --- a/tests/ui/union/union-derive-eq.next.stderr +++ b/tests/ui/union/union-derive-eq.next.stderr @@ -7,6 +7,8 @@ LL | union U2 { LL | a: PartialEqNotEq, | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` | diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 1e898fb7b78ab..83b56bb6b19ad 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -5,6 +5,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:19:11 @@ -13,6 +14,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `str` cannot be known at compilation time @@ -22,6 +24,8 @@ LL | const _: as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:22:11 @@ -30,6 +34,8 @@ LL | const _: as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/wf/wf-trait-fn-arg.next.stderr b/tests/ui/wf/wf-trait-fn-arg.next.stderr index c55dc5c8a121a..d5dd36fad6dd6 100644 --- a/tests/ui/wf/wf-trait-fn-arg.next.stderr +++ b/tests/ui/wf/wf-trait-fn-arg.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self, x: &Bar); | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-arg.rs:11:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self, x: &Bar) where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-ret.next.stderr b/tests/ui/wf/wf-trait-fn-ret.next.stderr index b3dca17672d31..0ad786c2fd566 100644 --- a/tests/ui/wf/wf-trait-fn-ret.next.stderr +++ b/tests/ui/wf/wf-trait-fn-ret.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self) -> &Bar; | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-ret.rs:10:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self) -> &Bar where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr index 8c8a5fa3e7041..db5454d0f3c22 100644 --- a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr +++ b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | Bar: Copy; | ^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:10:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | Bar: Copy, Self: Eq;