mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Auto merge of #155552 - JonathanBrouwer:rollup-JKIpTuW, r=JonathanBrouwer
Rollup of 11 pull requests Successful merges: - rust-lang/rust#154654 (Move `std::io::ErrorKind` to `core::io`) - rust-lang/rust#145270 (Fix an ICE observed with an explicit tail-call in a default trait method) - rust-lang/rust#154895 (borrowck: Apply `user_arg_index` nomenclature more broadly) - rust-lang/rust#155213 (resolve: Make sure visibilities of import declarations make sense) - rust-lang/rust#155346 (`single_use_lifetimes`: respect `anonymous_lifetime_in_impl_trait`) - rust-lang/rust#155517 (Add a test for Mach-O `#[link_section]` API inherited from LLVM) - rust-lang/rust#155549 (Remove some unnecessary lifetimes.) - rust-lang/rust#154248 (resolve : mark repr_simd as internal) - rust-lang/rust#154772 (slightly optimize the `non-camel-case-types` lint) - rust-lang/rust#155541 (Add `#[rust_analyzer::prefer_underscore_import]` to the traits in `rustc_type_ir::inherent`) - rust-lang/rust#155544 (bootstrap: Make "detected modifications" for download-rustc less verbose)
This commit is contained in:
@@ -499,18 +499,18 @@ fn give_name_if_anonymous_region_appears_in_arguments(
|
||||
fr: RegionVid,
|
||||
) -> Option<RegionName> {
|
||||
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 @@ fn give_name_if_anonymous_region_appears_in_arguments(
|
||||
|
||||
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
|
||||
|
||||
@@ -31,7 +31,7 @@ pub(crate) fn get_var_name_and_span_for_region(
|
||||
})
|
||||
.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 @@ pub(crate) fn get_upvar_name_and_span_for_region(
|
||||
///
|
||||
/// 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<usize> {
|
||||
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 @@ pub(crate) fn get_argument_name_and_span_for_region(
|
||||
&self,
|
||||
body: &Body<'tcx>,
|
||||
local_names: &IndexSlice<Local, Option<Symbol>>,
|
||||
argument_index: usize,
|
||||
user_arg_index: usize,
|
||||
) -> (Option<Symbol>, 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];
|
||||
|
||||
@@ -107,7 +107,7 @@ fn on_successor_discovered(&mut self, current_node: LocalizedNode, successor: Lo
|
||||
/// - 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<()> {
|
||||
|
||||
@@ -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<Ty<'tcx>>,
|
||||
|
||||
@@ -303,6 +303,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(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 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(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.
|
||||
|
||||
@@ -1901,14 +1901,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
struct FnCallDiagCtxt<'a, 'b, 'tcx> {
|
||||
arg_matching_ctxt: ArgMatchingCtxt<'a, 'b, 'tcx>,
|
||||
struct FnCallDiagCtxt<'a, 'tcx> {
|
||||
arg_matching_ctxt: ArgMatchingCtxt<'a, 'tcx>,
|
||||
errors: Vec<Error<'tcx>>,
|
||||
matched_inputs: IndexVec<ExpectedIdx, Option<ProvidedIdx>>,
|
||||
}
|
||||
|
||||
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<ProvidedIdx, Compatibility<'tcx>>,
|
||||
formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
|
||||
@@ -2629,7 +2629,7 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
|
||||
(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,
|
||||
@@ -2805,22 +2805,22 @@ fn maybe_suggest_expect_for_unwrap(&self, provided_ty: Ty<'tcx>) -> Option<Span>
|
||||
}
|
||||
}
|
||||
|
||||
struct ArgMatchingCtxt<'a, 'b, 'tcx> {
|
||||
args_ctxt: ArgsCtxt<'a, 'b, 'tcx>,
|
||||
struct ArgMatchingCtxt<'a, 'tcx> {
|
||||
args_ctxt: ArgsCtxt<'a, 'tcx>,
|
||||
provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, 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<ProvidedIdx, Compatibility<'tcx>>,
|
||||
formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
|
||||
@@ -2951,23 +2951,23 @@ fn remove_idx_is_perfect(&self, idx: usize) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
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<ProvidedIdx, Compatibility<'tcx>>,
|
||||
formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
provided_args: IndexVec<ProvidedIdx, &'tcx Expr<'tcx>>,
|
||||
@@ -2978,7 +2978,7 @@ fn new(
|
||||
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,
|
||||
@@ -3085,8 +3085,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<ProvidedIdx, Compatibility<'tcx>>,
|
||||
formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
|
||||
@@ -3100,17 +3100,17 @@ struct CallCtxt<'a, 'b, 'tcx> {
|
||||
callee_ty: Option<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
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<ProvidedIdx, Compatibility<'tcx>>,
|
||||
formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
|
||||
provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
|
||||
@@ -3120,7 +3120,7 @@ fn new(
|
||||
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, ..) => {
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
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 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
}
|
||||
}
|
||||
|
||||
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>,
|
||||
|
||||
@@ -958,15 +958,15 @@ fn perform_2229_migration_analysis(
|
||||
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<NeededMigration>,
|
||||
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,
|
||||
|
||||
@@ -156,15 +156,15 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_
|
||||
}
|
||||
}
|
||||
|
||||
struct WrongDefaultImpl<'a, 'hir, 'tcx> {
|
||||
struct WrongDefaultImpl<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
type_def_id: DefId,
|
||||
orig_fields: FxHashMap<Symbol, &'a hir::FieldDef<'hir>>,
|
||||
fields: &'a [hir::ExprField<'hir>],
|
||||
orig_fields: FxHashMap<Symbol, &'a hir::FieldDef<'tcx>>,
|
||||
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 =
|
||||
|
||||
@@ -51,31 +51,27 @@
|
||||
/// 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::<Vec<_>>().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 {
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
SHADOWING_SUPERTRAIT_ITEMS,
|
||||
SINGLE_USE_LIFETIMES,
|
||||
STABLE_FEATURES,
|
||||
TAIL_CALL_TRACK_CALLER,
|
||||
TAIL_EXPR_DROP_ORDER,
|
||||
TEST_UNSTABLE_LINT,
|
||||
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
|
||||
|
||||
@@ -61,14 +61,14 @@ pub fn from_cli(tcx: TyCtxt<'_>) -> Self {
|
||||
/// 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 @@ pub fn set_show_pass_num(mut self) -> Self {
|
||||
}
|
||||
|
||||
#[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 @@ pub fn set_disambiguator(mut self, disambiguator: &'dis dyn Display) -> Self {
|
||||
#[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<DefId>) -> Vec<DefId> {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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,
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
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 @@ fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
|
||||
// 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 @@ fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
|
||||
// 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 @@ fn check_tail_call(&mut self, call: &Expr<'_>, expr: &Expr<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<'_>) {
|
||||
|
||||
@@ -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<Span>,
|
||||
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"));
|
||||
|
||||
@@ -37,14 +37,14 @@ struct StaticSccIdx {}
|
||||
// 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<DefId>,
|
||||
// contains for each `MonoItem` the `MonoItem`s it uses
|
||||
used_map: &'b UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
used_map: &'a UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
|
||||
}
|
||||
|
||||
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 @@ fn num_nodes(&self) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
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<Item = StaticNodeIdx> {
|
||||
let def_id = self.statics[node_idx.index()];
|
||||
self.used_map[&MonoItem::Static(def_id)].iter().filter_map(|&mono_item| match mono_item {
|
||||
|
||||
@@ -251,16 +251,15 @@ pub(crate) fn build_reduced_graph(
|
||||
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 @@ pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) {
|
||||
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 @@ fn build_reduced_graph_for_external_crate_res(
|
||||
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);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
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::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 @@ fn resolve_ident_in_scope_set_inner<'r>(
|
||||
// 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 @@ fn resolve_ident_in_scope_set_inner<'r>(
|
||||
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 @@ fn maybe_push_ambiguity(
|
||||
decl: Decl<'ra>,
|
||||
scope: Scope<'ra>,
|
||||
innermost_results: &[(Decl<'ra>, Scope<'ra>)],
|
||||
import_vis: Option<Visibility>,
|
||||
import: Option<ImportSummary>,
|
||||
) -> 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;
|
||||
};
|
||||
|
||||
@@ -37,8 +37,9 @@
|
||||
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 @@ pub(crate) fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport {
|
||||
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<NodeId> {
|
||||
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<NodeId> {
|
||||
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 @@ pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> De
|
||||
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 @@ fn select_glob_decl(
|
||||
}
|
||||
} 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 @@ pub(crate) fn try_plant_decl_into_local_module(
|
||||
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 @@ pub(crate) fn try_plant_decl_into_local_module(
|
||||
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 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
|
||||
&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 @@ fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportErr
|
||||
// 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,
|
||||
|
||||
@@ -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 @@ fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||
}
|
||||
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 @@ fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
|
||||
LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
|
||||
| LifetimeRibKind::ImplTrait
|
||||
| LifetimeRibKind::Elided(_)
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::ConcreteAnonConst(_)
|
||||
@@ -1780,6 +1784,15 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
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 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
| LifetimeRibKind::Generics { .. }
|
||||
| LifetimeRibKind::ElisionFailure
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::ImplTrait
|
||||
| LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
|
||||
}
|
||||
}
|
||||
@@ -2000,7 +2014,9 @@ fn resolve_anonymous_lifetime(
|
||||
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 @@ fn resolve_elided_lifetimes_in_path(
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -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<Visibility> = None,
|
||||
/// Some import data, in case we are resolving an import's final segment.
|
||||
import: Option<ImportSummary> = None,
|
||||
}
|
||||
|
||||
impl Finalize {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
self as ty, ClauseKind, CollectAndApply, FieldInfo, Interner, PredicateKind, UpcastFrom,
|
||||
};
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Ty<I: Interner<Ty = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -195,6 +196,7 @@ fn is_guaranteed_unsized_raw(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Tys<I: Interner<Tys = Self>>:
|
||||
Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
|
||||
{
|
||||
@@ -203,6 +205,7 @@ pub trait Tys<I: Interner<Tys = Self>>:
|
||||
fn output(self) -> I::Ty;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait FSigKind<I: Interner<FSigKind = Self>>: Copy + Debug + Hash + Eq {
|
||||
/// The identity function.
|
||||
fn fn_sig_kind(self) -> Self;
|
||||
@@ -220,6 +223,7 @@ pub trait FSigKind<I: Interner<FSigKind = Self>>: Copy + Debug + Hash + Eq {
|
||||
fn c_variadic(self) -> bool;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
|
||||
/// The identity function.
|
||||
fn abi(self) -> Self;
|
||||
@@ -237,6 +241,7 @@ pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
|
||||
fn unpack_abi(abi_index: u8) -> Self;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
|
||||
/// The `safe` safety mode.
|
||||
fn safe() -> Self;
|
||||
@@ -251,6 +256,7 @@ pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
|
||||
fn prefix_str(self) -> &'static str;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Region<I: Interner<Region = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -276,6 +282,7 @@ fn is_bound(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Const<I: Interner<Const = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -320,19 +327,23 @@ fn is_ct_error(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
|
||||
fn ty(self) -> I::Ty;
|
||||
fn valtree(self) -> I::ValTree;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
|
||||
fn args(self) -> I::GenericArgs;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
||||
fn count(&self) -> usize;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait GenericArg<I: Interner<GenericArg = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -387,6 +398,7 @@ fn is_non_region_infer(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Term<I: Interner<Term = Self>>:
|
||||
Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
|
||||
{
|
||||
@@ -434,6 +446,7 @@ fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
||||
Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
|
||||
{
|
||||
@@ -473,6 +486,7 @@ fn as_coroutine(self) -> ty::CoroutineArgs<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Predicate<I: Interner<Predicate = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -528,6 +542,7 @@ fn allow_normalization(self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Clause<I: Interner<Clause = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -577,6 +592,7 @@ fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>
|
||||
fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Clauses<I: Interner<Clauses = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
@@ -589,16 +605,19 @@ pub trait Clauses<I: Interner<Clauses = Self>>:
|
||||
{
|
||||
}
|
||||
|
||||
#[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<I: Interner>: Copy + Debug + Hash + Eq {
|
||||
fn def_id(self) -> I::AdtId;
|
||||
|
||||
@@ -635,10 +654,12 @@ fn sizedness_constraint(
|
||||
fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||
fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Features<I: Interner>: Copy {
|
||||
fn generic_const_exprs(self) -> bool;
|
||||
|
||||
@@ -647,6 +668,7 @@ pub trait Features<I: Interner>: Copy {
|
||||
fn feature_bound_holds_in_crate(self, symbol: I::Symbol) -> bool;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||
fn is_local(self) -> bool;
|
||||
|
||||
@@ -663,6 +685,7 @@ impl<I: Interner, T: DefId<I> + Into<I::DefId> + TryFrom<I::DefId, Error: std::f
|
||||
{
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait BoundExistentialPredicates<I: Interner>:
|
||||
Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
|
||||
{
|
||||
@@ -677,10 +700,12 @@ fn projection_bounds(
|
||||
) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
|
||||
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 @@ fn as_slice(&self) -> &[Self::Item] {
|
||||
}
|
||||
}
|
||||
|
||||
#[rust_analyzer::prefer_underscore_import]
|
||||
pub trait Symbol<I>: Copy + Hash + PartialEq + Eq + Debug {
|
||||
fn is_kw_underscore_lifetime(self) -> bool;
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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<Self> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -305,7 +305,7 @@ pub mod autodiff {
|
||||
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;
|
||||
|
||||
@@ -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)]
|
||||
|
||||
+4
-318
@@ -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<dyn error::Error + Send + Sync>,
|
||||
}
|
||||
|
||||
/// 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 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
|
||||
}
|
||||
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 @@ unsafe fn decode_repr<C, F>(ptr: NonNull<()>, make_custom: F) -> ErrorData<C>
|
||||
}
|
||||
}
|
||||
|
||||
// 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<ErrorKind> {
|
||||
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)
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2196,6 +2196,42 @@ pub fn check_stage0_version(
|
||||
}
|
||||
}
|
||||
|
||||
fn print_rustc_modifications(
|
||||
dwn_ctx: &DownloadContext<'_>,
|
||||
if_unchanged: bool,
|
||||
mut modifications: Vec<PathBuf>,
|
||||
) -> 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<DownloadContext<'a>>,
|
||||
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 => {
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// A regression test for <https://github.com/rust-lang/rust/issues/144985>.
|
||||
// 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);
|
||||
}
|
||||
@@ -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() {}
|
||||
@@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
||||
@@ -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() {}
|
||||
@@ -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() {}
|
||||
@@ -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`.
|
||||
@@ -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() {}
|
||||
@@ -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`.
|
||||
@@ -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() {}
|
||||
@@ -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() {}
|
||||
@@ -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`.
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
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(());
|
||||
}
|
||||
|
||||
@@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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;
|
||||
| +++
|
||||
|
||||
|
||||
@@ -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!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 1 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
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`.
|
||||
|
||||
@@ -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<Item = &'a i32>) {
|
||||
//[with-gate]~^ ERROR: lifetime parameter `'a` only used once [single_use_lifetimes]
|
||||
for i in x {
|
||||
dbg!(i);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(&[1, 2, 3]);
|
||||
}
|
||||
@@ -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<Item = &i32>) {
|
||||
//[with-gate]~^ ERROR: lifetime parameter `'a` only used once [single_use_lifetimes]
|
||||
for i in x {
|
||||
dbg!(i);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(&[1, 2, 3]);
|
||||
}
|
||||
@@ -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<Item = &'a i32>) {
|
||||
| ^^ 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<Item = &'a i32>) {
|
||||
LL + fn foo(x: impl IntoIterator<Item = &i32>) {
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Reference in New Issue
Block a user