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:
bors
2026-04-20 16:15:13 +00:00
55 changed files with 1142 additions and 605 deletions
@@ -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];
+2 -2
View File
@@ -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>>,
+2 -2
View File
@@ -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.
+27 -27
View File
@@ -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>,
+6 -6
View File
@@ -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 =
+14 -18
View File
@@ -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 {
+1
View File
@@ -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,
+10 -10
View File
@@ -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<'_>) {
+3 -3
View File
@@ -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);
+12 -14
View File
@@ -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;
};
+52 -19
View File
@@ -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,
+21 -3
View File
@@ -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)
+11 -2
View File
@@ -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 {
+26
View File
@@ -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
View File
@@ -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)]
+372
View File
@@ -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())
}
}
+3
View File
@@ -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;
+1 -1
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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),
}
}
+1 -64
View File
@@ -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)
+5
View File
@@ -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)]
+1 -1
View File
@@ -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))
}
}
+37 -18
View File
@@ -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 => {
+14
View File
@@ -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");
}
}
}
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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;
| +++
+1 -1
View File
@@ -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!();
}
}
+2 -27
View File
@@ -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