authorbors <bors@rust-lang.org> 2026-07-06 15:35:34 UTC
committerbors <bors@rust-lang.org> 2026-07-06 15:35:34 UTC
log36714a9983d6ba11203d8bb87a1b372247fbcf06
tree2b441c68cb73945c8f297305f33f23021788c28c
parent3c00c96d3af4d5b5e101e56cc161a608b21366ee
parent68dfc1d61f551e2aa49e18f911545d5e4c38544f

Auto merge of #158864 - JonathanBrouwer:rollup-re2xAGf, r=JonathanBrouwer

Rollup of 12 pull requests Successful merges: - rust-lang/rust#156976 (enable eager `param_env` norm in new solver) - rust-lang/rust#158537 (Add `std::io::cursor::WriteThroughCursor`) - rust-lang/rust#158540 (Move `std::io::Seek` to `core::io`) - rust-lang/rust#157820 (consider subtyping when checking if an infer var is sized) - rust-lang/rust#158505 (Update POSIX edition links) - rust-lang/rust#158853 (Fix typo for link on nto-qnx.md) - rust-lang/rust#157466 (Better error message when bare type in impl parameter list) - rust-lang/rust#157966 (Emit a suggestion to cast the never type into a concrete type when it fails to satisfy an `impl Trait` bound) - rust-lang/rust#158381 (Expose debug scope of statement and terminator in rustc_public) - rust-lang/rust#158405 (rustc_target: Add ARMv8-M related target features) - rust-lang/rust#158770 (Weaken guarantee for `From<legacy::RangeInclusive> for RangeInclusive`) - rust-lang/rust#158820 (Fix rustdoc ICE on deprecated note in inlined re-export chain)

73 files changed, 1143 insertions(+), 725 deletions(-)

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs+7-12
......@@ -239,26 +239,21 @@ fn compare_method_predicate_entailment<'tcx>(
239239 let hybrid_preds = hybrid_preds.into_iter().map(Unnormalized::skip_norm_wip);
240240 let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
241241 let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds));
242 // FIXME(-Zhigher-ranked-assumptions): The `hybrid_preds`
242 // NOTE(-Zhigher-ranked-assumptions): The `hybrid_preds`
243243 // should be well-formed. However, using them may result in
244244 // region errors as we currently don't track placeholder
245245 // assumptions.
246246 //
247 // To avoid being backwards incompatible with the old solver,
248 // we also eagerly normalize the where-bounds in the new solver
249 // here while ignoring region constraints. This means we can then
250 // use where-bounds whose normalization results in placeholder
251 // errors further down without getting any errors.
247 // We eagerly normalize the where-clauses here while ignoring
248 // region constraints. This means we can then use where-bounds
249 // whose normalization results in placeholder errors further
250 // down without getting any errors.
252251 //
253 // It should be sound to do so as the only region errors here
252 // This should be sound to do so as the only region errors here
254253 // should be due to missing implied bounds.
255254 //
256255 // cc trait-system-refactor-initiative/issues/166.
257 let param_env = if tcx.next_trait_solver_globally() {
258 traits::deeply_normalize_param_env_ignoring_regions(tcx, param_env, normalize_cause)
259 } else {
260 traits::normalize_param_env_or_error(tcx, param_env, normalize_cause)
261 };
256 let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
262257 debug!(caller_bounds=?param_env.caller_bounds());
263258
264259 let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis());
compiler/rustc_hir_typeck/src/closure.rs+6-5
......@@ -23,6 +23,7 @@ use rustc_trait_selection::traits;
2323use tracing::{debug, instrument, trace};
2424
2525use super::{CoroutineTypes, Expectation, FnCtxt, check_fn};
26use crate::fn_ctxt::UseSubtyping;
2627
2728/// What signature do we *expect* the closure to have from context?
2829#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
......@@ -317,7 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
317318 ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates(
318319 Ty::new_var(self.tcx, self.root_var(vid)),
319320 closure_kind,
320 self.obligations_for_self_ty(vid)
321 self.obligations_for_self_ty(vid, UseSubtyping::No)
321322 .into_iter()
322323 .map(|obl| (obl.predicate, obl.cause.span)),
323324 ),
......@@ -587,7 +588,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
587588
588589 // FIXME: We may want to elaborate here, though I assume this will be exceedingly rare.
589590 let mut return_ty = None;
590 for bound in self.obligations_for_self_ty(return_vid) {
591 for bound in self.obligations_for_self_ty(return_vid, UseSubtyping::No) {
591592 if let Some(ret_projection) = bound.predicate.as_projection_clause()
592593 && let Some(ret_projection) = ret_projection.no_bound_vars()
593594 && self.tcx.is_lang_item(ret_projection.def_id(), LangItem::FutureOutput)
......@@ -987,9 +988,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
987988
988989 let output_ty = match *ret_ty.kind() {
989990 ty::Infer(ty::TyVar(ret_vid)) => {
990 self.obligations_for_self_ty(ret_vid).into_iter().find_map(|obligation| {
991 get_future_output(obligation.predicate, obligation.cause.span)
992 })?
991 self.obligations_for_self_ty(ret_vid, UseSubtyping::No).into_iter().find_map(
992 |obligation| get_future_output(obligation.predicate, obligation.cause.span),
993 )?
993994 }
994995 ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. }, .. }) => {
995996 return Some(Ty::new_error_with_message(
compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs+8-4
......@@ -755,14 +755,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
755755
756756 pub(crate) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool {
757757 let sized_did = self.tcx.lang_items().sized_trait();
758 self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| {
759 match obligation.predicate.kind().skip_binder() {
758
759 // NB: `T: Sized` implies that all subtypes and all supertypes of `T` are also sized,
760 // so it's valid to use subtyping here. (subtyping has to preserve layout and
761 // `T <: U => &T <: &U`, so subtyping can't change sizedness)
762 self.obligations_for_self_ty(self_ty, super::UseSubtyping::Yes).into_iter().any(
763 |obligation| match obligation.predicate.kind().skip_binder() {
760764 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
761765 Some(data.def_id()) == sized_did
762766 }
763767 _ => false,
764 }
765 })
768 },
769 )
766770 }
767771
768772 pub(crate) fn err_args(&self, len: usize, guar: ErrorGuaranteed) -> Vec<Ty<'tcx>> {
compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs+46-13
......@@ -13,19 +13,38 @@ use tracing::{debug, instrument, trace};
1313
1414use crate::FnCtxt;
1515
16/// Whatever to use subtyping or not when inspecting obligations
17#[derive(Debug, Copy, Clone)]
18pub(crate) enum UseSubtyping {
19 /// Do **not** use subtyping. [`FnCtxt::obligations_for_self_ty`] will only return obligations
20 /// where the self type is known to be equal to the provided vid.
21 No,
22
23 /// Use subtyping. [`FnCtxt::obligations_for_self_ty`] will return obligations
24 /// where the self type is related to the provided vid via subtyping.
25 ///
26 /// Using this requires extra care, as traits holding for a subtype or a supertype, does not
27 /// necessarily imply that they hold for the respective supertype or subtype.
28 Yes,
29}
30
1631impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1732 /// Returns a list of all obligations whose self type has been unified
1833 /// with the unconstrained type `self_ty`.
1934 #[instrument(skip(self), level = "debug")]
20 pub(crate) fn obligations_for_self_ty(&self, self_ty: ty::TyVid) -> PredicateObligations<'tcx> {
35 pub(crate) fn obligations_for_self_ty(
36 &self,
37 self_ty: ty::TyVid,
38 subtyping: UseSubtyping,
39 ) -> PredicateObligations<'tcx> {
2140 if self.next_trait_solver() {
22 self.obligations_for_self_ty_next(self_ty)
41 self.obligations_for_self_ty_next(self_ty, subtyping)
2342 } else {
24 let ty_var_root = self.root_var(self_ty);
2543 let mut obligations = self.fulfillment_cx.borrow().pending_obligations();
2644 trace!("pending_obligations = {:#?}", obligations);
27 obligations
28 .retain(|obligation| self.predicate_has_self_ty(obligation.predicate, ty_var_root));
45 obligations.retain(|obligation| {
46 self.predicate_has_self_ty(obligation.predicate, self_ty, subtyping)
47 });
2948 obligations
3049 }
3150 }
......@@ -35,14 +54,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3554 &self,
3655 predicate: ty::Predicate<'tcx>,
3756 expected_vid: ty::TyVid,
57 subtyping: UseSubtyping,
3858 ) -> bool {
3959 match predicate.kind().skip_binder() {
4060 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
41 self.type_matches_expected_vid(data.self_ty(), expected_vid)
61 self.type_matches_expected_vid(data.self_ty(), expected_vid, subtyping)
4262 }
4363 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
4464 if data.projection_term.kind.is_trait_projection() {
45 self.type_matches_expected_vid(data.self_ty(), expected_vid)
65 self.type_matches_expected_vid(data.self_ty(), expected_vid, subtyping)
4666 } else {
4767 false
4868 }
......@@ -64,14 +84,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6484 }
6585
6686 #[instrument(level = "debug", skip(self), ret)]
67 fn type_matches_expected_vid(&self, ty: Ty<'tcx>, expected_vid: ty::TyVid) -> bool {
87 fn type_matches_expected_vid(
88 &self,
89 ty: Ty<'tcx>,
90 expected_vid: ty::TyVid,
91 subtyping: UseSubtyping,
92 ) -> bool {
6893 let ty = self.shallow_resolve(ty);
6994 debug!(?ty);
7095
7196 match *ty.kind() {
72 ty::Infer(ty::TyVar(found_vid)) => {
73 self.root_var(expected_vid) == self.root_var(found_vid)
74 }
97 ty::Infer(ty::TyVar(found_vid)) => match subtyping {
98 UseSubtyping::No => self.root_var(expected_vid) == self.root_var(found_vid),
99 UseSubtyping::Yes => {
100 self.sub_unification_table_root_var(expected_vid)
101 == self.sub_unification_table_root_var(found_vid)
102 }
103 },
75104 _ => false,
76105 }
77106 }
......@@ -79,6 +108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
79108 pub(crate) fn obligations_for_self_ty_next(
80109 &self,
81110 self_ty: ty::TyVid,
111 subtyping: UseSubtyping,
82112 ) -> PredicateObligations<'tcx> {
83113 // We only look at obligations which may reference the self type.
84114 // This lookup uses the `sub_root` instead of the inference variable
......@@ -93,6 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
93123 .borrow()
94124 .pending_obligations_potentially_referencing_sub_root(&self.infcx, sub_root_var);
95125 debug!(?obligations);
126
96127 let mut obligations_for_self_ty = PredicateObligations::new();
97128 for obligation in obligations {
98129 let mut visitor = NestedObligationsForSelfTy {
......@@ -100,6 +131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
100131 self_ty,
101132 obligations_for_self_ty: &mut obligations_for_self_ty,
102133 root_cause: &obligation.cause,
134 subtyping,
103135 };
104136
105137 let goal = obligation.as_goal();
......@@ -182,6 +214,7 @@ struct NestedObligationsForSelfTy<'a, 'tcx> {
182214 self_ty: ty::TyVid,
183215 root_cause: &'a ObligationCause<'tcx>,
184216 obligations_for_self_ty: &'a mut PredicateObligations<'tcx>,
217 subtyping: UseSubtyping,
185218}
186219
187220impl<'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'_, 'tcx> {
......@@ -209,7 +242,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'_, 'tcx> {
209242 .orig_values()
210243 .iter()
211244 .filter_map(|arg| arg.as_type())
212 .any(|ty| self.fcx.type_matches_expected_vid(ty, self.self_ty))
245 .any(|ty| self.fcx.type_matches_expected_vid(ty, self.self_ty, self.subtyping))
213246 {
214247 debug!(goal = ?inspect_goal.goal(), "goal does not mention self type");
215248 return;
......@@ -217,7 +250,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'_, 'tcx> {
217250
218251 let tcx = self.fcx.tcx;
219252 let goal = inspect_goal.goal();
220 if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
253 if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty, self.subtyping) {
221254 self.obligations_for_self_ty.push(traits::Obligation::new(
222255 tcx,
223256 self.root_cause.clone(),
compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs+1
......@@ -8,6 +8,7 @@ mod suggestions;
88use std::cell::{Cell, RefCell};
99use std::ops::Deref;
1010
11pub(crate) use inspect_obligations::UseSubtyping;
1112use rustc_errors::DiagCtxtHandle;
1213use rustc_hir::attrs::{DivergingBlockBehavior, DivergingFallbackBehavior};
1314use rustc_hir::def_id::{DefId, LocalDefId};
compiler/rustc_infer/src/infer/type_variable.rs+3-5
......@@ -246,13 +246,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
246246 }
247247
248248 /// Returns the "root" variable of `vid` in the `sub_unification_table`
249 /// equivalence table. All type variables that have been are related via
249 /// equivalence table. All type variables that have been related via
250250 /// equality or subtyping will yield the same root variable (per the
251251 /// union-find algorithm), so `sub_unification_table_root_var(a)
252 /// == sub_unification_table_root_var(b)` implies that:
253 /// ```text
254 /// exists X. (a <: X || X <: a) && (b <: X || X <: b)
255 /// ```
252 /// == sub_unification_table_root_var(b)` implies that `a` and `b` are
253 /// transitively related via subtyping.
256254 pub(crate) fn sub_unification_table_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
257255 self.sub_unification_table().find(vid).vid
258256 }
compiler/rustc_parse/src/errors.rs+30
......@@ -4660,3 +4660,33 @@ pub(crate) struct UseRegularStructSuggestion {
46604660 #[suggestion_part(code = "")]
46614661 pub semicolon: Option<Span>,
46624662}
4663#[derive(Diagnostic)]
4664#[diag("expected type parameter, found path `{$path}`")]
4665pub(crate) struct FoundPathInGenerics {
4666 #[primary_span]
4667 pub span: Span,
4668 pub path: String,
4669}
4670#[derive(Subdiagnostic)]
4671#[suggestion(
4672 "you might have meant to bind a type parameter to a trait",
4673 applicability = "maybe-incorrect",
4674 code = "T: "
4675)]
4676
4677pub(crate) struct SuggestBindTypeParameter {
4678 #[primary_span]
4679 pub span: Span,
4680}
4681
4682#[derive(Subdiagnostic)]
4683#[suggestion(
4684 "alternatively, you might have meant to introduce type parameter",
4685 applicability = "maybe-incorrect",
4686 code = "{parameters}"
4687)]
4688pub(crate) struct SuggestIntroduceTypeParameter {
4689 #[primary_span]
4690 pub span: Span,
4691 pub parameters: String,
4692}
compiler/rustc_parse/src/parser/diagnostics.rs+55-9
......@@ -6,7 +6,7 @@ use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
66use rustc_ast::util::parser::AssocOp;
77use rustc_ast::{
88 self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
9 Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind,
9 Block, BlockCheckMode, Expr, ExprKind, GenericArg, GenericArgs, Generics, Item, ItemKind,
1010 MgcaDisambiguation, Param, Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
1111};
1212use rustc_ast_pretty::pprust;
......@@ -31,14 +31,16 @@ use crate::errors::{
3131 AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
3232 ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
3333 DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound,
34 ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets,
35 GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition,
36 InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse,
37 MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg,
38 SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg,
39 SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
40 TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
41 UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
34 ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, FoundPathInGenerics,
35 GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
36 HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
37 IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, MisspelledKw,
38 PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
39 StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt,
40 SuggEscapeIdentifier, SuggRemoveComma, SuggestBindTypeParameter, SuggestIntroduceTypeParameter,
41 TernaryOperator, TernaryOperatorSuggestion, UnexpectedConstInGenericParam,
42 UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
43 UseEqInstead, WrapType,
4244};
4345use crate::exp;
4446use crate::parser::FnContext;
......@@ -3164,4 +3166,48 @@ impl<'a> Parser<'a> {
31643166 }
31653167 Ok(())
31663168 }
3169 pub(super) fn maybe_type_in_generic_parameter(&mut self, origin_error: Diag<'a>) -> Diag<'a> {
3170 if !self.may_recover() {
3171 return origin_error;
3172 }
3173 self.with_recovery(super::Recovery::Forbidden, |snapshot| {
3174 snapshot.bump();
3175 let lo = snapshot.token.span.shrink_to_lo();
3176
3177 let ty = match snapshot.parse_ty() {
3178 Ok(t) => t,
3179 Err(err) => {
3180 err.cancel();
3181 return origin_error;
3182 }
3183 };
3184 let TyKind::Path(_, path) = ty.kind else {
3185 return origin_error;
3186 };
3187 let Some(GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, ref args })) =
3188 path.segments[0].args
3189 else {
3190 return origin_error;
3191 };
3192
3193 let path_span = path.span;
3194 let mut new_error = snapshot.dcx().create_err(FoundPathInGenerics {
3195 span: path_span,
3196 path: snapshot.span_to_snippet(path_span).unwrap(),
3197 });
3198 new_error.subdiagnostic(SuggestBindTypeParameter { span: lo });
3199 origin_error.cancel();
3200
3201 let params = args
3202 .iter()
3203 .map(|arg| snapshot.span_to_snippet(arg.span()).unwrap())
3204 .collect::<Vec<_>>()
3205 .join(", ");
3206 new_error.subdiagnostic(SuggestIntroduceTypeParameter {
3207 span: path_span,
3208 parameters: params,
3209 });
3210 new_error
3211 })
3212 }
31673213}
compiler/rustc_parse/src/parser/item.rs+16-3
......@@ -662,11 +662,20 @@ impl<'a> Parser<'a> {
662662 let constness = self.parse_constness(Case::Sensitive);
663663 let safety = self.parse_safety(Case::Sensitive);
664664 self.expect_keyword(exp!(Impl))?;
665
665 let mut generics_snapshot = None;
666666 // First, parse generic parameters if necessary.
667667 let mut generics = if self.choose_generics_over_qpath(0) {
668668 self.parse_generics()?
669669 } else {
670 // We might be mistakenly trying to use a generic type as a generic parameter.
671 // impl<X<T>> Trait for Y<T> { ... }
672 if self.look_ahead(0, |t| t == &token::Lt)
673 && self.look_ahead(1, |t| t.is_ident())
674 && self.look_ahead(2, |t| t == &token::Lt)
675 {
676 generics_snapshot = Some(self.create_snapshot_for_diagnostic());
677 }
678
670679 let mut generics = Generics::default();
671680 // impl A for B {}
672681 // /\ this is where `generics.span` should point when there are no type params.
......@@ -698,9 +707,13 @@ impl<'a> Parser<'a> {
698707 for_span: span.to(self.token.span),
699708 }));
700709 } else {
701 self.parse_ty_with_generics_recovery(&generics)?
710 self.parse_ty_with_generics_recovery(&generics).map_err(|e| {
711 let Some(mut snapshot) = generics_snapshot else {
712 return e;
713 };
714 snapshot.maybe_type_in_generic_parameter(e)
715 })?
702716 };
703
704717 // If `for` is missing we try to recover.
705718 let has_for = self.eat_keyword(exp!(For));
706719 let missing_for_span = self.prev_token.span.between(self.token.span);
compiler/rustc_public/src/mir/body.rs+2-2
......@@ -139,7 +139,7 @@ pub struct BasicBlock {
139139#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
140140pub struct Terminator {
141141 pub kind: TerminatorKind,
142 pub span: Span,
142 pub source_info: SourceInfo,
143143}
144144
145145impl Terminator {
......@@ -468,7 +468,7 @@ pub enum NonDivergingIntrinsic {
468468#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
469469pub struct Statement {
470470 pub kind: StatementKind,
471 pub span: Span,
471 pub source_info: SourceInfo,
472472}
473473
474474#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
compiler/rustc_public/src/mir/visit.rs+8-8
......@@ -139,9 +139,9 @@ macro_rules! make_mir_visitor {
139139 fn super_basic_block(&mut self, bb: &$($mutability)? BasicBlock) {
140140 let BasicBlock { statements, terminator } = bb;
141141 for stmt in statements {
142 self.visit_statement(stmt, Location(stmt.span));
142 self.visit_statement(stmt, Location(stmt.source_info.span));
143143 }
144 self.visit_terminator(terminator, Location(terminator.span));
144 self.visit_terminator(terminator, Location(terminator.source_info.span));
145145 }
146146
147147 fn super_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) {
......@@ -159,8 +159,8 @@ macro_rules! make_mir_visitor {
159159 }
160160
161161 fn super_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) {
162 let Statement { kind, span } = stmt;
163 self.visit_span(span);
162 let Statement { kind, source_info } = stmt;
163 self.visit_span(&$($mutability)? source_info.span);
164164 match kind {
165165 StatementKind::Assign(place, rvalue) => {
166166 self.visit_place(place, PlaceContext::MUTATING, location);
......@@ -199,8 +199,8 @@ macro_rules! make_mir_visitor {
199199 }
200200
201201 fn super_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) {
202 let Terminator { kind, span } = term;
203 self.visit_span(span);
202 let Terminator { kind, source_info } = term;
203 self.visit_span(&$($mutability)? source_info.span);
204204 match kind {
205205 TerminatorKind::Goto { .. }
206206 | TerminatorKind::Resume
......@@ -540,7 +540,7 @@ impl Location {
540540pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize) -> Location {
541541 let bb = &body.blocks[*bb_idx];
542542 let stmt = &bb.statements[stmt_idx];
543 Location(stmt.span)
543 Location(stmt.source_info.span)
544544}
545545
546546/// Location of the terminator for a given basic block. Assumes that `bb_idx` is valid for a given
......@@ -548,7 +548,7 @@ pub fn statement_location(body: &Body, bb_idx: &BasicBlockIdx, stmt_idx: usize)
548548pub fn terminator_location(body: &Body, bb_idx: &BasicBlockIdx) -> Location {
549549 let bb = &body.blocks[*bb_idx];
550550 let terminator = &bb.terminator;
551 Location(terminator.span)
551 Location(terminator.source_info.span)
552552}
553553
554554/// Reference to a place used to represent a partial projection.
compiler/rustc_public/src/unstable/convert/stable/mir.rs+2-2
......@@ -74,7 +74,7 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
7474 ) -> Self::T {
7575 Statement {
7676 kind: self.kind.stable(tables, cx),
77 span: self.source_info.span.stable(tables, cx),
77 source_info: self.source_info.stable(tables, cx),
7878 }
7979 }
8080}
......@@ -695,7 +695,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
695695 use crate::mir::Terminator;
696696 Terminator {
697697 kind: self.kind.stable(tables, cx),
698 span: self.source_info.span.stable(tables, cx),
698 source_info: self.source_info.stable(tables, cx),
699699 }
700700 }
701701}
compiler/rustc_target/src/target_features.rs+9-3
......@@ -153,6 +153,7 @@ type ImpliedFeatures = &'static [&'static str];
153153static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
154154 // tidy-alphabetical-start
155155 ("aclass", Unstable(sym::arm_target_feature), &[]),
156 ("acquire-release", Unstable(sym::arm_target_feature), &[]),
156157 ("aes", Unstable(sym::arm_target_feature), &["neon"]),
157158 (
158159 "atomics-32",
......@@ -171,6 +172,8 @@ static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
171172 ("fpregs", Unstable(sym::arm_target_feature), &[]),
172173 ("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
173174 ("mclass", Unstable(sym::arm_target_feature), &[]),
175 ("mve", Unstable(sym::arm_target_feature), &["v8.1m.main", "dsp", "fpregs"]),
176 ("mve.fp", Unstable(sym::arm_target_feature), &["mve"]),
174177 ("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
175178 ("rclass", Unstable(sym::arm_target_feature), &[]),
176179 ("sha2", Unstable(sym::arm_target_feature), &["neon"]),
......@@ -188,9 +191,13 @@ static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
188191 ("v5te", Unstable(sym::arm_target_feature), &[]),
189192 ("v6", Unstable(sym::arm_target_feature), &["v5te"]),
190193 ("v6k", Unstable(sym::arm_target_feature), &["v6"]),
191 ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
194 ("v6m", Unstable(sym::arm_target_feature), &["v6"]),
195 ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "v8m", "thumb2"]),
192196 ("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
193197 ("v8", Unstable(sym::arm_target_feature), &["v7"]),
198 ("v8.1m.main", Unstable(sym::arm_target_feature), &["v8m.main"]),
199 ("v8m", Unstable(sym::arm_target_feature), &["v6m"]),
200 ("v8m.main", Unstable(sym::arm_target_feature), &["v7"]),
194201 ("vfp2", Unstable(sym::arm_target_feature), &[]),
195202 ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
196203 ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
......@@ -1073,9 +1080,8 @@ const X86_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static
10731080const AARCH64_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
10741081 &[(128, "neon")];
10751082
1076// We might want to add "helium" too.
10771083const ARM_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
1078 &[(128, "neon")];
1084 &[(128, "neon"), (128, "mve")];
10791085
10801086const AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI: &'static [(u64, &'static str)] =
10811087 &[(1024, "")];
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs+14-3
......@@ -4479,7 +4479,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
44794479 }
44804480 ObligationCauseCode::OpaqueReturnType(expr_info) => {
44814481 let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info {
4482 let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
44834482 let expr = tcx.hir_expect_expr(hir_id);
44844483 (expr_ty, expr)
44854484 } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id()
......@@ -4494,15 +4493,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
44944493 && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
44954494 && self.can_eq(param_env, pred.self_ty(), expr_ty)
44964495 {
4497 let expr_ty = tcx.short_string(expr_ty, err.long_ty_path());
44984496 (expr_ty, expr)
44994497 } else {
45004498 return;
45014499 };
4500 let expr_ty_string = tcx.short_string(expr_ty, err.long_ty_path());
4501 if expr_ty.is_never()
4502 && let span = expr.span.source_callsite()
4503 && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span)
4504 && span != expr.span
4505 {
4506 err.span_suggestion(
4507 span,
4508 "`!` can be coerced to any type; consider casting it to a concrete type that implements the trait",
4509 format!("{snippet} as /* Type */"),
4510 Applicability::HasPlaceholders,
4511 );
4512 }
45024513 err.span_label(
45034514 expr.span,
45044515 with_forced_trimmed_paths!(format!(
4505 "return type was inferred to be `{expr_ty}` here",
4516 "return type was inferred to be `{expr_ty_string}` here",
45064517 )),
45074518 );
45084519 suggest_remove_deref(err, &expr);
compiler/rustc_trait_selection/src/traits/mod.rs+11-78
......@@ -30,7 +30,6 @@ use rustc_errors::ErrorGuaranteed;
3030pub use rustc_infer::traits::*;
3131use rustc_macros::TypeVisitable;
3232use rustc_middle::query::Providers;
33use rustc_middle::span_bug;
3433use rustc_middle::ty::error::{ExpectedFound, TypeError};
3534use rustc_middle::ty::{
3635 self, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder,
......@@ -257,12 +256,6 @@ fn do_normalize_predicates<'tcx>(
257256 elaborated_env: ty::ParamEnv<'tcx>,
258257 predicates: Vec<ty::Clause<'tcx>>,
259258) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
260 // Even if we move back to eager normalization elsewhere,
261 // param env normalization remains lazy in the next solver.
262 if tcx.next_trait_solver_globally() {
263 return Ok(predicates);
264 }
265
266259 // FIXME. We should really... do something with these region
267260 // obligations. But this call just continues the older
268261 // behavior (i.e., doesn't cause any new bugs), and it would
......@@ -294,17 +287,20 @@ fn do_normalize_predicates<'tcx>(
294287
295288 // We can use the `elaborated_env` here; the region code only
296289 // cares about declarations like `'a: 'b`.
290 //
297291 // FIXME: It's very weird that we ignore region obligations but apparently
298292 // still need to use `resolve_regions` as we need the resolved regions in
299293 // the normalized predicates.
300 let errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
301 if !errors.is_empty() {
302 tcx.dcx().span_delayed_bug(
303 span,
304 format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"),
305 );
306 }
307
294 //
295 // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now.
296 // There're placeholder constraints `leaking` out. This is a hack to work around
297 // the fact that we don't support placeholder assumptions right now and is necessary
298 // for `compare_method_predicate_entailment`. We should remove this once we
299 // have proper support for implied bounds on binders.
300 //
301 // This is required by trait-system-refactor-initiative#166. The new solver encounters
302 // this more frequently as we entirely ignore outlives predicates with the old solver.
303 let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
308304 match infcx.fully_resolve(predicates) {
309305 Ok(predicates) => Ok(predicates),
310306 Err(fixup_err) => {
......@@ -481,69 +477,6 @@ pub fn normalize_param_env_or_error<'tcx>(
481477 ty::ParamEnv::new(tcx.mk_clauses(&predicates))
482478}
483479
484/// Deeply normalize the param env using the next solver ignoring
485/// region errors.
486///
487/// FIXME(-Zhigher-ranked-assumptions): this is a hack to work around
488/// the fact that we don't support placeholder assumptions right now
489/// and is necessary for `compare_method_predicate_entailment`, see the
490/// use of this function for more info. We should remove this once we
491/// have proper support for implied bounds on binders.
492#[instrument(level = "debug", skip(tcx))]
493pub fn deeply_normalize_param_env_ignoring_regions<'tcx>(
494 tcx: TyCtxt<'tcx>,
495 unnormalized_env: ty::ParamEnv<'tcx>,
496 cause: ObligationCause<'tcx>,
497) -> ty::ParamEnv<'tcx> {
498 let predicates: Vec<_> =
499 util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect();
500
501 debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
502
503 let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates));
504 if !elaborated_env.has_aliases() {
505 return elaborated_env;
506 }
507
508 let span = cause.span;
509 let infcx = tcx
510 .infer_ctxt()
511 .with_next_trait_solver(true)
512 .ignoring_regions()
513 .build(TypingMode::non_body_analysis());
514 let predicates = match crate::solve::deeply_normalize::<_, FulfillmentError<'tcx>>(
515 infcx.at(&cause, elaborated_env),
516 Unnormalized::new_wip(predicates),
517 ) {
518 Ok(predicates) => predicates,
519 Err(errors) => {
520 infcx.err_ctxt().report_fulfillment_errors(errors);
521 // An unnormalized env is better than nothing.
522 debug!("normalize_param_env_or_error: errored resolving predicates");
523 return elaborated_env;
524 }
525 };
526
527 debug!("do_normalize_predicates: normalized predicates = {:?}", predicates);
528 // FIXME(-Zhigher-ranked-assumptions): We're ignoring region errors for now.
529 // There're placeholder constraints `leaking` out.
530 // See the fixme in the enclosing function's docs for more.
531 let _errors = infcx.resolve_regions(cause.body_id, elaborated_env, []);
532
533 let predicates = match infcx.fully_resolve(predicates) {
534 Ok(predicates) => predicates,
535 Err(fixup_err) => {
536 span_bug!(
537 span,
538 "inference variables in normalized parameter environment: {}",
539 fixup_err
540 )
541 }
542 };
543 debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
544 ty::ParamEnv::new(tcx.mk_clauses(&predicates))
545}
546
547480#[derive(Debug)]
548481pub enum EvaluateConstErr {
549482 /// The constant being evaluated was either a generic parameter or inference variable, *or*,
library/alloc/src/io/impls.rs+64-1
......@@ -1,5 +1,7 @@
11use crate::boxed::Box;
2use crate::io::SizeHint;
2use crate::io::{self, Seek, SeekFrom, SizeHint};
3#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
4use crate::sync::Arc;
35
46// =============================================================================
57// Forwarding implementations
......@@ -18,5 +20,66 @@ impl<T> SizeHint for Box<T> {
1820 }
1921}
2022
23#[stable(feature = "rust1", since = "1.0.0")]
24impl<S: Seek + ?Sized> Seek for Box<S> {
25 #[inline]
26 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
27 (**self).seek(pos)
28 }
29
30 #[inline]
31 fn rewind(&mut self) -> io::Result<()> {
32 (**self).rewind()
33 }
34
35 #[inline]
36 fn stream_len(&mut self) -> io::Result<u64> {
37 (**self).stream_len()
38 }
39
40 #[inline]
41 fn stream_position(&mut self) -> io::Result<u64> {
42 (**self).stream_position()
43 }
44
45 #[inline]
46 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
47 (**self).seek_relative(offset)
48 }
49}
50
2151// =============================================================================
2252// In-memory buffer implementations
53
54#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
55#[stable(feature = "io_traits_arc", since = "1.73.0")]
56impl<S: Seek + ?Sized> Seek for Arc<S>
57where
58 for<'a> &'a S: Seek,
59 S: crate::io::IoHandle,
60{
61 #[inline]
62 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
63 (&**self).seek(pos)
64 }
65
66 #[inline]
67 fn rewind(&mut self) -> io::Result<()> {
68 (&**self).rewind()
69 }
70
71 #[inline]
72 fn stream_len(&mut self) -> io::Result<u64> {
73 (&**self).stream_len()
74 }
75
76 #[inline]
77 fn stream_position(&mut self) -> io::Result<u64> {
78 (&**self).stream_position()
79 }
80
81 #[inline]
82 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
83 (&**self).seek_relative(offset)
84 }
85}
library/alloc/src/io/mod.rs+3-3
......@@ -13,9 +13,9 @@ pub use core::io::const_error;
1313pub use core::io::{BorrowedBuf, BorrowedCursor};
1414#[unstable(feature = "alloc_io", issue = "154046")]
1515pub use core::io::{
16 Chain, Cursor, Empty, Error, ErrorKind, IoSlice, IoSliceMut, Repeat, Result, Sink, Take, empty,
17 repeat, sink,
16 Chain, Cursor, Empty, Error, ErrorKind, IoSlice, IoSliceMut, Repeat, Result, Seek, SeekFrom,
17 Sink, Take, empty, repeat, sink,
1818};
1919#[doc(hidden)]
2020#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
21pub use core::io::{IoHandle, OsFunctions, SizeHint, chain, take};
21pub use core::io::{IoHandle, OsFunctions, SizeHint, chain, stream_len_default, take};
library/alloc/src/lib.rs+1
......@@ -155,6 +155,7 @@
155155#![feature(ptr_metadata)]
156156#![feature(raw_os_error_ty)]
157157#![feature(rev_into_inner)]
158#![feature(seek_stream_len)]
158159#![feature(set_ptr_value)]
159160#![feature(share_trait)]
160161#![feature(sized_type_properties)]
library/core/src/ascii/ascii_char.rs+2-2
......@@ -1049,8 +1049,8 @@ impl AsciiChar {
10491049 /// before using this function.
10501050 ///
10511051 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1052 /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
1053 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
1052 /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
1053 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
10541054 ///
10551055 /// # Examples
10561056 ///
library/core/src/char/methods.rs+2-2
......@@ -2354,8 +2354,8 @@ impl char {
23542354 /// before using this function.
23552355 ///
23562356 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
2357 /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
2358 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
2357 /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
2358 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
23592359 ///
23602360 /// # Examples
23612361 ///
library/core/src/io/cursor.rs+38-1
......@@ -1,3 +1,5 @@
1use crate::io::{self, ErrorKind, SeekFrom};
2
13/// A `Cursor` wraps an in-memory buffer and provides it with a
24/// [`Seek`] implementation.
35///
......@@ -21,7 +23,7 @@
2123/// [`File`]: ../../std/fs/struct.File.html
2224/// [`Read`]: ../../std/io/trait.Read.html
2325/// [`Write`]: ../../std/io/trait.Write.html
24/// [`Seek`]: ../../std/io/trait.Seek.html
26/// [`Seek`]: crate::io::Seek
2527/// [Vec]: ../../alloc/vec/struct.Vec.html
2628///
2729/// ```no_run
......@@ -291,3 +293,38 @@ where
291293 self.pos = other.pos;
292294 }
293295}
296
297#[stable(feature = "rust1", since = "1.0.0")]
298impl<T> io::Seek for Cursor<T>
299where
300 T: AsRef<[u8]>,
301{
302 fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
303 let (base_pos, offset) = match style {
304 SeekFrom::Start(n) => {
305 self.set_position(n);
306 return Ok(n);
307 }
308 SeekFrom::End(n) => (self.get_ref().as_ref().len() as u64, n),
309 SeekFrom::Current(n) => (self.position(), n),
310 };
311 match base_pos.checked_add_signed(offset) {
312 Some(n) => {
313 self.set_position(n);
314 Ok(n)
315 }
316 None => Err(io::const_error!(
317 ErrorKind::InvalidInput,
318 "invalid seek to a negative or overflowing position",
319 )),
320 }
321 }
322
323 fn stream_len(&mut self) -> io::Result<u64> {
324 Ok(self.get_ref().as_ref().len() as u64)
325 }
326
327 fn stream_position(&mut self) -> io::Result<u64> {
328 Ok(self.position())
329 }
330}
library/core/src/io/error.rs+1-1
......@@ -80,7 +80,7 @@ pub type Result<T> = result::Result<T, Error>;
8080// FIXME(#74481): Hard-links required to link from `core` to `std`
8181/// [Read]: ../../std/io/trait.Read.html
8282/// [Write]: ../../std/io/trait.Write.html
83/// [Seek]: ../../std/io/trait.Seek.html
83/// [Seek]: crate::io::Seek
8484#[stable(feature = "rust1", since = "1.0.0")]
8585#[rustc_has_incoherent_inherent_impls]
8686pub struct Error {
library/core/src/io/impls.rs+29-1
......@@ -1,4 +1,4 @@
1use crate::io::SizeHint;
1use crate::io::{self, Seek, SeekFrom, SizeHint};
22
33// =============================================================================
44// Forwarding implementations
......@@ -17,6 +17,34 @@ impl<T> SizeHint for &mut T {
1717 }
1818}
1919
20#[stable(feature = "rust1", since = "1.0.0")]
21impl<S: Seek + ?Sized> Seek for &mut S {
22 #[inline]
23 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
24 (**self).seek(pos)
25 }
26
27 #[inline]
28 fn rewind(&mut self) -> io::Result<()> {
29 (**self).rewind()
30 }
31
32 #[inline]
33 fn stream_len(&mut self) -> io::Result<u64> {
34 (**self).stream_len()
35 }
36
37 #[inline]
38 fn stream_position(&mut self) -> io::Result<u64> {
39 (**self).stream_position()
40 }
41
42 #[inline]
43 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
44 (**self).seek_relative(offset)
45 }
46}
47
2048// =============================================================================
2149// In-memory buffer implementations
2250
library/core/src/io/mod.rs+4-1
......@@ -5,6 +5,7 @@ mod cursor;
55mod error;
66mod impls;
77mod io_slice;
8mod seek;
89mod size_hint;
910mod util;
1011
......@@ -21,12 +22,14 @@ pub use self::{
2122 cursor::Cursor,
2223 error::{Error, ErrorKind, Result},
2324 io_slice::{IoSlice, IoSliceMut},
25 seek::{Seek, SeekFrom},
2426 util::{Chain, Empty, Repeat, Sink, Take, empty, repeat, sink},
2527};
2628#[doc(hidden)]
2729#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
2830pub use self::{
2931 error::{Custom, CustomOwner, OsFunctions},
32 seek::stream_len_default,
3033 size_hint::SizeHint,
3134 util::{chain, take},
3235};
......@@ -46,7 +49,7 @@ pub use self::{
4649/// [file]: ../../std/fs/struct.File.html
4750/// [arc]: ../../alloc/sync/struct.Arc.html
4851/// [`Write`]: ../../std/io/trait.Write.html
49/// [`Seek`]: ../../std/io/trait.Seek.html
52/// [`Seek`]: crate::io::Seek
5053#[doc(hidden)]
5154#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
5255pub trait IoHandle {}
library/core/src/io/seek.rs created+221
......@@ -0,0 +1,221 @@
1use crate::io::Result;
2
3/// The `Seek` trait provides a cursor which can be moved within a stream of
4/// bytes.
5///
6/// The stream typically has a fixed size, allowing seeking relative to either
7/// end or the current offset.
8///
9/// # Examples
10///
11/// `File`s implement `Seek`:
12///
13/// ```no_run
14/// use std::io;
15/// use std::io::prelude::*;
16/// use std::fs::File;
17/// use std::io::SeekFrom;
18///
19/// fn main() -> io::Result<()> {
20/// let mut f = File::open("foo.txt")?;
21///
22/// // move the cursor 42 bytes from the start of the file
23/// f.seek(SeekFrom::Start(42))?;
24/// Ok(())
25/// }
26/// ```
27#[stable(feature = "rust1", since = "1.0.0")]
28#[cfg_attr(not(test), rustc_diagnostic_item = "IoSeek")]
29pub trait Seek {
30 /// Seek to an offset, in bytes, in a stream.
31 ///
32 /// A seek beyond the end of a stream is allowed, but behavior is defined
33 /// by the implementation.
34 ///
35 /// If the seek operation completed successfully,
36 /// this method returns the new position from the start of the stream.
37 /// That position can be used later with [`SeekFrom::Start`].
38 ///
39 /// # Errors
40 ///
41 /// Seeking can fail, for example because it might involve flushing a buffer.
42 ///
43 /// Seeking to a negative offset is considered an error.
44 #[stable(feature = "rust1", since = "1.0.0")]
45 fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
46
47 /// Rewind to the beginning of a stream.
48 ///
49 /// This is a convenience method, equivalent to `seek(SeekFrom::Start(0))`.
50 ///
51 /// # Errors
52 ///
53 /// Rewinding can fail, for example because it might involve flushing a buffer.
54 ///
55 /// # Example
56 ///
57 /// ```no_run
58 /// use std::io::{Read, Seek, Write};
59 /// use std::fs::OpenOptions;
60 ///
61 /// let mut f = OpenOptions::new()
62 /// .write(true)
63 /// .read(true)
64 /// .create(true)
65 /// .open("foo.txt")?;
66 ///
67 /// let hello = "Hello!\n";
68 /// write!(f, "{hello}")?;
69 /// f.rewind()?;
70 ///
71 /// let mut buf = String::new();
72 /// f.read_to_string(&mut buf)?;
73 /// assert_eq!(&buf, hello);
74 /// # std::io::Result::Ok(())
75 /// ```
76 #[stable(feature = "seek_rewind", since = "1.55.0")]
77 fn rewind(&mut self) -> Result<()> {
78 self.seek(SeekFrom::Start(0))?;
79 Ok(())
80 }
81
82 /// Returns the length of this stream (in bytes).
83 ///
84 /// The default implementation uses up to three seek operations. If this
85 /// method returns successfully, the seek position is unchanged (i.e. the
86 /// position before calling this method is the same as afterwards).
87 /// However, if this method returns an error, the seek position is
88 /// unspecified.
89 ///
90 /// If you need to obtain the length of *many* streams and you don't care
91 /// about the seek position afterwards, you can reduce the number of seek
92 /// operations by simply calling `seek(SeekFrom::End(0))` and using its
93 /// return value (it is also the stream length).
94 ///
95 /// Note that length of a stream can change over time (for example, when
96 /// data is appended to a file). So calling this method multiple times does
97 /// not necessarily return the same length each time.
98 ///
99 /// # Example
100 ///
101 /// ```no_run
102 /// #![feature(seek_stream_len)]
103 /// use std::{
104 /// io::{self, Seek},
105 /// fs::File,
106 /// };
107 ///
108 /// fn main() -> io::Result<()> {
109 /// let mut f = File::open("foo.txt")?;
110 ///
111 /// let len = f.stream_len()?;
112 /// println!("The file is currently {len} bytes long");
113 /// Ok(())
114 /// }
115 /// ```
116 #[unstable(feature = "seek_stream_len", issue = "59359")]
117 fn stream_len(&mut self) -> Result<u64> {
118 stream_len_default(self)
119 }
120
121 /// Returns the current seek position from the start of the stream.
122 ///
123 /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
124 ///
125 /// # Example
126 ///
127 /// ```no_run
128 /// use std::{
129 /// io::{self, BufRead, BufReader, Seek},
130 /// fs::File,
131 /// };
132 ///
133 /// fn main() -> io::Result<()> {
134 /// let mut f = BufReader::new(File::open("foo.txt")?);
135 ///
136 /// let before = f.stream_position()?;
137 /// f.read_line(&mut String::new())?;
138 /// let after = f.stream_position()?;
139 ///
140 /// println!("The first line was {} bytes long", after - before);
141 /// Ok(())
142 /// }
143 /// ```
144 #[stable(feature = "seek_convenience", since = "1.51.0")]
145 fn stream_position(&mut self) -> Result<u64> {
146 self.seek(SeekFrom::Current(0))
147 }
148
149 /// Seeks relative to the current position.
150 ///
151 /// This is equivalent to `self.seek(SeekFrom::Current(offset))` but
152 /// doesn't return the new position which can allow some implementations
153 /// such as `BufReader` to perform more efficient seeks.
154 ///
155 /// # Example
156 ///
157 /// ```no_run
158 /// use std::{
159 /// io::{self, Seek},
160 /// fs::File,
161 /// };
162 ///
163 /// fn main() -> io::Result<()> {
164 /// let mut f = File::open("foo.txt")?;
165 /// f.seek_relative(10)?;
166 /// assert_eq!(f.stream_position()?, 10);
167 /// Ok(())
168 /// }
169 /// ```
170 #[stable(feature = "seek_seek_relative", since = "1.80.0")]
171 fn seek_relative(&mut self, offset: i64) -> Result<()> {
172 self.seek(SeekFrom::Current(offset))?;
173 Ok(())
174 }
175}
176
177/// The default implementation of [`Seek::stream_len`].
178/// This may be desirable in `libstd` where the default implementation is desirable,
179/// but additional work needs to be done before or after.
180#[doc(hidden)]
181#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
182pub fn stream_len_default<T: Seek + ?Sized>(self_: &mut T) -> Result<u64> {
183 let old_pos = self_.stream_position()?;
184 let len = self_.seek(SeekFrom::End(0))?;
185
186 // Avoid seeking a third time when we were already at the end of the
187 // stream. The branch is usually way cheaper than a seek operation.
188 if old_pos != len {
189 self_.seek(SeekFrom::Start(old_pos))?;
190 }
191
192 Ok(len)
193}
194
195/// Enumeration of possible methods to seek within an I/O object.
196///
197/// It is used by the [`Seek`] trait.
198#[derive(Copy, PartialEq, Eq, Clone, Debug)]
199#[stable(feature = "rust1", since = "1.0.0")]
200#[cfg_attr(not(test), rustc_diagnostic_item = "SeekFrom")]
201pub enum SeekFrom {
202 /// Sets the offset to the provided number of bytes.
203 #[stable(feature = "rust1", since = "1.0.0")]
204 Start(#[stable(feature = "rust1", since = "1.0.0")] u64),
205
206 /// Sets the offset to the size of this object plus the specified number of
207 /// bytes.
208 ///
209 /// It is possible to seek beyond the end of an object, but it's an error to
210 /// seek before byte 0.
211 #[stable(feature = "rust1", since = "1.0.0")]
212 End(#[stable(feature = "rust1", since = "1.0.0")] i64),
213
214 /// Sets the offset to the current position plus the specified number of
215 /// bytes.
216 ///
217 /// It is possible to seek beyond the end of an object, but it's an error to
218 /// seek before byte 0.
219 #[stable(feature = "rust1", since = "1.0.0")]
220 Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
221}
library/core/src/io/util.rs+62-1
......@@ -1,4 +1,4 @@
1use crate::io::SizeHint;
1use crate::io::{ErrorKind, Result, Seek, SeekFrom, SizeHint};
22use crate::{cmp, fmt};
33
44/// `Empty` ignores any data written via [`Write`], and will always be empty
......@@ -23,6 +23,24 @@ impl SizeHint for Empty {
2323 }
2424}
2525
26#[stable(feature = "empty_seek", since = "1.51.0")]
27impl Seek for Empty {
28 #[inline]
29 fn seek(&mut self, _pos: SeekFrom) -> Result<u64> {
30 Ok(0)
31 }
32
33 #[inline]
34 fn stream_len(&mut self) -> Result<u64> {
35 Ok(0)
36 }
37
38 #[inline]
39 fn stream_position(&mut self) -> Result<u64> {
40 Ok(0)
41 }
42}
43
2644/// Creates a value that is always at EOF for reads, and ignores all data written.
2745///
2846/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`]
......@@ -464,6 +482,49 @@ impl<T> Take<T> {
464482 }
465483}
466484
485#[stable(feature = "seek_io_take", since = "1.89.0")]
486impl<T: Seek> Seek for Take<T> {
487 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
488 let new_position = match pos {
489 SeekFrom::Start(v) => Some(v),
490 SeekFrom::Current(v) => self.position().checked_add_signed(v),
491 SeekFrom::End(v) => self.len.checked_add_signed(v),
492 };
493 let new_position = match new_position {
494 Some(v) if v <= self.len => v,
495 _ => return Err(ErrorKind::InvalidInput.into()),
496 };
497 while new_position != self.position() {
498 if let Some(offset) = new_position.checked_signed_diff(self.position()) {
499 self.inner.seek_relative(offset)?;
500 self.limit = self.limit.wrapping_sub(offset as u64);
501 break;
502 }
503 let offset = if new_position > self.position() { i64::MAX } else { i64::MIN };
504 self.inner.seek_relative(offset)?;
505 self.limit = self.limit.wrapping_sub(offset as u64);
506 }
507 Ok(new_position)
508 }
509
510 fn stream_len(&mut self) -> Result<u64> {
511 Ok(self.len)
512 }
513
514 fn stream_position(&mut self) -> Result<u64> {
515 Ok(self.position())
516 }
517
518 fn seek_relative(&mut self, offset: i64) -> Result<()> {
519 if !self.position().checked_add_signed(offset).is_some_and(|p| p <= self.len) {
520 return Err(ErrorKind::InvalidInput.into());
521 }
522 self.inner.seek_relative(offset)?;
523 self.limit = self.limit.wrapping_sub(offset as u64);
524 Ok(())
525 }
526}
527
467528#[doc(hidden)]
468529#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
469530#[must_use]
library/core/src/num/mod.rs+2-2
......@@ -1125,8 +1125,8 @@ impl u8 {
11251125 /// before using this function.
11261126 ///
11271127 /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
1128 /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
1129 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
1128 /// [pct]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_01
1129 /// [bfs]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html#tag_19_06_05
11301130 ///
11311131 /// # Examples
11321132 ///
library/core/src/range.rs+13-8
......@@ -402,7 +402,8 @@ const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
402402 ///
403403 /// # Panics
404404 ///
405 /// Panics if the legacy range iterator has been exhausted.
405 /// If the legacy range iterator has been exhausted,
406 /// this function will either panic or return an empty range.
406407 ///
407408 /// # Examples
408409 ///
......@@ -419,19 +420,23 @@ const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
419420 /// assert_eq!((empty.start, empty.last), (0, 0));
420421 /// ```
421422 ///
422 /// ```should_panic
423 /// ```
424 /// # // This test requires unwinding to work.
425 /// # // Disable it when unwinding isn't available.
426 /// # #[cfg(panic = "unwind")]
427 /// # fn main() {
423428 /// use core::range::legacy;
424429 /// use core::range::RangeInclusive;
430 /// use std::panic::catch_unwind;
425431 ///
426432 /// let mut exhausted: legacy::RangeInclusive<i32> = 0..=0;
427433 /// exhausted.next();
428 /// # if exhausted.is_empty() {
429 /// # // assert!s don't work correctly in `should_panic` doctests since you
430 /// # // can't assert the panic message. Skip the rest of the test instead,
431 /// # // so that the expected panic doesn't happen and the test fails.
432 /// assert!(exhausted.is_empty());
433 /// let _ = RangeInclusive::from(exhausted); // this panics
434 /// let result = catch_unwind(|| RangeInclusive::from(exhausted));
435 /// // The `from` call either panicked or returned an empty range.
436 /// assert!(result.is_err() || result.is_ok_and(|range| range.is_empty()));
434437 /// # }
438 /// # #[cfg(not(panic = "unwind"))]
439 /// # fn main() {}
435440 /// ```
436441 #[inline]
437442 fn from(value: legacy::RangeInclusive<T>) -> Self {
library/std/src/io/cursor.rs+82-69
......@@ -7,42 +7,7 @@ pub use core::io::Cursor;
77use crate::alloc::Allocator;
88use crate::cmp;
99use crate::io::prelude::*;
10use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
11
12#[stable(feature = "rust1", since = "1.0.0")]
13impl<T> io::Seek for Cursor<T>
14where
15 T: AsRef<[u8]>,
16{
17 fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
18 let (base_pos, offset) = match style {
19 SeekFrom::Start(n) => {
20 self.set_position(n);
21 return Ok(n);
22 }
23 SeekFrom::End(n) => (self.get_ref().as_ref().len() as u64, n),
24 SeekFrom::Current(n) => (self.position(), n),
25 };
26 match base_pos.checked_add_signed(offset) {
27 Some(n) => {
28 self.set_position(n);
29 Ok(n)
30 }
31 None => Err(io::const_error!(
32 ErrorKind::InvalidInput,
33 "invalid seek to a negative or overflowing position",
34 )),
35 }
36 }
37
38 fn stream_len(&mut self) -> io::Result<u64> {
39 Ok(self.get_ref().as_ref().len() as u64)
40 }
41
42 fn stream_position(&mut self) -> io::Result<u64> {
43 Ok(self.position())
44 }
45}
10use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
4611
4712#[stable(feature = "rust1", since = "1.0.0")]
4813impl<T> Read for Cursor<T>
......@@ -137,6 +102,54 @@ where
137102 }
138103}
139104
105/// Trait used to allow indirect implementation of `Write` for `Cursor<Self>`.
106/// Since [`Cursor`] is not a foundational type, it is not possible to implement
107/// `Write` for `Cursor<T>` if `Write` is defined in `libcore` and `T` is in a
108/// downstream crate (e.g., `liballoc` or `libstd`).
109///
110/// Methods are identical in purpose and meaning to their `Write` namesakes.
111trait WriteThroughCursor: Sized {
112 fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize>;
113 fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize>;
114 fn is_write_vectored(this: &Cursor<Self>) -> bool;
115 fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()>;
116 fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()>;
117 fn flush(this: &mut Cursor<Self>) -> io::Result<()>;
118}
119
120#[stable(feature = "rust1", since = "1.0.0")]
121impl<W: WriteThroughCursor> Write for Cursor<W> {
122 #[inline]
123 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
124 WriteThroughCursor::write(self, buf)
125 }
126
127 #[inline]
128 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
129 WriteThroughCursor::write_vectored(self, bufs)
130 }
131
132 #[inline]
133 fn is_write_vectored(&self) -> bool {
134 WriteThroughCursor::is_write_vectored(self)
135 }
136
137 #[inline]
138 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
139 WriteThroughCursor::write_all(self, buf)
140 }
141
142 #[inline]
143 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
144 WriteThroughCursor::write_all_vectored(self, bufs)
145 }
146
147 #[inline]
148 fn flush(&mut self) -> io::Result<()> {
149 WriteThroughCursor::flush(self)
150 }
151}
152
140153// Non-resizing write implementation
141154#[inline]
142155fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
......@@ -348,117 +361,117 @@ impl Write for Cursor<&mut [u8]> {
348361}
349362
350363#[stable(feature = "cursor_mut_vec", since = "1.25.0")]
351impl<A> Write for Cursor<&mut Vec<u8, A>>
364impl<A> WriteThroughCursor for &mut Vec<u8, A>
352365where
353366 A: Allocator,
354367{
355 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
356 let (pos, inner) = self.into_parts_mut();
368 fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
369 let (pos, inner) = this.into_parts_mut();
357370 vec_write_all(pos, inner, buf)
358371 }
359372
360 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
361 let (pos, inner) = self.into_parts_mut();
373 fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
374 let (pos, inner) = this.into_parts_mut();
362375 vec_write_all_vectored(pos, inner, bufs)
363376 }
364377
365378 #[inline]
366 fn is_write_vectored(&self) -> bool {
379 fn is_write_vectored(_this: &Cursor<Self>) -> bool {
367380 true
368381 }
369382
370 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
371 let (pos, inner) = self.into_parts_mut();
383 fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
384 let (pos, inner) = this.into_parts_mut();
372385 vec_write_all(pos, inner, buf)?;
373386 Ok(())
374387 }
375388
376 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
377 let (pos, inner) = self.into_parts_mut();
389 fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
390 let (pos, inner) = this.into_parts_mut();
378391 vec_write_all_vectored(pos, inner, bufs)?;
379392 Ok(())
380393 }
381394
382395 #[inline]
383 fn flush(&mut self) -> io::Result<()> {
396 fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
384397 Ok(())
385398 }
386399}
387400
388401#[stable(feature = "rust1", since = "1.0.0")]
389impl<A> Write for Cursor<Vec<u8, A>>
402impl<A> WriteThroughCursor for Vec<u8, A>
390403where
391404 A: Allocator,
392405{
393 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
394 let (pos, inner) = self.into_parts_mut();
406 fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
407 let (pos, inner) = this.into_parts_mut();
395408 vec_write_all(pos, inner, buf)
396409 }
397410
398 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
399 let (pos, inner) = self.into_parts_mut();
411 fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
412 let (pos, inner) = this.into_parts_mut();
400413 vec_write_all_vectored(pos, inner, bufs)
401414 }
402415
403416 #[inline]
404 fn is_write_vectored(&self) -> bool {
417 fn is_write_vectored(_this: &Cursor<Self>) -> bool {
405418 true
406419 }
407420
408 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
409 let (pos, inner) = self.into_parts_mut();
421 fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
422 let (pos, inner) = this.into_parts_mut();
410423 vec_write_all(pos, inner, buf)?;
411424 Ok(())
412425 }
413426
414 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
415 let (pos, inner) = self.into_parts_mut();
427 fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
428 let (pos, inner) = this.into_parts_mut();
416429 vec_write_all_vectored(pos, inner, bufs)?;
417430 Ok(())
418431 }
419432
420433 #[inline]
421 fn flush(&mut self) -> io::Result<()> {
434 fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
422435 Ok(())
423436 }
424437}
425438
426439#[stable(feature = "cursor_box_slice", since = "1.5.0")]
427impl<A> Write for Cursor<Box<[u8], A>>
440impl<A> WriteThroughCursor for Box<[u8], A>
428441where
429442 A: Allocator,
430443{
431444 #[inline]
432 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
433 let (pos, inner) = self.into_parts_mut();
445 fn write(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<usize> {
446 let (pos, inner) = this.into_parts_mut();
434447 slice_write(pos, inner, buf)
435448 }
436449
437450 #[inline]
438 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
439 let (pos, inner) = self.into_parts_mut();
451 fn write_vectored(this: &mut Cursor<Self>, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
452 let (pos, inner) = this.into_parts_mut();
440453 slice_write_vectored(pos, inner, bufs)
441454 }
442455
443456 #[inline]
444 fn is_write_vectored(&self) -> bool {
457 fn is_write_vectored(_this: &Cursor<Self>) -> bool {
445458 true
446459 }
447460
448461 #[inline]
449 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
450 let (pos, inner) = self.into_parts_mut();
462 fn write_all(this: &mut Cursor<Self>, buf: &[u8]) -> io::Result<()> {
463 let (pos, inner) = this.into_parts_mut();
451464 slice_write_all(pos, inner, buf)
452465 }
453466
454467 #[inline]
455 fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
456 let (pos, inner) = self.into_parts_mut();
468 fn write_all_vectored(this: &mut Cursor<Self>, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
469 let (pos, inner) = this.into_parts_mut();
457470 slice_write_all_vectored(pos, inner, bufs)
458471 }
459472
460473 #[inline]
461 fn flush(&mut self) -> io::Result<()> {
474 fn flush(_this: &mut Cursor<Self>) -> io::Result<()> {
462475 Ok(())
463476 }
464477}
library/std/src/io/impls.rs+1-86
......@@ -3,7 +3,7 @@ mod tests;
33
44use crate::alloc::Allocator;
55use crate::collections::VecDeque;
6use crate::io::{self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
6use crate::io::{self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Write};
77use crate::sync::Arc;
88use crate::{cmp, fmt, mem, str};
99
......@@ -90,33 +90,6 @@ impl<W: Write + ?Sized> Write for &mut W {
9090 }
9191}
9292#[stable(feature = "rust1", since = "1.0.0")]
93impl<S: Seek + ?Sized> Seek for &mut S {
94 #[inline]
95 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
96 (**self).seek(pos)
97 }
98
99 #[inline]
100 fn rewind(&mut self) -> io::Result<()> {
101 (**self).rewind()
102 }
103
104 #[inline]
105 fn stream_len(&mut self) -> io::Result<u64> {
106 (**self).stream_len()
107 }
108
109 #[inline]
110 fn stream_position(&mut self) -> io::Result<u64> {
111 (**self).stream_position()
112 }
113
114 #[inline]
115 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
116 (**self).seek_relative(offset)
117 }
118}
119#[stable(feature = "rust1", since = "1.0.0")]
12093impl<B: BufRead + ?Sized> BufRead for &mut B {
12194 #[inline]
12295 fn fill_buf(&mut self) -> io::Result<&[u8]> {
......@@ -229,33 +202,6 @@ impl<W: Write + ?Sized> Write for Box<W> {
229202 }
230203}
231204#[stable(feature = "rust1", since = "1.0.0")]
232impl<S: Seek + ?Sized> Seek for Box<S> {
233 #[inline]
234 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
235 (**self).seek(pos)
236 }
237
238 #[inline]
239 fn rewind(&mut self) -> io::Result<()> {
240 (**self).rewind()
241 }
242
243 #[inline]
244 fn stream_len(&mut self) -> io::Result<u64> {
245 (**self).stream_len()
246 }
247
248 #[inline]
249 fn stream_position(&mut self) -> io::Result<u64> {
250 (**self).stream_position()
251 }
252
253 #[inline]
254 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
255 (**self).seek_relative(offset)
256 }
257}
258#[stable(feature = "rust1", since = "1.0.0")]
259205impl<B: BufRead + ?Sized> BufRead for Box<B> {
260206 #[inline]
261207 fn fill_buf(&mut self) -> io::Result<&[u8]> {
......@@ -804,34 +750,3 @@ where
804750 (&**self).write_fmt(fmt)
805751 }
806752}
807#[stable(feature = "io_traits_arc", since = "1.73.0")]
808impl<S: Seek + ?Sized> Seek for Arc<S>
809where
810 for<'a> &'a S: Seek,
811 S: crate::io::IoHandle,
812{
813 #[inline]
814 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
815 (&**self).seek(pos)
816 }
817
818 #[inline]
819 fn rewind(&mut self) -> io::Result<()> {
820 (&**self).rewind()
821 }
822
823 #[inline]
824 fn stream_len(&mut self) -> io::Result<u64> {
825 (&**self).stream_len()
826 }
827
828 #[inline]
829 fn stream_position(&mut self) -> io::Result<u64> {
830 (&**self).stream_position()
831 }
832
833 #[inline]
834 fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
835 (&**self).seek_relative(offset)
836 }
837}
library/std/src/io/mod.rs+2-264
......@@ -299,7 +299,6 @@ mod tests;
299299
300300use core::slice::memchr;
301301
302pub(crate) use alloc_crate::io::IoHandle;
303302#[unstable(feature = "raw_os_error_ty", issue = "107792")]
304303pub use alloc_crate::io::RawOsError;
305304#[doc(hidden)]
......@@ -311,8 +310,9 @@ pub use alloc_crate::io::const_error;
311310pub use alloc_crate::io::{BorrowedBuf, BorrowedCursor};
312311#[stable(feature = "rust1", since = "1.0.0")]
313312pub use alloc_crate::io::{
314 Chain, Empty, Error, ErrorKind, Repeat, Result, Sink, Take, empty, repeat, sink,
313 Chain, Empty, Error, ErrorKind, Repeat, Result, Seek, SeekFrom, Sink, Take, empty, repeat, sink,
315314};
315pub(crate) use alloc_crate::io::{IoHandle, stream_len_default};
316316#[stable(feature = "iovec", since = "1.36.0")]
317317pub use alloc_crate::io::{IoSlice, IoSliceMut};
318318use alloc_crate::io::{OsFunctions, SizeHint};
......@@ -1762,225 +1762,6 @@ pub trait Write {
17621762 }
17631763}
17641764
1765/// The `Seek` trait provides a cursor which can be moved within a stream of
1766/// bytes.
1767///
1768/// The stream typically has a fixed size, allowing seeking relative to either
1769/// end or the current offset.
1770///
1771/// # Examples
1772///
1773/// [`File`]s implement `Seek`:
1774///
1775/// [`File`]: crate::fs::File
1776///
1777/// ```no_run
1778/// use std::io;
1779/// use std::io::prelude::*;
1780/// use std::fs::File;
1781/// use std::io::SeekFrom;
1782///
1783/// fn main() -> io::Result<()> {
1784/// let mut f = File::open("foo.txt")?;
1785///
1786/// // move the cursor 42 bytes from the start of the file
1787/// f.seek(SeekFrom::Start(42))?;
1788/// Ok(())
1789/// }
1790/// ```
1791#[stable(feature = "rust1", since = "1.0.0")]
1792#[cfg_attr(not(test), rustc_diagnostic_item = "IoSeek")]
1793pub trait Seek {
1794 /// Seek to an offset, in bytes, in a stream.
1795 ///
1796 /// A seek beyond the end of a stream is allowed, but behavior is defined
1797 /// by the implementation.
1798 ///
1799 /// If the seek operation completed successfully,
1800 /// this method returns the new position from the start of the stream.
1801 /// That position can be used later with [`SeekFrom::Start`].
1802 ///
1803 /// # Errors
1804 ///
1805 /// Seeking can fail, for example because it might involve flushing a buffer.
1806 ///
1807 /// Seeking to a negative offset is considered an error.
1808 #[stable(feature = "rust1", since = "1.0.0")]
1809 fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
1810
1811 /// Rewind to the beginning of a stream.
1812 ///
1813 /// This is a convenience method, equivalent to `seek(SeekFrom::Start(0))`.
1814 ///
1815 /// # Errors
1816 ///
1817 /// Rewinding can fail, for example because it might involve flushing a buffer.
1818 ///
1819 /// # Example
1820 ///
1821 /// ```no_run
1822 /// use std::io::{Read, Seek, Write};
1823 /// use std::fs::OpenOptions;
1824 ///
1825 /// let mut f = OpenOptions::new()
1826 /// .write(true)
1827 /// .read(true)
1828 /// .create(true)
1829 /// .open("foo.txt")?;
1830 ///
1831 /// let hello = "Hello!\n";
1832 /// write!(f, "{hello}")?;
1833 /// f.rewind()?;
1834 ///
1835 /// let mut buf = String::new();
1836 /// f.read_to_string(&mut buf)?;
1837 /// assert_eq!(&buf, hello);
1838 /// # std::io::Result::Ok(())
1839 /// ```
1840 #[stable(feature = "seek_rewind", since = "1.55.0")]
1841 fn rewind(&mut self) -> Result<()> {
1842 self.seek(SeekFrom::Start(0))?;
1843 Ok(())
1844 }
1845
1846 /// Returns the length of this stream (in bytes).
1847 ///
1848 /// The default implementation uses up to three seek operations. If this
1849 /// method returns successfully, the seek position is unchanged (i.e. the
1850 /// position before calling this method is the same as afterwards).
1851 /// However, if this method returns an error, the seek position is
1852 /// unspecified.
1853 ///
1854 /// If you need to obtain the length of *many* streams and you don't care
1855 /// about the seek position afterwards, you can reduce the number of seek
1856 /// operations by simply calling `seek(SeekFrom::End(0))` and using its
1857 /// return value (it is also the stream length).
1858 ///
1859 /// Note that length of a stream can change over time (for example, when
1860 /// data is appended to a file). So calling this method multiple times does
1861 /// not necessarily return the same length each time.
1862 ///
1863 /// # Example
1864 ///
1865 /// ```no_run
1866 /// #![feature(seek_stream_len)]
1867 /// use std::{
1868 /// io::{self, Seek},
1869 /// fs::File,
1870 /// };
1871 ///
1872 /// fn main() -> io::Result<()> {
1873 /// let mut f = File::open("foo.txt")?;
1874 ///
1875 /// let len = f.stream_len()?;
1876 /// println!("The file is currently {len} bytes long");
1877 /// Ok(())
1878 /// }
1879 /// ```
1880 #[unstable(feature = "seek_stream_len", issue = "59359")]
1881 fn stream_len(&mut self) -> Result<u64> {
1882 stream_len_default(self)
1883 }
1884
1885 /// Returns the current seek position from the start of the stream.
1886 ///
1887 /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
1888 ///
1889 /// # Example
1890 ///
1891 /// ```no_run
1892 /// use std::{
1893 /// io::{self, BufRead, BufReader, Seek},
1894 /// fs::File,
1895 /// };
1896 ///
1897 /// fn main() -> io::Result<()> {
1898 /// let mut f = BufReader::new(File::open("foo.txt")?);
1899 ///
1900 /// let before = f.stream_position()?;
1901 /// f.read_line(&mut String::new())?;
1902 /// let after = f.stream_position()?;
1903 ///
1904 /// println!("The first line was {} bytes long", after - before);
1905 /// Ok(())
1906 /// }
1907 /// ```
1908 #[stable(feature = "seek_convenience", since = "1.51.0")]
1909 fn stream_position(&mut self) -> Result<u64> {
1910 self.seek(SeekFrom::Current(0))
1911 }
1912
1913 /// Seeks relative to the current position.
1914 ///
1915 /// This is equivalent to `self.seek(SeekFrom::Current(offset))` but
1916 /// doesn't return the new position which can allow some implementations
1917 /// such as [`BufReader`] to perform more efficient seeks.
1918 ///
1919 /// # Example
1920 ///
1921 /// ```no_run
1922 /// use std::{
1923 /// io::{self, Seek},
1924 /// fs::File,
1925 /// };
1926 ///
1927 /// fn main() -> io::Result<()> {
1928 /// let mut f = File::open("foo.txt")?;
1929 /// f.seek_relative(10)?;
1930 /// assert_eq!(f.stream_position()?, 10);
1931 /// Ok(())
1932 /// }
1933 /// ```
1934 ///
1935 /// [`BufReader`]: crate::io::BufReader
1936 #[stable(feature = "seek_seek_relative", since = "1.80.0")]
1937 fn seek_relative(&mut self, offset: i64) -> Result<()> {
1938 self.seek(SeekFrom::Current(offset))?;
1939 Ok(())
1940 }
1941}
1942
1943pub(crate) fn stream_len_default<T: Seek + ?Sized>(self_: &mut T) -> Result<u64> {
1944 let old_pos = self_.stream_position()?;
1945 let len = self_.seek(SeekFrom::End(0))?;
1946
1947 // Avoid seeking a third time when we were already at the end of the
1948 // stream. The branch is usually way cheaper than a seek operation.
1949 if old_pos != len {
1950 self_.seek(SeekFrom::Start(old_pos))?;
1951 }
1952
1953 Ok(len)
1954}
1955
1956/// Enumeration of possible methods to seek within an I/O object.
1957///
1958/// It is used by the [`Seek`] trait.
1959#[derive(Copy, PartialEq, Eq, Clone, Debug)]
1960#[stable(feature = "rust1", since = "1.0.0")]
1961#[cfg_attr(not(test), rustc_diagnostic_item = "SeekFrom")]
1962pub enum SeekFrom {
1963 /// Sets the offset to the provided number of bytes.
1964 #[stable(feature = "rust1", since = "1.0.0")]
1965 Start(#[stable(feature = "rust1", since = "1.0.0")] u64),
1966
1967 /// Sets the offset to the size of this object plus the specified number of
1968 /// bytes.
1969 ///
1970 /// It is possible to seek beyond the end of an object, but it's an error to
1971 /// seek before byte 0.
1972 #[stable(feature = "rust1", since = "1.0.0")]
1973 End(#[stable(feature = "rust1", since = "1.0.0")] i64),
1974
1975 /// Sets the offset to the current position plus the specified number of
1976 /// bytes.
1977 ///
1978 /// It is possible to seek beyond the end of an object, but it's an error to
1979 /// seek before byte 0.
1980 #[stable(feature = "rust1", since = "1.0.0")]
1981 Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
1982}
1983
19841765fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> Result<usize> {
19851766 let mut read = 0;
19861767 loop {
......@@ -2632,49 +2413,6 @@ impl<T: BufRead> BufRead for Take<T> {
26322413 }
26332414}
26342415
2635#[stable(feature = "seek_io_take", since = "1.89.0")]
2636impl<T: Seek> Seek for Take<T> {
2637 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
2638 let new_position = match pos {
2639 SeekFrom::Start(v) => Some(v),
2640 SeekFrom::Current(v) => self.position().checked_add_signed(v),
2641 SeekFrom::End(v) => self.len.checked_add_signed(v),
2642 };
2643 let new_position = match new_position {
2644 Some(v) if v <= self.len => v,
2645 _ => return Err(ErrorKind::InvalidInput.into()),
2646 };
2647 while new_position != self.position() {
2648 if let Some(offset) = new_position.checked_signed_diff(self.position()) {
2649 self.inner.seek_relative(offset)?;
2650 self.limit = self.limit.wrapping_sub(offset as u64);
2651 break;
2652 }
2653 let offset = if new_position > self.position() { i64::MAX } else { i64::MIN };
2654 self.inner.seek_relative(offset)?;
2655 self.limit = self.limit.wrapping_sub(offset as u64);
2656 }
2657 Ok(new_position)
2658 }
2659
2660 fn stream_len(&mut self) -> Result<u64> {
2661 Ok(self.len)
2662 }
2663
2664 fn stream_position(&mut self) -> Result<u64> {
2665 Ok(self.position())
2666 }
2667
2668 fn seek_relative(&mut self, offset: i64) -> Result<()> {
2669 if !self.position().checked_add_signed(offset).is_some_and(|p| p <= self.len) {
2670 return Err(ErrorKind::InvalidInput.into());
2671 }
2672 self.inner.seek_relative(offset)?;
2673 self.limit = self.limit.wrapping_sub(offset as u64);
2674 Ok(())
2675 }
2676}
2677
26782416/// An iterator over `u8` values of a reader.
26792417///
26802418/// This struct is generally created by calling [`bytes`] on a reader.
library/std/src/io/util.rs+1-20
......@@ -5,8 +5,7 @@ mod tests;
55
66use crate::fmt;
77use crate::io::{
8 self, BorrowedCursor, BufRead, Empty, IoSlice, IoSliceMut, Read, Repeat, Seek, SeekFrom, Sink,
9 Write,
8 self, BorrowedCursor, BufRead, Empty, IoSlice, IoSliceMut, Read, Repeat, Sink, Write,
109};
1110
1211#[stable(feature = "rust1", since = "1.0.0")]
......@@ -84,24 +83,6 @@ impl BufRead for Empty {
8483 }
8584}
8685
87#[stable(feature = "empty_seek", since = "1.51.0")]
88impl Seek for Empty {
89 #[inline]
90 fn seek(&mut self, _pos: SeekFrom) -> io::Result<u64> {
91 Ok(0)
92 }
93
94 #[inline]
95 fn stream_len(&mut self) -> io::Result<u64> {
96 Ok(0)
97 }
98
99 #[inline]
100 fn stream_position(&mut self) -> io::Result<u64> {
101 Ok(0)
102 }
103}
104
10586#[stable(feature = "empty_write", since = "1.73.0")]
10687impl Write for Empty {
10788 #[inline]
library/std/src/lib.rs+1
......@@ -374,6 +374,7 @@
374374#![feature(random)]
375375#![feature(raw_os_error_ty)]
376376#![feature(seek_io_take_position)]
377#![feature(seek_stream_len)]
377378#![feature(share_trait)]
378379#![feature(slice_internals)]
379380#![feature(slice_ptr_get)]
library/std/src/os/fd/owned.rs+1-1
......@@ -199,7 +199,7 @@ impl Drop for OwnedFd {
199199 unsafe {
200200 // Note that errors are ignored when closing a file descriptor. According to POSIX 2024,
201201 // we can and indeed should retry `close` on `EINTR`
202 // (https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/close.html),
202 // (https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html),
203203 // but it is not clear yet how well widely-used implementations are conforming with this
204204 // mandate since older versions of POSIX left the state of the FD after an `EINTR`
205205 // unspecified. Ignoring errors is "fine" because some of the major Unices (in
library/std/src/os/unix/process.rs+1-1
......@@ -102,7 +102,7 @@ pub impl(self) trait CommandExt {
102102 /// locations might not appear where intended.
103103 ///
104104 /// [POSIX fork() specification]:
105 /// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
105 /// https://pubs.opengroup.org/onlinepubs/9799919799/functions/fork.html
106106 /// [`std::env`]: mod@crate::env
107107 /// [`Error::new`]: ../../../io/struct.Error.html#method.new
108108 /// [`Error::other`]: ../../../io/struct.Error.html#method.other
library/std/src/path.rs+1-1
......@@ -4137,7 +4137,7 @@ impl Error for NormalizeError {}
41374137/// Note that this [may change in the future][changes].
41384138///
41394139/// [changes]: io#platform-specific-behavior
4140/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
4140/// [posix-semantics]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html#tag_04_16
41414141/// [windows-path]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfullpathnamew
41424142/// [cygwin-path]: https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
41434143#[stable(feature = "absolute_path", since = "1.79.0")]
library/std/src/sys/fs/unix.rs+1-1
......@@ -1926,7 +1926,7 @@ impl fmt::Debug for File {
19261926// Format in octal, followed by the mode format used in `ls -l`.
19271927//
19281928// References:
1929// https://pubs.opengroup.org/onlinepubs/009696899/utilities/ls.html
1929// https://pubs.opengroup.org/onlinepubs/9799919799/utilities/ls.html
19301930// https://www.gnu.org/software/libc/manual/html_node/Testing-File-Type.html
19311931// https://www.gnu.org/software/libc/manual/html_node/Permission-Bits.html
19321932//
library/std/src/sys/pal/unix/conf.rs+1-1
......@@ -11,7 +11,7 @@ pub fn page_size() -> usize {
1111/// `_CS_PATH` or `_CS_V[67]_ENV` in the future).
1212///
1313/// [posix_confstr]:
14/// https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html
14/// https://pubs.opengroup.org/onlinepubs/9799919799/functions/confstr.html
1515#[cfg(target_vendor = "apple")]
1616pub fn confstr(
1717 key: crate::ffi::c_int,
library/std/src/sys/pal/unix/sync/mutex.rs+1-1
......@@ -25,7 +25,7 @@ impl Mutex {
2525 // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have
2626 // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you
2727 // try to re-lock it from the same thread when you already hold a lock
28 // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html).
28 // (https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_mutex_init.html).
2929 // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL
3030 // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that
3131 // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same
library/std/src/sys/path/unix.rs+2-2
......@@ -20,8 +20,8 @@ pub const HAS_PREFIXES: bool = false;
2020pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
2121 // This is mostly a wrapper around collecting `Path::components`, with
2222 // exceptions made where this conflicts with the POSIX specification.
23 // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
24 // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
23 // See 4.16 Pathname Resolution, IEEE Std 1003.1-2024
24 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html#tag_04_16
2525
2626 // Get the components, skipping the redundant leading "." component if it exists.
2727 let mut components = path.strip_prefix(".").unwrap_or(path).components();
library/std/src/sys/process/unix/unix.rs+1-1
......@@ -1101,7 +1101,7 @@ impl ExitStatus {
11011101 pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
11021102 // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is
11031103 // true on all actual versions of Unix, is widely assumed, and is specified in SuS
1104 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
1104 // https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html. If it is not
11051105 // true for a platform pretending to be Unix, the tests (our doctests, and also
11061106 // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
11071107 match NonZero::try_from(self.0) {
library/std/src/sys/process/unix/unsupported/wait_status.rs+1-1
......@@ -46,7 +46,7 @@ impl ExitStatus {
4646 pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
4747 // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is
4848 // true on all actual versions of Unix, is widely assumed, and is specified in SuS
49 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
49 // https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html. If it is not
5050 // true for a platform pretending to be Unix, the tests (our doctests, and also
5151 // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
5252 match NonZero::try_from(self.wait_status) {
library/std/src/sys/process/unix/vxworks.rs+1-1
......@@ -221,7 +221,7 @@ impl ExitStatus {
221221 pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
222222 // This assumes that WIFEXITED(status) && WEXITSTATUS==0 corresponds to status==0. This is
223223 // true on all actual versions of Unix, is widely assumed, and is specified in SuS
224 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
224 // https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html. If it is not
225225 // true for a platform pretending to be Unix, the tests (our doctests, and also
226226 // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
227227 match NonZero::try_from(self.0) {
src/doc/rustc/src/platform-support/nto-qnx.md+1-1
......@@ -2,7 +2,7 @@
22
33**Tier: 3**
44
5Support for the [QNX®][qnx.com] [QNX Software Development Platform (SDP)], version 7.0, 7.1 and 8.0.
5Support for the [QNX®](https://qnx.com) [QNX Software Development Platform (SDP)], version 7.0, 7.1 and 8.0.
66
77[QNX Software Development Platform (SDP)]: https://qnx.software/en/software/products-and-solutions/qnx-software-development-platform
88
src/librustdoc/passes/collect_intra_doc_links.rs+14-5
......@@ -31,7 +31,7 @@ use smallvec::{SmallVec, smallvec};
3131use tracing::{debug, info, instrument, trace};
3232
3333use crate::clean::utils::find_nearest_parent_module;
34use crate::clean::{self, Crate, Item, ItemId, ItemLink, PrimitiveType};
34use crate::clean::{self, Crate, Item, ItemId, ItemLink, PrimitiveType, reexport_chain};
3535use crate::core::DocContext;
3636use crate::html::markdown::{MarkdownLink, MarkdownLinkRange, markdown_links};
3737use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
......@@ -1148,10 +1148,19 @@ impl LinkCollector<'_, '_> {
11481148 // `use` statement, we need to use the `def_id` of the `use` statement, not the
11491149 // inlined item.
11501150 // <https://github.com/rust-lang/rust/pull/151120>
1151 let item_id = if let Some(inline_stmt_id) = item.inline_stmt_id
1152 && find_attr!(tcx, inline_stmt_id, Deprecated { span, ..} if span == depr_span)
1153 {
1154 inline_stmt_id.to_def_id()
1151 let item_id = if let Some(inline_stmt_id) = item.inline_stmt_id {
1152 let target_def_id = item.item_id.expect_def_id();
1153 reexport_chain(tcx, inline_stmt_id, target_def_id)
1154 .iter()
1155 .flat_map(|reexport| reexport.id())
1156 .find(|&reexport_def_id| {
1157 find_attr!(
1158 tcx,
1159 reexport_def_id,
1160 Deprecated { span, .. } if span == depr_span
1161 )
1162 })
1163 .unwrap_or(target_def_id)
11551164 } else {
11561165 item.item_id.expect_def_id()
11571166 };
tests/crashes/136661.rs deleted-25
......@@ -1,25 +0,0 @@
1//@ known-bug: #136661
2
3#![allow(unused)]
4
5trait Supertrait<T> {}
6
7trait Other {
8 fn method(&self) {}
9}
10
11impl WithAssoc for &'static () {
12 type As = ();
13}
14
15trait WithAssoc {
16 type As;
17}
18
19trait Trait<P: WithAssoc>: Supertrait<P::As> {
20 fn method(&self) {}
21}
22
23fn hrtb<T: for<'a> Trait<&'a ()>>() {}
24
25pub fn main() {}
tests/rustdoc-ui/intra-doc/deprecated-note-from-inlined-reexport-chain.rs created+18
......@@ -0,0 +1,18 @@
1//@ check-pass
2
3// Regression test for https://github.com/rust-lang/rust/issues/158745.
4// This checks that rustdoc resolves intra-doc links in deprecation notes using
5// the re-export that carries the attribute, even when that re-export is later
6// inlined through another re-export.
7
8#![deny(rustdoc::broken_intra_doc_links)]
9
10mod bar {
11 pub struct A;
12}
13
14#[deprecated(note = "[std::io::ErrorKind::NotFound]")]
15pub use bar::A;
16
17#[doc(inline)]
18pub use A as X;
tests/ui-fulldeps/rustc_public/check_transform.rs+1-1
......@@ -95,7 +95,7 @@ fn change_panic_msg(mut body: Body, new_msg: &str) -> Body {
9595 let new_const = MirConst::from_str(new_msg);
9696 args[0] = Operand::Constant(ConstOperand {
9797 const_: new_const,
98 span: bb.terminator.span,
98 span: bb.terminator.source_info.span,
9999 user_ty: None,
100100 });
101101 }
tests/ui/check-cfg/target_feature.stderr+7
......@@ -14,6 +14,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
1414`7e10`
1515`a`
1616`aclass`
17`acquire-release`
1718`addsubiw`
1819`adx`
1920`aes`
......@@ -223,6 +224,8 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
223224`mul32high`
224225`multivalue`
225226`mutable-globals`
227`mve`
228`mve.fp`
226229`neon`
227230`nnp-assist`
228231`nontrapping-fptoint`
......@@ -366,6 +369,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
366369`v68`
367370`v69`
368371`v6k`
372`v6m`
369373`v6t2`
370374`v7`
371375`v71`
......@@ -374,6 +378,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
374378`v79`
375379`v8`
376380`v8.1a`
381`v8.1m.main`
377382`v8.2a`
378383`v8.3a`
379384`v8.4a`
......@@ -382,6 +387,8 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
382387`v8.7a`
383388`v8.8a`
384389`v8.9a`
390`v8m`
391`v8m.main`
385392`v8plus`
386393`v9`
387394`v9.1a`
tests/ui/impl-trait/return-never-type.rs created+14
......@@ -0,0 +1,14 @@
1//@ edition:2024
2
3#![feature(never_type)]
4
5use std::ops::Add;
6
7fn foo() -> impl Add<u32> {
8 //~^ ERROR cannot add `u32` to `!`
9 //~| HELP the trait `Add<u32>` is not implemented for `!`
10 unimplemented!()
11 //~^ HELP `!` can be coerced to any type; consider casting it to a concrete type that implements the trait
12}
13
14fn main() {}
tests/ui/impl-trait/return-never-type.stderr created+18
......@@ -0,0 +1,18 @@
1error[E0277]: cannot add `u32` to `!`
2 --> $DIR/return-never-type.rs:7:13
3 |
4LL | fn foo() -> impl Add<u32> {
5 | ^^^^^^^^^^^^^ no implementation for `! + u32`
6...
7LL | unimplemented!()
8 | ---------------- return type was inferred to be `!` here
9 |
10 = help: the trait `Add<u32>` is not implemented for `!`
11help: `!` can be coerced to any type; consider casting it to a concrete type that implements the trait
12 |
13LL | unimplemented!() as /* Type */
14 | +++++++++++++
15
16error: aborting due to 1 previous error
17
18For more information about this error, try `rustc --explain E0277`.
tests/ui/impl-trait/unsized_coercion.next.stderr deleted-19
......@@ -1,19 +0,0 @@
1error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
2 --> $DIR/unsized_coercion.rs:12:15
3 |
4LL | fn hello() -> Box<impl Trait> {
5 | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6 |
7 = help: the trait `Sized` is not implemented for `dyn Trait`
8
9error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
10 --> $DIR/unsized_coercion.rs:15:17
11 |
12LL | let x = hello();
13 | ^^^^^^^ doesn't have a size known at compile-time
14 |
15 = help: the trait `Sized` is not implemented for `dyn Trait`
16
17error: aborting due to 2 previous errors
18
19For more information about this error, try `rustc --explain E0277`.
tests/ui/impl-trait/unsized_coercion.rs+1-3
......@@ -3,17 +3,15 @@
33
44//@ revisions: next old
55//@[next] compile-flags: -Znext-solver
6//@[old] check-pass
6//@ check-pass
77
88trait Trait {}
99
1010impl Trait for u32 {}
1111
1212fn hello() -> Box<impl Trait> {
13//[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
1413 if true {
1514 let x = hello();
16 //[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
1715 let y: Box<dyn Trait> = x;
1816 }
1917 Box::new(1u32)
tests/ui/parser/bare-type-in-impl-parameter.rs created+1
......@@ -0,0 +1 @@
1impl<Y<A, B, C>> Z for X<T> {} //~ ERROR: expected type parameter, found path `Y<A, B, C>`
tests/ui/parser/bare-type-in-impl-parameter.stderr created+18
......@@ -0,0 +1,18 @@
1error: expected type parameter, found path `Y<A, B, C>`
2 --> $DIR/bare-type-in-impl-parameter.rs:1:6
3 |
4LL | impl<Y<A, B, C>> Z for X<T> {}
5 | ^^^^^^^^^^
6 |
7help: you might have meant to bind a type parameter to a trait
8 |
9LL | impl<T: Y<A, B, C>> Z for X<T> {}
10 | ++
11help: alternatively, you might have meant to introduce type parameter
12 |
13LL - impl<Y<A, B, C>> Z for X<T> {}
14LL + impl<A, B, C> Z for X<T> {}
15 |
16
17error: aborting due to 1 previous error
18
tests/ui/process/process-spawn-failure.rs+1-1
......@@ -38,7 +38,7 @@ fn find_zombies() {
3838 extern crate libc;
3939 let my_pid = unsafe { libc::getpid() };
4040
41 // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html
41 // https://pubs.opengroup.org/onlinepubs/9799919799/utilities/ps.html
4242 let ps_cmd_output = Command::new("ps").args(&["-A", "-o", "pid,ppid,args"]).output().unwrap();
4343 let ps_output = String::from_utf8_lossy(&ps_cmd_output.stdout);
4444 // On AIX, the PPID is not always present, such as when a process is blocked
tests/ui/sized/infer_var_subtyping.rs created+19
......@@ -0,0 +1,19 @@
1// Regression test for failure #4 in <https://github.com/rust-lang/rust/issues/155924>.
2//
3// This checks that when we are checking the sized-ness of an inference variable
4// (here coming from the never-to-any coercion) we consider subtyping. That is,
5// `?0` is sized if `(?0 <: ?1 || ?0 :> ?1) && ?1: Sized`).
6//
7//@ revisions: current next
8//@ ignore-compare-mode-next-solver (explicit revisions)
9//@[next] compile-flags: -Znext-solver
10//@ check-pass
11
12#![feature(never_type)]
13
14fn blah(e: !) {
15 let source = Box::new(e);
16 let _: Box<dyn Send> = source;
17}
18
19fn main() {}
tests/ui/specialization/min_specialization/next-solver-region-resolution.rs+1-1
......@@ -16,7 +16,7 @@ where
1616}
1717
1818impl<'a, T> Foo for &T
19//~^ ERROR: conflicting implementations of trait `Foo` for type `&_`
19//~^ ERROR: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
2020where
2121 Self::Item: Baz,
2222{
tests/ui/specialization/min_specialization/next-solver-region-resolution.stderr+13-8
......@@ -1,17 +1,22 @@
1error[E0119]: conflicting implementations of trait `Foo` for type `&_`
1error[E0391]: cycle detected when computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>`
22 --> $DIR/next-solver-region-resolution.rs:18:1
33 |
4LL | / impl<'a, T> Foo for &'a T
5LL | | where
6LL | | Self::Item: 'a,
7 | |___________________- first implementation here
8...
94LL | / impl<'a, T> Foo for &T
105LL | |
116LL | | where
127LL | | Self::Item: Baz,
13 | |____________________^ conflicting implementation for `&_`
8 | |____________________^
9 |
10 = note: ...which immediately requires computing normalized predicates of `<impl at $DIR/next-solver-region-resolution.rs:18:1: 21:21>` again
11note: cycle used when computing whether impls specialize one another
12 --> $DIR/next-solver-region-resolution.rs:12:1
13 |
14LL | / impl<'a, T> Foo for &'a T
15LL | | where
16LL | | Self::Item: 'a,
17 | |___________________^
18 = note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>
1419
1520error: aborting due to 1 previous error
1621
17For more information about this error, try `rustc --explain E0119`.
22For more information about this error, try `rustc --explain E0391`.
tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr+3-1
......@@ -18,8 +18,9 @@ LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
1818 = note: ...which requires building an abstract representation for `accept0::{constant#0}`...
1919 = note: ...which requires building THIR for `accept0::{constant#0}`...
2020 = note: ...which requires type-checking `accept0::{constant#0}`...
21 = note: ...which requires computing normalized predicates of `accept0::{constant#0}`...
2122 = note: ...which again requires evaluating type-level constant, completing the cycle
22 = note: cycle used when checking that `accept0` is well-formed
23 = note: cycle used when computing normalized predicates of `accept0`
2324 = note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>
2425
2526error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const
......@@ -32,6 +33,7 @@ LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
3233 = note: ...which requires building an abstract representation for `accept1::{constant#0}`...
3334 = note: ...which requires building THIR for `accept1::{constant#0}`...
3435 = note: ...which requires type-checking `accept1::{constant#0}`...
36 = note: ...which requires computing normalized predicates of `accept1::{constant#0}`...
3537 = note: ...which requires evaluating type-level constant...
3638 = note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
3739 = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle
tests/ui/traits/next-solver/alias-bound-unsound.rs+1
......@@ -21,6 +21,7 @@ trait Foo {
2121impl Foo for () {
2222 type Item = String where String: Copy;
2323 //~^ ERROR overflow evaluating the requirement `String: Copy`
24 //~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
2425}
2526
2627fn main() {
tests/ui/traits/next-solver/alias-bound-unsound.stderr+9-3
......@@ -1,3 +1,9 @@
1error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
2 --> $DIR/alias-bound-unsound.rs:22:5
3 |
4LL | type Item = String where String: Copy;
5 | ^^^^^^^^^
6
17error[E0275]: overflow evaluating the requirement `String: Copy`
28 --> $DIR/alias-bound-unsound.rs:22:38
39 |
......@@ -13,17 +19,17 @@ LL | type Item: Copy
1319 | ^^^^ this trait's associated type doesn't have the requirement `String: Copy`
1420
1521error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String`
16 --> $DIR/alias-bound-unsound.rs:28:22
22 --> $DIR/alias-bound-unsound.rs:29:22
1723 |
1824LL | let _ = identity(<() as Foo>::copy_me(&x));
1925 | ^^^^^^^^^^^^^^^^^^^^^^^^
2026
2127error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
22 --> $DIR/alias-bound-unsound.rs:28:43
28 --> $DIR/alias-bound-unsound.rs:29:43
2329 |
2430LL | let _ = identity(<() as Foo>::copy_me(&x));
2531 | ^^
2632
27error: aborting due to 3 previous errors
33error: aborting due to 4 previous errors
2834
2935For more information about this error, try `rustc --explain E0275`.
tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs+1
......@@ -38,6 +38,7 @@ fn impls_bound<T: Bound>() {
3838// - normalize `<Foo as Trait<T>>::Assoc`
3939// - via blanket impl, requires where-clause `Foo: Bound` -> cycle
4040fn generic<T>()
41//~^ ERROR the trait bound `Foo: Bound` is not satisfied
4142where
4243 <Foo as Trait<T>>::Assoc: Bound,
4344 //~^ ERROR the trait bound `Foo: Bound` is not satisfied
tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr+30-3
......@@ -1,5 +1,32 @@
11error[E0277]: the trait bound `Foo: Bound` is not satisfied
2 --> $DIR/normalizes-to-is-not-productive.rs:42:31
2 --> $DIR/normalizes-to-is-not-productive.rs:40:1
3 |
4LL | / fn generic<T>()
5LL | |
6LL | | where
7LL | | <Foo as Trait<T>>::Assoc: Bound,
8 | |____________________________________^ unsatisfied trait bound
9 |
10help: the trait `Bound` is not implemented for `Foo`
11 --> $DIR/normalizes-to-is-not-productive.rs:18:1
12 |
13LL | struct Foo;
14 | ^^^^^^^^^^
15help: the trait `Bound` is implemented for `u32`
16 --> $DIR/normalizes-to-is-not-productive.rs:11:1
17 |
18LL | impl Bound for u32 {
19 | ^^^^^^^^^^^^^^^^^^
20note: required for `Foo` to implement `Trait<T>`
21 --> $DIR/normalizes-to-is-not-productive.rs:23:19
22 |
23LL | impl<T: Bound, U> Trait<U> for T {
24 | ----- ^^^^^^^^ ^
25 | |
26 | unsatisfied trait bound introduced here
27
28error[E0277]: the trait bound `Foo: Bound` is not satisfied
29 --> $DIR/normalizes-to-is-not-productive.rs:43:31
330 |
431LL | <Foo as Trait<T>>::Assoc: Bound,
532 | ^^^^^ unsatisfied trait bound
......@@ -30,7 +57,7 @@ LL | | }
3057 | |_^ required by this bound in `Bound`
3158
3259error[E0277]: the trait bound `Foo: Bound` is not satisfied
33 --> $DIR/normalizes-to-is-not-productive.rs:47:19
60 --> $DIR/normalizes-to-is-not-productive.rs:48:19
3461 |
3562LL | impls_bound::<Foo>();
3663 | ^^^ unsatisfied trait bound
......@@ -51,6 +78,6 @@ note: required by a bound in `impls_bound`
5178LL | fn impls_bound<T: Bound>() {
5279 | ^^^^^ required by this bound in `impls_bound`
5380
54error: aborting due to 2 previous errors
81error: aborting due to 3 previous errors
5582
5683For more information about this error, try `rustc --explain E0277`.
tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs+1-1
......@@ -14,7 +14,7 @@ fn foo<T>()
1414where
1515 T: for<'a> Proj<'a, Assoc = for<'b> fn(<T as Proj<'b>>::Assoc)>,
1616 (): Trait<<T as Proj<'static>>::Assoc>
17 //~^ ERROR: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
17 //~^ ERROR: the trait bound `(): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not satisfied
1818{
1919}
2020
tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr+7-4
......@@ -1,11 +1,14 @@
1error[E0275]: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
1error[E0277]: the trait bound `(): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not satisfied
22 --> $DIR/find-param-recursion-issue-152716.rs:16:9
33 |
44LL | (): Trait<<T as Proj<'static>>::Assoc>
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not implemented for `()`
66 |
7 = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`find_param_recursion_issue_152716`)
7help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
8 |
9LL | (): Trait<<T as Proj<'static>>::Assoc>, (): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>
10 | +++++++++++++++++++++++++++++++++++++++++++++++++++
811
912error: aborting due to 1 previous error
1013
11For more information about this error, try `rustc --explain E0275`.
14For more information about this error, try `rustc --explain E0277`.
tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr+11-1
......@@ -35,6 +35,16 @@ LL | trait A<T> {
3535LL | fn f()
3636 | ^ this trait's associated function doesn't have the requirement `_: A<T>`
3737
38error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
39 --> $DIR/normalize-param-env-2.rs:22:5
40 |
41LL | / fn f()
42LL | | where
43LL | | Self::Assoc: A<T>,
44 | |__________________________^
45 |
46 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
47
3848error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
3949 --> $DIR/normalize-param-env-2.rs:24:22
4050 |
......@@ -82,7 +92,7 @@ LL | where
8292LL | Self::Assoc: A<T>,
8393 | ^^^^ required by this bound in `A::f`
8494
85error: aborting due to 8 previous errors
95error: aborting due to 9 previous errors
8696
8797Some errors have detailed explanations: E0275, E0283.
8898For more information about an error, try `rustc --explain E0275`.
tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr+9-1
......@@ -1,3 +1,11 @@
1error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc == _`
2 --> $DIR/normalize-param-env-4.rs:17:1
3 |
4LL | / fn foo<T>()
5LL | | where
6LL | | <T as Trait>::Assoc: Trait,
7 | |_______________________________^
8
19error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
210 --> $DIR/normalize-param-env-4.rs:19:26
311 |
......@@ -22,6 +30,6 @@ note: required by a bound in `impls_trait`
2230LL | fn impls_trait<T: Trait>() {}
2331 | ^^^^^ required by this bound in `impls_trait`
2432
25error: aborting due to 3 previous errors
33error: aborting due to 4 previous errors
2634
2735For more information about this error, try `rustc --explain E0275`.
tests/ui/traits/next-solver/normalize/param_env-region-constraints-ambiguity.rs created+101
......@@ -0,0 +1,101 @@
1//@ revisions: current next
2//@ ignore-compare-mode-next-solver (explicit revisions)
3//@[next] compile-flags: -Znext-solver
4//@ check-pass
5
6// Regression test for trait-system-refactor-initiative#265. Different where-clauses
7// normalizing to the same bound caused ambiguity errors if we lazily normalized
8// where-clauses when using them to prove a goal.
9//
10// We avoid these errors by eagerly normalizing the `param_env`.
11
12mod one {
13 trait Trait {
14 type Assoc<'a>
15 where
16 Self: 'a;
17 }
18
19 trait Bound<'a> {}
20 fn impls_bound<'a, T: Bound<'a>>() {}
21 fn foo<'a, T: 'a>()
22 where
23 T: Trait<Assoc<'a> = T> + Bound<'a>,
24 T::Assoc<'a>: Bound<'a>,
25 {
26 impls_bound::<'_, T>();
27 }
28}
29
30mod two {
31 trait Trait {
32 type Assoc<'a>
33 where
34 Self: 'a;
35 }
36
37 trait Bound {}
38 fn impls_bound<T: Bound>() {}
39 fn foo<'a, T: 'a>()
40 where
41 T: Trait<Assoc<'a> = T> + Bound,
42 T::Assoc<'a>: Bound,
43 {
44 impls_bound::<T>();
45 }
46}
47
48// Minimization of tokio-par-util.
49mod three {
50 trait Trait1 {
51 type Assoc1;
52 }
53
54 trait Trait2 {
55 type Assoc2;
56 }
57
58 struct Indir<T>(T);
59 impl<T> Trait2 for Indir<T>
60 where
61 T: Trait1,
62 T::Assoc1: Trait2 + 'static,
63 {
64 type Assoc2 = <T::Assoc1 as Trait2>::Assoc2;
65 }
66
67 struct WrapperTwo<T, U>(T, U);
68
69 impl<T, U> Trait1 for WrapperTwo<T, U>
70 where
71 T: Trait1,
72 T::Assoc1: Trait2 + 'static,
73 // additional region constraint in this candidate so they
74 // can't be merged.
75 U: Trait1<Assoc1 = <Indir<T> as Trait2>::Assoc2>,
76 U: Trait1<Assoc1 = <T::Assoc1 as Trait2>::Assoc2>,
77 {
78 type Assoc1 = i32;
79 }
80}
81
82// Minimization of `qazer`
83mod four {
84 trait Value {
85 type SelfType<'a>
86 where
87 Self: 'a;
88 }
89
90 trait Repository<T> {}
91 struct RedbRepo<From, Into>(From, Into);
92
93 impl<From, Into> Repository<Into> for RedbRepo<From, Into>
94 where
95 for<'a> From: Value<SelfType<'a> = From> + Clone + 'static,
96 for<'a> <From as Value>::SelfType<'a>: Clone,
97 {
98 }
99}
100
101fn main() {}
tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs+1-2
......@@ -13,8 +13,7 @@ fn needs_bar<S: Bar>() {}
1313
1414fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
1515 needs_bar::<T::Assoc1>();
16 //~^ ERROR: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
17 //~| ERROR: the size for values of type `<T as Foo2>::Assoc2` cannot be known at compilation time
16 //~^ ERROR: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
1817}
1918
2019fn main() {}
tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr+4-25
......@@ -1,8 +1,8 @@
1error[E0277]: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
1error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
22 --> $DIR/recursive-self-normalization-2.rs:15:17
33 |
44LL | needs_bar::<T::Assoc1>();
5 | ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo2>::Assoc2`
5 | ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
66 |
77note: required by a bound in `needs_bar`
88 --> $DIR/recursive-self-normalization-2.rs:12:17
......@@ -11,30 +11,9 @@ LL | fn needs_bar<S: Bar>() {}
1111 | ^^^ required by this bound in `needs_bar`
1212help: consider further restricting the associated type
1313 |
14LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar {
14LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
1515 | ++++++++++++++++++++++++++++++
1616
17error[E0277]: the size for values of type `<T as Foo2>::Assoc2` cannot be known at compilation time
18 --> $DIR/recursive-self-normalization-2.rs:15:17
19 |
20LL | needs_bar::<T::Assoc1>();
21 | ^^^^^^^^^ doesn't have a size known at compile-time
22 |
23 = help: the trait `Sized` is not implemented for `<T as Foo2>::Assoc2`
24note: required by an implicit `Sized` bound in `needs_bar`
25 --> $DIR/recursive-self-normalization-2.rs:12:14
26 |
27LL | fn needs_bar<S: Bar>() {}
28 | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar`
29help: consider further restricting the associated type
30 |
31LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Sized {
32 | ++++++++++++++++++++++++++++++++
33help: consider relaxing the implicit `Sized` restriction
34 |
35LL | fn needs_bar<S: Bar + ?Sized>() {}
36 | ++++++++
37
38error: aborting due to 2 previous errors
17error: aborting due to 1 previous error
3918
4019For more information about this error, try `rustc --explain E0277`.
tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-1.rs created+41
......@@ -0,0 +1,41 @@
1//@ check-pass
2//@ revisions: current next
3//@ ignore-compare-mode-next-solver (explicit revisions)
4//@[next] compile-flags: -Znext-solver
5
6// In `fn hrtb` normalizing the elaborated where-clause
7// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in
8// a region error as `&'a ()` is not equal to `&'static ()`.
9//
10// This happens even though the where-clauses themselves are well-formed
11// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable.
12//
13// I don't think this can cause unsoundness and has already been accepted in the
14// old solver as we didn't register TypeOutlives constraints if `ignoring_regions`
15// is set. The new solver always registers outlives constraints, so this then
16// caused an error there. We need to ignore these region errors with the new solver
17// due to trait-system-refactor-initiative#166.
18
19#![allow(unused)]
20
21trait Supertrait<T> {}
22
23trait Other {
24 fn method(&self) {}
25}
26
27impl<T: 'static> WithAssoc for T {
28 type As = T;
29}
30
31trait WithAssoc {
32 type As;
33}
34
35trait Trait<P: WithAssoc>: Supertrait<P::As> {
36 fn method(&self) {}
37}
38
39fn hrtb<T: for<'a> Trait<&'a ()>>() {}
40
41pub fn main() {}
tests/ui/traits/normalize/normalize-param-env-missing-implied-bound-2.rs created+39
......@@ -0,0 +1,39 @@
1//@ check-pass
2//@ revisions: current next
3//@ ignore-compare-mode-next-solver (explicit revisions)
4//@[next] compile-flags: -Znext-solver
5
6// In `fn hrtb` normalizing the elaborated where-clause
7// `T: for<'a> Supertrait<<&'a () as WithAssoc>::As>` results in
8// a region error as `&'a ()` is not `'static`.
9//
10// This happens even though the where-clauses themselves are well-formed
11// as we never have to prove `&'a (): WithAssoc` as `'a` is a bound variable.
12//
13// Unlike `normalize-param-env-missing-implied-bound-1.rs` this snippet caused
14// an ICE with the old trait solver, as we did register region constraints from
15// relating types. This ICE was tracked in #136661.
16
17#![allow(unused)]
18
19trait Supertrait<T> {}
20
21trait Other {
22 fn method(&self) {}
23}
24
25impl WithAssoc for &'static () {
26 type As = ();
27}
28
29trait WithAssoc {
30 type As;
31}
32
33trait Trait<P: WithAssoc>: Supertrait<P::As> {
34 fn method(&self) {}
35}
36
37fn hrtb<T: for<'a> Trait<&'a ()>>() {}
38
39pub fn main() {}