diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c82d114f91857..963f902b71fcb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -499,18 +499,18 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fr: RegionVid, ) -> Option { let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs(); - let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?; + let user_arg_index = self.regioncx.get_user_arg_index_for_region(self.infcx.tcx, fr)?; let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys - [implicit_inputs + argument_index]; + [implicit_inputs + user_arg_index]; let (_, span) = self.regioncx.get_argument_name_and_span_for_region( self.body, self.local_names(), - argument_index, + user_arg_index, ); let highlight = self - .get_argument_hir_ty_for_highlighting(argument_index) + .get_argument_hir_ty_for_highlighting(user_arg_index) .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty)) .unwrap_or_else(|| { // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to @@ -528,10 +528,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn get_argument_hir_ty_for_highlighting( &self, - argument_index: usize, + user_arg_index: usize, ) -> Option<&hir::Ty<'tcx>> { let fn_decl = self.infcx.tcx.hir_fn_decl_by_hir_id(self.mir_hir_id())?; - let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?; + // Closures don't have implicit self arguments in HIR, so use `user_arg_index` directly. + let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(user_arg_index)?; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like // `|x|`... in that case, we can't highlight the type but diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 114b4695f5fc9..b51604fb2903a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -31,7 +31,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) .or_else(|| { debug!("get_var_name_and_span_for_region: attempting argument"); - self.get_argument_index_for_region(tcx, fr).and_then(|index| { + self.get_user_arg_index_for_region(tcx, fr).and_then(|index| { let local = self.user_arg_index_to_local(body, index); if body_uses_local(body, local) { Some(self.get_argument_name_and_span_for_region(body, local_names, index)) @@ -93,26 +93,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// N.B., in the case of a closure, the index is indexing into the signature as seen by the /// user - in particular, index 0 is not the implicit self parameter. - pub(crate) fn get_argument_index_for_region( + pub(crate) fn get_user_arg_index_for_region( &self, tcx: TyCtxt<'tcx>, fr: RegionVid, ) -> Option { let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); - let argument_index = + let user_arg_index = self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( |arg_ty| { - debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}"); + debug!("get_user_arg_index_for_region: arg_ty = {arg_ty:?}"); tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr) }, )?; debug!( - "get_argument_index_for_region: found {fr:?} in argument {argument_index} which has type {:?}", - self.universal_regions().unnormalized_input_tys[argument_index], + "get_user_arg_index_for_region: found {fr:?} in argument {user_arg_index} which has type {:?}", + self.universal_regions().unnormalized_input_tys[user_arg_index], ); - Some(argument_index) + Some(user_arg_index) } /// Given the index of an argument as seen from the user (i.e. excluding @@ -128,9 +128,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, body: &Body<'tcx>, local_names: &IndexSlice>, - argument_index: usize, + user_arg_index: usize, ) -> (Option, Span) { - let argument_local = self.user_arg_index_to_local(body, argument_index); + let argument_local = self.user_arg_index_to_local(body, user_arg_index); debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}"); let argument_name = local_names[argument_local]; diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index af50f68640f8b..5285f724b02ec 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -107,7 +107,7 @@ impl LocalizedConstraintGraphVisitor for LocalizedOutlivesConstraintCollector { /// - a mermaid graph of the NLL regions and the constraints between them /// - a mermaid graph of the NLL SCCs and the constraints between them fn emit_polonius_dump<'tcx>( - dumper: &MirDumper<'_, '_, 'tcx>, + dumper: &MirDumper<'_, 'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, borrow_set: &BorrowSet<'tcx>, @@ -186,7 +186,7 @@ fn emit_polonius_dump<'tcx>( /// Emits the polonius MIR, as escaped HTML. fn emit_html_mir<'tcx>( - dumper: &MirDumper<'_, '_, 'tcx>, + dumper: &MirDumper<'_, 'tcx>, body: &Body<'tcx>, out: &mut dyn io::Write, ) -> io::Result<()> { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index d057b67087c7b..ab31ed61c123f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -79,6 +79,9 @@ pub(crate) struct UniversalRegions<'tcx> { /// /// N.B., associated types in these types have not been normalized, /// as the name suggests. =) + /// + /// N.B., in the case of a closure, index 0 is the implicit self parameter, + /// and not the first input as seen by the user. pub unnormalized_input_tys: &'tcx [Ty<'tcx>], pub yield_ty: Option>, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1785014954093..82402b3c7e31c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -303,6 +303,8 @@ declare_features! ( (internal, panic_runtime, "1.10.0", Some(32837)), /// Allows using pattern types. (internal, pattern_types, "1.79.0", Some(123646)), + /// Allows `repr(simd)` and importing the various simd intrinsics. + (internal, repr_simd, "1.4.0", Some(27731)), /// Allows using compiler's own crates. (unstable, rustc_private, "1.0.0", Some(27812)), /// Allows using internal rustdoc features like `doc(keyword)`. @@ -657,8 +659,6 @@ declare_features! ( (incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), - /// Allows `repr(simd)` and importing the various simd intrinsics. - (unstable, repr_simd, "1.4.0", Some(27731)), /// Allows bounding the return type of AFIT/RPITIT. (unstable, return_type_notation, "1.70.0", Some(109417)), /// Target features on riscv. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 991c996dffbf7..57c9ad3b8e10f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1901,14 +1901,14 @@ impl FnParam<'_> { } } -struct FnCallDiagCtxt<'a, 'b, 'tcx> { - arg_matching_ctxt: ArgMatchingCtxt<'a, 'b, 'tcx>, +struct FnCallDiagCtxt<'a, 'tcx> { + arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>, errors: Vec>, matched_inputs: IndexVec>, } -impl<'a, 'b, 'tcx> Deref for FnCallDiagCtxt<'a, 'b, 'tcx> { - type Target = ArgMatchingCtxt<'a, 'b, 'tcx>; +impl<'a, 'tcx> Deref for FnCallDiagCtxt<'a, 'tcx> { + type Target = ArgMatchingCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { &self.arg_matching_ctxt @@ -1921,9 +1921,9 @@ enum ArgumentsFormatting { Multiline { fallback_indent: String, brace_indent: String }, } -impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { +impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> { fn new( - arg: &'a FnCtxt<'b, 'tcx>, + arg: &'a FnCtxt<'a, 'tcx>, compatibility_diagonal: IndexVec>, formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, @@ -2618,7 +2618,7 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { (suggestions, labels, suggestion_text) } - fn label_generic_mismatches(&self, err: &mut Diag<'b>) { + fn label_generic_mismatches(&self, err: &mut Diag<'a>) { self.fn_ctxt.label_generic_mismatches( err, self.fn_def_id, @@ -2778,22 +2778,22 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { } } -struct ArgMatchingCtxt<'a, 'b, 'tcx> { - args_ctxt: ArgsCtxt<'a, 'b, 'tcx>, +struct ArgMatchingCtxt<'a, 'tcx> { + args_ctxt: ArgsCtxt<'a, 'tcx>, provided_arg_tys: IndexVec, Span)>, } -impl<'a, 'b, 'tcx> Deref for ArgMatchingCtxt<'a, 'b, 'tcx> { - type Target = ArgsCtxt<'a, 'b, 'tcx>; +impl<'a, 'tcx> Deref for ArgMatchingCtxt<'a, 'tcx> { + type Target = ArgsCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { &self.args_ctxt } } -impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> { +impl<'a, 'tcx> ArgMatchingCtxt<'a, 'tcx> { fn new( - arg: &'a FnCtxt<'b, 'tcx>, + arg: &'a FnCtxt<'a, 'tcx>, compatibility_diagonal: IndexVec>, formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, @@ -2924,23 +2924,23 @@ impl<'a, 'b, 'tcx> ArgMatchingCtxt<'a, 'b, 'tcx> { } } -struct ArgsCtxt<'a, 'b, 'tcx> { - call_ctxt: CallCtxt<'a, 'b, 'tcx>, +struct ArgsCtxt<'a, 'tcx> { + call_ctxt: CallCtxt<'a, 'tcx>, call_metadata: CallMetadata, args_span: Span, } -impl<'a, 'b, 'tcx> Deref for ArgsCtxt<'a, 'b, 'tcx> { - type Target = CallCtxt<'a, 'b, 'tcx>; +impl<'a, 'tcx> Deref for ArgsCtxt<'a, 'tcx> { + type Target = CallCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { &self.call_ctxt } } -impl<'a, 'b, 'tcx> ArgsCtxt<'a, 'b, 'tcx> { +impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> { fn new( - arg: &'a FnCtxt<'b, 'tcx>, + arg: &'a FnCtxt<'a, 'tcx>, compatibility_diagonal: IndexVec>, formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, @@ -2951,7 +2951,7 @@ impl<'a, 'b, 'tcx> ArgsCtxt<'a, 'b, 'tcx> { call_expr: &'tcx Expr<'tcx>, tuple_arguments: TupleArgumentsFlag, ) -> Self { - let call_ctxt: CallCtxt<'_, '_, '_> = CallCtxt::new( + let call_ctxt: CallCtxt<'_, '_> = CallCtxt::new( arg, compatibility_diagonal, formal_and_expected_inputs, @@ -3058,8 +3058,8 @@ struct CallMetadata { is_method: bool, } -struct CallCtxt<'a, 'b, 'tcx> { - fn_ctxt: &'a FnCtxt<'b, 'tcx>, +struct CallCtxt<'a, 'tcx> { + fn_ctxt: &'a FnCtxt<'a, 'tcx>, compatibility_diagonal: IndexVec>, formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, @@ -3073,17 +3073,17 @@ struct CallCtxt<'a, 'b, 'tcx> { callee_ty: Option>, } -impl<'a, 'b, 'tcx> Deref for CallCtxt<'a, 'b, 'tcx> { - type Target = &'a FnCtxt<'b, 'tcx>; +impl<'a, 'tcx> Deref for CallCtxt<'a, 'tcx> { + type Target = &'a FnCtxt<'a, 'tcx>; fn deref(&self) -> &Self::Target { &self.fn_ctxt } } -impl<'a, 'b, 'tcx> CallCtxt<'a, 'b, 'tcx> { +impl<'a, 'tcx> CallCtxt<'a, 'tcx> { fn new( - fn_ctxt: &'a FnCtxt<'b, 'tcx>, + fn_ctxt: &'a FnCtxt<'a, 'tcx>, compatibility_diagonal: IndexVec>, formal_and_expected_inputs: IndexVec, Ty<'tcx>)>, provided_args: IndexVec>, @@ -3093,7 +3093,7 @@ impl<'a, 'b, 'tcx> CallCtxt<'a, 'b, 'tcx> { call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, tuple_arguments: TupleArgumentsFlag, - ) -> CallCtxt<'a, 'b, 'tcx> { + ) -> CallCtxt<'a, 'tcx> { let callee_expr = match &call_expr.peel_blocks().kind { hir::ExprKind::Call(callee, _) => Some(*callee), hir::ExprKind::MethodCall(_, receiver, ..) => { diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index d846f4433dc70..515a72f5041cb 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -16,15 +16,15 @@ use tracing::debug; use crate::FnCtxt; use crate::method::probe::{self, Pick}; -struct AmbiguousTraitMethodCall<'a, 'b, 'tcx> { +struct AmbiguousTraitMethodCall<'a, 'tcx> { segment_name: Symbol, self_expr_span: Span, pick: &'a Pick<'tcx>, tcx: TyCtxt<'tcx>, - edition: &'b str, + edition: &'static str, } -impl<'a, 'b, 'c, 'tcx> Diagnostic<'a, ()> for AmbiguousTraitMethodCall<'b, 'c, 'tcx> { +impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for AmbiguousTraitMethodCall<'b, 'tcx> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { let Self { segment_name, self_expr_span, pick, tcx, edition } = self; let mut lint = Diag::new( @@ -80,20 +80,18 @@ impl<'a, 'b, 'c, 'tcx> Diagnostic<'a, ()> for AmbiguousTraitMethodCall<'b, 'c, ' } } -struct AmbiguousTraitMethod<'a, 'b, 'tcx, 'pcx, 'fnctx> { - segment: &'a hir::PathSegment<'pcx>, +struct AmbiguousTraitMethod<'a, 'tcx, 'fnctx> { + segment: &'a hir::PathSegment<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, pick: &'a Pick<'tcx>, args: &'tcx [hir::Expr<'tcx>], - edition: &'b str, + edition: &'static str, span: Span, this: &'a FnCtxt<'fnctx, 'tcx>, } -impl<'a, 'b, 'c, 'tcx, 'pcx, 'fnctx> Diagnostic<'a, ()> - for AmbiguousTraitMethod<'b, 'c, 'tcx, 'pcx, 'fnctx> -{ +impl<'a, 'c, 'tcx, 'fnctx> Diagnostic<'a, ()> for AmbiguousTraitMethod<'c, 'tcx, 'fnctx> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { let Self { segment, call_expr, self_expr, pick, args, edition, span, this } = self; let mut lint = Diag::new( @@ -158,7 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(super) fn lint_edition_dependent_dot_call( &self, self_ty: Ty<'tcx>, - segment: &hir::PathSegment<'_>, + segment: &hir::PathSegment<'tcx>, span: Span, call_expr: &'tcx hir::Expr<'tcx>, self_expr: &'tcx hir::Expr<'tcx>, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index cf6861a4bd765..04b548ce0e9f0 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -958,15 +958,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { capture_clause: hir::CaptureBy, span: Span, ) { - struct MigrationLint<'a, 'b, 'tcx> { + struct MigrationLint<'a, 'tcx> { closure_def_id: LocalDefId, - this: &'a FnCtxt<'b, 'tcx>, + this: &'a FnCtxt<'a, 'tcx>, body_id: hir::BodyId, need_migrations: Vec, migration_message: String, } - impl<'a, 'b, 'c, 'tcx> Diagnostic<'a, ()> for MigrationLint<'b, 'c, 'tcx> { + impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for MigrationLint<'b, 'tcx> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { let Self { closure_def_id, this, body_id, need_migrations, migration_message } = self; @@ -2084,8 +2084,8 @@ fn drop_location_span(tcx: TyCtxt<'_>, hir_id: HirId) -> Span { tcx.sess.source_map().end_point(owner_span) } -struct InferBorrowKind<'fcx, 'a, 'tcx> { - fcx: &'fcx FnCtxt<'a, 'tcx>, +struct InferBorrowKind<'a, 'tcx> { + fcx: &'a FnCtxt<'a, 'tcx>, // The def-id of the closure whose kind and upvar accesses are being inferred. closure_def_id: LocalDefId, @@ -2119,7 +2119,7 @@ struct InferBorrowKind<'fcx, 'a, 'tcx> { fake_reads: Vec<(Place<'tcx>, FakeReadCause, HirId)>, } -impl<'fcx, 'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'fcx, 'a, 'tcx> { +impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { #[instrument(skip(self), level = "debug")] fn fake_read( &mut self, diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index 825888f2810ca..e585f50bd5ae0 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -156,15 +156,15 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { } } -struct WrongDefaultImpl<'a, 'hir, 'tcx> { +struct WrongDefaultImpl<'a, 'tcx> { tcx: TyCtxt<'tcx>, type_def_id: DefId, - orig_fields: FxHashMap>, - fields: &'a [hir::ExprField<'hir>], + orig_fields: FxHashMap>, + fields: &'a [hir::ExprField<'tcx>], impl_span: Span, } -impl<'a, 'b, 'hir, 'tcx> Diagnostic<'a, ()> for WrongDefaultImpl<'b, 'hir, 'tcx> { +impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for WrongDefaultImpl<'b, 'tcx> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { let Self { tcx, type_def_id, orig_fields, fields, impl_span } = self; let mut diag = diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index f5f057c9f3eca..13429f328565d 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -51,31 +51,27 @@ declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]); /// be upper cased or lower cased. For the purposes of the lint suggestion, we care about being able /// to change the char's case. fn char_has_case(c: char) -> bool { - let mut l = c.to_lowercase(); - let mut u = c.to_uppercase(); - while let Some(l) = l.next() { - match u.next() { - Some(u) if l != u => return true, - _ => {} - } - } - u.next().is_some() + !c.to_lowercase().eq(c.to_uppercase()) +} + +// contains a capitalisable character followed by, or preceded by, an underscore +fn has_underscore_case(s: &str) -> bool { + let mut last = '\0'; + s.chars().any(|c| match (std::mem::replace(&mut last, c), c) { + ('_', cs) | (cs, '_') => char_has_case(cs), + _ => false, + }) } fn is_camel_case(name: &str) -> bool { let name = name.trim_matches('_'); - if name.is_empty() { + let Some(first) = name.chars().next() else { return true; - } + }; - // start with a non-lowercase letter rather than non-uppercase + // start with a non-lowercase letter rather than uppercase // ones (some scripts don't have a concept of upper/lowercase) - !name.chars().next().unwrap().is_lowercase() - && !name.contains("__") - && !name.chars().collect::>().array_windows().any(|&[fst, snd]| { - // contains a capitalisable character followed by, or preceded by, an underscore - char_has_case(fst) && snd == '_' || char_has_case(snd) && fst == '_' - }) + !(first.is_lowercase() || name.contains("__") || has_underscore_case(name)) } fn to_camel_case(s: &str) -> String { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2d9be11cb3057..b027872dd99cc 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -109,6 +109,7 @@ declare_lint_pass! { SHADOWING_SUPERTRAIT_ITEMS, SINGLE_USE_LIFETIMES, STABLE_FEATURES, + TAIL_CALL_TRACK_CALLER, TAIL_EXPR_DROP_ORDER, TEST_UNSTABLE_LINT, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index bf3d595e99436..d160aada80a83 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -61,14 +61,14 @@ impl PrettyPrintMirOptions { /// Manages MIR dumping, which is MIR writing done to a file with a specific name. In particular, /// it makes it impossible to dump MIR to one of these files when it hasn't been requested from the /// command line. Layered on top of `MirWriter`, which does the actual writing. -pub struct MirDumper<'dis, 'de, 'tcx> { +pub struct MirDumper<'a, 'tcx> { show_pass_num: bool, pass_name: &'static str, - disambiguator: &'dis dyn Display, - writer: MirWriter<'de, 'tcx>, + disambiguator: &'a dyn Display, + writer: MirWriter<'a, 'tcx>, } -impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { +impl<'a, 'tcx> MirDumper<'a, 'tcx> { // If dumping should be performed (e.g. because it was requested on the // CLI), returns a `MirDumper` with default values for the following fields: // - `show_pass_num`: `false` @@ -112,7 +112,7 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { } #[must_use] - pub fn set_disambiguator(mut self, disambiguator: &'dis dyn Display) -> Self { + pub fn set_disambiguator(mut self, disambiguator: &'a dyn Display) -> Self { self.disambiguator = disambiguator; self } @@ -120,7 +120,7 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { #[must_use] pub fn set_extra_data( mut self, - extra_data: &'de dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, + extra_data: &'a dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, ) -> Self { self.writer.extra_data = extra_data; self @@ -369,13 +369,13 @@ pub fn write_mir_pretty<'tcx>( } /// Does the writing of MIR to output, e.g. a file. -pub struct MirWriter<'de, 'tcx> { +pub struct MirWriter<'a, 'tcx> { tcx: TyCtxt<'tcx>, - extra_data: &'de dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, + extra_data: &'a dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, options: PrettyPrintMirOptions, } -impl<'de, 'tcx> MirWriter<'de, 'tcx> { +impl<'a, 'tcx> MirWriter<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { MirWriter { tcx, extra_data: &|_, _| Ok(()), options: PrettyPrintMirOptions::from_cli(tcx) } } @@ -709,7 +709,7 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option) -> Vec { /////////////////////////////////////////////////////////////////////////// // Basic blocks and their parts (statements, terminators, ...) -impl<'de, 'tcx> MirWriter<'de, 'tcx> { +impl<'a, 'tcx> MirWriter<'a, 'tcx> { /// Write out a human-readable textual representation for the given basic block. fn write_basic_block( &self, diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 0dca1eb062d4d..8052ee26df841 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -4,12 +4,13 @@ use rustc_errors::Applicability; use rustc_hir::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::span_bug; use rustc_middle::thir::visit::{self, Visitor}; use rustc_middle::thir::{BodyTy, Expr, ExprId, ExprKind, Thir}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; +use rustc_span::{ErrorGuaranteed, Span}; pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), ErrorGuaranteed> { let (thir, expr) = tcx.thir_body(def)?; @@ -21,7 +22,6 @@ pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), E } let is_closure = matches!(tcx.def_kind(def), DefKind::Closure); - let caller_ty = tcx.type_of(def).skip_binder(); let mut visitor = TailCallCkVisitor { tcx, @@ -30,7 +30,7 @@ pub(crate) fn check_tail_calls(tcx: TyCtxt<'_>, def: LocalDefId) -> Result<(), E // FIXME(#132279): we're clearly in a body here. typing_env: ty::TypingEnv::non_body_analysis(tcx, def), is_closure, - caller_ty, + caller_def_id: def, }; visitor.visit_expr(&thir[expr]); @@ -47,8 +47,8 @@ struct TailCallCkVisitor<'a, 'tcx> { /// The result of the checks, `Err(_)` if there was a problem with some /// tail call, `Ok(())` if all of them were fine. found_errors: Result<(), ErrorGuaranteed>, - /// Type of the caller function. - caller_ty: Ty<'tcx>, + /// `LocalDefId` of the caller function. + caller_def_id: LocalDefId, } impl<'tcx> TailCallCkVisitor<'_, 'tcx> { @@ -148,11 +148,13 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { // we should think what is the expected behavior here. // (we should probably just accept this by revealing opaques?) if caller_sig.inputs_and_output != callee_sig.inputs_and_output { + let caller_ty = self.tcx.type_of(self.caller_def_id).skip_binder(); + self.report_signature_mismatch( expr.span, self.tcx.liberate_late_bound_regions( CRATE_DEF_ID.to_def_id(), - self.caller_ty.fn_sig(self.tcx), + caller_ty.fn_sig(self.tcx), ), self.tcx.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)), ); @@ -173,7 +175,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { // coercing the function to an `fn()` pointer. (although in that case the tailcall is // basically useless -- the shim calls the actual function, so tailcalling the shim is // equivalent to calling the function) - let caller_needs_location = self.needs_location(self.caller_ty); + let caller_needs_location = self.caller_needs_location(); if caller_needs_location { self.report_track_caller_caller(expr.span); @@ -189,19 +191,11 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { } } - /// Returns true if function of type `ty` needs location argument - /// (i.e. if a function is marked as `#[track_caller]`). - /// - /// Panics if the function's instance can't be immediately resolved. - fn needs_location(&self, ty: Ty<'tcx>) -> bool { - if let &ty::FnDef(did, substs) = ty.kind() { - let instance = - ty::Instance::expect_resolve(self.tcx, self.typing_env, did, substs, DUMMY_SP); - - instance.def.requires_caller_location(self.tcx) - } else { - false - } + /// Returns true if the caller function needs a location argument + /// (i.e. if a function is marked as `#[track_caller]`) + fn caller_needs_location(&self) -> bool { + let flags = self.tcx.codegen_fn_attrs(self.caller_def_id).flags; + flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } fn report_in_closure(&mut self, expr: &Expr<'_>) { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 793d9ef18eb61..857a4056bae87 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -649,14 +649,14 @@ pub(crate) enum UnusedUnsafeEnclosing { }, } -pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { - pub(crate) cx: &'m RustcPatCtxt<'p, 'tcx>, +pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'a, 'tcx> { + pub(crate) cx: &'a RustcPatCtxt<'a, 'tcx>, pub(crate) scrut_span: Span, pub(crate) braces_span: Option, pub(crate) ty: Ty<'tcx>, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, msg!("non-exhaustive patterns: type `{$ty}` is non-empty")); diff --git a/compiler/rustc_monomorphize/src/graph_checks/statics.rs b/compiler/rustc_monomorphize/src/graph_checks/statics.rs index 1e97d196e72d4..16642b9960126 100644 --- a/compiler/rustc_monomorphize/src/graph_checks/statics.rs +++ b/compiler/rustc_monomorphize/src/graph_checks/statics.rs @@ -37,14 +37,14 @@ newtype_index! { // Adjacency-list graph for statics using `StaticNodeIdx` as node type. // We cannot use `DefId` as the node type directly because each node must be // represented by an index in the range `0..num_nodes`. -struct StaticRefGraph<'a, 'b, 'tcx> { +struct StaticRefGraph<'a, 'tcx> { // maps from `StaticNodeIdx` to `DefId` and vice versa statics: &'a FxIndexSet, // contains for each `MonoItem` the `MonoItem`s it uses - used_map: &'b UnordMap, Vec>>, + used_map: &'a UnordMap, Vec>>, } -impl<'a, 'b, 'tcx> DirectedGraph for StaticRefGraph<'a, 'b, 'tcx> { +impl<'a, 'tcx> DirectedGraph for StaticRefGraph<'a, 'tcx> { type Node = StaticNodeIdx; fn num_nodes(&self) -> usize { @@ -52,7 +52,7 @@ impl<'a, 'b, 'tcx> DirectedGraph for StaticRefGraph<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> Successors for StaticRefGraph<'a, 'b, 'tcx> { +impl<'a, 'tcx> Successors for StaticRefGraph<'a, 'tcx> { fn successors(&self, node_idx: StaticNodeIdx) -> impl Iterator { let def_id = self.statics[node_idx.index()]; self.used_map[&MonoItem::Static(def_id)].iter().filter_map(|&mono_item| match mono_item { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 237f69eb534e7..a2231d8d3b0f9 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -251,16 +251,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) { let def_id = module.def_id(); let children = self.tcx.module_children(def_id); - let parent_scope = ParentScope::module(module.to_module(), self.arenas); for (i, child) in children.iter().enumerate() { - self.build_reduced_graph_for_external_crate_res(child, parent_scope, i, None) + self.build_reduced_graph_for_external_crate_res(child, module, i, None) } for (i, child) in self.cstore().ambig_module_children_untracked(self.tcx, def_id).enumerate() { self.build_reduced_graph_for_external_crate_res( &child.main, - parent_scope, + module, children.len() + i, Some(&child.second), ) @@ -271,11 +270,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn build_reduced_graph_for_external_crate_res( &self, child: &ModChild, - parent_scope: ParentScope<'ra>, + parent: ExternModule<'ra>, child_index: usize, ambig_child: Option<&ModChild>, ) { - let parent = parent_scope.module.expect_extern(); let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| { this.def_span( reexport_chain @@ -288,7 +286,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ident = IdentKey::new(orig_ident); let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - let expansion = parent_scope.expansion; + let expansion = LocalExpnId::ROOT; let ambig = ambig_child.map(|ambig_child| { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 56a0ee2acc1a6..33e9ac1d430a4 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -5,7 +5,6 @@ use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; -use rustc_middle::ty::Visibility; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; use rustc_session::parse::feature_err; @@ -24,9 +23,9 @@ use crate::late::{ use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind, - Determinacy, Finalize, IdentKey, ImportKind, LateDecl, LocalModule, Module, ModuleKind, - ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, - Scope, ScopeSet, Segment, Stage, Symbol, Used, errors, + Determinacy, Finalize, IdentKey, ImportKind, ImportSummary, LateDecl, LocalModule, Module, + ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, + Resolver, Scope, ScopeSet, Segment, Stage, Symbol, Used, errors, }; #[derive(Copy, Clone)] @@ -485,11 +484,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We do not need to report them if we are either in speculative resolution, // or in late resolution when everything is already imported and expanded // and no ambiguities exist. - let import_vis = match finalize { + let import = match finalize { None | Some(Finalize { stage: Stage::Late, .. }) => { return ControlFlow::Break(Ok(decl)); } - Some(Finalize { import_vis, .. }) => import_vis, + Some(Finalize { import, .. }) => import, }; if let Some(&(innermost_decl, _)) = innermost_results.first() { @@ -503,7 +502,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl, scope, &innermost_results, - import_vis, + import, ) { // No need to search for more potential ambiguities, one is enough. return ControlFlow::Break(Ok(innermost_decl)); @@ -790,19 +789,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, scope: Scope<'ra>, innermost_results: &[(Decl<'ra>, Scope<'ra>)], - import_vis: Option, + import: Option, ) -> bool { let (innermost_decl, innermost_scope) = innermost_results[0]; let (res, innermost_res) = (decl.res(), innermost_decl.res()); let ambig_vis = if res != innermost_res { None - } else if let Some(import_vis) = import_vis - && let min = - (|d: Decl<'_>| d.vis().min(import_vis.to_def_id(), self.tcx).expect_local()) - && let (min1, min2) = (min(decl), min(innermost_decl)) - && min1 != min2 + } else if let Some(import) = import + && let vis1 = self.import_decl_vis(decl, import) + && let vis2 = self.import_decl_vis(innermost_decl, import) + && vis1 != vis2 { - Some((min1, min2)) + Some((vis1, vis2)) } else { return false; }; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 067dbd06d7b02..9df075561b3f2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -37,8 +37,9 @@ use crate::errors::{ use crate::ref_mut::CmCell; use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, - Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, + IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, + PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, + names_to_string, }; /// A potential import declaration in the process of being planted into a module. @@ -267,6 +268,14 @@ impl<'ra> ImportData<'ra> { ImportKind::MacroExport => Reexport::MacroExport, } } + + fn summary(&self) -> ImportSummary { + ImportSummary { + vis: self.vis, + nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(), + is_single: matches!(self.kind, ImportKind::Single { .. }), + } + } } /// Records information about the resolution of a name in a namespace of a module. @@ -327,9 +336,9 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: Import<'_>, decl: Decl<'_>) -> Option { - match (&import.kind, &decl.kind) { - (ImportKind::Single { .. }, DeclKind::Import { import: decl_import, .. }) +fn pub_use_of_private_extern_crate_hack(import: ImportSummary, decl: Decl<'_>) -> Option { + match (import.is_single, decl.kind) { + (true, DeclKind::Import { import: decl_import, .. }) if let ImportKind::ExternCrate { id, .. } = decl_import.kind && import.vis.is_public() => { @@ -361,23 +370,42 @@ fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { + pub(crate) fn import_decl_vis(&self, decl: Decl<'ra>, import: ImportSummary) -> Visibility { + assert!(import.vis.is_accessible_from(import.nearest_parent_mod, self.tcx)); + let decl_vis = decl.vis(); + if decl_vis.is_at_least(import.vis, self.tcx) { + // Ordered, import is less visible than the imported declaration, or the same, + // use the import's visibility. + import.vis + } else if decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx) { + // Ordered, imported declaration is less visible than the import, but is still visible + // from the current module, use the declaration's visibility. + assert!(import.vis.is_at_least(decl_vis, self.tcx)); + if pub_use_of_private_extern_crate_hack(import, decl).is_some() { + import.vis + } else { + decl_vis.expect_local() + } + } else { + // Ordered or not, the imported declaration is too private for the current module. + // It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE` + // case), because either some error will be reported, or the import declaration + // will be thrown away (unfortunately cannot use delayed bug here for this reason). + // Use import visibility to keep the all declaration visibilities in a module ordered. + import.vis + } + } + /// Given an import and the declaration that it points to, /// create the corresponding import declaration. pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> Decl<'ra> { - let import_vis = import.vis.to_def_id(); - let vis = if decl.vis().is_at_least(import_vis, self.tcx) - || pub_use_of_private_extern_crate_hack(import, decl).is_some() - { - import_vis - } else { - decl.vis() - }; + let vis = self.import_decl_vis(decl, import.summary()); if let ImportKind::Glob { ref max_vis, .. } = import.kind - && (vis == import_vis + && (vis == import.vis || max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx))) { - max_vis.set_unchecked(Some(vis.expect_local())) + max_vis.set_unchecked(Some(vis)) } self.arenas.alloc_decl(DeclData { @@ -385,7 +413,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ambiguity: CmCell::new(None), warn_ambiguity: CmCell::new(false), span: import.span, - vis: CmCell::new(vis), + vis: CmCell::new(vis.to_def_id()), expansion: import.parent_scope.expansion, parent_module: Some(import.parent_scope.module), }) @@ -448,6 +476,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } else if !old_glob_decl.vis().is_at_least(glob_decl.vis(), self.tcx) { // We are glob-importing the same item but with greater visibility. + // All visibilities here are ordered because all of them are ancestors of `module`. // FIXME: Update visibility in place, but without regressions // (#152004, #151124, #152347). glob_decl @@ -471,7 +500,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, warn_ambiguity: bool, ) -> Result<(), Decl<'ra>> { + assert!(!decl.warn_ambiguity.get()); + assert!(decl.ambiguity.get().is_none()); let module = decl.parent_module.unwrap().expect_local(); + assert!(self.is_accessible_from(decl.vis(), module.to_module())); let res = decl.res(); self.check_reserved_macro_name(ident.name, orig_ident_span, res); // Even if underscore names cannot be looked up, we still need to add them to modules, @@ -487,7 +519,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { orig_ident_span, warn_ambiguity, |this, resolution| { - assert!(!decl.warn_ambiguity.get()); if decl.is_glob_import() { resolution.glob_decl = Some(match resolution.glob_decl { Some(old_decl) => this.select_glob_decl( @@ -1261,7 +1292,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import.parent_scope, Some(Finalize { report_private: false, - import_vis: Some(import.vis), + import: Some(import.summary()), ..finalize }), bindings[ns].get().decl(), @@ -1461,7 +1492,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // All namespaces must be re-exported with extra visibility for an error to occur. if !any_successful_reexport { let (ns, binding) = reexport_error.unwrap(); - if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import, binding) { + if let Some(extern_crate_id) = + pub_use_of_private_extern_crate_hack(import.summary(), binding) + { let extern_crate_sp = self.tcx.source_span(self.local_def_id(extern_crate_id)); self.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index db71f7ed79d8b..87a2ba972e493 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -365,6 +365,9 @@ enum LifetimeRibKind { /// This rib acts as a barrier to forbid reference to lifetimes of a parent item. Item, + + /// Lifetimes cannot be elided in `impl Trait` types without `#![feature(anonymous_lifetime_in_impl_trait)]`. + ImplTrait, } #[derive(Copy, Clone, Debug)] @@ -941,7 +944,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc } TyKind::ImplTrait(..) => { let candidates = self.lifetime_elision_candidates.take(); - visit::walk_ty(self, ty); + self.with_lifetime_rib(LifetimeRibKind::ImplTrait, |this| visit::walk_ty(this, ty)); self.lifetime_elision_candidates = candidates; } TyKind::TraitObject(bounds, ..) => { @@ -1353,6 +1356,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc LifetimeRibKind::AnonymousCreateParameter { .. } | LifetimeRibKind::AnonymousReportError | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } + | LifetimeRibKind::ImplTrait | LifetimeRibKind::Elided(_) | LifetimeRibKind::ElisionFailure | LifetimeRibKind::ConcreteAnonConst(_) @@ -1780,6 +1784,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeRibKind::ConcreteAnonConst(_) => { span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind) } + + LifetimeRibKind::ImplTrait => { + if self.r.tcx.features().anonymous_lifetime_in_impl_trait() + { + None + } else { + Some(LifetimeUseSet::Many) + } + } }) .unwrap_or(LifetimeUseSet::Many); debug!(?use_ctxt, ?use_set); @@ -1819,6 +1832,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ElisionFailure | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::ImplTrait | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {} } } @@ -2000,7 +2014,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; } LifetimeRibKind::Item => break, - LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} + LifetimeRibKind::Generics { .. } + | LifetimeRibKind::ConstParamTy + | LifetimeRibKind::ImplTrait => {} LifetimeRibKind::ConcreteAnonConst(_) => { // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`. span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind) @@ -2323,7 +2339,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } break; } - LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} + LifetimeRibKind::Generics { .. } + | LifetimeRibKind::ConstParamTy + | LifetimeRibKind::ImplTrait => {} LifetimeRibKind::ConcreteAnonConst(_) => { // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`. span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af3006eda385e..a44a7b30b4e60 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2722,6 +2722,15 @@ enum Stage { Late, } +/// Parts of import data required for finalizing import resolution. +/// Does not carry a lifetime, so it can be stored in `Finalize`. +#[derive(Copy, Clone, Debug)] +struct ImportSummary { + vis: Visibility, + nearest_parent_mod: LocalDefId, + is_single: bool, +} + /// Invariant: if `Finalize` is used, expansion and import resolution must be complete. #[derive(Copy, Clone, Debug)] struct Finalize { @@ -2740,8 +2749,8 @@ struct Finalize { used: Used = Used::Other, /// Finalizing early or late resolution. stage: Stage = Stage::Early, - /// Nominal visibility of the import item, in case we are resolving an import's final segment. - import_vis: Option = None, + /// Some import data, in case we are resolving an import's final segment. + import: Option = None, } impl Finalize { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index cf94dc4298958..a336313e90b8f 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -17,6 +17,7 @@ use crate::{ self as ty, ClauseKind, CollectAndApply, FieldInfo, Interner, PredicateKind, UpcastFrom, }; +#[rust_analyzer::prefer_underscore_import] pub trait Ty>: Copy + Debug @@ -195,6 +196,7 @@ pub trait Ty>: } } +#[rust_analyzer::prefer_underscore_import] pub trait Tys>: Copy + Debug + Hash + Eq + SliceLike + TypeFoldable + Default { @@ -203,6 +205,7 @@ pub trait Tys>: fn output(self) -> I::Ty; } +#[rust_analyzer::prefer_underscore_import] pub trait FSigKind>: Copy + Debug + Hash + Eq { /// The identity function. fn fn_sig_kind(self) -> Self; @@ -220,6 +223,7 @@ pub trait FSigKind>: Copy + Debug + Hash + Eq { fn c_variadic(self) -> bool; } +#[rust_analyzer::prefer_underscore_import] pub trait Abi>: Copy + Debug + Hash + Eq { /// The identity function. fn abi(self) -> Self; @@ -237,6 +241,7 @@ pub trait Abi>: Copy + Debug + Hash + Eq { fn unpack_abi(abi_index: u8) -> Self; } +#[rust_analyzer::prefer_underscore_import] pub trait Safety>: Copy + Debug + Hash + Eq { /// The `safe` safety mode. fn safe() -> Self; @@ -251,6 +256,7 @@ pub trait Safety>: Copy + Debug + Hash + Eq { fn prefix_str(self) -> &'static str; } +#[rust_analyzer::prefer_underscore_import] pub trait Region>: Copy + Debug @@ -276,6 +282,7 @@ pub trait Region>: } } +#[rust_analyzer::prefer_underscore_import] pub trait Const>: Copy + Debug @@ -320,19 +327,23 @@ pub trait Const>: } } +#[rust_analyzer::prefer_underscore_import] pub trait ValueConst>: Copy + Debug + Hash + Eq { fn ty(self) -> I::Ty; fn valtree(self) -> I::ValTree; } +#[rust_analyzer::prefer_underscore_import] pub trait ExprConst>: Copy + Debug + Hash + Eq + Relate { fn args(self) -> I::GenericArgs; } +#[rust_analyzer::prefer_underscore_import] pub trait GenericsOf> { fn count(&self) -> usize; } +#[rust_analyzer::prefer_underscore_import] pub trait GenericArg>: Copy + Debug @@ -387,6 +398,7 @@ pub trait GenericArg>: } } +#[rust_analyzer::prefer_underscore_import] pub trait Term>: Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate { @@ -434,6 +446,7 @@ pub trait Term>: } } +#[rust_analyzer::prefer_underscore_import] pub trait GenericArgs>: Copy + Debug + Hash + Eq + SliceLike + Default + Relate { @@ -473,6 +486,7 @@ pub trait GenericArgs>: } } +#[rust_analyzer::prefer_underscore_import] pub trait Predicate>: Copy + Debug @@ -528,6 +542,7 @@ pub trait Predicate>: } } +#[rust_analyzer::prefer_underscore_import] pub trait Clause>: Copy + Debug @@ -577,6 +592,7 @@ pub trait Clause>: fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder>) -> Self; } +#[rust_analyzer::prefer_underscore_import] pub trait Clauses>: Copy + Debug @@ -589,16 +605,19 @@ pub trait Clauses>: { } +#[rust_analyzer::prefer_underscore_import] pub trait IntoKind { type Kind; fn kind(self) -> Self::Kind; } +#[rust_analyzer::prefer_underscore_import] pub trait ParamLike: Copy + Debug + Hash + Eq { fn index(self) -> u32; } +#[rust_analyzer::prefer_underscore_import] pub trait AdtDef: Copy + Debug + Hash + Eq { fn def_id(self) -> I::AdtId; @@ -635,10 +654,12 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { fn destructor(self, interner: I) -> Option; } +#[rust_analyzer::prefer_underscore_import] pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { fn caller_bounds(self) -> impl SliceLike; } +#[rust_analyzer::prefer_underscore_import] pub trait Features: Copy { fn generic_const_exprs(self) -> bool; @@ -647,6 +668,7 @@ pub trait Features: Copy { fn feature_bound_holds_in_crate(self, symbol: I::Symbol) -> bool; } +#[rust_analyzer::prefer_underscore_import] pub trait DefId: Copy + Debug + Hash + Eq + TypeFoldable { fn is_local(self) -> bool; @@ -663,6 +685,7 @@ impl + Into + TryFrom: Copy + Debug + Hash + Eq + Relate + SliceLike>> { @@ -677,10 +700,12 @@ pub trait BoundExistentialPredicates: ) -> impl IntoIterator>>; } +#[rust_analyzer::prefer_underscore_import] pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { fn dummy() -> Self; } +#[rust_analyzer::prefer_underscore_import] pub trait OpaqueTypeStorageEntries: Debug + Copy + Default { /// Whether the number of opaques has changed in a way that necessitates /// reevaluating a goal. For now, this is only when the number of non-duplicated @@ -767,6 +792,7 @@ impl<'a, S: SliceLike> SliceLike for &'a S { } } +#[rust_analyzer::prefer_underscore_import] pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { fn is_kw_underscore_lifetime(self) -> bool; } diff --git a/library/alloctests/benches/lib.rs b/library/alloctests/benches/lib.rs index 4a25778d88c83..b7e09fc2e162b 100644 --- a/library/alloctests/benches/lib.rs +++ b/library/alloctests/benches/lib.rs @@ -1,5 +1,6 @@ // This is marked as `test = true` and hence picked up by `./x miri`, but that would be too slow. #![cfg(not(miri))] +#![allow(internal_features)] #![feature(iter_next_chunk)] #![feature(repr_simd)] #![feature(slice_partition_dedup)] diff --git a/library/core/src/io/error.rs b/library/core/src/io/error.rs new file mode 100644 index 0000000000000..fe12de2952f0a --- /dev/null +++ b/library/core/src/io/error.rs @@ -0,0 +1,372 @@ +#![unstable(feature = "core_io", issue = "154046")] + +use crate::fmt; + +/// A list specifying general categories of I/O error. +/// +/// This list is intended to grow over time and it is not recommended to +/// exhaustively match against it. +/// +/// # Handling errors and matching on `ErrorKind` +/// +/// In application code, use `match` for the `ErrorKind` values you are +/// expecting; use `_` to match "all other errors". +/// +/// In comprehensive and thorough tests that want to verify that a test doesn't +/// return any known incorrect error kind, you may want to cut-and-paste the +/// current full list of errors from here into your test code, and then match +/// `_` as the correct case. This seems counterintuitive, but it will make your +/// tests more robust. In particular, if you want to verify that your code does +/// produce an unrecognized error kind, the robust solution is to check for all +/// the recognized error kinds and fail in those cases. +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")] +#[allow(deprecated)] +#[non_exhaustive] +pub enum ErrorKind { + /// An entity was not found, often a file. + #[stable(feature = "rust1", since = "1.0.0")] + NotFound, + /// The operation lacked the necessary privileges to complete. + #[stable(feature = "rust1", since = "1.0.0")] + PermissionDenied, + /// The connection was refused by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] + ConnectionRefused, + /// The connection was reset by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] + ConnectionReset, + /// The remote host is not reachable. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + HostUnreachable, + /// The network containing the remote host is not reachable. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + NetworkUnreachable, + /// The connection was aborted (terminated) by the remote server. + #[stable(feature = "rust1", since = "1.0.0")] + ConnectionAborted, + /// The network operation failed because it was not connected yet. + #[stable(feature = "rust1", since = "1.0.0")] + NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + #[stable(feature = "rust1", since = "1.0.0")] + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + #[stable(feature = "rust1", since = "1.0.0")] + AddrNotAvailable, + /// The system's networking is down. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + NetworkDown, + /// The operation failed because a pipe was closed. + #[stable(feature = "rust1", since = "1.0.0")] + BrokenPipe, + /// An entity already exists, often a file. + #[stable(feature = "rust1", since = "1.0.0")] + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + #[stable(feature = "rust1", since = "1.0.0")] + WouldBlock, + /// A filesystem object is, unexpectedly, not a directory. + /// + /// For example, a filesystem path was specified where one of the intermediate directory + /// components was, in fact, a plain file. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + NotADirectory, + /// The filesystem object is, unexpectedly, a directory. + /// + /// A directory was specified when a non-directory was expected. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + IsADirectory, + /// A non-empty directory was specified where an empty directory was expected. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + DirectoryNotEmpty, + /// The filesystem or storage medium is read-only, but a write operation was attempted. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + ReadOnlyFilesystem, + /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. + /// + /// There was a loop (or excessively long chain) resolving a filesystem object + /// or file IO object. + /// + /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the + /// system-specific limit on the depth of symlink traversal. + #[unstable(feature = "io_error_more", issue = "86442")] + FilesystemLoop, + /// Stale network file handle. + /// + /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated + /// by problems with the network or server. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + StaleNetworkFileHandle, + /// A parameter was incorrect. + #[stable(feature = "rust1", since = "1.0.0")] + InvalidInput, + /// Data not valid for the operation were encountered. + /// + /// Unlike [`InvalidInput`], this typically means that the operation + /// parameters were valid, however the error was caused by malformed + /// input data. + /// + /// For example, a function that reads a file into a string will error with + /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: ErrorKind::InvalidInput + #[stable(feature = "io_invalid_data", since = "1.2.0")] + InvalidData, + /// The I/O operation's timeout expired, causing it to be canceled. + #[stable(feature = "rust1", since = "1.0.0")] + TimedOut, + /// An error returned when an operation could not be completed because a + /// call to an underlying writer returned [`Ok(0)`]. + /// + /// This typically means that an operation could only succeed if it wrote a + /// particular number of bytes but only a smaller number of bytes could be + /// written. + /// + /// [`Ok(0)`]: Ok + #[stable(feature = "rust1", since = "1.0.0")] + WriteZero, + /// The underlying storage (typically, a filesystem) is full. + /// + /// This does not include out of quota errors. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + StorageFull, + /// Seek on unseekable file. + /// + /// Seeking was attempted on an open file handle which is not suitable for seeking - for + /// example, on Unix, a named pipe opened with `File::open`. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + NotSeekable, + /// Filesystem quota or some other kind of quota was exceeded. + #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")] + QuotaExceeded, + /// File larger than allowed or supported. + /// + /// This might arise from a hard limit of the underlying filesystem or file access API, or from + /// an administratively imposed resource limitation. Simple disk full, and out of quota, have + /// their own errors. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + FileTooLarge, + /// Resource is busy. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + ResourceBusy, + /// Executable file is busy. + /// + /// An attempt was made to write to a file which is also in use as a running program. (Not all + /// operating systems detect this situation.) + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + ExecutableFileBusy, + /// Deadlock (avoided). + /// + /// A file locking operation would result in deadlock. This situation is typically detected, if + /// at all, on a best-effort basis. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + Deadlock, + /// Cross-device or cross-filesystem (hard) link or rename. + #[stable(feature = "io_error_crosses_devices", since = "1.85.0")] + CrossesDevices, + /// Too many (hard) links to the same filesystem object. + /// + /// The filesystem does not support making so many hardlinks to the same file. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + TooManyLinks, + /// A filename was invalid. + /// + /// This error can also occur if a length limit for a name was exceeded. + #[stable(feature = "io_error_invalid_filename", since = "1.87.0")] + InvalidFilename, + /// Program argument list too long. + /// + /// When trying to run an external program, a system or process limit on the size of the + /// arguments would have been exceeded. + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] + ArgumentListTooLong, + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + #[stable(feature = "rust1", since = "1.0.0")] + Interrupted, + + /// This operation is unsupported on this platform. + /// + /// This means that the operation can never succeed. + #[stable(feature = "unsupported_error", since = "1.53.0")] + Unsupported, + + // ErrorKinds which are primarily categorisations for OS error + // codes should be added above. + // + /// An error returned when an operation could not be completed because an + /// "end of file" was reached prematurely. + /// + /// This typically means that an operation could only succeed if it read a + /// particular number of bytes but only a smaller number of bytes could be + /// read. + #[stable(feature = "read_exact", since = "1.6.0")] + UnexpectedEof, + + /// An operation could not be completed, because it failed + /// to allocate enough memory. + #[stable(feature = "out_of_memory_error", since = "1.54.0")] + OutOfMemory, + + /// The operation was partially successful and needs to be checked + /// later on due to not blocking. + #[unstable(feature = "io_error_inprogress", issue = "130840")] + InProgress, + + // "Unusual" error kinds which do not correspond simply to (sets + // of) OS error codes, should be added just above this comment. + // `Other` and `Uncategorized` should remain at the end: + // + /// A custom error that does not fall under any other I/O error kind. + /// + /// This can be used to construct your own errors that do not match any + /// [`ErrorKind`]. + /// + /// This [`ErrorKind`] is not used by the standard library. + /// + /// Errors from the standard library that do not fall under any of the I/O + /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. + /// New [`ErrorKind`]s might be added in the future for some of those. + #[stable(feature = "rust1", since = "1.0.0")] + Other, + + /// Any I/O error from the standard library that's not part of this list. + /// + /// Errors that are `Uncategorized` now may move to a different or a new + /// [`ErrorKind`] variant in the future. It is not recommended to match + /// an error against `Uncategorized`; use a wildcard match (`_`) instead. + #[unstable(feature = "io_error_uncategorized", issue = "none")] + #[doc(hidden)] + Uncategorized, +} + +impl ErrorKind { + pub(crate) const fn as_str(&self) -> &'static str { + use ErrorKind::*; + match *self { + // tidy-alphabetical-start + AddrInUse => "address in use", + AddrNotAvailable => "address not available", + AlreadyExists => "entity already exists", + ArgumentListTooLong => "argument list too long", + BrokenPipe => "broken pipe", + ConnectionAborted => "connection aborted", + ConnectionRefused => "connection refused", + ConnectionReset => "connection reset", + CrossesDevices => "cross-device link or rename", + Deadlock => "deadlock", + DirectoryNotEmpty => "directory not empty", + ExecutableFileBusy => "executable file busy", + FileTooLarge => "file too large", + FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", + HostUnreachable => "host unreachable", + InProgress => "in progress", + Interrupted => "operation interrupted", + InvalidData => "invalid data", + InvalidFilename => "invalid filename", + InvalidInput => "invalid input parameter", + IsADirectory => "is a directory", + NetworkDown => "network down", + NetworkUnreachable => "network unreachable", + NotADirectory => "not a directory", + NotConnected => "not connected", + NotFound => "entity not found", + NotSeekable => "seek on unseekable file", + Other => "other error", + OutOfMemory => "out of memory", + PermissionDenied => "permission denied", + QuotaExceeded => "quota exceeded", + ReadOnlyFilesystem => "read-only filesystem or storage medium", + ResourceBusy => "resource busy", + StaleNetworkFileHandle => "stale network file handle", + StorageFull => "no storage space", + TimedOut => "timed out", + TooManyLinks => "too many links", + Uncategorized => "uncategorized error", + UnexpectedEof => "unexpected end of file", + Unsupported => "unsupported", + WouldBlock => "operation would block", + WriteZero => "write zero", + // tidy-alphabetical-end + } + } + + // This compiles to the same code as the check+transmute, but doesn't require + // unsafe, or to hard-code max ErrorKind or its size in a way the compiler + // couldn't verify. + #[inline] + #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] + #[doc(hidden)] + pub const fn from_prim(ek: u32) -> Option { + macro_rules! from_prim { + ($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{ + // Force a compile error if the list gets out of date. + const _: fn(e: $Enum) = |e: $Enum| match e { + $($Enum::$Variant => (),)* + }; + match $prim { + $(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)* + _ => None, + } + }} + } + from_prim!(ek => ErrorKind { + NotFound, + PermissionDenied, + ConnectionRefused, + ConnectionReset, + HostUnreachable, + NetworkUnreachable, + ConnectionAborted, + NotConnected, + AddrInUse, + AddrNotAvailable, + NetworkDown, + BrokenPipe, + AlreadyExists, + WouldBlock, + NotADirectory, + IsADirectory, + DirectoryNotEmpty, + ReadOnlyFilesystem, + FilesystemLoop, + StaleNetworkFileHandle, + InvalidInput, + InvalidData, + TimedOut, + WriteZero, + StorageFull, + NotSeekable, + QuotaExceeded, + FileTooLarge, + ResourceBusy, + ExecutableFileBusy, + Deadlock, + CrossesDevices, + TooManyLinks, + InvalidFilename, + ArgumentListTooLong, + Interrupted, + Other, + UnexpectedEof, + Unsupported, + OutOfMemory, + InProgress, + Uncategorized, + }) + } +} + +#[stable(feature = "io_errorkind_display", since = "1.60.0")] +impl fmt::Display for ErrorKind { + /// Shows a human-readable description of the `ErrorKind`. + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str(self.as_str()) + } +} diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs index 2f20180cdc9a2..c34421523b643 100644 --- a/library/core/src/io/mod.rs +++ b/library/core/src/io/mod.rs @@ -1,6 +1,9 @@ //! Traits, helpers, and type definitions for core I/O functionality. mod borrowed_buf; +mod error; #[unstable(feature = "core_io_borrowed_buf", issue = "117693")] pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor}; +#[unstable(feature = "core_io", issue = "154046")] +pub use self::error::ErrorKind; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3b72752cee9a1..bdc1c48f70dfe 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -305,7 +305,7 @@ pub mod bstr; pub mod cell; pub mod char; pub mod ffi; -#[unstable(feature = "core_io_borrowed_buf", issue = "117693")] +#[unstable(feature = "core_io", issue = "154046")] pub mod io; pub mod iter; pub mod net; diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index ed18f5a34fd28..c4292c2a421b1 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -36,6 +36,7 @@ #![feature(const_unsigned_bigint_helpers)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] +#![feature(core_io)] #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index e6c6f7d766c02..6f565bb37c53b 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -1,6 +1,9 @@ #[cfg(test)] mod tests; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::io::ErrorKind; + // On 64-bit platforms, `io::Error` may use a bit-packed representation to // reduce size. However, this representation assumes that error codes are // always 32-bit wide. @@ -206,323 +209,6 @@ struct Custom { error: Box, } -/// A list specifying general categories of I/O error. -/// -/// This list is intended to grow over time and it is not recommended to -/// exhaustively match against it. -/// -/// It is used with the [`io::Error`] type. -/// -/// [`io::Error`]: Error -/// -/// # Handling errors and matching on `ErrorKind` -/// -/// In application code, use `match` for the `ErrorKind` values you are -/// expecting; use `_` to match "all other errors". -/// -/// In comprehensive and thorough tests that want to verify that a test doesn't -/// return any known incorrect error kind, you may want to cut-and-paste the -/// current full list of errors from here into your test code, and then match -/// `_` as the correct case. This seems counterintuitive, but it will make your -/// tests more robust. In particular, if you want to verify that your code does -/// produce an unrecognized error kind, the robust solution is to check for all -/// the recognized error kinds and fail in those cases. -#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "io_errorkind")] -#[allow(deprecated)] -#[non_exhaustive] -pub enum ErrorKind { - /// An entity was not found, often a file. - #[stable(feature = "rust1", since = "1.0.0")] - NotFound, - /// The operation lacked the necessary privileges to complete. - #[stable(feature = "rust1", since = "1.0.0")] - PermissionDenied, - /// The connection was refused by the remote server. - #[stable(feature = "rust1", since = "1.0.0")] - ConnectionRefused, - /// The connection was reset by the remote server. - #[stable(feature = "rust1", since = "1.0.0")] - ConnectionReset, - /// The remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - HostUnreachable, - /// The network containing the remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - NetworkUnreachable, - /// The connection was aborted (terminated) by the remote server. - #[stable(feature = "rust1", since = "1.0.0")] - ConnectionAborted, - /// The network operation failed because it was not connected yet. - #[stable(feature = "rust1", since = "1.0.0")] - NotConnected, - /// A socket address could not be bound because the address is already in - /// use elsewhere. - #[stable(feature = "rust1", since = "1.0.0")] - AddrInUse, - /// A nonexistent interface was requested or the requested address was not - /// local. - #[stable(feature = "rust1", since = "1.0.0")] - AddrNotAvailable, - /// The system's networking is down. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - NetworkDown, - /// The operation failed because a pipe was closed. - #[stable(feature = "rust1", since = "1.0.0")] - BrokenPipe, - /// An entity already exists, often a file. - #[stable(feature = "rust1", since = "1.0.0")] - AlreadyExists, - /// The operation needs to block to complete, but the blocking operation was - /// requested to not occur. - #[stable(feature = "rust1", since = "1.0.0")] - WouldBlock, - /// A filesystem object is, unexpectedly, not a directory. - /// - /// For example, a filesystem path was specified where one of the intermediate directory - /// components was, in fact, a plain file. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - NotADirectory, - /// The filesystem object is, unexpectedly, a directory. - /// - /// A directory was specified when a non-directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - IsADirectory, - /// A non-empty directory was specified where an empty directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - DirectoryNotEmpty, - /// The filesystem or storage medium is read-only, but a write operation was attempted. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - ReadOnlyFilesystem, - /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. - /// - /// There was a loop (or excessively long chain) resolving a filesystem object - /// or file IO object. - /// - /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the - /// system-specific limit on the depth of symlink traversal. - #[unstable(feature = "io_error_more", issue = "86442")] - FilesystemLoop, - /// Stale network file handle. - /// - /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated - /// by problems with the network or server. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - StaleNetworkFileHandle, - /// A parameter was incorrect. - #[stable(feature = "rust1", since = "1.0.0")] - InvalidInput, - /// Data not valid for the operation were encountered. - /// - /// Unlike [`InvalidInput`], this typically means that the operation - /// parameters were valid, however the error was caused by malformed - /// input data. - /// - /// For example, a function that reads a file into a string will error with - /// `InvalidData` if the file's contents are not valid UTF-8. - /// - /// [`InvalidInput`]: ErrorKind::InvalidInput - #[stable(feature = "io_invalid_data", since = "1.2.0")] - InvalidData, - /// The I/O operation's timeout expired, causing it to be canceled. - #[stable(feature = "rust1", since = "1.0.0")] - TimedOut, - /// An error returned when an operation could not be completed because a - /// call to [`write`] returned [`Ok(0)`]. - /// - /// This typically means that an operation could only succeed if it wrote a - /// particular number of bytes but only a smaller number of bytes could be - /// written. - /// - /// [`write`]: crate::io::Write::write - /// [`Ok(0)`]: Ok - #[stable(feature = "rust1", since = "1.0.0")] - WriteZero, - /// The underlying storage (typically, a filesystem) is full. - /// - /// This does not include out of quota errors. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - StorageFull, - /// Seek on unseekable file. - /// - /// Seeking was attempted on an open file handle which is not suitable for seeking - for - /// example, on Unix, a named pipe opened with `File::open`. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - NotSeekable, - /// Filesystem quota or some other kind of quota was exceeded. - #[stable(feature = "io_error_quota_exceeded", since = "1.85.0")] - QuotaExceeded, - /// File larger than allowed or supported. - /// - /// This might arise from a hard limit of the underlying filesystem or file access API, or from - /// an administratively imposed resource limitation. Simple disk full, and out of quota, have - /// their own errors. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - FileTooLarge, - /// Resource is busy. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - ResourceBusy, - /// Executable file is busy. - /// - /// An attempt was made to write to a file which is also in use as a running program. (Not all - /// operating systems detect this situation.) - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - ExecutableFileBusy, - /// Deadlock (avoided). - /// - /// A file locking operation would result in deadlock. This situation is typically detected, if - /// at all, on a best-effort basis. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - Deadlock, - /// Cross-device or cross-filesystem (hard) link or rename. - #[stable(feature = "io_error_crosses_devices", since = "1.85.0")] - CrossesDevices, - /// Too many (hard) links to the same filesystem object. - /// - /// The filesystem does not support making so many hardlinks to the same file. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - TooManyLinks, - /// A filename was invalid. - /// - /// This error can also occur if a length limit for a name was exceeded. - #[stable(feature = "io_error_invalid_filename", since = "1.87.0")] - InvalidFilename, - /// Program argument list too long. - /// - /// When trying to run an external program, a system or process limit on the size of the - /// arguments would have been exceeded. - #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] - ArgumentListTooLong, - /// This operation was interrupted. - /// - /// Interrupted operations can typically be retried. - #[stable(feature = "rust1", since = "1.0.0")] - Interrupted, - - /// This operation is unsupported on this platform. - /// - /// This means that the operation can never succeed. - #[stable(feature = "unsupported_error", since = "1.53.0")] - Unsupported, - - // ErrorKinds which are primarily categorisations for OS error - // codes should be added above. - // - /// An error returned when an operation could not be completed because an - /// "end of file" was reached prematurely. - /// - /// This typically means that an operation could only succeed if it read a - /// particular number of bytes but only a smaller number of bytes could be - /// read. - #[stable(feature = "read_exact", since = "1.6.0")] - UnexpectedEof, - - /// An operation could not be completed, because it failed - /// to allocate enough memory. - #[stable(feature = "out_of_memory_error", since = "1.54.0")] - OutOfMemory, - - /// The operation was partially successful and needs to be checked - /// later on due to not blocking. - #[unstable(feature = "io_error_inprogress", issue = "130840")] - InProgress, - - // "Unusual" error kinds which do not correspond simply to (sets - // of) OS error codes, should be added just above this comment. - // `Other` and `Uncategorized` should remain at the end: - // - /// A custom error that does not fall under any other I/O error kind. - /// - /// This can be used to construct your own [`Error`]s that do not match any - /// [`ErrorKind`]. - /// - /// This [`ErrorKind`] is not used by the standard library. - /// - /// Errors from the standard library that do not fall under any of the I/O - /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. - /// New [`ErrorKind`]s might be added in the future for some of those. - #[stable(feature = "rust1", since = "1.0.0")] - Other, - - /// Any I/O error from the standard library that's not part of this list. - /// - /// Errors that are `Uncategorized` now may move to a different or a new - /// [`ErrorKind`] variant in the future. It is not recommended to match - /// an error against `Uncategorized`; use a wildcard match (`_`) instead. - #[unstable(feature = "io_error_uncategorized", issue = "none")] - #[doc(hidden)] - Uncategorized, -} - -impl ErrorKind { - pub(crate) fn as_str(&self) -> &'static str { - use ErrorKind::*; - match *self { - // tidy-alphabetical-start - AddrInUse => "address in use", - AddrNotAvailable => "address not available", - AlreadyExists => "entity already exists", - ArgumentListTooLong => "argument list too long", - BrokenPipe => "broken pipe", - ConnectionAborted => "connection aborted", - ConnectionRefused => "connection refused", - ConnectionReset => "connection reset", - CrossesDevices => "cross-device link or rename", - Deadlock => "deadlock", - DirectoryNotEmpty => "directory not empty", - ExecutableFileBusy => "executable file busy", - FileTooLarge => "file too large", - FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", - HostUnreachable => "host unreachable", - InProgress => "in progress", - Interrupted => "operation interrupted", - InvalidData => "invalid data", - InvalidFilename => "invalid filename", - InvalidInput => "invalid input parameter", - IsADirectory => "is a directory", - NetworkDown => "network down", - NetworkUnreachable => "network unreachable", - NotADirectory => "not a directory", - NotConnected => "not connected", - NotFound => "entity not found", - NotSeekable => "seek on unseekable file", - Other => "other error", - OutOfMemory => "out of memory", - PermissionDenied => "permission denied", - QuotaExceeded => "quota exceeded", - ReadOnlyFilesystem => "read-only filesystem or storage medium", - ResourceBusy => "resource busy", - StaleNetworkFileHandle => "stale network file handle", - StorageFull => "no storage space", - TimedOut => "timed out", - TooManyLinks => "too many links", - Uncategorized => "uncategorized error", - UnexpectedEof => "unexpected end of file", - Unsupported => "unsupported", - WouldBlock => "operation would block", - WriteZero => "write zero", - // tidy-alphabetical-end - } - } -} - -#[stable(feature = "io_errorkind_display", since = "1.60.0")] -impl fmt::Display for ErrorKind { - /// Shows a human-readable description of the `ErrorKind`. - /// - /// This is similar to `impl Display for Error`, but doesn't require first converting to Error. - /// - /// # Examples - /// ``` - /// use std::io::ErrorKind; - /// assert_eq!("entity not found", ErrorKind::NotFound.to_string()); - /// ``` - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.write_str(self.as_str()) - } -} - /// Intended for use for errors not exposed to the user, where allocating onto /// the heap (for normal construction via Error::new) is too costly. #[stable(feature = "io_error_from_errorkind", since = "1.14.0")] @@ -1051,7 +737,7 @@ impl fmt::Display for Error { write!(fmt, "{detail} (os error {code})") } ErrorData::Custom(ref c) => c.error.fmt(fmt), - ErrorData::Simple(kind) => write!(fmt, "{}", kind.as_str()), + ErrorData::Simple(kind) => kind.fmt(fmt), ErrorData::SimpleMessage(msg) => msg.message.fmt(fmt), } } diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 7353816a8171b..7c237825459af 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -253,7 +253,7 @@ where } TAG_SIMPLE => { let kind_bits = (bits >> 32) as u32; - let kind = kind_from_prim(kind_bits).unwrap_or_else(|| { + let kind = ErrorKind::from_prim(kind_bits).unwrap_or_else(|| { debug_assert!(false, "Invalid io::error::Repr bits: `Repr({:#018x})`", bits); // This means the `ptr` passed in was not valid, which violates // the unsafe contract of `decode_repr`. @@ -283,69 +283,6 @@ where } } -// This compiles to the same code as the check+transmute, but doesn't require -// unsafe, or to hard-code max ErrorKind or its size in a way the compiler -// couldn't verify. -#[inline] -fn kind_from_prim(ek: u32) -> Option { - macro_rules! from_prim { - ($prim:expr => $Enum:ident { $($Variant:ident),* $(,)? }) => {{ - // Force a compile error if the list gets out of date. - const _: fn(e: $Enum) = |e: $Enum| match e { - $($Enum::$Variant => ()),* - }; - match $prim { - $(v if v == ($Enum::$Variant as _) => Some($Enum::$Variant),)* - _ => None, - } - }} - } - from_prim!(ek => ErrorKind { - NotFound, - PermissionDenied, - ConnectionRefused, - ConnectionReset, - HostUnreachable, - NetworkUnreachable, - ConnectionAborted, - NotConnected, - AddrInUse, - AddrNotAvailable, - NetworkDown, - BrokenPipe, - AlreadyExists, - WouldBlock, - NotADirectory, - IsADirectory, - DirectoryNotEmpty, - ReadOnlyFilesystem, - FilesystemLoop, - StaleNetworkFileHandle, - InvalidInput, - InvalidData, - TimedOut, - WriteZero, - StorageFull, - NotSeekable, - QuotaExceeded, - FileTooLarge, - ResourceBusy, - ExecutableFileBusy, - Deadlock, - CrossesDevices, - TooManyLinks, - InvalidFilename, - ArgumentListTooLong, - Interrupted, - Other, - UnexpectedEof, - Unsupported, - OutOfMemory, - InProgress, - Uncategorized, - }) -} - // Some static checking to alert us if a change breaks any of the assumptions // that our encoding relies on for correctness and soundness. (Some of these are // a bit overly thorough/cautious, admittedly) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index faac8d9e51fd2..807befec1ad11 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -321,7 +321,9 @@ #![feature(const_default)] #![feature(core_float_math)] #![feature(core_intrinsics)] +#![feature(core_io)] #![feature(core_io_borrowed_buf)] +#![feature(core_io_internals)] #![feature(cstr_display)] #![feature(drop_guard)] #![feature(duration_constants)] @@ -344,6 +346,9 @@ #![feature(hashmap_internals)] #![feature(hint_must_use)] #![feature(int_from_ascii)] +#![feature(io_error_inprogress)] +#![feature(io_error_more)] +#![feature(io_error_uncategorized)] #![feature(ip)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] diff --git a/library/std/src/sys/io/error/sgx.rs b/library/std/src/sys/io/error/sgx.rs index 8b3e08b0b661b..b7b4030422e12 100644 --- a/library/std/src/sys/io/error/sgx.rs +++ b/library/std/src/sys/io/error/sgx.rs @@ -60,6 +60,6 @@ pub fn error_string(errno: i32) -> String { } else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) { format!("user-specified error {errno:08x}") } else { - decode_error_kind(errno).as_str().into() + format!("{}", decode_error_kind(errno)) } } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 04f020e44dd12..6841182808140 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2196,6 +2196,42 @@ pub fn check_stage0_version( } } +fn print_rustc_modifications( + dwn_ctx: &DownloadContext<'_>, + if_unchanged: bool, + mut modifications: Vec, +) -> Option<()> { + if !dwn_ctx.exec_ctx.is_verbose() { + modifications.retain(|path| !path.starts_with("compiler")); + } + if modifications.is_empty() { + // only compiler changes; still force a rebuild but don't say why. + eprintln!( + "skipping rustc download with `download-rustc = 'if-unchanged'` due to local changes" + ); + return None; + } + + eprintln!( + "NOTE: detected {} modifications that could affect a build of rustc", + modifications.len() + ); + for file in modifications.iter().take(10) { + eprintln!("- {}", file.display()); + } + if modifications.len() > 10 { + eprintln!("- ... and {} more", modifications.len() - 10); + } + + if if_unchanged { + eprintln!("skipping rustc download due to `download-rustc = 'if-unchanged'`"); + None + } else { + eprintln!("downloading unconditionally due to `download-rustc = true`"); + Some(()) + } +} + pub fn download_ci_rustc_commit<'a>( dwn_ctx: impl AsRef>, rust_info: &channel::GitInfo, @@ -2250,24 +2286,7 @@ pub fn download_ci_rustc_commit<'a>( return None; } - eprintln!( - "NOTE: detected {} modifications that could affect a build of rustc", - modifications.len() - ); - for file in modifications.iter().take(10) { - eprintln!("- {}", file.display()); - } - if modifications.len() > 10 { - eprintln!("- ... and {} more", modifications.len() - 10); - } - - if if_unchanged { - eprintln!("skipping rustc download due to `download-rustc = 'if-unchanged'`"); - return None; - } else { - eprintln!("downloading unconditionally due to `download-rustc = true`"); - } - + print_rustc_modifications(dwn_ctx, if_unchanged, modifications)?; upstream } PathFreshness::MissingUpstream => { diff --git a/tests/run-make/macho-link-section/foo.rs b/tests/run-make/macho-link-section/foo.rs new file mode 100644 index 0000000000000..0ac2f9a9d1c0e --- /dev/null +++ b/tests/run-make/macho-link-section/foo.rs @@ -0,0 +1,14 @@ +#[unsafe(no_mangle)] +#[unsafe(link_section = "__TEXT,custom_code,regular,pure_instructions")] +static CODE: [u8; 10] = *b"0123456789"; + +#[unsafe(no_mangle)] +#[unsafe(link_section = "__DATA,all_attributes,regular,pure_instructions\ + +no_toc+strip_static_syms+no_dead_strip+live_support\ + +self_modifying_code+debug")] +static ALL_THE_ATTRIBUTES: u32 = 42; + +#[unsafe(no_mangle)] +#[unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs")] +static CONSTRUCTOR: extern "C" fn() = constructor; +extern "C" fn constructor() {} diff --git a/tests/run-make/macho-link-section/rmake.rs b/tests/run-make/macho-link-section/rmake.rs new file mode 100644 index 0000000000000..e59dc5f40f4f4 --- /dev/null +++ b/tests/run-make/macho-link-section/rmake.rs @@ -0,0 +1,47 @@ +//! Test that various Mach-O `#[link_section]` values are parsed and passed on correctly by codegen +//! backends. +//@ only-apple +use run_make_support::{llvm_objdump, rustc}; + +fn main() { + rustc().input("foo.rs").crate_type("lib").arg("--emit=obj").run(); + + let stdout = + llvm_objdump().arg("--macho").arg("--private-headers").input("foo.o").run().stdout_utf8(); + + let expected = [ + ("__TEXT", "custom_code", "S_REGULAR", "PURE_INSTRUCTIONS"), + ("__DATA", "__mod_init_func", "S_MOD_INIT_FUNC_POINTERS", "(none)"), + ( + "__DATA", + "all_attributes", + "S_REGULAR", + "PURE_INSTRUCTIONS NO_TOC STRIP_STATIC_SYMS \ + NO_DEAD_STRIP LIVE_SUPPORT SELF_MODIFYING_CODE DEBUG", + ), + ]; + + for (segment, section, section_type, section_attributes) in expected { + let mut found = false; + // Skip header. + for section_info in stdout.split("Section").skip(1) { + if section_info.contains(&format!("segname {segment}")) + && section_info.contains(&format!("sectname {section}")) + { + assert!( + section_info.contains(&format!("type {section_type}")), + "should have type {section_type:?}" + ); + assert!( + section_info.contains(&format!("attributes {section_attributes}\n")), + "should have attributes {section_attributes:?}" + ); + found = true; + } + } + + if !found { + panic!("could not find section {section} in binary"); + } + } +} diff --git a/tests/rustdoc-html/intra-doc/deprecated.rs b/tests/rustdoc-html/intra-doc/deprecated.rs index 6f8639593a2d4..1705fe8fc7abe 100644 --- a/tests/rustdoc-html/intra-doc/deprecated.rs +++ b/tests/rustdoc-html/intra-doc/deprecated.rs @@ -1,6 +1,6 @@ //@ has deprecated/struct.A.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start' -//@ has deprecated/struct.B1.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' -//@ has deprecated/struct.B2.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' +//@ has deprecated/struct.B1.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' +//@ has deprecated/struct.B2.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' #[deprecated = "[start][std::ops::Range::start]"] pub struct A; diff --git a/tests/rustdoc-html/intra-doc/field.rs b/tests/rustdoc-html/intra-doc/field.rs index e98419618e23f..610eb1ec1bf65 100644 --- a/tests/rustdoc-html/intra-doc/field.rs +++ b/tests/rustdoc-html/intra-doc/field.rs @@ -1,9 +1,9 @@ //@ has field/index.html '//a[@href="{{channel}}/core/ops/range/struct.Range.html#structfield.start"]' 'start' -//@ has field/index.html '//a[@href="{{channel}}/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' +//@ has field/index.html '//a[@href="{{channel}}/core/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found' //@ has field/index.html '//a[@href="struct.FieldAndMethod.html#structfield.x"]' 'x' //@ has field/index.html '//a[@href="enum.VariantAndMethod.html#variant.X"]' 'X' //! [start][std::ops::Range::start] -//! [not_found][std::io::ErrorKind::NotFound] +//! [not_found][core::io::ErrorKind::NotFound] //! [x][field@crate::FieldAndMethod::x] //! [X][variant@crate::VariantAndMethod::X] diff --git a/tests/ui/explicit-tail-calls/caller_is_track_caller.rs b/tests/ui/explicit-tail-calls/caller_is_track_caller.rs index 4e5f3f12f8399..a3a116cbd61b6 100644 --- a/tests/ui/explicit-tail-calls/caller_is_track_caller.rs +++ b/tests/ui/explicit-tail-calls/caller_is_track_caller.rs @@ -13,4 +13,13 @@ fn c() { become a(); //~ error: a function marked with `#[track_caller]` cannot perform a tail-call } +trait Trait { + fn d(&self); + + #[track_caller] + fn e(&self) { + become self.d(); //~ error: a function marked with `#[track_caller]` cannot perform a tail-call + } +} + fn main() {} diff --git a/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr b/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr index 79b9b45986c47..8c2ebf67bdb96 100644 --- a/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr +++ b/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr @@ -10,5 +10,11 @@ error: a function marked with `#[track_caller]` cannot perform a tail-call LL | become a(); | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: a function marked with `#[track_caller]` cannot perform a tail-call + --> $DIR/caller_is_track_caller.rs:21:9 + | +LL | become self.d(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/explicit-tail-calls/default-trait-method.rs b/tests/ui/explicit-tail-calls/default-trait-method.rs new file mode 100644 index 0000000000000..fbf2e80ced45e --- /dev/null +++ b/tests/ui/explicit-tail-calls/default-trait-method.rs @@ -0,0 +1,38 @@ +// A regression test for . +// Previously, using `become` in a default trait method would lead to an ICE +// in a path determining whether the method in question is marked as `#[track_caller]`. +// +//@ run-pass +//@ ignore-backends: gcc + +#![feature(explicit_tail_calls)] +#![expect(incomplete_features)] + +trait Trait { + fn bar(&self) -> usize { + 123 + } + + fn foo(&self) -> usize { + #[allow(tail_call_track_caller)] + become self.bar(); + } +} + +struct Struct; + +impl Trait for Struct {} + +struct OtherStruct; + +impl Trait for OtherStruct { + #[track_caller] + fn bar(&self) -> usize { + 456 + } +} + +fn main() { + assert_eq!(Struct.foo(), 123); + assert_eq!(OtherStruct.foo(), 456); +} diff --git a/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.rs b/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.rs new file mode 100644 index 0000000000000..514e4e1277afa --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.rs @@ -0,0 +1,12 @@ +// Ensure `ErrorKind` from `core` is gated behind `core_io` +//@ edition:2024 + +use std::io::ErrorKind as ErrorKindFromStd; + +use core::io::ErrorKind as ErrorKindFromCore; +//~^ ERROR use of unstable library feature `core_io` + +// Asserting both ErrorKinds are the same. +const _: [ErrorKindFromCore; 1] = [ErrorKindFromStd::Other]; + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.stderr b/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.stderr new file mode 100644 index 0000000000000..499b603761dce --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-io_error_kind_in_core.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of unstable library feature `core_io` + --> $DIR/feature-gate-io_error_kind_in_core.rs:6:5 + | +LL | use core::io::ErrorKind as ErrorKindFromCore; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #154046 for more information + = help: add `#![feature(core_io)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs new file mode 100644 index 0000000000000..96d2953ab4cd4 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv-pass.rs @@ -0,0 +1,23 @@ +//@ check-pass + +mod m { + pub struct S {} +} + +mod one_private { + use crate::m::*; + pub use crate::m::*; +} + +// One of the ambiguous imports is not visible from here, +// and does not contribute to the ambiguity. +use crate::one_private::S; + +// Separate module to make visibilities `in crate::inner` and `in crate::one_private` unordered. +mod inner { + // One of the ambiguous imports is not visible from here, + // and does not contribute to the ambiguity. + use crate::one_private::S; +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs new file mode 100644 index 0000000000000..7c0e0142f702f --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.rs @@ -0,0 +1,21 @@ +mod m { + pub struct S {} +} + +mod both { + pub mod private { + use crate::m::*; + pub(super) use crate::m::*; + } +} + +use crate::both::private::S; +//~^ ERROR struct import `S` is private + +// Separate module to make visibilities `in crate::inner` and `in crate::both(::private)` unordered. +mod inner { + use crate::both::private::S; + //~^ ERROR struct import `S` is private +} + +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr new file mode 100644 index 0000000000000..6e77808855a6c --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob-priv.stderr @@ -0,0 +1,47 @@ +error[E0603]: struct import `S` is private + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:12:27 + | +LL | use crate::both::private::S; + | ^ private struct import + | +note: the struct import `S` is defined here... + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:8:24 + | +LL | pub(super) use crate::m::*; + | ^^^^^^^^^^^ +note: ...and refers to the struct `S` which is defined here + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:2:5 + | +LL | pub struct S {} + | ^^^^^^^^^^^^ you could import this directly +help: import `S` through the re-export + | +LL - use crate::both::private::S; +LL + use m::S; + | + +error[E0603]: struct import `S` is private + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:17:31 + | +LL | use crate::both::private::S; + | ^ private struct import + | +note: the struct import `S` is defined here... + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:8:24 + | +LL | pub(super) use crate::m::*; + | ^^^^^^^^^^^ +note: ...and refers to the struct `S` which is defined here + --> $DIR/ambiguous-import-visibility-globglob-priv.rs:2:5 + | +LL | pub struct S {} + | ^^^^^^^^^^^^ you could import this directly +help: import `S` through the re-export + | +LL - use crate::both::private::S; +LL + use m::S; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/ambiguous-import-visibility-globglob.rs b/tests/ui/imports/ambiguous-import-visibility-globglob.rs new file mode 100644 index 0000000000000..5af32abd1c600 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-globglob.rs @@ -0,0 +1,39 @@ +//@ check-pass + +// FIXME: should report "ambiguous import visibility" in all the cases below. + +mod m { + pub struct S {} +} + +mod min_vis_first { + use crate::m::*; + pub(crate) use crate::m::*; + pub use crate::m::*; + + pub use self::S as S1; + pub(crate) use self::S as S2; + use self::S as S3; // OK +} + +mod mid_vis_first { + pub(crate) use crate::m::*; + use crate::m::*; + pub use crate::m::*; + + pub use self::S as S1; + pub(crate) use self::S as S2; + use self::S as S3; // OK +} + +mod max_vis_first { + pub use crate::m::*; + use crate::m::*; + pub(crate) use crate::m::*; + + pub use self::S as S1; + pub(crate) use self::S as S2; + use self::S as S3; // OK +} + +fn main() {} diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr new file mode 100644 index 0000000000000..e09c193f5e6ba --- /dev/null +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -0,0 +1,27 @@ +error[E0423]: expected value, found struct `S` + --> $DIR/private-from-decl-macro.rs:27:17 + | +LL | pub struct S {} + | --------------- `S` defined here +... +LL | let s = S; + | ^ + | +note: constant `m::S` exists but is inaccessible + --> $DIR/private-from-decl-macro.rs:10:5 + | +LL | const S: u8 = 0; + | ^^^^^^^^^^^^^^^^ not accessible +help: use struct literal syntax instead + | +LL | let s = S {}; + | ++ +help: a local variable with a similar name exists (notice the capitalization) + | +LL - let s = S; +LL + let s = s; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/imports/private-from-decl-macro.rs b/tests/ui/imports/private-from-decl-macro.rs new file mode 100644 index 0000000000000..cdb3bb40ef7b5 --- /dev/null +++ b/tests/ui/imports/private-from-decl-macro.rs @@ -0,0 +1,35 @@ +//@ revisions: pass fail +//@[pass] check-pass + +#![feature(decl_macro)] + +mod m { + // Name in two namespaces, one public, one private. + // The private name is filtered away when importing, even from a macro 2.0 + pub struct S {} + const S: u8 = 0; + + pub macro mac_single($S:ident) { + use crate::m::$S; + } + + pub macro mac_glob() { + use crate::m::*; + } +} + +mod single { + crate::m::mac_single!(S); + + fn check() { + let s = S {}; + #[cfg(fail)] + let s = S; //[fail]~ ERROR expected value, found struct `S` + } +} + +mod glob { + crate::m::mac_glob!(); +} + +fn main() {} diff --git a/tests/ui/privacy/restricted/decl-macros.rs b/tests/ui/privacy/restricted/decl-macros.rs new file mode 100644 index 0000000000000..2e4dbddc8a872 --- /dev/null +++ b/tests/ui/privacy/restricted/decl-macros.rs @@ -0,0 +1,15 @@ +#![feature(decl_macro)] + +mod m { + pub macro mac() { + struct A {} + pub(self) struct B {} //~ ERROR visibilities can only be restricted to ancestor modules + pub(in crate::m) struct C {} //~ ERROR visibilities can only be restricted to ancestor modules + } +} + +mod n { + crate::m::mac!(); +} + +fn main() {} diff --git a/tests/ui/privacy/restricted/decl-macros.stderr b/tests/ui/privacy/restricted/decl-macros.stderr new file mode 100644 index 0000000000000..c932bb5fe9416 --- /dev/null +++ b/tests/ui/privacy/restricted/decl-macros.stderr @@ -0,0 +1,25 @@ +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/decl-macros.rs:6:13 + | +LL | pub(self) struct B {} + | ^^^^ +... +LL | crate::m::mac!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0742]: visibilities can only be restricted to ancestor modules + --> $DIR/decl-macros.rs:7:16 + | +LL | pub(in crate::m) struct C {} + | ^^^^^^^^ +... +LL | crate::m::mac!(); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0742`. diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.rs b/tests/ui/pub/pub-reexport-priv-extern-crate.rs index 9d615be30f450..bc91cf4bc7551 100644 --- a/tests/ui/pub/pub-reexport-priv-extern-crate.rs +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.rs @@ -4,6 +4,8 @@ pub use core as reexported_core; //~ ERROR `core` is private and cannot be re-ex mod foo1 { extern crate core; + pub use self::core as core2; //~ ERROR extern crate `core` is private and cannot be re-exported + //~^ WARN this was previously accepted } mod foo2 { @@ -17,4 +19,7 @@ mod baz { pub use crate::foo2::bar::core; //~ ERROR crate import `core` is private } -fn main() {} +fn main() { + // Check that `foo1::core2` has the reexport's visibility and is accessible. + foo1::core2::mem::drop(()); +} diff --git a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr index dbb080e1b0940..1b8279c643318 100644 --- a/tests/ui/pub/pub-reexport-priv-extern-crate.stderr +++ b/tests/ui/pub/pub-reexport-priv-extern-crate.stderr @@ -1,5 +1,5 @@ error[E0603]: crate import `core` is private - --> $DIR/pub-reexport-priv-extern-crate.rs:10:22 + --> $DIR/pub-reexport-priv-extern-crate.rs:12:22 | LL | use crate::foo1::core; | ^^^^ private crate import @@ -11,13 +11,13 @@ LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ error[E0603]: crate import `core` is private - --> $DIR/pub-reexport-priv-extern-crate.rs:17:31 + --> $DIR/pub-reexport-priv-extern-crate.rs:19:31 | LL | pub use crate::foo2::bar::core; | ^^^^ private crate import | note: the crate import `core` is defined here - --> $DIR/pub-reexport-priv-extern-crate.rs:12:9 + --> $DIR/pub-reexport-priv-extern-crate.rs:14:9 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,20 @@ help: consider making the `extern crate` item publicly accessible LL | pub extern crate core; | +++ -error: aborting due to 3 previous errors +error[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/pub-reexport-priv-extern-crate.rs:7:13 + | +LL | pub use self::core as core2; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0365, E0603. For more information about an error, try `rustc --explain E0365`. @@ -55,3 +68,18 @@ help: consider making the `extern crate` item publicly accessible LL | pub extern crate core; | +++ +Future breakage diagnostic: +error[E0365]: extern crate `core` is private and cannot be re-exported + --> $DIR/pub-reexport-priv-extern-crate.rs:7:13 + | +LL | pub use self::core as core2; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 + = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default +help: consider making the `extern crate` item publicly accessible + | +LL | pub extern crate core; + | +++ + diff --git a/tests/ui/resolve/decl-macro-use-no-ice.rs b/tests/ui/resolve/decl-macro-use-no-ice.rs index 39b9cb03fea0d..ec103ab3b2080 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.rs +++ b/tests/ui/resolve/decl-macro-use-no-ice.rs @@ -11,7 +11,7 @@ mod foo { pub macro m() { use f; //~ ERROR `f` is private, and cannot be re-exported - f!(); //~ ERROR macro import `f` is private + f!(); } } diff --git a/tests/ui/resolve/decl-macro-use-no-ice.stderr b/tests/ui/resolve/decl-macro-use-no-ice.stderr index 9fb75b48b428c..619a5737090e0 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.stderr +++ b/tests/ui/resolve/decl-macro-use-no-ice.stderr @@ -17,31 +17,6 @@ LL | foo::m!(); | --------- in this macro invocation = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0603]: macro import `f` is private - --> $DIR/decl-macro-use-no-ice.rs:14:9 - | -LL | f!(); - | ^ private macro import -... -LL | foo::m!(); - | --------- in this macro invocation - | -note: the macro import `f` is defined here... - --> $DIR/decl-macro-use-no-ice.rs:13:13 - | -LL | use f; - | ^ -... -LL | foo::m!(); - | --------- in this macro invocation -note: ...and refers to the macro `f` which is defined here - --> $DIR/decl-macro-use-no-ice.rs:10:5 - | -LL | macro f() {} - | ^^^^^^^^^ - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0364, E0603. -For more information about an error, try `rustc --explain E0364`. +For more information about this error, try `rustc --explain E0364`. diff --git a/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.rs b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.rs new file mode 100644 index 0000000000000..7032633b290c4 --- /dev/null +++ b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.rs @@ -0,0 +1,20 @@ +//@ revisions: with-gate without-gate +//@ [with-gate] run-rustfix +//@ [without-gate] check-pass + +#![cfg_attr(with_gate, feature(anonymous_lifetime_in_impl_trait))] + +#![deny(single_use_lifetimes)] + +// https://github.com/rust-lang/rust/issues/153836 + +fn foo<'a>(x: impl IntoIterator) { +//[with-gate]~^ ERROR: lifetime parameter `'a` only used once [single_use_lifetimes] + for i in x { + dbg!(i); + } +} + +fn main() { + foo(&[1, 2, 3]); +} diff --git a/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.fixed b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.fixed new file mode 100644 index 0000000000000..49317a4e833f7 --- /dev/null +++ b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.fixed @@ -0,0 +1,20 @@ +//@ revisions: with-gate without-gate +//@ [with-gate] run-rustfix +//@ [without-gate] check-pass + +#![cfg_attr(with_gate, feature(anonymous_lifetime_in_impl_trait))] + +#![deny(single_use_lifetimes)] + +// https://github.com/rust-lang/rust/issues/153836 + +fn foo(x: impl IntoIterator) { +//[with-gate]~^ ERROR: lifetime parameter `'a` only used once [single_use_lifetimes] + for i in x { + dbg!(i); + } +} + +fn main() { + foo(&[1, 2, 3]); +} diff --git a/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.stderr b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.stderr new file mode 100644 index 0000000000000..ef6a3a7e7ddcb --- /dev/null +++ b/tests/ui/single-use-lifetime/anonymous_lifetime_in_impl_trait.with-gate.stderr @@ -0,0 +1,19 @@ +error: lifetime parameter `'a` only used once + --> $DIR/anonymous_lifetime_in_impl_trait.rs:11:8 + | +LL | fn foo<'a>(x: impl IntoIterator) { + | ^^ this lifetime... -- ...is used only here + | +note: the lint level is defined here + --> $DIR/anonymous_lifetime_in_impl_trait.rs:7:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ +help: elide the single-use lifetime + | +LL - fn foo<'a>(x: impl IntoIterator) { +LL + fn foo(x: impl IntoIterator) { + | + +error: aborting due to 1 previous error +