diff options
162 files changed, 2781 insertions, 2120 deletions
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index bf58e485158..bac411d1eb0 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core" } --compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.145", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.145", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 14fc23593f0..d94fc552528 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -132,10 +132,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if cx.sess().opts.optimize == config::OptLevel::No { return ty; } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { ty = ty.make_restrict() } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } ty diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 89e5cf1b8c6..bba19d06258 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 1631ecfeecf..fb0ca31c543 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -1,6 +1,7 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; +use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; @@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; -use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange}; use crate::base; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 570ef938dc4..1e1f577bb3a 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use gccjit::{ Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type, }; +use rustc_abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; @@ -18,7 +19,6 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, }; diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 86d3de225f7..3f6fdea9fb8 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -1,6 +1,7 @@ use std::ops::Range; use gccjit::{Location, RValue}; +use rustc_abi::Size; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; use rustc_data_structures::sync::Lrc; @@ -10,8 +11,7 @@ use rustc_middle::mir::{self, Body, SourceScope}; use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; -use rustc_target::abi::Size; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::builder::Builder; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index 442488b7fd6..7cdbe3c0c62 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -4,7 +4,7 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index fe6a65bed03..4a1db8d662a 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -3,12 +3,11 @@ //! 128-bit integers on 32-bit platforms and thus require to be handled manually. use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; +use rustc_abi::{Endian, ExternAbi}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::Endian; -use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; -use rustc_target::spec; +use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; use crate::builder::{Builder, ToGccComp}; use crate::common::{SignType, TypeReflection}; @@ -401,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 48606f5f91c..a1123fafe2f 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -7,6 +7,9 @@ use std::iter; #[cfg(feature = "master")] use gccjit::FunctionType; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; +#[cfg(feature = "master")] +use rustc_abi::ExternAbi; +use rustc_abi::HasDataLayout; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -25,11 +28,8 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::HasDataLayout; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::PanicStrategy; -#[cfg(feature = "master")] -use rustc_target::spec::abi::Abi; #[cfg(feature = "master")] use crate::abi::FnAbiGccExt; @@ -1238,7 +1238,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(*mut i8, *mut i8) -> ()` @@ -1249,7 +1249,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` @@ -1258,7 +1258,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.i32, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); cx.rust_try_fn.set(Some(rust_try)); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 1be452e5d05..12a7dab155b 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -3,6 +3,7 @@ use std::iter::FromIterator; use gccjit::{BinaryOp, RValue, ToRValue, Type}; #[cfg(feature = "master")] use gccjit::{ComparisonOp, UnaryOp}; +use rustc_abi::{Align, Size}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; #[cfg(feature = "master")] @@ -17,7 +18,6 @@ use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::{Align, Size}; use crate::builder::Builder; #[cfg(not(feature = "master"))] diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 4ea5544721d..cb08723431a 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -4,13 +4,13 @@ use std::convert::TryInto; #[cfg(feature = "master")] use gccjit::CType; use gccjit::{RValue, Struct, Type}; +use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, ty}; -use rustc_target::abi::{AddressSpace, Align, Integer, Size}; use crate::common::TypeReflection; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 0efdf36da48..8b8b54753e7 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -3,7 +3,9 @@ use std::fmt::Write; use gccjit::{Struct, Type}; use rustc_abi as abi; use rustc_abi::Primitive::*; -use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants}; +use rustc_abi::{ + BackendRepr, FieldsShape, Integer, PointeeInfo, Reg, Size, TyAbiInterface, Variants, +}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; @@ -11,8 +13,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; -use rustc_target::abi::TyAbiInterface; -use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; +use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 4a508fc0cf6..41f8465ae91 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -11,6 +11,15 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { } for id in tcx.hir_crate_items(()).opaques() { + if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } + | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = + tcx.hir().expect_opaque_ty(id).origin + && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) + && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() + { + continue; + } + let ty = tcx.type_of(id).instantiate_identity(); let span = tcx.def_span(id); tcx.dcx().emit_err(crate::errors::TypeOf { span, ty }); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 5d00ecbe918..65021a0cd11 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -831,7 +831,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // prim -> prim (Int(CEnum), Int(_)) => { - self.cenum_impl_drop_lint(fcx); + self.err_if_cenum_impl_drop(fcx); Ok(CastKind::EnumCast) } (Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast), @@ -1091,19 +1091,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } - fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { + fn err_if_cenum_impl_drop(&self, fcx: &FnCtxt<'a, 'tcx>) { if let ty::Adt(d, _) = self.expr_ty.kind() && d.has_dtor(fcx.tcx) { let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty); - fcx.tcx.emit_node_span_lint( - lint::builtin::CENUM_IMPL_DROP_CAST, - self.expr.hir_id, - self.span, - errors::CastEnumDrop { expr_ty, cast_ty }, - ); + fcx.dcx().emit_err(errors::CastEnumDrop { span: self.span, expr_ty, cast_ty }); } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 052adaa69b2..143736072aa 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -677,9 +677,11 @@ pub(crate) struct CannotCastToBool<'tcx> { pub help: CannotCastToBoolHelp, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag(hir_typeck_cast_enum_drop)] pub(crate) struct CastEnumDrop<'tcx> { + #[primary_span] + pub span: Span, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 778997045f0..5ce9e0556b4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1626,6 +1626,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() { ty::Int(_) | ty::Uint(_) => Some(ty), + // These exist to direct casts like `0x61 as char` to use + // the right integer type to cast from, instead of falling back to + // i32 due to no further constraints. ty::Char => Some(tcx.types.u8), ty::RawPtr(..) => Some(tcx.types.usize), ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize), diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c947ecde656..2e7415cec5d 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -570,8 +570,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { let ty = match <.kind { - rustc_hir::PatExprKind::Lit { lit, .. } => { - self.check_expr_lit(lit, Expectation::NoExpectation) + rustc_hir::PatExprKind::Lit { lit, negated } => { + let ty = self.check_expr_lit(lit, Expectation::NoExpectation); + if *negated { + self.register_bound( + ty, + self.tcx.require_lang_item(LangItem::Neg, Some(lt.span)), + ObligationCause::dummy_with_span(lt.span), + ); + } + ty } rustc_hir::PatExprKind::ConstBlock(c) => { self.check_expr_const_block(c, Expectation::NoExpectation) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ad15b764bcc..2cd67cc4da2 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -137,6 +137,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { expected, ty::Contravariant, actual, + self.cause.span, ) .map(|goals| self.goals_to_obligations(goals)) } else { @@ -163,8 +164,15 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: ToTrace<'tcx>, { if self.infcx.next_trait_solver { - NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual) - .map(|goals| self.goals_to_obligations(goals)) + NextSolverRelate::relate( + self.infcx, + self.param_env, + expected, + ty::Covariant, + actual, + self.cause.span, + ) + .map(|goals| self.goals_to_obligations(goals)) } else { let mut op = TypeRelating::new( self.infcx, @@ -208,8 +216,15 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: Relate<TyCtxt<'tcx>>, { if self.infcx.next_trait_solver { - NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual) - .map(|goals| self.goals_to_obligations(goals)) + NextSolverRelate::relate( + self.infcx, + self.param_env, + expected, + ty::Invariant, + actual, + self.cause.span, + ) + .map(|goals| self.goals_to_obligations(goals)) } else { let mut op = TypeRelating::new( self.infcx, diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 69ab0e69e21..eae69ec3e0f 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::combine::PredicateEmittingRelation; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{DUMMY_SP, ErrorGuaranteed}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; @@ -203,23 +203,23 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.probe(|_| probe()) } - fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) { + fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, span: Span) { self.inner.borrow_mut().unwrap_region_constraints().make_subregion( - SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + SubregionOrigin::RelateRegionParamBound(span, None), sub, sup, ); } - fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) { + fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) { self.inner.borrow_mut().unwrap_region_constraints().make_eqregion( - SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + SubregionOrigin::RelateRegionParamBound(span, None), a, b, ); } - fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) { - self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy()); + fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) { + self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span)); } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 83a168c3f44..fd6c17735c5 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -595,6 +595,11 @@ fn register_builtins(store: &mut LintStore) { <https://github.com/rust-lang/rust/pull/125380> for more information", ); store.register_removed("unsupported_calling_conventions", "converted into hard error"); + store.register_removed( + "cenum_impl_drop_cast", + "converted into hard error, \ + see <https://github.com/rust-lang/rust/issues/73333> for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5b4a1f174cb..9561b3de5f8 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -27,7 +27,6 @@ declare_lint_pass! { BARE_TRAIT_OBJECTS, BINDINGS_WITH_VARIANT_NAME, BREAK_WITH_LABEL_AND_LOOP, - CENUM_IMPL_DROP_CAST, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED, @@ -2613,58 +2612,6 @@ declare_lint! { } declare_lint! { - /// The `cenum_impl_drop_cast` lint detects an `as` cast of a field-less - /// `enum` that implements [`Drop`]. - /// - /// [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html - /// - /// ### Example - /// - /// ```rust,compile_fail - /// # #![allow(unused)] - /// enum E { - /// A, - /// } - /// - /// impl Drop for E { - /// fn drop(&mut self) { - /// println!("Drop"); - /// } - /// } - /// - /// fn main() { - /// let e = E::A; - /// let i = e as u32; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Casting a field-less `enum` that does not implement [`Copy`] to an - /// integer moves the value without calling `drop`. This can result in - /// surprising behavior if it was expected that `drop` should be called. - /// Calling `drop` automatically would be inconsistent with other move - /// operations. Since neither behavior is clear or consistent, it was - /// decided that a cast of this nature will no longer be allowed. - /// - /// This is a [future-incompatible] lint to transition this to a hard error - /// in the future. See [issue #73333] for more details. - /// - /// [future-incompatible]: ../index.md#future-incompatible-lints - /// [issue #73333]: https://github.com/rust-lang/rust/issues/73333 - /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html - pub CENUM_IMPL_DROP_CAST, - Deny, - "a C-like enum implementing Drop is cast", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #73333 <https://github.com/rust-lang/rust/issues/73333>", - }; -} - -declare_lint! { /// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer /// and a pointer. /// diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 0f408375e05..3cd148cd442 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -142,10 +142,6 @@ impl<'tcx, R> QueryResponse<'tcx, R> { pub type QueryOutlivesConstraint<'tcx> = (ty::OutlivesPredicate<'tcx, GenericArg<'tcx>>, ConstraintCategory<'tcx>); -TrivialTypeTraversalImpls! { - crate::infer::canonical::Certainty, -} - #[derive(Default)] pub struct CanonicalParamEnvCache<'tcx> { map: Lock< diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 3eb563d7d6e..c32cf5f8253 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -163,6 +163,7 @@ impl<'tcx> graph::Predecessors for BasicBlocks<'tcx> { } } +// Done here instead of in `structural_impls.rs` because `Cache` is private, as is `basic_blocks`. TrivialTypeTraversalImpls! { Cache } impl<S: Encoder> Encodable<S> for Cache { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 8c085fa310a..1222ba052cc 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -95,8 +95,6 @@ impl From<ReportedErrorInfo> for ErrorGuaranteed { } } -TrivialTypeTraversalImpls! { ErrorHandled } - pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>; pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index cfb78e5dddf..68d5e5f4dd2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -34,7 +34,6 @@ use self::visit::TyContext; use crate::mir::interpret::{AllocRange, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{ @@ -59,7 +58,6 @@ pub mod tcx; mod terminator; pub mod traversal; -mod type_foldable; pub mod visit; pub use consts::*; @@ -927,8 +925,6 @@ pub enum BindingForm<'tcx> { RefForGuard, } -TrivialTypeTraversalImpls! { BindingForm<'tcx> } - mod binding_form_impl { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_query_system::ich::StableHashingContext; diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs deleted file mode 100644 index 9893dd0484c..00000000000 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! `TypeFoldable` implementations for MIR types - -use rustc_ast::InlineAsmTemplatePiece; -use rustc_hir::UnsafeBinderCastKind; -use rustc_hir::def_id::LocalDefId; - -use super::*; - -TrivialTypeTraversalImpls! { - BlockTailInfo, - MirPhase, - SourceInfo, - FakeReadCause, - RetagKind, - SourceScope, - SourceScopeLocalData, - UserTypeAnnotationIndex, - BorrowKind, - RawPtrKind, - CastKind, - BasicBlock, - SwitchTargets, - CoroutineKind, - CoroutineSavedLocal, - UnsafeBinderCastKind, -} - -TrivialTypeTraversalImpls! { - ConstValue<'tcx>, - NullOp<'tcx>, -} - -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] { - fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( - self, - _folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self) - } -} - -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] { - fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( - self, - _folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self) - } -} - -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> { - fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( - self, - _folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self) - } -} - -impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> { - fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v)) - } -} diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index d0ce4e6242e..1314a235610 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -427,10 +427,6 @@ pub enum IsConstable { Ctor, } -TrivialTypeTraversalAndLiftImpls! { - IsConstable, -} - /// The 'location' at which we try to perform HIR-based wf checking. /// This information is used to obtain an `hir::Ty`, which /// we can walk in order to obtain precise spans for any diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 094fc62afbb..b7cd545d02d 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -260,8 +260,6 @@ impl From<ErrorGuaranteed> for OverflowError { } } -TrivialTypeTraversalImpls! { OverflowError } - impl<'tcx> From<OverflowError> for SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { match overflow_error { diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 002d3819621..c9b9ec771b3 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,8 +30,6 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable { } } -TrivialTypeTraversalImpls! { NotConstEvaluatable } - pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<'tcx, ty::Const<'tcx>>>, ErrorGuaranteed>; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 86248b495cd..1a98db54581 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -76,11 +76,11 @@ use crate::traits::solve::{ }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, BoundConstness, Clause, Clauses, Const, GenericArg, - GenericArgs, GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, - ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, - PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, - TyKind, TyVid, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs, + GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy, + Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, + PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, + Visibility, }; #[allow(rustc::usage_of_ty_tykind)] @@ -2243,21 +2243,23 @@ macro_rules! nop_list_lift { }; } -nop_lift! {type_; Ty<'a> => Ty<'tcx>} -nop_lift! {region; Region<'a> => Region<'tcx>} -nop_lift! {const_; Const<'a> => Const<'tcx>} -nop_lift! {pat; Pattern<'a> => Pattern<'tcx>} -nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} -nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} -nop_lift! {predicate; Clause<'a> => Clause<'tcx>} -nop_lift! {layout; Layout<'a> => Layout<'tcx>} - -nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>} -nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} -nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind} +nop_lift! { type_; Ty<'a> => Ty<'tcx> } +nop_lift! { region; Region<'a> => Region<'tcx> } +nop_lift! { const_; Const<'a> => Const<'tcx> } +nop_lift! { pat; Pattern<'a> => Pattern<'tcx> } +nop_lift! { const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx> } +nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> } +nop_lift! { predicate; Clause<'a> => Clause<'tcx> } +nop_lift! { layout; Layout<'a> => Layout<'tcx> } + +nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> } +nop_list_lift! { + poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx> +} +nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind } // This is the impl for `&'a GenericArgs<'a>`. -nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>} +nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> } macro_rules! nop_slice_lift { ($ty:ty => $lifted:ty) => { @@ -2277,11 +2279,7 @@ macro_rules! nop_slice_lift { }; } -nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>} - -TrivialLiftImpls! { - ImplPolarity, PredicatePolarity, Promoted, BoundConstness, -} +nop_slice_lift! { ty::ValTree<'a> => ty::ValTree<'tcx> } macro_rules! sty_debug_print { ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{ diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 03b26b44538..c33f952fc86 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -6,15 +6,18 @@ use std::fmt::{self, Debug}; use rustc_abi::TyAndLayout; +use rustc_ast::InlineAsmTemplatePiece; use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; +use rustc_hir::def_id::LocalDefId; +use rustc_span::Span; use rustc_span::source_map::Spanned; use rustc_type_ir::ConstKind; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Pattern, Region}; -use crate::mir::interpret; +use crate::mir::PlaceElem; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; @@ -221,76 +224,89 @@ impl<'tcx> fmt::Debug for Region<'tcx> { // copy...), just add them to one of these lists as appropriate. // For things for which the type library provides traversal implementations -// for all Interners, we only need to provide a Lift implementation: +// for all Interners, we only need to provide a Lift implementation. TrivialLiftImpls! { - (), - bool, - usize, - u64, + (), + bool, + usize, + u64, + // tidy-alphabetical-start + crate::mir::interpret::AllocId, + crate::mir::interpret::Scalar, + crate::mir::Promoted, + rustc_abi::ExternAbi, + rustc_abi::Size, + rustc_hir::Safety, + rustc_type_ir::BoundConstness, + rustc_type_ir::PredicatePolarity, + // tidy-alphabetical-end } // For some things about which the type library does not know, or does not // provide any traversal implementations, we need to provide a traversal // implementation (only for TyCtxt<'_> interners). TrivialTypeTraversalImpls! { - ::rustc_abi::FieldIdx, - ::rustc_abi::VariantIdx, - crate::middle::region::Scope, - ::rustc_ast::InlineAsmOptions, - ::rustc_ast::InlineAsmTemplatePiece, - ::rustc_ast::NodeId, - ::rustc_hir::def::Res, - ::rustc_hir::def_id::LocalDefId, - ::rustc_hir::ByRef, - ::rustc_hir::HirId, - ::rustc_hir::MatchSource, - ::rustc_target::asm::InlineAsmRegOrRegClass, - crate::mir::coverage::BlockMarkerId, - crate::mir::coverage::CounterId, - crate::mir::coverage::ExpressionId, - crate::mir::coverage::ConditionId, + // tidy-alphabetical-start + crate::infer::canonical::Certainty, + crate::mir::BasicBlock, + crate::mir::BindingForm<'tcx>, + crate::mir::BlockTailInfo, + crate::mir::BorrowKind, + crate::mir::CastKind, + crate::mir::ConstValue<'tcx>, + crate::mir::CoroutineSavedLocal, + crate::mir::FakeReadCause, crate::mir::Local, + crate::mir::MirPhase, + crate::mir::NullOp<'tcx>, crate::mir::Promoted, + crate::mir::RawPtrKind, + crate::mir::RetagKind, + crate::mir::SourceInfo, + crate::mir::SourceScope, + crate::mir::SourceScopeLocalData, + crate::mir::SwitchTargets, + crate::traits::IsConstable, + crate::traits::OverflowError, + crate::ty::abstract_const::NotConstEvaluatable, crate::ty::adjustment::AutoBorrowMutability, + crate::ty::adjustment::PointerCoercion, crate::ty::AdtKind, - crate::ty::BoundRegion, - // Including `BoundRegionKind` is a *bit* dubious, but direct - // references to bound region appear in `ty::Error`, and aren't - // really meant to be folded. In general, we can only fold a fully - // general `Region`. - crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, + crate::ty::BoundRegion, + crate::ty::BoundVar, crate::ty::Placeholder<crate::ty::BoundRegion>, crate::ty::Placeholder<crate::ty::BoundTy>, crate::ty::Placeholder<ty::BoundVar>, - crate::ty::LateParamRegion, - crate::ty::adjustment::PointerCoercion, - ::rustc_span::Ident, - ::rustc_span::Span, - ::rustc_span::Symbol, - ty::BoundVar, - ty::ValTree<'tcx>, + crate::ty::UserTypeAnnotationIndex, + crate::ty::ValTree<'tcx>, + rustc_abi::FieldIdx, + rustc_abi::VariantIdx, + rustc_ast::InlineAsmOptions, + rustc_ast::InlineAsmTemplatePiece, + rustc_hir::CoroutineKind, + rustc_hir::def_id::LocalDefId, + rustc_hir::HirId, + rustc_hir::MatchSource, + rustc_span::Ident, + rustc_span::Span, + rustc_span::Symbol, + rustc_target::asm::InlineAsmRegOrRegClass, + // tidy-alphabetical-end } + // For some things about which the type library does not know, or does not // provide any traversal implementations, we need to provide a traversal // implementation and a lift implementation (the former only for TyCtxt<'_> // interners). TrivialTypeTraversalAndLiftImpls! { - ::rustc_hir::def_id::DefId, - crate::ty::ClosureKind, + // tidy-alphabetical-start + crate::ty::instance::ReifyReason, crate::ty::ParamConst, crate::ty::ParamTy, - crate::ty::instance::ReifyReason, - interpret::AllocId, - interpret::CtfeProvenance, - interpret::Scalar, - rustc_abi::Size, -} - -TrivialLiftImpls! { - ::rustc_hir::Safety, - ::rustc_abi::ExternAbi, + rustc_hir::def_id::DefId, + // tidy-alphabetical-end } /////////////////////////////////////////////////////////////////////////// @@ -672,3 +688,39 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Debug + Clone> TypeFoldable<TyCtxt<'t }) } } + +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + _folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self) + } +} + +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + _folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self) + } +} + +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + _folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self) + } +} + +impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> { + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v)) + } +} diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index e4e452aff75..84c9297e658 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -105,13 +105,12 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar)); } - let trunc = |n| { - let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { - Ok(layout) => layout.size, - Err(_) => { - tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) - } - }; + let trunc = |n, width: ty::UintTy| { + let width = width + .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) + .bit_width() + .unwrap(); + let width = Size::from_bits(width); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -145,9 +144,11 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) } - (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { - trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }) - } + (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui), + (ast::LitKind::Int(n, _), ty::Int(i)) => trunc( + if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, + i.to_unsigned(), + ), (ast::LitKind::Float(n, _), ty::Float(fty)) => { parse_float_into_constval(*n, *fty, neg).unwrap() } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 49db522cf0e..f303053390c 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,4 +1,5 @@ -use rustc_ast as ast; +use rustc_abi::Size; +use rustc_ast::{self as ast}; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::LitToConstInput; @@ -17,13 +18,12 @@ pub(crate) fn lit_to_const<'tcx>( return ty::Const::new_error(tcx, guar); } - let trunc = |n| { - let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { - Ok(layout) => layout.size, - Err(_) => { - tcx.dcx().bug(format!("couldn't compute width of literal: {:?}", lit_input.lit)) - } - }; + let trunc = |n, width: ty::UintTy| { + let width = width + .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) + .bit_width() + .unwrap(); + let width = Size::from_bits(width); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); @@ -55,9 +55,15 @@ pub(crate) fn lit_to_const<'tcx>( let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } - (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { - let scalar_int = - trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }); + (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => { + let scalar_int = trunc(n.get(), *ui); + ty::ValTree::from_scalar_int(scalar_int) + } + (ast::LitKind::Int(n, _), ty::Int(i)) => { + let scalar_int = trunc( + if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, + i.to_unsigned(), + ); ty::ValTree::from_scalar_int(scalar_int) } (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()), diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 2d2d50e62f9..a64941cce3a 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -4,15 +4,13 @@ use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; -pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized { - type Infcx: InferCtxtLike<Interner = <Self as SolverDelegate>::Interner>; +pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { + type Infcx: InferCtxtLike<Interner = Self::Interner>; type Interner: Interner; fn cx(&self) -> Self::Interner { (**self).cx() } - type Span: Copy; - fn build_with_canonical<V>( cx: Self::Interner, canonical: &ty::CanonicalQueryInput<Self::Interner, V>, @@ -23,7 +21,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size fn fresh_var_for_kind_with_span( &self, arg: <Self::Interner as Interner>::GenericArg, - span: Self::Span, + span: <Self::Interner as Interner>::Span, ) -> <Self::Interner as Interner>::GenericArg; // FIXME: Uplift the leak check into this crate. @@ -61,6 +59,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size fn instantiate_canonical_var_with_infer( &self, cv_info: ty::CanonicalVarInfo<Self::Interner>, + span: <Self::Interner as Interner>::Span, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> <Self::Interner as Interner>::GenericArg; @@ -86,6 +85,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size &self, key: ty::OpaqueTypeKey<Self::Interner>, hidden_ty: <Self::Interner as Interner>::Ty, + span: <Self::Interner as Interner>::Span, ); fn reset_opaque_types(&self); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index e99cd3d2727..39e365806cb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -255,20 +255,29 @@ where self.delegate, &original_values, &response, + self.origin_span, ); let Response { var_values, external_constraints, certainty } = self.delegate.instantiate_canonical(response, instantiation); - Self::unify_query_var_values(self.delegate, param_env, &original_values, var_values); + Self::unify_query_var_values( + self.delegate, + param_env, + &original_values, + var_values, + self.origin_span, + ); let ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals, } = &*external_constraints; + self.register_region_constraints(region_constraints); self.register_new_opaque_types(opaque_types); + (normalization_nested_goals.clone(), certainty) } @@ -279,6 +288,7 @@ where delegate: &D, original_values: &[I::GenericArg], response: &Canonical<I, T>, + span: I::Span, ) -> CanonicalVarValues<I> { // FIXME: Longterm canonical queries should deal with all placeholders // created inside of the query directly instead of returning them to the @@ -331,7 +341,7 @@ where // A variable from inside a binder of the query. While ideally these shouldn't // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. - delegate.instantiate_canonical_var_with_infer(info, |idx| { + delegate.instantiate_canonical_var_with_infer(info, span, |idx| { ty::UniverseIndex::from(prev_universe.index() + idx.index()) }) } else if info.is_existential() { @@ -345,7 +355,7 @@ where if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] { v } else { - delegate.instantiate_canonical_var_with_infer(info, |_| prev_universe) + delegate.instantiate_canonical_var_with_infer(info, span, |_| prev_universe) } } else { // For placeholders which were already part of the input, we simply map this @@ -376,12 +386,13 @@ where param_env: I::ParamEnv, original_values: &[I::GenericArg], var_values: CanonicalVarValues<I>, + span: I::Span, ) { assert_eq!(original_values.len(), var_values.len()); for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) { let goals = - delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap(); + delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap(); assert!(goals.is_empty()); } } @@ -401,7 +412,7 @@ where fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) { for &(key, ty) in opaque_types { - self.delegate.inject_new_hidden_type_unchecked(key, ty); + self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span); } } } @@ -431,7 +442,7 @@ where // `rustc_trait_selection::solve::inspect::analyse`. pub fn instantiate_canonical_state<D, I, T: TypeFoldable<I>>( delegate: &D, - span: D::Span, + span: I::Span, param_env: I::ParamEnv, orig_values: &mut Vec<I::GenericArg>, state: inspect::CanonicalState<I, T>, @@ -451,10 +462,10 @@ where } let instantiation = - EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state); + EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state, span); let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation); - EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values); + EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values, span); data } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 91ad24bff67..48a05488148 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -78,6 +78,8 @@ where nested_goals: NestedGoals<I>, + pub(super) origin_span: I::Span, + // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`? // // If so, then it can no longer be used to make a canonical query response, @@ -134,6 +136,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate { &self, goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>, generate_proof_tree: GenerateProofTree, + span: <Self::Interner as Interner>::Span, ) -> ( Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<Self::Interner>>, @@ -174,8 +177,9 @@ where &self, goal: Goal<I, I::Predicate>, generate_proof_tree: GenerateProofTree, + span: I::Span, ) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) { - EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { + EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } @@ -186,7 +190,7 @@ where goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>, ) -> bool { self.probe(|| { - EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| { + EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) .0 @@ -203,9 +207,13 @@ where Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>, ) { - EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { - ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal) - }) + EvalCtxt::enter_root( + self, + self.cx().recursion_limit(), + generate_proof_tree, + I::Span::dummy(), + |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal), + ) } } @@ -229,6 +237,7 @@ where delegate: &D, root_depth: usize, generate_proof_tree: GenerateProofTree, + origin_span: I::Span, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option<inspect::GoalEvaluation<I>>) { let mut search_graph = SearchGraph::new(root_depth); @@ -248,6 +257,7 @@ where variables: Default::default(), var_values: CanonicalVarValues::dummy(), is_normalizes_to_goal: false, + origin_span, tainted: Ok(()), }; let result = f(&mut ecx); @@ -289,12 +299,13 @@ where max_input_universe: canonical_input.canonical.max_universe, search_graph, nested_goals: NestedGoals::new(), + origin_span: I::Span::dummy(), tainted: Ok(()), inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), }; for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { - ecx.delegate.inject_new_hidden_type_unchecked(key, ty); + ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span); } if !ecx.nested_goals.is_empty() { @@ -822,8 +833,12 @@ where let identity_args = self.fresh_args_for_item(alias.def_id); let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args); let ctor_term = rigid_ctor.to_term(cx); - let obligations = - self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?; + let obligations = self.delegate.eq_structurally_relating_aliases( + param_env, + term, + ctor_term, + self.origin_span, + )?; debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { @@ -841,7 +856,12 @@ where lhs: T, rhs: T, ) -> Result<(), NoSolution> { - let result = self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs)?; + let result = self.delegate.eq_structurally_relating_aliases( + param_env, + lhs, + rhs, + self.origin_span, + )?; assert_eq!(result, vec![]); Ok(()) } @@ -864,7 +884,7 @@ where variance: ty::Variance, rhs: T, ) -> Result<(), NoSolution> { - let goals = self.delegate.relate(param_env, lhs, variance, rhs)?; + let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; self.add_goals(GoalSource::Misc, goals); Ok(()) } @@ -881,7 +901,7 @@ where lhs: T, rhs: T, ) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> { - Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?) + Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?) } pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>( @@ -917,12 +937,12 @@ where } pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { - self.delegate.register_ty_outlives(ty, lt); + self.delegate.register_ty_outlives(ty, lt, self.origin_span); } pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) { // `b : a` ==> `a <= b` - self.delegate.sub_regions(b, a); + self.delegate.sub_regions(b, a, self.origin_span); } /// Computes the list of goals required for `arg` to be well-formed diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs index be69a6e84ea..add96a1fdf7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs @@ -39,6 +39,7 @@ where max_input_universe, search_graph: outer_ecx.search_graph, nested_goals: outer_ecx.nested_goals.clone(), + origin_span: outer_ecx.origin_span, tainted: outer_ecx.tainted, inspect: outer_ecx.inspect.take_and_enter_probe(), }; diff --git a/compiler/rustc_target/src/callconv/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs index 2e8b16d3a93..c64164372a1 100644 --- a/compiler/rustc_target/src/callconv/nvptx64.rs +++ b/compiler/rustc_target/src/callconv/nvptx64.rs @@ -1,5 +1,5 @@ use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget}; -use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform}; +use crate::abi::call::{ArgAbi, FnAbi, Reg, Size, Uniform}; use crate::abi::{HasDataLayout, TyAbiInterface}; fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { @@ -53,21 +53,37 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if matches!(arg.mode, PassMode::Pair(..)) && (arg.layout.is_adt() || arg.layout.is_tuple()) { - let align_bytes = arg.layout.align.abi.bytes(); + match arg.mode { + super::PassMode::Ignore | super::PassMode::Direct(_) => return, + super::PassMode::Pair(_, _) => {} + super::PassMode::Cast { .. } => unreachable!(), + super::PassMode::Indirect { .. } => {} + } + + // FIXME only allow structs and wide pointers here + // panic!( + // "`extern \"ptx-kernel\"` doesn't allow passing types other than primitives and structs" + // ); + + let align_bytes = arg.layout.align.abi.bytes(); - let unit = match align_bytes { - 1 => Reg::i8(), - 2 => Reg::i16(), - 4 => Reg::i32(), - 8 => Reg::i64(), - 16 => Reg::i128(), - _ => unreachable!("Align is given as power of 2 no larger than 16 bytes"), - }; - arg.cast_to(Uniform::new(unit, Size::from_bytes(2 * align_bytes))); + let unit = match align_bytes { + 1 => Reg::i8(), + 2 => Reg::i16(), + 4 => Reg::i32(), + 8 => Reg::i64(), + 16 => Reg::i128(), + _ => unreachable!("Align is given as power of 2 no larger than 16 bytes"), + }; + if arg.layout.size.bytes() / align_bytes == 1 { + // Make sure we pass the struct as array at the LLVM IR level and not as a single integer. + arg.cast_to(CastTarget { + prefix: [Some(unit), None, None, None, None, None, None, None], + rest: Uniform::new(unit, Size::ZERO), + attrs: ArgAttributes::new(), + }); } else { - // FIXME: find a better way to do this. See https://github.com/rust-lang/rust/issues/117271. - arg.make_direct_deprecated(); + arg.cast_to(Uniform::new(unit, arg.layout.size)); } } diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs index 1ae879d01bd..1c537491a6c 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs @@ -18,6 +18,11 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(), arch: "powerpc".into(), - options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base }, + options: TargetOptions { + endian: Endian::Big, + features: "+secure-plt".into(), + mcount: "_mcount".into(), + ..base + }, } } diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index 4a5ab375c73..4f5d9c661b0 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { abi: "spe".into(), endian: Endian::Big, + features: "+secure-plt".into(), mcount: "_mcount".into(), ..base }, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index abb79493432..58d8a3a6254 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -43,8 +43,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.tcx } - type Span = Span; - fn build_with_canonical<V>( interner: TyCtxt<'tcx>, canonical: &CanonicalQueryInput<'tcx, V>, @@ -147,9 +145,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< fn instantiate_canonical_var_with_infer( &self, cv_info: CanonicalVarInfo<'tcx>, + span: Span, universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex, ) -> ty::GenericArg<'tcx> { - self.0.instantiate_canonical_var(DUMMY_SP, cv_info, universe_map) + self.0.instantiate_canonical_var(span, cv_info, universe_map) } fn insert_hidden_type( @@ -175,11 +174,13 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< self.0.add_item_bounds_for_hidden_type(def_id, args, param_env, hidden_ty, goals); } - fn inject_new_hidden_type_unchecked(&self, key: ty::OpaqueTypeKey<'tcx>, hidden_ty: Ty<'tcx>) { - self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { - ty: hidden_ty, - span: DUMMY_SP, - }) + fn inject_new_hidden_type_unchecked( + &self, + key: ty::OpaqueTypeKey<'tcx>, + hidden_ty: Ty<'tcx>, + span: Span, + ) { + self.0.inject_new_hidden_type_unchecked(key, ty::OpaqueHiddenType { ty: hidden_ty, span }) } fn reset_opaque_types(&self) { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 0db44eda847..c238e708ab8 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -82,7 +82,7 @@ impl<'tcx> ObligationStorage<'tcx> { self.overflowed.extend(ExtractIf::new(&mut self.pending, |o| { let goal = o.clone().into(); let result = <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(goal, GenerateProofTree::No) + .evaluate_root_goal(goal, GenerateProofTree::No, o.cause.span) .0; matches!(result, Ok((HasChanged::Yes, _))) })); @@ -163,7 +163,7 @@ where for obligation in self.obligations.unstalled_for_select() { let goal = obligation.clone().into(); let result = <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(goal, GenerateProofTree::No) + .evaluate_root_goal(goal, GenerateProofTree::No, obligation.cause.span) .0; self.inspect_evaluated_obligation(infcx, &obligation, &result); let (changed, certainty) = match result { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index c64bc19835b..8edd623e5d0 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -88,7 +88,11 @@ pub(super) fn fulfillment_error_for_stalled<'tcx>( ) -> FulfillmentError<'tcx> { let (code, refine_obligation) = infcx.probe(|_| { match <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No) + .evaluate_root_goal( + root_obligation.clone().into(), + GenerateProofTree::No, + root_obligation.cause.span, + ) .0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 9ba48cd588f..9f4ee54bd4c 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -238,7 +238,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // constraints, we get an ICE if we already applied the constraints // from the chosen candidate. let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes, span).1) .unwrap(); InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) } @@ -440,8 +440,11 @@ impl<'tcx> InferCtxt<'tcx> { depth: usize, visitor: &mut V, ) -> V::Result { - let (_, proof_tree) = - <&SolverDelegate<'tcx>>::from(self).evaluate_root_goal(goal, GenerateProofTree::Yes); + let (_, proof_tree) = <&SolverDelegate<'tcx>>::from(self).evaluate_root_goal( + goal, + GenerateProofTree::Yes, + visitor.span(), + ); let proof_tree = proof_tree.unwrap(); visitor.visit_goal(&InspectGoal::new(self, depth, proof_tree, None, GoalSource::Misc)) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c528179ae0e..169f3a78c26 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -489,21 +489,16 @@ fn fn_abi_sanity_check<'tcx>( // have to allow it -- but we absolutely shouldn't let any more targets do // that. (Also see <https://github.com/rust-lang/rust/issues/115666>.) // - // The unstable abi `PtxKernel` also uses Direct for now. - // It needs to switch to something else before stabilization can happen. - // (See issue: https://github.com/rust-lang/rust/issues/117271) - // - // And finally the unadjusted ABI is ill specified and uses Direct for all - // args, but unfortunately we need it for calling certain LLVM intrinsics. + // The unadjusted ABI also uses Direct for all args and is ill-specified, + // but unfortunately we need it for calling certain LLVM intrinsics. match spec_abi { ExternAbi::Unadjusted => {} - ExternAbi::PtxKernel => {} ExternAbi::C { unwind: _ } if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {} _ => { panic!( - "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" and \"ptx-kernel\" functions and on wasm\n\ + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" functions and on wasm\n\ Problematic type: {:#?}", arg.layout, ); diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index a892b88c2c6..c9b636132f8 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -201,17 +201,20 @@ pub trait InferCtxtLike: Sized { &self, sub: <Self::Interner as Interner>::Region, sup: <Self::Interner as Interner>::Region, + span: <Self::Interner as Interner>::Span, ); fn equate_regions( &self, a: <Self::Interner as Interner>::Region, b: <Self::Interner as Interner>::Region, + span: <Self::Interner as Interner>::Span, ); fn register_ty_outlives( &self, ty: <Self::Interner as Interner>::Ty, r: <Self::Interner as Interner>::Region, + span: <Self::Interner as Interner>::Span, ); } diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index aae5aeb5fb3..fab1a11304d 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -47,23 +47,16 @@ TrivialTypeTraversalImpls! { u16, u32, u64, - String, + // tidy-alphabetical-start crate::AliasRelationDirection, - crate::AliasTyKind, crate::BoundConstness, crate::DebruijnIndex, - crate::FloatTy, - crate::InferTy, - crate::IntVarValue, crate::PredicatePolarity, - crate::RegionVid, crate::solve::BuiltinImplSource, crate::solve::Certainty, crate::solve::GoalSource, - crate::solve::MaybeCause, - crate::solve::NoSolution, crate::UniverseIndex, crate::Variance, - rustc_ast_ir::Movability, rustc_ast_ir::Mutability, + // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index ad10ad5af9c..dc2312b2da3 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -13,6 +13,7 @@ pub trait RelateExt: InferCtxtLike { lhs: T, variance: ty::Variance, rhs: T, + span: <Self::Interner as Interner>::Span, ) -> Result< Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, TypeError<Self::Interner>, @@ -23,6 +24,7 @@ pub trait RelateExt: InferCtxtLike { param_env: <Self::Interner as Interner>::ParamEnv, lhs: T, rhs: T, + span: <Self::Interner as Interner>::Span, ) -> Result< Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, TypeError<Self::Interner>, @@ -36,12 +38,13 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx { lhs: T, variance: ty::Variance, rhs: T, + span: <Self::Interner as Interner>::Span, ) -> Result< Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, TypeError<Self::Interner>, > { let mut relate = - SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env); + SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span); relate.relate(lhs, rhs)?; Ok(relate.goals) } @@ -51,12 +54,18 @@ impl<Infcx: InferCtxtLike> RelateExt for Infcx { param_env: <Self::Interner as Interner>::ParamEnv, lhs: T, rhs: T, + span: <Self::Interner as Interner>::Span, ) -> Result< Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, TypeError<Self::Interner>, > { - let mut relate = - SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env); + let mut relate = SolverRelating::new( + self, + StructurallyRelateAliases::Yes, + ty::Invariant, + param_env, + span, + ); relate.relate(lhs, rhs)?; Ok(relate.goals) } @@ -68,6 +77,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { // Immutable fields. structurally_relate_aliases: StructurallyRelateAliases, param_env: I::ParamEnv, + span: I::Span, // Mutable fields. ambient_variance: ty::Variance, goals: Vec<Goal<I, I::Predicate>>, @@ -106,10 +116,12 @@ where structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, param_env: I::ParamEnv, + span: I::Span, ) -> Self { SolverRelating { infcx, structurally_relate_aliases, + span, ambient_variance, param_env, goals: vec![], @@ -241,10 +253,10 @@ where fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region> { match self.ambient_variance { // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) - ty::Covariant => self.infcx.sub_regions(b, a), + ty::Covariant => self.infcx.sub_regions(b, a, self.span), // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) - ty::Contravariant => self.infcx.sub_regions(a, b), - ty::Invariant => self.infcx.equate_regions(a, b), + ty::Contravariant => self.infcx.sub_regions(a, b, self.span), + ty::Invariant => self.infcx.equate_regions(a, b, self.span), ty::Bivariant => { unreachable!("Expected bivariance to be handled in relate_with_variance") } diff --git a/library/Cargo.lock b/library/Cargo.lock index 30875482dc0..8b78908e6d7 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.143" +version = "0.1.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85ba2077e3eab3dd81be4ece6b7fb2ad0887c1fb813e9a45400baf75c6c7c29" +checksum = "da0705f5abaaab7168ccc14f8f340ded61be2bd3ebea86b9834b6acbc8495de8" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 96caac890a3..db7eaf52fb2 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.145", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/core/src/iter/sources/from_fn.rs b/library/core/src/iter/sources/from_fn.rs index 75cc0ffe3c7..1c7e1b30a2f 100644 --- a/library/core/src/iter/sources/from_fn.rs +++ b/library/core/src/iter/sources/from_fn.rs @@ -1,7 +1,7 @@ use crate::fmt; /// Creates an iterator with the provided closure -/// `F: FnMut() -> Option<T>` as its `[next](Iterator::next)` method. +/// `F: FnMut() -> Option<T>` as its [`next`](Iterator::next) method. /// /// The iterator will yield the `T`s returned from the closure. /// diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 40526f9583e..7b2ced2cc4b 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -182,10 +182,10 @@ pub use self::function::{Fn, FnMut, FnOnce}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::index::{Index, IndexMut}; pub(crate) use self::index_range::IndexRange; -#[unstable(feature = "one_sided_range", issue = "69780")] -pub use self::range::OneSidedRange; #[stable(feature = "inclusive_range", since = "1.26.0")] pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; +#[unstable(feature = "one_sided_range", issue = "69780")] +pub use self::range::{OneSidedRange, OneSidedRangeBound}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[unstable(feature = "try_trait_v2_residual", issue = "91285")] diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 727a22e454d..42e07a0e51d 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -979,6 +979,19 @@ impl<T> RangeBounds<T> for RangeToInclusive<&T> { } } +/// An internal helper for `split_off` functions indicating +/// which end a `OneSidedRange` is bounded on. +#[unstable(feature = "one_sided_range", issue = "69780")] +#[allow(missing_debug_implementations)] +pub enum OneSidedRangeBound { + /// The range is bounded inclusively from below and is unbounded above. + StartInclusive, + /// The range is bounded exclusively from above and is unbounded below. + End, + /// The range is bounded inclusively from above and is unbounded below. + EndInclusive, +} + /// `OneSidedRange` is implemented for built-in range types that are unbounded /// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, /// but `..`, `d..e`, and `f..=g` do not. @@ -986,13 +999,38 @@ impl<T> RangeBounds<T> for RangeToInclusive<&T> { /// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded` /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. #[unstable(feature = "one_sided_range", issue = "69780")] -pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> {} +pub trait OneSidedRange<T: ?Sized>: RangeBounds<T> { + /// An internal-only helper function for `split_off` and + /// `split_off_mut` that returns the bound of the one-sided range. + fn bound(self) -> (OneSidedRangeBound, T); +} #[unstable(feature = "one_sided_range", issue = "69780")] -impl<T> OneSidedRange<T> for RangeTo<T> where Self: RangeBounds<T> {} +impl<T> OneSidedRange<T> for RangeTo<T> +where + Self: RangeBounds<T>, +{ + fn bound(self) -> (OneSidedRangeBound, T) { + (OneSidedRangeBound::End, self.end) + } +} #[unstable(feature = "one_sided_range", issue = "69780")] -impl<T> OneSidedRange<T> for RangeFrom<T> where Self: RangeBounds<T> {} +impl<T> OneSidedRange<T> for RangeFrom<T> +where + Self: RangeBounds<T>, +{ + fn bound(self) -> (OneSidedRangeBound, T) { + (OneSidedRangeBound::StartInclusive, self.start) + } +} #[unstable(feature = "one_sided_range", issue = "69780")] -impl<T> OneSidedRange<T> for RangeToInclusive<T> where Self: RangeBounds<T> {} +impl<T> OneSidedRange<T> for RangeToInclusive<T> +where + Self: RangeBounds<T>, +{ + fn bound(self) -> (OneSidedRangeBound, T) { + (OneSidedRangeBound::EndInclusive, self.end) + } +} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 1993a7491e1..fe9d7c10db2 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -10,7 +10,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics::{exact_div, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; -use crate::ops::{Bound, OneSidedRange, Range, RangeBounds, RangeInclusive}; +use crate::ops::{OneSidedRange, OneSidedRangeBound, Range, RangeBounds, RangeInclusive}; use crate::panic::const_panic; use crate::simd::{self, Simd}; use crate::ub_checks::assert_unsafe_precondition; @@ -83,14 +83,12 @@ pub use raw::{from_raw_parts, from_raw_parts_mut}; /// which to split. Returns `None` if the split index would overflow. #[inline] fn split_point_of(range: impl OneSidedRange<usize>) -> Option<(Direction, usize)> { - use Bound::*; - - Some(match (range.start_bound(), range.end_bound()) { - (Unbounded, Excluded(i)) => (Direction::Front, *i), - (Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?), - (Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?), - (Included(i), Unbounded) => (Direction::Back, *i), - _ => unreachable!(), + use OneSidedRangeBound::{End, EndInclusive, StartInclusive}; + + Some(match range.bound() { + (StartInclusive, i) => (Direction::Back, i), + (End, i) => (Direction::Front, i), + (EndInclusive, i) => (Direction::Front, i.checked_add(1)?), }) } @@ -4294,25 +4292,25 @@ impl<T> [T] { /// /// # Examples /// - /// Taking the first three elements of a slice: + /// Splitting off the first three elements of a slice: /// /// ``` /// #![feature(slice_take)] /// /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; - /// let mut first_three = slice.take(..3).unwrap(); + /// let mut first_three = slice.split_off(..3).unwrap(); /// /// assert_eq!(slice, &['d']); /// assert_eq!(first_three, &['a', 'b', 'c']); /// ``` /// - /// Taking the last two elements of a slice: + /// Splitting off the last two elements of a slice: /// /// ``` /// #![feature(slice_take)] /// /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; - /// let mut tail = slice.take(2..).unwrap(); + /// let mut tail = slice.split_off(2..).unwrap(); /// /// assert_eq!(slice, &['a', 'b']); /// assert_eq!(tail, &['c', 'd']); @@ -4325,16 +4323,19 @@ impl<T> [T] { /// /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; /// - /// assert_eq!(None, slice.take(5..)); - /// assert_eq!(None, slice.take(..5)); - /// assert_eq!(None, slice.take(..=4)); + /// assert_eq!(None, slice.split_off(5..)); + /// assert_eq!(None, slice.split_off(..5)); + /// assert_eq!(None, slice.split_off(..=4)); /// let expected: &[char] = &['a', 'b', 'c', 'd']; - /// assert_eq!(Some(expected), slice.take(..4)); + /// assert_eq!(Some(expected), slice.split_off(..4)); /// ``` #[inline] #[must_use = "method does not modify the slice if the range is out of bounds"] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take<'a, R: OneSidedRange<usize>>(self: &mut &'a Self, range: R) -> Option<&'a Self> { + pub fn split_off<'a, R: OneSidedRange<usize>>( + self: &mut &'a Self, + range: R, + ) -> Option<&'a Self> { let (direction, split_index) = split_point_of(range)?; if split_index > self.len() { return None; @@ -4363,13 +4364,13 @@ impl<T> [T] { /// /// # Examples /// - /// Taking the first three elements of a slice: + /// Splitting off the first three elements of a slice: /// /// ``` /// #![feature(slice_take)] /// /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; - /// let mut first_three = slice.take_mut(..3).unwrap(); + /// let mut first_three = slice.split_off_mut(..3).unwrap(); /// /// assert_eq!(slice, &mut ['d']); /// assert_eq!(first_three, &mut ['a', 'b', 'c']); @@ -4381,7 +4382,7 @@ impl<T> [T] { /// #![feature(slice_take)] /// /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; - /// let mut tail = slice.take_mut(2..).unwrap(); + /// let mut tail = slice.split_off_mut(2..).unwrap(); /// /// assert_eq!(slice, &mut ['a', 'b']); /// assert_eq!(tail, &mut ['c', 'd']); @@ -4394,16 +4395,16 @@ impl<T> [T] { /// /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; /// - /// assert_eq!(None, slice.take_mut(5..)); - /// assert_eq!(None, slice.take_mut(..5)); - /// assert_eq!(None, slice.take_mut(..=4)); + /// assert_eq!(None, slice.split_off_mut(5..)); + /// assert_eq!(None, slice.split_off_mut(..5)); + /// assert_eq!(None, slice.split_off_mut(..=4)); /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd']; - /// assert_eq!(Some(expected), slice.take_mut(..4)); + /// assert_eq!(Some(expected), slice.split_off_mut(..4)); /// ``` #[inline] #[must_use = "method does not modify the slice if the range is out of bounds"] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take_mut<'a, R: OneSidedRange<usize>>( + pub fn split_off_mut<'a, R: OneSidedRange<usize>>( self: &mut &'a mut Self, range: R, ) -> Option<&'a mut Self> { @@ -4435,14 +4436,14 @@ impl<T> [T] { /// #![feature(slice_take)] /// /// let mut slice: &[_] = &['a', 'b', 'c']; - /// let first = slice.take_first().unwrap(); + /// let first = slice.split_off_first().unwrap(); /// /// assert_eq!(slice, &['b', 'c']); /// assert_eq!(first, &'a'); /// ``` #[inline] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> { + pub fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { let (first, rem) = self.split_first()?; *self = rem; Some(first) @@ -4459,7 +4460,7 @@ impl<T> [T] { /// #![feature(slice_take)] /// /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; - /// let first = slice.take_first_mut().unwrap(); + /// let first = slice.split_off_first_mut().unwrap(); /// *first = 'd'; /// /// assert_eq!(slice, &['b', 'c']); @@ -4467,7 +4468,7 @@ impl<T> [T] { /// ``` #[inline] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + pub fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { let (first, rem) = mem::take(self).split_first_mut()?; *self = rem; Some(first) @@ -4484,14 +4485,14 @@ impl<T> [T] { /// #![feature(slice_take)] /// /// let mut slice: &[_] = &['a', 'b', 'c']; - /// let last = slice.take_last().unwrap(); + /// let last = slice.split_off_last().unwrap(); /// /// assert_eq!(slice, &['a', 'b']); /// assert_eq!(last, &'c'); /// ``` #[inline] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> { + pub fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { let (last, rem) = self.split_last()?; *self = rem; Some(last) @@ -4508,7 +4509,7 @@ impl<T> [T] { /// #![feature(slice_take)] /// /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; - /// let last = slice.take_last_mut().unwrap(); + /// let last = slice.split_off_last_mut().unwrap(); /// *last = 'd'; /// /// assert_eq!(slice, &['a', 'b']); @@ -4516,7 +4517,7 @@ impl<T> [T] { /// ``` #[inline] #[unstable(feature = "slice_take", issue = "62280")] - pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + pub fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { let (last, rem) = mem::take(self).split_last_mut()?; *self = rem; Some(last) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 39fa6c1a25f..5b258a7c844 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -160,6 +160,182 @@ impl str { self.len() == 0 } + /// Converts a slice of bytes to a string slice. + /// + /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice + /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between + /// the two. Not all byte slices are valid string slices, however: [`&str`] requires + /// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid + /// UTF-8, and then does the conversion. + /// + /// [`&str`]: str + /// [byteslice]: prim@slice + /// + /// If you are sure that the byte slice is valid UTF-8, and you don't want to + /// incur the overhead of the validity check, there is an unsafe version of + /// this function, [`from_utf8_unchecked`], which has the same + /// behavior but skips the check. + /// + /// If you need a `String` instead of a `&str`, consider + /// [`String::from_utf8`][string]. + /// + /// [string]: ../std/string/struct.String.html#method.from_utf8 + /// + /// Because you can stack-allocate a `[u8; N]`, and you can take a + /// [`&[u8]`][byteslice] of it, this function is one way to have a + /// stack-allocated string. There is an example of this in the + /// examples section below. + /// + /// [byteslice]: slice + /// + /// # Errors + /// + /// Returns `Err` if the slice is not UTF-8 with a description as to why the + /// provided slice is not UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::str; + /// + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// // We can use the ? (try) operator to check if the bytes are valid + /// let sparkle_heart = str::from_utf8(&sparkle_heart)?; + /// + /// assert_eq!("💖", sparkle_heart); + /// # Ok::<_, str::Utf8Error>(()) + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// use std::str; + /// + /// // some invalid bytes, in a vector + /// let sparkle_heart = vec![0, 159, 146, 150]; + /// + /// assert!(str::from_utf8(&sparkle_heart).is_err()); + /// ``` + /// + /// See the docs for [`Utf8Error`] for more details on the kinds of + /// errors that can be returned. + /// + /// A "stack allocated string": + /// + /// ``` + /// use std::str; + /// + /// // some bytes, in a stack-allocated array + /// let sparkle_heart = [240, 159, 146, 150]; + /// + /// // We know these bytes are valid, so just use `unwrap()`. + /// let sparkle_heart: &str = str::from_utf8(&sparkle_heart).unwrap(); + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[unstable(feature = "inherent_str_constructors", issue = "131114")] + pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { + converts::from_utf8(v) + } + + /// Converts a mutable slice of bytes to a mutable string slice. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::str; + /// + /// // "Hello, Rust!" as a mutable vector + /// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33]; + /// + /// // As we know these bytes are valid, we can use `unwrap()` + /// let outstr = str::from_utf8_mut(&mut hellorust).unwrap(); + /// + /// assert_eq!("Hello, Rust!", outstr); + /// ``` + /// + /// Incorrect bytes: + /// + /// ``` + /// use std::str; + /// + /// // Some invalid bytes in a mutable vector + /// let mut invalid = vec![128, 223]; + /// + /// assert!(str::from_utf8_mut(&mut invalid).is_err()); + /// ``` + /// See the docs for [`Utf8Error`] for more details on the kinds of + /// errors that can be returned. + #[unstable(feature = "inherent_str_constructors", issue = "131114")] + #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] + pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { + converts::from_utf8_mut(v) + } + + /// Converts a slice of bytes to a string slice without checking + /// that the string contains valid UTF-8. + /// + /// See the safe version, [`from_utf8`], for more information. + /// + /// # Safety + /// + /// The bytes passed in must be valid UTF-8. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::str; + /// + /// // some bytes, in a vector + /// let sparkle_heart = vec![240, 159, 146, 150]; + /// + /// let sparkle_heart = unsafe { + /// str::from_utf8_unchecked(&sparkle_heart) + /// }; + /// + /// assert_eq!("💖", sparkle_heart); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "inherent_str_constructors", issue = "131114")] + pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { + // SAFETY: converts::from_utf8_unchecked has the same safety requirements as this function. + unsafe { converts::from_utf8_unchecked(v) } + } + + /// Converts a slice of bytes to a string slice without checking + /// that the string contains valid UTF-8; mutable version. + /// + /// See the immutable version, [`from_utf8_unchecked()`] for more information. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::str; + /// + /// let mut heart = vec![240, 159, 146, 150]; + /// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) }; + /// + /// assert_eq!("💖", heart); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "inherent_str_constructors", issue = "131114")] + pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { + // SAFETY: converts::from_utf8_unchecked_mut has the same safety requirements as this function. + unsafe { converts::from_utf8_unchecked_mut(v) } + } + /// Checks that `index`-th byte is the first byte in a UTF-8 code point /// sequence or the end of the string. /// diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index 510dd4967c9..ea5322da381 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -2399,18 +2399,18 @@ fn slice_rsplit_once() { assert_eq!(v.rsplit_once(|&x| x == 0), None); } -macro_rules! take_tests { +macro_rules! split_off_tests { (slice: &[], $($tts:tt)*) => { - take_tests!(ty: &[()], slice: &[], $($tts)*); + split_off_tests!(ty: &[()], slice: &[], $($tts)*); }; (slice: &mut [], $($tts:tt)*) => { - take_tests!(ty: &mut [()], slice: &mut [], $($tts)*); + split_off_tests!(ty: &mut [()], slice: &mut [], $($tts)*); }; (slice: &$slice:expr, $($tts:tt)*) => { - take_tests!(ty: &[_], slice: &$slice, $($tts)*); + split_off_tests!(ty: &[_], slice: &$slice, $($tts)*); }; (slice: &mut $slice:expr, $($tts:tt)*) => { - take_tests!(ty: &mut [_], slice: &mut $slice, $($tts)*); + split_off_tests!(ty: &mut [_], slice: &mut $slice, $($tts)*); }; (ty: $ty:ty, slice: $slice:expr, method: $method:ident, $(($test_name:ident, ($($args:expr),*), $output:expr, $remaining:expr),)*) => { $( @@ -2425,64 +2425,64 @@ macro_rules! take_tests { }; } -take_tests! { - slice: &[0, 1, 2, 3], method: take, - (take_in_bounds_range_to, (..1), Some(&[0] as _), &[1, 2, 3]), - (take_in_bounds_range_to_inclusive, (..=0), Some(&[0] as _), &[1, 2, 3]), - (take_in_bounds_range_from, (2..), Some(&[2, 3] as _), &[0, 1]), - (take_oob_range_to, (..5), None, &[0, 1, 2, 3]), - (take_oob_range_to_inclusive, (..=4), None, &[0, 1, 2, 3]), - (take_oob_range_from, (5..), None, &[0, 1, 2, 3]), +split_off_tests! { + slice: &[0, 1, 2, 3], method: split_off, + (split_off_in_bounds_range_to, (..1), Some(&[0] as _), &[1, 2, 3]), + (split_off_in_bounds_range_to_inclusive, (..=0), Some(&[0] as _), &[1, 2, 3]), + (split_off_in_bounds_range_from, (2..), Some(&[2, 3] as _), &[0, 1]), + (split_off_oob_range_to, (..5), None, &[0, 1, 2, 3]), + (split_off_oob_range_to_inclusive, (..=4), None, &[0, 1, 2, 3]), + (split_off_oob_range_from, (5..), None, &[0, 1, 2, 3]), } -take_tests! { - slice: &mut [0, 1, 2, 3], method: take_mut, - (take_mut_in_bounds_range_to, (..1), Some(&mut [0] as _), &mut [1, 2, 3]), - (take_mut_in_bounds_range_to_inclusive, (..=0), Some(&mut [0] as _), &mut [1, 2, 3]), - (take_mut_in_bounds_range_from, (2..), Some(&mut [2, 3] as _), &mut [0, 1]), - (take_mut_oob_range_to, (..5), None, &mut [0, 1, 2, 3]), - (take_mut_oob_range_to_inclusive, (..=4), None, &mut [0, 1, 2, 3]), - (take_mut_oob_range_from, (5..), None, &mut [0, 1, 2, 3]), +split_off_tests! { + slice: &mut [0, 1, 2, 3], method: split_off_mut, + (split_off_mut_in_bounds_range_to, (..1), Some(&mut [0] as _), &mut [1, 2, 3]), + (split_off_mut_in_bounds_range_to_inclusive, (..=0), Some(&mut [0] as _), &mut [1, 2, 3]), + (split_off_mut_in_bounds_range_from, (2..), Some(&mut [2, 3] as _), &mut [0, 1]), + (split_off_mut_oob_range_to, (..5), None, &mut [0, 1, 2, 3]), + (split_off_mut_oob_range_to_inclusive, (..=4), None, &mut [0, 1, 2, 3]), + (split_off_mut_oob_range_from, (5..), None, &mut [0, 1, 2, 3]), } -take_tests! { - slice: &[1, 2], method: take_first, - (take_first_nonempty, (), Some(&1), &[2]), +split_off_tests! { + slice: &[1, 2], method: split_off_first, + (split_off_first_nonempty, (), Some(&1), &[2]), } -take_tests! { - slice: &mut [1, 2], method: take_first_mut, - (take_first_mut_nonempty, (), Some(&mut 1), &mut [2]), +split_off_tests! { + slice: &mut [1, 2], method: split_off_first_mut, + (split_off_first_mut_nonempty, (), Some(&mut 1), &mut [2]), } -take_tests! { - slice: &[1, 2], method: take_last, - (take_last_nonempty, (), Some(&2), &[1]), +split_off_tests! { + slice: &[1, 2], method: split_off_last, + (split_off_last_nonempty, (), Some(&2), &[1]), } -take_tests! { - slice: &mut [1, 2], method: take_last_mut, - (take_last_mut_nonempty, (), Some(&mut 2), &mut [1]), +split_off_tests! { + slice: &mut [1, 2], method: split_off_last_mut, + (split_off_last_mut_nonempty, (), Some(&mut 2), &mut [1]), } -take_tests! { - slice: &[], method: take_first, - (take_first_empty, (), None, &[]), +split_off_tests! { + slice: &[], method: split_off_first, + (split_off_first_empty, (), None, &[]), } -take_tests! { - slice: &mut [], method: take_first_mut, - (take_first_mut_empty, (), None, &mut []), +split_off_tests! { + slice: &mut [], method: split_off_first_mut, + (split_off_first_mut_empty, (), None, &mut []), } -take_tests! { - slice: &[], method: take_last, - (take_last_empty, (), None, &[]), +split_off_tests! { + slice: &[], method: split_off_last, + (split_off_last_empty, (), None, &[]), } -take_tests! { - slice: &mut [], method: take_last_mut, - (take_last_mut_empty, (), None, &mut []), +split_off_tests! { + slice: &mut [], method: split_off_last_mut, + (split_off_last_mut_empty, (), None, &mut []), } #[cfg(not(miri))] // unused in Miri @@ -2497,19 +2497,19 @@ macro_rules! empty_max_mut { } #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) -take_tests! { - slice: &[(); usize::MAX], method: take, - (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), - (take_oob_max_range_to_inclusive, (..=usize::MAX), None, EMPTY_MAX), - (take_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX), +split_off_tests! { + slice: &[(); usize::MAX], method: split_off, + (split_off_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), + (split_off_oob_max_range_to_inclusive, (..=usize::MAX), None, EMPTY_MAX), + (split_off_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX), } #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) -take_tests! { - slice: &mut [(); usize::MAX], method: take_mut, - (take_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]), - (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), - (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), +split_off_tests! { + slice: &mut [(); usize::MAX], method: split_off_mut, + (split_off_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]), + (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), } #[test] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 944c3438557..aa391a4b317 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.143" } +compiler_builtins = { version = "=0.1.145" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index ba9c948a2e9..e8355cc31d7 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -6,8 +6,7 @@ mod tests; pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use crate::sys::net::netc as c; -use crate::sys_common::net::LookupHost; +use crate::sys::net::{LookupHost, netc as c}; use crate::sys_common::{FromInner, IntoInner}; use crate::{io, iter, mem, option, slice, vec}; diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 67a0f7e439d..9b68f872955 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -15,7 +15,8 @@ use crate::io::prelude::*; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::iter::FusedIterator; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; -use crate::sys_common::{AsInner, FromInner, IntoInner, net as net_imp}; +use crate::sys::net as net_imp; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; /// A TCP stream between a local and a remote socket. diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 674c5fb7d6e..3eb798ad34a 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -12,7 +12,8 @@ mod tests; use crate::fmt; use crate::io::{self, ErrorKind}; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs}; -use crate::sys_common::{AsInner, FromInner, IntoInner, net as net_imp}; +use crate::sys::net as net_imp; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; /// A UDP socket. diff --git a/library/std/src/os/fd/net.rs b/library/std/src/os/fd/net.rs index 843f45f7f5f..34479ca0e19 100644 --- a/library/std/src/os/fd/net.rs +++ b/library/std/src/os/fd/net.rs @@ -1,6 +1,6 @@ use crate::os::fd::owned::OwnedFd; use crate::os::fd::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{net, sys}; macro_rules! impl_as_raw_fd { @@ -24,7 +24,7 @@ macro_rules! impl_from_raw_fd { unsafe fn from_raw_fd(fd: RawFd) -> net::$t { unsafe { let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))); - net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + net::$t::from_inner(sys::net::$t::from_inner(socket)) } } } diff --git a/library/std/src/os/hermit/io/net.rs b/library/std/src/os/hermit/io/net.rs index 7a774345b23..233bc885fc7 100644 --- a/library/std/src/os/hermit/io/net.rs +++ b/library/std/src/os/hermit/io/net.rs @@ -23,7 +23,7 @@ macro_rules! impl_from_raw_fd { unsafe fn from_raw_fd(fd: RawFd) -> net::$t { unsafe { let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))); - net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + net::$t::from_inner(sys::net::$t::from_inner(socket)) } } } diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index b8601b533fe..b8c3440542d 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -48,7 +48,7 @@ use crate::marker::PhantomData; use crate::mem::ManuallyDrop; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, net, sys}; /// Raw file descriptors. @@ -387,7 +387,7 @@ macro_rules! impl_from_raw_fd { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> net::$t { let socket = unsafe { sys::net::Socket::from_raw_fd(fd) }; - net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + net::$t::from_inner(sys::net::$t::from_inner(socket)) } } )*}; diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 6658248d574..c0517fab950 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -6,7 +6,7 @@ use crate::os::windows::io::{AsHandle, AsSocket}; use crate::os::windows::io::{OwnedHandle, OwnedSocket}; use crate::os::windows::raw; -use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fs, io, net, ptr, sys}; /// Raw HANDLEs. @@ -262,7 +262,7 @@ impl FromRawSocket for net::TcpStream { unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream { unsafe { let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock)); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(sock)) + net::TcpStream::from_inner(sys::net::TcpStream::from_inner(sock)) } } } @@ -272,7 +272,7 @@ impl FromRawSocket for net::TcpListener { unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener { unsafe { let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock)); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(sock)) + net::TcpListener::from_inner(sys::net::TcpListener::from_inner(sock)) } } } @@ -282,7 +282,7 @@ impl FromRawSocket for net::UdpSocket { unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket { unsafe { let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock)); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(sock)) + net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(sock)) } } } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f17dd47dece..39a0bc6e337 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -12,6 +12,7 @@ pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; pub mod exit_guard; +pub mod net; pub mod os_str; pub mod path; pub mod random; diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/net/connection/sgx.rs index c966886d163..b390a5eac5f 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -1,7 +1,7 @@ -use super::abi::usercalls; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs}; use crate::sync::Arc; +use crate::sys::abi::usercalls; use crate::sys::fd::FileDesc; use crate::sys::{AsInner, FromInner, IntoInner, TryIntoInner, sgx_ineffective, unsupported}; use crate::time::Duration; diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys/net/connection/socket.rs index 74306978d22..6fe3430b53f 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys/net/connection/socket.rs @@ -5,12 +5,32 @@ use crate::ffi::{c_int, c_void}; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::sys::common::small_c_string::run_with_cstr; -use crate::sys::net::{Socket, cvt, cvt_gai, cvt_r, init, netc as c, wrlen_t}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, fmt, mem, ptr}; cfg_if::cfg_if! { + if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(target_os = "solid_asp3")] { + mod solid; + pub use solid::*; + } else if #[cfg(target_family = "unix")] { + mod unix; + pub use unix::*; + } else if #[cfg(all(target_os = "wasi", target_env = "p2"))] { + mod wasip2; + pub use wasip2::*; + } else if #[cfg(target_os = "windows")] { + mod windows; + pub use windows::*; + } +} + +use netc as c; + +cfg_if::cfg_if! { if #[cfg(any( target_os = "dragonfly", target_os = "freebsd", @@ -24,11 +44,11 @@ cfg_if::cfg_if! { target_os = "nuttx", target_vendor = "apple", ))] { - use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; - use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; + use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; + use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; } else { - use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP; - use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP; + use c::IPV6_ADD_MEMBERSHIP; + use c::IPV6_DROP_MEMBERSHIP; } } diff --git a/library/std/src/sys/pal/hermit/net.rs b/library/std/src/sys/net/connection/socket/hermit.rs index 4e12374203e..42179dcc915 100644 --- a/library/std/src/sys/pal/hermit/net.rs +++ b/library/std/src/sys/net/connection/socket/hermit.rs @@ -2,21 +2,20 @@ use core::ffi::c_int; -use super::fd::FileDesc; +pub(crate) use hermit_abi as netc; + use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; +use crate::sys::fd::FileDesc; +use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys::time::Instant; -use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; +pub use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, mem}; -#[allow(unused_extern_crates)] -pub extern crate hermit_abi as netc; - -pub use crate::sys::{cvt, cvt_r}; - +#[expect(non_camel_case_types)] pub type wrlen_t = usize; pub fn cvt_gai(err: i32) -> io::Result<()> { diff --git a/library/std/src/sys/pal/solid/net.rs b/library/std/src/sys/net/connection/socket/solid.rs index 5f6436807e2..f85ecbb883e 100644 --- a/library/std/src/sys/pal/solid/net.rs +++ b/library/std/src/sys/net/connection/socket/solid.rs @@ -1,24 +1,23 @@ use libc::{c_int, c_void, size_t}; use self::netc::{MSG_PEEK, sockaddr, socklen_t}; -use super::abi; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}; -use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys::abi; +use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, mem, ptr, str}; pub mod netc { - pub use super::super::abi::sockets::*; + pub use crate::sys::abi::sockets::*; } +#[expect(non_camel_case_types)] pub type wrlen_t = size_t; -const READ_LIMIT: usize = libc::ssize_t::MAX as usize; - const fn max_iov() -> usize { // Judging by the source code, it's unlimited, but specify a lower // value just in case. @@ -78,7 +77,7 @@ fn last_error() -> io::Error { io::Error::from_raw_os_error(unsafe { netc::SOLID_NET_GetLastError() }) } -pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { +pub fn error_name(er: abi::ER) -> Option<&'static str> { unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok() } @@ -87,7 +86,7 @@ pub fn is_interrupted(er: abi::ER) -> bool { er == netc::SOLID_NET_ERR_BASE - libc::EINTR } -pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { +pub fn decode_error_kind(er: abi::ER) -> ErrorKind { let errno = netc::SOLID_NET_ERR_BASE - er; match errno as libc::c_int { libc::ECONNREFUSED => ErrorKind::ConnectionRefused, @@ -268,17 +267,6 @@ impl Socket { self.recv_from_with_flags(buf, MSG_PEEK) } - pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let ret = cvt(unsafe { - netc::write( - self.as_raw_fd(), - buf.as_ptr() as *const c_void, - cmp::min(buf.len(), READ_LIMIT), - ) - })?; - Ok(ret as usize) - } - pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { let ret = cvt(unsafe { netc::writev( diff --git a/library/std/src/sys_common/net/tests.rs b/library/std/src/sys/net/connection/socket/tests.rs index fc236b8027b..fc236b8027b 100644 --- a/library/std/src/sys_common/net/tests.rs +++ b/library/std/src/sys/net/connection/socket/tests.rs diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/net/connection/socket/unix.rs index d73b9fd5eb8..da631605527 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -5,8 +5,8 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; -use crate::sys::pal::unix::IsMinusOne; -use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys::pal::IsMinusOne; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem}; @@ -19,11 +19,11 @@ cfg_if::cfg_if! { } } -pub use crate::sys::{cvt, cvt_r}; +pub(crate) use libc as netc; -#[allow(unused_extern_crates)] -pub extern crate libc as netc; +pub use crate::sys::{cvt, cvt_r}; +#[expect(non_camel_case_types)] pub type wrlen_t = size_t; pub struct Socket(FileDesc); diff --git a/library/std/src/sys/pal/wasip2/net.rs b/library/std/src/sys/net/connection/socket/wasip2.rs index f009a51821f..9d1c05a473e 100644 --- a/library/std/src/sys/pal/wasip2/net.rs +++ b/library/std/src/sys/net/connection/socket/wasip2.rs @@ -6,8 +6,8 @@ use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys::unsupported; -use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem, str}; diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/net/connection/socket/windows.rs index a92853c642c..80cf37eaf05 100644 --- a/library/std/src/sys/pal/windows/net.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -9,7 +9,7 @@ use crate::os::windows::io::{ }; use crate::sync::OnceLock; use crate::sys::c; -use crate::sys_common::{AsInner, FromInner, IntoInner, net}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, mem, ptr, sys}; @@ -110,6 +110,7 @@ pub mod netc { } } +#[expect(missing_debug_implementations)] pub struct Socket(OwnedSocket); static WSA_CLEANUP: OnceLock<unsafe extern "system" fn() -> i32> = OnceLock::new(); @@ -400,12 +401,12 @@ impl Socket { let error = unsafe { c::WSAGetLastError() }; if error == c::WSAESHUTDOWN { - Ok((0, net::sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((0, super::sockaddr_to_addr(&storage, addrlen as usize)?)) } else { Err(io::Error::from_raw_os_error(error)) } } - _ => Ok((result as usize, net::sockaddr_to_addr(&storage, addrlen as usize)?)), + _ => Ok((result as usize, super::sockaddr_to_addr(&storage, addrlen as usize)?)), } } @@ -450,11 +451,11 @@ impl Socket { } None => 0, }; - net::setsockopt(self, c::SOL_SOCKET, kind, timeout) + super::setsockopt(self, c::SOL_SOCKET, kind, timeout) } pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> { - let raw: u32 = net::getsockopt(self, c::SOL_SOCKET, kind)?; + let raw: u32 = super::getsockopt(self, c::SOL_SOCKET, kind)?; if raw == 0 { Ok(None) } else { @@ -487,26 +488,26 @@ impl Socket { l_linger: linger.unwrap_or_default().as_secs() as c_ushort, }; - net::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger) + super::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger) } pub fn linger(&self) -> io::Result<Option<Duration>> { - let val: c::LINGER = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?; + let val: c::LINGER = super::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?; Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { - net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) + super::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) } pub fn nodelay(&self) -> io::Result<bool> { - let raw: c::BOOL = net::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; + let raw: c::BOOL = super::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; Ok(raw != 0) } pub fn take_error(&self) -> io::Result<Option<io::Error>> { - let raw: c_int = net::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?; + let raw: c_int = super::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } } diff --git a/library/std/src/sys/pal/unsupported/net.rs b/library/std/src/sys/net/connection/unsupported.rs index 87e6106468f..87e6106468f 100644 --- a/library/std/src/sys/pal/unsupported/net.rs +++ b/library/std/src/sys/net/connection/unsupported.rs diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/net/connection/wasip1.rs index a6486799828..27e3a528af4 100644 --- a/library/std/src/sys/pal/wasi/net.rs +++ b/library/std/src/sys/net/connection/wasip1.rs @@ -1,12 +1,11 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use super::err2io; -use super::fd::WasiFd; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; -use crate::sys::unsupported; +use crate::sys::fd::WasiFd; +use crate::sys::{err2io, unsupported}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::Duration; diff --git a/library/std/src/sys/pal/xous/net/dns.rs b/library/std/src/sys/net/connection/xous/dns.rs index ff6e49ed2d4..ff6e49ed2d4 100644 --- a/library/std/src/sys/pal/xous/net/dns.rs +++ b/library/std/src/sys/net/connection/xous/dns.rs diff --git a/library/std/src/sys/pal/xous/net/mod.rs b/library/std/src/sys/net/connection/xous/mod.rs index 3e18ed24208..3e18ed24208 100644 --- a/library/std/src/sys/pal/xous/net/mod.rs +++ b/library/std/src/sys/net/connection/xous/mod.rs diff --git a/library/std/src/sys/pal/xous/net/tcplistener.rs b/library/std/src/sys/net/connection/xous/tcplistener.rs index 640a02a64f5..640a02a64f5 100644 --- a/library/std/src/sys/pal/xous/net/tcplistener.rs +++ b/library/std/src/sys/net/connection/xous/tcplistener.rs diff --git a/library/std/src/sys/pal/xous/net/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 572dd6b3b63..572dd6b3b63 100644 --- a/library/std/src/sys/pal/xous/net/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs diff --git a/library/std/src/sys/pal/xous/net/udp.rs b/library/std/src/sys/net/connection/xous/udp.rs index 1b7ecac6d3a..1b7ecac6d3a 100644 --- a/library/std/src/sys/pal/xous/net/udp.rs +++ b/library/std/src/sys/net/connection/xous/udp.rs diff --git a/library/std/src/sys/net/mod.rs b/library/std/src/sys/net/mod.rs new file mode 100644 index 00000000000..5aa197fbc0d --- /dev/null +++ b/library/std/src/sys/net/mod.rs @@ -0,0 +1,36 @@ +cfg_if::cfg_if! { + if #[cfg(any( + all(target_family = "unix", not(target_os = "l4re")), + target_os = "windows", + target_os = "hermit", + all(target_os = "wasi", target_env = "p2"), + target_os = "solid_asp3", + ))] { + mod connection { + mod socket; + pub use socket::*; + } + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod connection { + mod sgx; + pub use sgx::*; + } + } else if #[cfg(all(target_os = "wasi", target_env = "p1"))] { + mod connection { + mod wasip1; + pub use wasip1::*; + } + } else if #[cfg(target_os = "xous")] { + mod connection { + mod xous; + pub use xous::*; + } + } else { + mod connection { + mod unsupported; + pub use unsupported::*; + } + } +} + +pub use connection::*; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index d833c9d632c..032007aa4dc 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -24,7 +24,6 @@ pub mod fd; pub mod fs; pub mod futex; pub mod io; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index ce8a2fed4bc..0f5935d0c71 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -17,7 +17,6 @@ pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; mod libunwind_integration; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/solid/error.rs b/library/std/src/sys/pal/solid/error.rs index e092497856d..b399463c0c2 100644 --- a/library/std/src/sys/pal/solid/error.rs +++ b/library/std/src/sys/pal/solid/error.rs @@ -1,6 +1,7 @@ pub use self::itron::error::{ItronError as SolidError, expect_success}; -use super::{abi, itron, net}; +use super::{abi, itron}; use crate::io::ErrorKind; +use crate::sys::net; /// Describe the specified SOLID error code. Returns `None` if it's an /// undefined error code. diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index d41042be518..caf848a4e9b 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -24,7 +24,6 @@ pub mod env; pub(crate) mod error; pub mod fs; pub mod io; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; @@ -51,7 +50,7 @@ pub fn unsupported_err() -> crate::io::Error { #[inline] pub fn is_interrupted(code: i32) -> bool { - net::is_interrupted(code) + crate::sys::net::is_interrupted(code) } pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind { diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index a9900f55b19..a9904e66664 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -15,7 +15,6 @@ pub mod env; pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/teeos/net.rs b/library/std/src/sys/pal/teeos/net.rs deleted file mode 100644 index fed95205027..00000000000 --- a/library/std/src/sys/pal/teeos/net.rs +++ /dev/null @@ -1,369 +0,0 @@ -use crate::fmt; -use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; -use crate::sys::unsupported; -use crate::time::Duration; - -pub struct TcpStream(!); - -impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> { - unsupported() - } - - pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> { - unsupported() - } - - pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { - self.0 - } - - pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { - self.0 - } - - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - self.0 - } - - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - self.0 - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - self.0 - } - - pub fn read(&self, _: &mut [u8]) -> io::Result<usize> { - self.0 - } - - pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> { - self.0 - } - - pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - self.0 - } - - pub fn is_read_vectored(&self) -> bool { - self.0 - } - - pub fn write(&self, _: &[u8]) -> io::Result<usize> { - self.0 - } - - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> { - self.0 - } - - pub fn is_write_vectored(&self) -> bool { - self.0 - } - - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - self.0 - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - self.0 - } - - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - self.0 - } - - pub fn duplicate(&self) -> io::Result<TcpStream> { - self.0 - } - - pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> { - self.0 - } - - pub fn linger(&self) -> io::Result<Option<Duration>> { - self.0 - } - - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn nodelay(&self) -> io::Result<bool> { - self.0 - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - self.0 - } - - pub fn ttl(&self) -> io::Result<u32> { - self.0 - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0 - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - self.0 - } -} - -impl fmt::Debug for TcpStream { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0 - } -} - -pub struct TcpListener(!); - -impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> { - unsupported() - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - self.0 - } - - pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - self.0 - } - - pub fn duplicate(&self) -> io::Result<TcpListener> { - self.0 - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - self.0 - } - - pub fn ttl(&self) -> io::Result<u32> { - self.0 - } - - pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn only_v6(&self) -> io::Result<bool> { - self.0 - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0 - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - self.0 - } -} - -impl fmt::Debug for TcpListener { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0 - } -} - -pub struct UdpSocket(!); - -impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { - unsupported() - } - - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - self.0 - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - self.0 - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.0 - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.0 - } - - pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> { - self.0 - } - - pub fn duplicate(&self) -> io::Result<UdpSocket> { - self.0 - } - - pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { - self.0 - } - - pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { - self.0 - } - - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - self.0 - } - - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - self.0 - } - - pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn broadcast(&self) -> io::Result<bool> { - self.0 - } - - pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn multicast_loop_v4(&self) -> io::Result<bool> { - self.0 - } - - pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - self.0 - } - - pub fn multicast_ttl_v4(&self) -> io::Result<u32> { - self.0 - } - - pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn multicast_loop_v6(&self) -> io::Result<bool> { - self.0 - } - - pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - self.0 - } - - pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - self.0 - } - - pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - self.0 - } - - pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - self.0 - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - self.0 - } - - pub fn ttl(&self) -> io::Result<u32> { - self.0 - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - self.0 - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - self.0 - } - - pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> { - self.0 - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - self.0 - } - - pub fn send(&self, _: &[u8]) -> io::Result<usize> { - self.0 - } - - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - self.0 - } -} - -impl fmt::Debug for UdpSocket { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0 - } -} - -pub struct LookupHost(!); - -impl LookupHost { - pub fn port(&self) -> u16 { - self.0 - } -} - -impl Iterator for LookupHost { - type Item = SocketAddr; - fn next(&mut self) -> Option<SocketAddr> { - self.0 - } -} - -impl TryFrom<&str> for LookupHost { - type Error = io::Error; - - fn try_from(_v: &str) -> io::Result<LookupHost> { - unsupported() - } -} - -impl<'a> TryFrom<(&'a str, u16)> for LookupHost { - type Error = io::Error; - - fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> { - unsupported() - } -} - -#[allow(nonstandard_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, - } -} - -pub type Socket = UdpSocket; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 111bed7a7eb..07025a304bf 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -19,8 +19,6 @@ pub mod fs; pub mod helpers; #[path = "../unsupported/io.rs"] pub mod io; -#[path = "../unsupported/net.rs"] -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs index 3077a72eac6..0757f1cb490 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/pal/uefi/process.rs @@ -1,6 +1,7 @@ use r_efi::protocols::simple_text_output; use super::helpers; +use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{OsStr, OsString}; use crate::num::{NonZero, NonZeroI32}; @@ -21,6 +22,7 @@ pub struct Command { args: Vec<OsString>, stdout: Option<Stdio>, stderr: Option<Stdio>, + env: CommandEnv, } // passed back to std::process with the pipes connected to the child, if any @@ -40,7 +42,13 @@ pub enum Stdio { impl Command { pub fn new(program: &OsStr) -> Command { - Command { prog: program.to_os_string(), args: Vec::new(), stdout: None, stderr: None } + Command { + prog: program.to_os_string(), + args: Vec::new(), + stdout: None, + stderr: None, + env: Default::default(), + } } pub fn arg(&mut self, arg: &OsStr) { @@ -48,7 +56,7 @@ impl Command { } pub fn env_mut(&mut self) -> &mut CommandEnv { - panic!("unsupported") + &mut self.env } pub fn cwd(&mut self, _dir: &OsStr) { @@ -76,7 +84,7 @@ impl Command { } pub fn get_envs(&self) -> CommandEnvs<'_> { - panic!("unsupported") + self.env.iter() } pub fn get_current_dir(&self) -> Option<&Path> { @@ -140,8 +148,30 @@ impl Command { cmd.stderr_inherit() }; + let env = env_changes(&self.env); + + // Set any new vars + if let Some(e) = &env { + for (k, (_, v)) in e { + match v { + Some(v) => crate::env::set_var(k, v), + None => crate::env::remove_var(k), + } + } + } + let stat = cmd.start_image()?; + // Rollback any env changes + if let Some(e) = env { + for (k, (v, _)) in e { + match v { + Some(v) => crate::env::set_var(k, v), + None => crate::env::remove_var(k), + } + } + } + let stdout = cmd.stdout()?; let stderr = cmd.stderr()?; @@ -725,3 +755,32 @@ mod uefi_command_internal { res.into_boxed_slice() } } + +/// Create a map of environment variable changes. Allows efficient setting and rolling back of +/// enviroment variable changes. +/// +/// Entry: (Old Value, New Value) +fn env_changes(env: &CommandEnv) -> Option<BTreeMap<EnvKey, (Option<OsString>, Option<OsString>)>> { + if env.is_unchanged() { + return None; + } + + let mut result = BTreeMap::<EnvKey, (Option<OsString>, Option<OsString>)>::new(); + + // Check if we want to clear all prior variables + if env.does_clear() { + for (k, v) in crate::env::vars_os() { + result.insert(k.into(), (Some(v), None)); + } + } + + for (k, v) in env.iter() { + let v: Option<OsString> = v.map(Into::into); + result + .entry(k.into()) + .and_modify(|cur| *cur = (cur.0.clone(), v.clone())) + .or_insert((crate::env::var_os(k), v)); + } + + Some(result) +} diff --git a/library/std/src/sys/pal/unix/l4re.rs b/library/std/src/sys/pal/unix/l4re.rs deleted file mode 100644 index 37dd370c514..00000000000 --- a/library/std/src/sys/pal/unix/l4re.rs +++ /dev/null @@ -1,564 +0,0 @@ -macro_rules! unimpl { - () => { - return Err(io::const_error!( - io::ErrorKind::Unsupported, - "No networking available on L4Re.", - )); - }; -} - -pub mod net { - #![allow(warnings)] - use crate::fmt; - use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; - use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; - use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; - use crate::sys::fd::FileDesc; - use crate::sys_common::{AsInner, FromInner, IntoInner}; - use crate::time::Duration; - - #[allow(unused_extern_crates)] - pub extern crate libc as netc; - - pub struct Socket(FileDesc); - impl Socket { - pub fn new(_: &SocketAddr, _: libc::c_int) -> io::Result<Socket> { - unimpl!(); - } - - pub fn new_raw(_: libc::c_int, _: libc::c_int) -> io::Result<Socket> { - unimpl!(); - } - - pub fn new_pair(_: libc::c_int, _: libc::c_int) -> io::Result<(Socket, Socket)> { - unimpl!(); - } - - pub fn connect_timeout(&self, _: &SocketAddr, _: Duration) -> io::Result<()> { - unimpl!(); - } - - pub fn accept( - &self, - _: *mut libc::sockaddr, - _: *mut libc::socklen_t, - ) -> io::Result<Socket> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result<Socket> { - unimpl!(); - } - - pub fn read(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> { - unimpl!(); - } - - pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - unimpl!(); - } - - pub fn is_read_vectored(&self) -> bool { - false - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn write(&self, _: &[u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> { - unimpl!(); - } - - pub fn is_write_vectored(&self) -> bool { - false - } - - pub fn set_timeout(&self, _: Option<Duration>, _: libc::c_int) -> io::Result<()> { - unimpl!(); - } - - pub fn timeout(&self, _: libc::c_int) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - unimpl!(); - } - - pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn linger(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn nodelay(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unimpl!(); - } - - // This is used by sys_common code to abstract over Windows and Unix. - pub fn as_raw(&self) -> RawFd { - self.as_raw_fd() - } - } - - impl AsInner<FileDesc> for Socket { - #[inline] - fn as_inner(&self) -> &FileDesc { - &self.0 - } - } - - impl FromInner<FileDesc> for Socket { - fn from_inner(file_desc: FileDesc) -> Socket { - Socket(file_desc) - } - } - - impl IntoInner<FileDesc> for Socket { - fn into_inner(self) -> FileDesc { - self.0 - } - } - - impl AsFd for Socket { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } - } - - impl AsRawFd for Socket { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } - } - - impl IntoRawFd for Socket { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } - } - - impl FromRawFd for Socket { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FromRawFd::from_raw_fd(raw_fd)) - } - } - - pub struct TcpStream { - inner: Socket, - } - - impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> { - unimpl!(); - } - - pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> { - unimpl!(); - } - - #[inline] - pub fn socket(&self) -> &Socket { - &self.inner - } - - pub fn into_socket(self) -> Socket { - self.inner - } - - pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn read(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> { - unimpl!(); - } - - pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - unimpl!(); - } - - pub fn is_read_vectored(&self) -> bool { - false - } - - pub fn write(&self, _: &[u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> { - unimpl!(); - } - - pub fn is_write_vectored(&self) -> bool { - false - } - - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - unimpl!(); - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - unimpl!(); - } - - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result<TcpStream> { - unimpl!(); - } - - pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn linger(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn nodelay(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result<u32> { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner<Socket> for TcpStream { - fn from_inner(socket: Socket) -> TcpStream { - TcpStream { inner: socket } - } - } - - impl fmt::Debug for TcpStream { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "No networking support available on L4Re") - } - } - - pub struct TcpListener { - inner: Socket, - } - - impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> { - unimpl!(); - } - - #[inline] - pub fn socket(&self) -> &Socket { - &self.inner - } - - pub fn into_socket(self) -> Socket { - self.inner - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - unimpl!(); - } - - pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result<TcpListener> { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result<u32> { - unimpl!(); - } - - pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn only_v6(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner<Socket> for TcpListener { - fn from_inner(socket: Socket) -> TcpListener { - TcpListener { inner: socket } - } - } - - impl fmt::Debug for TcpListener { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "No networking support available on L4Re.") - } - } - - pub struct UdpSocket { - inner: Socket, - } - - impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> { - unimpl!(); - } - - #[inline] - pub fn socket(&self) -> &Socket { - &self.inner - } - - pub fn into_socket(self) -> Socket { - self.inner - } - - pub fn peer_addr(&self) -> io::Result<SocketAddr> { - unimpl!(); - } - - pub fn socket_addr(&self) -> io::Result<SocketAddr> { - unimpl!(); - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result<UdpSocket> { - unimpl!(); - } - - pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> { - unimpl!(); - } - - pub fn read_timeout(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn write_timeout(&self) -> io::Result<Option<Duration>> { - unimpl!(); - } - - pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn broadcast(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_loop_v4(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_ttl_v4(&self) -> io::Result<u32> { - unimpl!(); - } - - pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_loop_v6(&self) -> io::Result<bool> { - unimpl!(); - } - - pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - unimpl!(); - } - - pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - unimpl!(); - } - - pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result<u32> { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result<Option<io::Error>> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn send(&self, _: &[u8]) -> io::Result<usize> { - unimpl!(); - } - - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner<Socket> for UdpSocket { - fn from_inner(socket: Socket) -> UdpSocket { - UdpSocket { inner: socket } - } - } - - impl fmt::Debug for UdpSocket { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "No networking support on L4Re available.") - } - } - - pub struct LookupHost { - original: *mut libc::addrinfo, - cur: *mut libc::addrinfo, - } - - impl Iterator for LookupHost { - type Item = SocketAddr; - fn next(&mut self) -> Option<SocketAddr> { - None - } - } - - impl LookupHost { - pub fn port(&self) -> u16 { - 0 // unimplemented - } - } - - unsafe impl Sync for LookupHost {} - unsafe impl Send for LookupHost {} - - impl TryFrom<&str> for LookupHost { - type Error = io::Error; - - fn try_from(_v: &str) -> io::Result<LookupHost> { - unimpl!(); - } - } - - impl<'a> TryFrom<(&'a str, u16)> for LookupHost { - type Error = io::Error; - - fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> { - unimpl!(); - } - } -} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 3cc1cae8d00..6862399b942 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -14,14 +14,8 @@ pub mod futex; pub mod io; #[cfg(any(target_os = "linux", target_os = "android"))] pub mod kernel_copy; -#[cfg(target_os = "l4re")] -mod l4re; #[cfg(target_os = "linux")] pub mod linux; -#[cfg(not(target_os = "l4re"))] -pub mod net; -#[cfg(target_os = "l4re")] -pub use self::l4re::net; pub mod os; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 01d516f7568..4941dd4918c 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -4,7 +4,6 @@ pub mod args; pub mod env; pub mod fs; pub mod io; -pub mod net; pub mod os; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 361802d101d..312ad28ab51 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -22,7 +22,6 @@ pub mod fs; pub mod futex; pub mod io; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; @@ -45,5 +44,4 @@ mod helpers; // import conflict rules. If we glob export `helpers` and `common` together, // then the compiler complains about conflicts. -use helpers::err2io; -pub use helpers::{abort_internal, decode_error_kind, is_interrupted}; +pub(crate) use helpers::{abort_internal, decode_error_kind, err2io, is_interrupted}; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 320712fdcc9..234e946d3b8 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -20,7 +20,6 @@ pub mod futex; #[path = "../wasi/io.rs"] pub mod io; -pub mod net; #[path = "../wasi/os.rs"] pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 41fe019f110..1280f353200 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -23,8 +23,6 @@ pub mod env; pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; -#[path = "../unsupported/net.rs"] -pub mod net; #[path = "../unsupported/os.rs"] pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 4282dbb5493..f9aa049ca9a 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -22,7 +22,6 @@ pub mod fs; pub mod futex; pub mod handle; pub mod io; -pub mod net; pub mod os; pub mod pipe; pub mod process; @@ -63,7 +62,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { // SAFETY: must be called only once during runtime cleanup. // NOTE: this is not guaranteed to run, for example when the program aborts. pub unsafe fn cleanup() { - net::cleanup(); + crate::sys::net::cleanup(); } #[inline] diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index a64cd068560..8ba2b6e2f20 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -7,7 +7,6 @@ pub mod env; pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 6ea05772029..9e9ae861070 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -18,8 +18,6 @@ pub mod env; pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; -#[path = "../unsupported/net.rs"] -pub mod net; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 4f7a131f6bb..959fbd4ca0a 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -26,20 +26,6 @@ pub mod process; pub mod wstr; pub mod wtf8; -cfg_if::cfg_if! { - if #[cfg(any( - all(unix, not(target_os = "l4re")), - windows, - target_os = "hermit", - target_os = "solid_asp3", - all(target_os = "wasi", target_env = "p2") - ))] { - pub mod net; - } else { - pub use crate::sys::net; - } -} - // common error constructors /// A trait for viewing representations from std types diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md index 17ea225805b..dba2c4b2aaf 100644 --- a/src/doc/rustc/src/platform-support/apple-darwin.md +++ b/src/doc/rustc/src/platform-support/apple-darwin.md @@ -30,6 +30,18 @@ The current default deployment target for `rustc` can be retrieved with [deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html [rustc-print]: ../command-line-arguments.md#option-print +### Host tooling + +The minimum supported OS versions for the host tooling (`rustc`, `cargo`, +etc.) are currently the same as for applications, namely 10.12 on x86 and 11.0 +on ARM64. +The minimum supported Xcode version is 9.2. + +Building from source likely requires that you can build LLVM from source too, +which [currently][llvm-os] requires Xcode 10.0 and macOS 10.13 (for LLVM 19). + +[llvm-os]: https://releases.llvm.org/19.1.0/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library + ### Binary format The default binary format is Mach-O, the executable format used on Apple's diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 70749f7cb17..d9bd11267da 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -33,6 +33,7 @@ features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] [build-dependencies] sha2 = "0.10.8" +minifier = { version = "0.3.2", default-features = false } [dev-dependencies] expect-test = "1.4.0" diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs index b4b0a8d0615..07269d5bdc2 100644 --- a/src/librustdoc/build.rs +++ b/src/librustdoc/build.rs @@ -1,3 +1,6 @@ +use std::str; + +use sha2::Digest; fn main() { // generate sha256 files // this avoids having to perform hashing at runtime @@ -40,14 +43,27 @@ fn main() { for path in files { let inpath = format!("html/{path}"); println!("cargo::rerun-if-changed={inpath}"); - let bytes = std::fs::read(inpath).expect("static path exists"); - use sha2::Digest; - let bytes = sha2::Sha256::digest(bytes); - let mut digest = format!("-{bytes:x}"); + let data_bytes = std::fs::read(&inpath).expect("static path exists"); + let hash_bytes = sha2::Sha256::digest(&data_bytes); + let mut digest = format!("-{hash_bytes:x}"); digest.truncate(9); let outpath = std::path::PathBuf::from(format!("{out_dir}/{path}.sha256")); std::fs::create_dir_all(outpath.parent().expect("all file paths are in a directory")) .expect("should be able to write to out_dir"); std::fs::write(&outpath, digest.as_bytes()).expect("write to out_dir"); + let minified_path = std::path::PathBuf::from(format!("{out_dir}/{path}.min")); + if path.ends_with(".js") || path.ends_with(".css") { + let minified: String = if path.ends_with(".css") { + minifier::css::minify(str::from_utf8(&data_bytes).unwrap()) + .unwrap() + .to_string() + .into() + } else { + minifier::js::minify(str::from_utf8(&data_bytes).unwrap()).to_string().into() + }; + std::fs::write(&minified_path, minified.as_bytes()).expect("write to out_dir"); + } else { + std::fs::copy(&inpath, &minified_path).unwrap(); + } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 55bd7da8816..b14381c0c40 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -516,8 +516,7 @@ fn projection_to_path_segment<'tcx>( ty.map_bound(|ty| &ty.args[generics.parent_count..]), false, def_id, - ) - .into(), + ), constraints: Default::default(), }, } @@ -2214,8 +2213,7 @@ pub(crate) fn clean_middle_ty<'tcx>( alias_ty.map_bound(|ty| ty.args.as_slice()), true, def_id, - ) - .into(), + ), constraints: Default::default(), }, }, @@ -2533,7 +2531,7 @@ fn clean_generic_args<'tcx>( ) -> GenericArgs { // FIXME(return_type_notation): Fix RTN parens rendering if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() { - let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into(); + let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::<ThinVec<_>>().into(); let output = match output.kind { hir::TyKind::Tup(&[]) => None, _ => Some(Box::new(clean_ty(output, cx))), @@ -2554,7 +2552,7 @@ fn clean_generic_args<'tcx>( } hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) - .collect::<Vec<_>>() + .collect::<ThinVec<_>>() .into(); let constraints = generic_args .constraints diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a44d74e6df6..583cd404dca 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2246,8 +2246,8 @@ impl GenericArg { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericArgs { - AngleBracketed { args: Box<[GenericArg]>, constraints: ThinVec<AssocItemConstraint> }, - Parenthesized { inputs: Box<[Type]>, output: Option<Box<Type>> }, + AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> }, + Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> }, } impl GenericArgs { @@ -2271,7 +2271,7 @@ impl GenericArgs { assoc: PathSegment { name: sym::Output, args: GenericArgs::AngleBracketed { - args: Vec::new().into_boxed_slice(), + args: ThinVec::new(), constraints: ThinVec::new(), }, }, @@ -2588,12 +2588,12 @@ mod size_asserts { static_assert_size!(Crate, 56); // frequently moved by-value static_assert_size!(DocFragment, 32); static_assert_size!(GenericArg, 32); - static_assert_size!(GenericArgs, 32); + static_assert_size!(GenericArgs, 24); static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); static_assert_size!(Item, 48); static_assert_size!(ItemKind, 48); - static_assert_size!(PathSegment, 40); + static_assert_size!(PathSegment, 32); static_assert_size!(Type, 32); // tidy-alphabetical-end } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index f1921b90cc6..8a7d140bb1a 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -81,11 +81,11 @@ pub(crate) fn clean_middle_generic_args<'tcx>( args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, mut has_self: bool, owner: DefId, -) -> Vec<GenericArg> { +) -> ThinVec<GenericArg> { let (args, bound_vars) = (args.skip_binder(), args.bound_vars()); if args.is_empty() { // Fast path which avoids executing the query `generics_of`. - return Vec::new(); + return ThinVec::new(); } // If the container is a trait object type, the arguments won't contain the self type but the @@ -144,7 +144,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( }; let offset = if has_self { 1 } else { 0 }; - let mut clean_args = Vec::with_capacity(args.len().saturating_sub(offset)); + let mut clean_args = ThinVec::with_capacity(args.len().saturating_sub(offset)); clean_args.extend(args.iter().enumerate().rev().filter_map(clean_arg)); clean_args.reverse(); clean_args diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index c6fb70eee08..fd4d9845c89 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -489,7 +489,7 @@ impl Options { let to_check = matches.opt_strs("check-theme"); if !to_check.is_empty() { let mut content = - std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap(); + std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap(); if let Some((_, inside)) = content.split_once("/* Begin theme: light */") { content = inside; } @@ -638,7 +638,7 @@ impl Options { let mut themes = Vec::new(); if matches.opt_present("theme") { let mut content = - std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.bytes).unwrap(); + std::str::from_utf8(static_files::STATIC_FILES.rustdoc_css.src_bytes).unwrap(); if let Some((_, inside)) = content.split_once("/* Begin theme: light */") { content = inside; } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e4a9a2b512e..8ac8b3a1f84 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -821,7 +821,7 @@ pub(crate) fn get_function_type_for_search( .map(|name| clean::PathSegment { name: *name, args: clean::GenericArgs::AngleBracketed { - args: Vec::new().into_boxed_slice(), + args: ThinVec::new(), constraints: ThinVec::new(), }, }) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index fb6f3bc2c76..57d07c05c11 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -207,14 +207,8 @@ fn write_static_files( if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) { static_files::for_each(|f: &static_files::StaticFile| { let filename = static_dir.join(f.output_filename()); - let contents: &[u8]; - let contents_vec: Vec<u8>; - if opt.disable_minification { - contents = f.bytes; - } else { - contents_vec = f.minified(); - contents = &contents_vec; - }; + let contents: &[u8] = + if opt.disable_minification { f.src_bytes } else { f.minified_bytes }; fs::write(&filename, contents).map_err(|e| PathError::new(e, &filename)) })?; } diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 0bcaf11da0c..45589a37069 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -8,26 +8,18 @@ use std::{fmt, str}; pub(crate) struct StaticFile { pub(crate) filename: PathBuf, - pub(crate) bytes: &'static [u8], + pub(crate) src_bytes: &'static [u8], + pub(crate) minified_bytes: &'static [u8], } impl StaticFile { - fn new(filename: &str, bytes: &'static [u8], sha256: &'static str) -> StaticFile { - Self { filename: static_filename(filename, sha256), bytes } - } - - pub(crate) fn minified(&self) -> Vec<u8> { - let extension = match self.filename.extension() { - Some(e) => e, - None => return self.bytes.to_owned(), - }; - if extension == "css" { - minifier::css::minify(str::from_utf8(self.bytes).unwrap()).unwrap().to_string().into() - } else if extension == "js" { - minifier::js::minify(str::from_utf8(self.bytes).unwrap()).to_string().into() - } else { - self.bytes.to_owned() - } + fn new( + filename: &str, + src_bytes: &'static [u8], + minified_bytes: &'static [u8], + sha256: &'static str, + ) -> StaticFile { + Self { filename: static_filename(filename, sha256), src_bytes, minified_bytes } } pub(crate) fn output_filename(&self) -> &Path { @@ -68,7 +60,7 @@ macro_rules! static_files { // sha256 files are generated in build.rs pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles { - $($field: StaticFile::new($file_path, include_bytes!($file_path), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+ + $($field: StaticFile::new($file_path, include_bytes!($file_path), include_bytes!(concat!(env!("OUT_DIR"), "/", $file_path, ".min")), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+ }); pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index afe81937495..fcee2960979 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -231,11 +231,11 @@ impl FromClean<clean::GenericArgs> for GenericArgs { use clean::GenericArgs::*; match args { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { - args: args.into_vec().into_json(renderer), + args: args.into_json(renderer), constraints: constraints.into_json(renderer), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { - inputs: inputs.into_vec().into_json(renderer), + inputs: inputs.into_json(renderer), output: output.map(|a| (*a).into_json(renderer)), }, } diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 8d99924a2d1..33dc57cbc07 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -338,6 +338,18 @@ impl Rustc { self } + /// Specify `-C debuginfo=...`. + pub fn debuginfo(&mut self, level: &str) -> &mut Self { + self.cmd.arg(format!("-Cdebuginfo={level}")); + self + } + + /// Specify `-C split-debuginfo={packed,unpacked,off}`. + pub fn split_debuginfo(&mut self, split_kind: &str) -> &mut Self { + self.cmd.arg(format!("-Csplit-debuginfo={split_kind}")); + self + } + /// Pass the `--verbose` flag. pub fn verbose(&mut self) -> &mut Self { self.cmd.arg("--verbose"); diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index 7ebe4a9ca13..ceb4ebbaca5 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -238,9 +238,7 @@ pub fn set_permissions<P: AsRef<Path>>(path: P, perm: std::fs::Permissions) { )); } -/// A function which prints all file names in the directory `dir` similarly to Unix's `ls`. -/// Useful for debugging. -/// Usage: `eprintln!("{:#?}", shallow_find_dir_entries(some_dir));` +/// List directory entries immediately under the given `dir`. #[track_caller] pub fn shallow_find_dir_entries<P: AsRef<Path>>(dir: P) -> Vec<PathBuf> { let paths = read_dir(dir); diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index a8c9bec57fd..7e63ab3159a 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -94,8 +94,8 @@ pub use artifact_names::{ /// Path-related helpers. pub use path_helpers::{ - cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, has_suffix, - not_contains, path, shallow_find_files, build_root, source_root, + build_root, cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, + has_suffix, not_contains, path, shallow_find_directories, shallow_find_files, source_root, }; /// Helpers for scoped test execution where certain properties are attempted to be maintained. diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs index 1c59f2feea4..b766e50e523 100644 --- a/src/tools/run-make-support/src/path_helpers.rs +++ b/src/tools/run-make-support/src/path_helpers.rs @@ -59,6 +59,25 @@ pub fn shallow_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>( matching_files } +/// Browse the directory `path` non-recursively and return all directories which respect the +/// parameters outlined by `closure`. +#[track_caller] +pub fn shallow_find_directories<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>( + path: P, + filter: F, +) -> Vec<PathBuf> { + let mut matching_files = Vec::new(); + for entry in rfs::read_dir(path) { + let entry = entry.expect("failed to read directory entry."); + let path = entry.path(); + + if path.is_dir() && filter(&path) { + matching_files.push(path); + } + } + matching_files +} + /// Returns true if the filename at `path` does not contain `expected`. pub fn not_contains<P: AsRef<Path>>(path: P, expected: &str) -> bool { !path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(expected)) diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 45b40b17ea3..e69de29bb2d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1 +0,0 @@ -run-make/split-debuginfo/Makefile diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 17786ed6d2f..39c9a148e9e 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2218,26 +2218,12 @@ ui/issues/issue-3993.rs ui/issues/issue-39970.rs ui/issues/issue-39984.rs ui/issues/issue-40000.rs -ui/issues/issue-40136.rs -ui/issues/issue-40235.rs ui/issues/issue-4025.rs ui/issues/issue-40288-2.rs ui/issues/issue-40288.rs -ui/issues/issue-40350.rs -ui/issues/issue-40408.rs -ui/issues/issue-40610.rs -ui/issues/issue-40749.rs -ui/issues/issue-40782.rs -ui/issues/issue-40827.rs -ui/issues/issue-40845.rs -ui/issues/issue-40861.rs -ui/issues/issue-40883.rs ui/issues/issue-40951.rs ui/issues/issue-41053.rs -ui/issues/issue-41139.rs -ui/issues/issue-41213.rs ui/issues/issue-41229-ref-str.rs -ui/issues/issue-41272.rs ui/issues/issue-41298.rs ui/issues/issue-41479.rs ui/issues/issue-41498.rs @@ -2360,7 +2346,6 @@ ui/issues/issue-4830.rs ui/issues/issue-48364.rs ui/issues/issue-48728.rs ui/issues/issue-4875.rs -ui/issues/issue-48838.rs ui/issues/issue-48984.rs ui/issues/issue-49298.rs ui/issues/issue-4935.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index d66ba157d10..fe51231c481 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1658; +const ISSUES_ENTRY_LIMIT: u32 = 1634; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs index fb3a325a41f..b3bfc66a5a5 100644 --- a/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs +++ b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs @@ -242,22 +242,6 @@ pub unsafe extern "ptx-kernel" fn f_float_array_arg(_a: [f32; 5]) {} //pub unsafe extern "ptx-kernel" fn f_u128_array_arg(_a: [u128; 5]) {} // CHECK: .visible .entry f_u32_slice_arg( -// CHECK: .param .u64 f_u32_slice_arg_param_0 -// CHECK: .param .u64 f_u32_slice_arg_param_1 +// CHECK: .param .align 8 .b8 f_u32_slice_arg_param_0[16] #[no_mangle] pub unsafe extern "ptx-kernel" fn f_u32_slice_arg(_a: &[u32]) {} - -// CHECK: .visible .entry f_tuple_u8_u8_arg( -// CHECK: .param .align 1 .b8 f_tuple_u8_u8_arg_param_0[2] -#[no_mangle] -pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_arg(_a: (u8, u8)) {} - -// CHECK: .visible .entry f_tuple_u32_u32_arg( -// CHECK: .param .align 4 .b8 f_tuple_u32_u32_arg_param_0[8] -#[no_mangle] -pub unsafe extern "ptx-kernel" fn f_tuple_u32_u32_arg(_a: (u32, u32)) {} - -// CHECK: .visible .entry f_tuple_u8_u8_u32_arg( -// CHECK: .param .align 4 .b8 f_tuple_u8_u8_u32_arg_param_0[8] -#[no_mangle] -pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_u32_arg(_a: (u8, u8, u32)) {} diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir deleted file mode 100644 index f53c9199a49..00000000000 --- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir +++ /dev/null @@ -1,71 +0,0 @@ -// MIR for `droppy` after built - -fn droppy() -> () { - let mut _0: (); - let _1: (); - let _2: Droppy; - let _4: Droppy; - let mut _5: isize; - let mut _6: u8; - let mut _7: bool; - let _8: Droppy; - scope 1 { - debug x => _2; - scope 2 { - debug y => _3; - } - scope 3 { - let _3: usize; - } - } - scope 4 { - debug z => _8; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - _2 = Droppy::C; - FakeRead(ForLet(None), _2); - StorageLive(_3); - StorageLive(_4); - _4 = move _2; - _5 = discriminant(_4); - _6 = copy _5 as u8 (IntToInt); - _7 = Le(copy _6, const 2_u8); - assume(move _7); - _3 = move _5 as usize (IntToInt); - drop(_4) -> [return: bb1, unwind: bb4]; - } - - bb1: { - StorageDead(_4); - FakeRead(ForLet(None), _3); - _1 = const (); - StorageDead(_3); - drop(_2) -> [return: bb2, unwind: bb5]; - } - - bb2: { - StorageDead(_2); - StorageDead(_1); - StorageLive(_8); - _8 = Droppy::B; - FakeRead(ForLet(None), _8); - _0 = const (); - drop(_8) -> [return: bb3, unwind: bb5]; - } - - bb3: { - StorageDead(_8); - return; - } - - bb4 (cleanup): { - drop(_2) -> [return: bb5, unwind terminate(cleanup)]; - } - - bb5 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs index 7ff0cdbfe8d..4fb9a27e309 100644 --- a/tests/mir-opt/building/enum_cast.rs +++ b/tests/mir-opt/building/enum_cast.rs @@ -41,27 +41,6 @@ fn far(far: Far) -> isize { far as isize } -// EMIT_MIR enum_cast.droppy.built.after.mir -enum Droppy { - A, - B, - C, -} - -impl Drop for Droppy { - fn drop(&mut self) {} -} - -fn droppy() { - { - let x = Droppy::C; - // remove this entire test once `cenum_impl_drop_cast` becomes a hard error - #[allow(cenum_impl_drop_cast)] - let y = x as usize; - } - let z = Droppy::B; -} - #[repr(i16)] enum SignedAroundZero { A = -2, diff --git a/tests/run-make/split-debuginfo/Makefile b/tests/run-make/split-debuginfo/Makefile deleted file mode 100644 index 5f463ffe8cd..00000000000 --- a/tests/run-make/split-debuginfo/Makefile +++ /dev/null @@ -1,371 +0,0 @@ -# ignore-cross-compile -# ignore-riscv64 On this platform only `-Csplit-debuginfo=off` is supported, see #120518 - -include ../tools.mk - -all: off packed unpacked - -ifeq ($(UNAME),Darwin) -# If disabled, don't run `dsymutil`. -off: - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g -C split-debuginfo=off - [ ! -d $(TMPDIR)/foo.dSYM ] - -# Packed by default, but only if debuginfo is requested -packed: - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs - [ ! -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g - [ -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - $(RUSTC) foo.rs -g -C split-debuginfo=packed - [ -d $(TMPDIR)/foo.dSYM ] - rm -rf $(TMPDIR)/*.dSYM - -# Object files are preserved with unpacked and `dsymutil` isn't run -unpacked: - $(RUSTC) foo.rs -g -C split-debuginfo=unpacked - ls $(TMPDIR)/*.o - [ ! -d $(TMPDIR)/foo.dSYM ] -else -ifdef IS_WINDOWS -# Windows only supports packed debuginfo - nothing to test. -off: -packed: -unpacked: -else -# Some non-Windows, non-Darwin platforms are not stable, and some are. -ifeq ($(UNAME),Linux) - UNSTABLEOPTS := -else - UNSTABLEOPTS := -Zunstable-options -endif - -# - Debuginfo in `.o` files -# - `.o` deleted -# - `.dwo` never created -# - `.dwp` never created -off: - $(RUSTC) foo.rs -g -C $(UNSTABLEOPTS) split-debuginfo=off - [ ! -f $(TMPDIR)/*.dwp ] - [ ! -f $(TMPDIR)/*.dwo ] - $(RUSTC) foo.rs -g - [ ! -f $(TMPDIR)/*.dwp ] - [ ! -f $(TMPDIR)/*.dwo ] - -packed: packed-split packed-single packed-lto packed-remapped packed-crosscrate - -# - Debuginfo in `.dwo` files -# - `.o` deleted -# - `.dwo` deleted -# - `.dwp` present -packed-split: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=packed -Zsplit-dwarf-kind=split - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` deleted -# - `.dwo` never created -# - `.dwp` present -packed-single: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=packed -Zsplit-dwarf-kind=single - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -packed-lto: packed-lto-split packed-lto-single - -# - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated -# - `.o` never created -# - `.dwo` never created -# - `.dwp` never created -packed-lto-split: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split \ - --crate-type=rlib -Clinker-plugin-lto - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - -# - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated -# - `.o` never created -# - `.dwo` never created -# - `.dwp` never created -packed-lto-single: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single \ - --crate-type=rlib -Clinker-plugin-lto - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - -packed-remapped: packed-remapped-split packed-remapped-single packed-remapped-scope packed-remapped-wrong-scope - -# - Debuginfo in `.dwo` files -# - `.o` and binary refer to remapped `.dwo` paths which do not exist -# - `.o` deleted -# - `.dwo` deleted -# - `.dwp` present -packed-remapped-split: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -C debuginfo=2 \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` deleted -# - `.dwo` never created -# - `.dwp` present -packed-remapped-single: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` deleted -# - `.dwo` never created -# - `.dwp` present -packed-remapped-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` deleted -# - `.dwo` never created -# - `.dwp` present -packed-remapped-wrong-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=packed -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/foo.dwp - rm $(TMPDIR)/$(call BIN,foo) - -packed-crosscrate: packed-crosscrate-split packed-crosscrate-single - -# - Debuginfo in `.dwo` files -# - (bar) `.rlib` file created, contains `.dwo` -# - (bar) `.o` deleted -# - (bar) `.dwo` deleted -# - (bar) `.dwp` never created -# - (main) `.o` deleted -# - (main) `.dwo` deleted -# - (main) `.dwp` present -packed-crosscrate-split: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=packed \ - -Zsplit-dwarf-kind=split -C debuginfo=2 -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=packed -Zsplit-dwarf-kind=split -C debuginfo=2 -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/main.dwp - rm $(TMPDIR)/$(call BIN,main) - -# - Debuginfo in `.o` files -# - (bar) `.rlib` file created, contains `.o` -# - (bar) `.o` deleted -# - (bar) `.dwo` never created -# - (bar) `.dwp` never created -# - (main) `.o` deleted -# - (main) `.dwo` never created -# - (main) `.dwp` present -packed-crosscrate-single: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=packed \ - -Zsplit-dwarf-kind=single -C debuginfo=2 -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=packed -Zsplit-dwarf-kind=single -C debuginfo=2 -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - rm $(TMPDIR)/main.dwp - rm $(TMPDIR)/$(call BIN,main) - -unpacked: unpacked-split unpacked-single unpacked-lto unpacked-remapped unpacked-crosscrate - -# - Debuginfo in `.dwo` files -# - `.o` deleted -# - `.dwo` present -# - `.dwp` never created -unpacked-split: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=unpacked -Zsplit-dwarf-kind=split - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` present -# - `.dwo` never created -# - `.dwp` never created -unpacked-single: - $(RUSTC) foo.rs -g $(UNSTABLEOPTS) -C split-debuginfo=unpacked -Zsplit-dwarf-kind=single - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -unpacked-lto: unpacked-lto-split unpacked-lto-single - -# - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated -# - `.o` present (bitcode) -# - `.dwo` never created -# - `.dwp` never created -unpacked-lto-split: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=split \ - --crate-type=rlib -Clinker-plugin-lto - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - -# - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated -# - `.o` present (bitcode) -# - `.dwo` never created -# - `.dwp` never created -unpacked-lto-single: - $(RUSTC) baz.rs -g $(UNSTABLEOPTS) -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single \ - --crate-type=rlib -Clinker-plugin-lto - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/libbaz.rlib - -unpacked-remapped: unpacked-remapped-split unpacked-remapped-single unpacked-remapped-scope unpacked-remapped-wrong-scope - -# - Debuginfo in `.dwo` files -# - `.o` and binary refer to remapped `.dwo` paths which do not exist -# - `.o` deleted -# - `.dwo` present -# - `.dwp` never created -unpacked-remapped-split: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -C debuginfo=2 \ - -Z split-dwarf-kind=split --remap-path-prefix $(TMPDIR)=/a foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` present -# - `.dwo` never created -# - `.dwp` never created -unpacked-remapped-single: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` present -# - `.dwo` never created -# - `.dwp` never created -unpacked-remapped-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=debuginfo foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -# - Debuginfo in `.o` files -# - `.o` and binary refer to remapped `.o` paths which do not exist -# - `.o` present -# - `.dwo` never created -# - `.dwp` never created -unpacked-remapped-wrong-scope: - $(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -C debuginfo=2 \ - -Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a \ - -Z remap-path-scope=macro foo.rs -g - objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (grep $(TMPDIR)) || exit 1 - rm $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,foo) - -unpacked-crosscrate: unpacked-crosscrate-split unpacked-crosscrate-single - -# - Debuginfo in `.dwo` files -# - (bar) `.rlib` file created, contains `.dwo` -# - (bar) `.o` deleted -# - (bar) `.dwo` present -# - (bar) `.dwp` never created -# - (main) `.o` deleted -# - (main) `.dwo` present -# - (main) `.dwp` never created -unpacked-crosscrate-split: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=unpacked \ - -Zsplit-dwarf-kind=split -C debuginfo=2 -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o && exit 1 || exit 0 - ls $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=unpacked -Zsplit-dwarf-kind=split -C debuginfo=2 -g main.rs - ls $(TMPDIR)/*.o && exit 1 || exit 0 - rm $(TMPDIR)/*.dwo - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,main) - -# - Debuginfo in `.o` files -# - (bar) `.rlib` file created, contains `.o` -# - (bar) `.o` present -# - (bar) `.dwo` never created -# - (bar) `.dwp` never created -# - (main) `.o` present -# - (main) `.dwo` never created -# - (main) `.dwp` never created -unpacked-crosscrate-single: - $(RUSTC) --crate-type lib $(UNSTABLEOPTS) -C split-debuginfo=unpacked \ - -Zsplit-dwarf-kind=single -C debuginfo=2 -g bar.rs - ls $(TMPDIR)/*.rlib - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - $(RUSTC) --extern bar=$(TMPDIR)/libbar.rlib $(UNSTABLEOPTS) \ - -C split-debuginfo=unpacked -Zsplit-dwarf-kind=single -C debuginfo=2 -g main.rs - ls $(TMPDIR)/*.o - ls $(TMPDIR)/*.dwo && exit 1 || exit 0 - ls $(TMPDIR)/*.dwp && exit 1 || exit 0 - rm $(TMPDIR)/$(call BIN,main) -endif -endif diff --git a/tests/run-make/split-debuginfo/rmake.rs b/tests/run-make/split-debuginfo/rmake.rs new file mode 100644 index 00000000000..530a5d119f1 --- /dev/null +++ b/tests/run-make/split-debuginfo/rmake.rs @@ -0,0 +1,1618 @@ +// ignore-tidy-linelength +//! Basic smoke tests for behavior of `-C split-debuginfo` and the combined behavior when used in +//! conjunction with other flags such as: +//! +//! - `--remap-path-prefix`: see +//! <https://doc.rust-lang.org/rustc/command-line-arguments.html#--remap-path-prefix-remap-source-names-in-output>. +//! - `-Z remap-path-scope`: see +//! - <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/remap-path-scope.html> +//! - <https://github.com/rust-lang/rust/issues/111540> +//! - RFC #3127 trim-paths: <https://github.com/rust-lang/rfcs/pull/3127> +//! - `-Z split-dwarf-kind`: see <https://github.com/rust-lang/rust/pull/89819>. +//! - `-Clinker-plugin-lto`: see <https://doc.rust-lang.org/rustc/linker-plugin-lto.html>. +//! +//! # Test implementation remark +//! +//! - The pattern match on enum variants are intentional, because I find that they are very +//! revealing with respect to the kind of test coverage that we have and don't have. +//! +//! # Known limitations +//! +//! - The linux test coverage of cross-interactions between `-C split-debuginfo` and other flags are +//! significantly higher than the lack of such coverage for Windows and Darwin. +//! - windows-gnu is not tested at all, see the `FIXME(#135531)`s below. +//! - This test for the most part merely checks for existence/absence of certain artifacts, it does +//! not sanity check if the debuginfo artifacts are actually usable or contains the expected +//! amount/quality of debuginfo, especially on windows-msvc and darwin. +//! - FIXME(#111540): this test has insufficient coverage in relation to trim-paths RFC, see also +//! the comment <https://github.com/rust-lang/rust/issues/111540#issuecomment-1994010274>. The +//! basic `llvm-dwarfdump` textual output inspection here is very fragile. The original `Makefile` +//! version used `objdump` (not to be confused with `llvm-objdump`) but inspected the wrong line +//! because it was looking at `DW_AT_GNU_dwo_name` when it should've been looking at +//! `DW_AT_comp_dir`. +//! - This test does not have good coverage for what values of `-Csplit-debuginfo` are stable vs +//! non-stable for the various targets, i.e. which values *should* be gated behind +//! `-Zunstable-options` for a given target. The `Makefile` version yolo'd a `-Zunstable-options` +//! for non-windows + non-linux + non-darwin, but had a misplaced interpolation which suggested to +//! me that that conditional `-Zunstable-options` never actually materialized. +//! +//! # Additional references +//! +//! - Apple `.dSYM` debug symbol bundles: <https://lldb.llvm.org/use/symbols.html>. +//! - LLVM `dsymutil`: <https://llvm.org/docs/CommandGuide/dsymutil.html>. + +// NOTE: this is a host test +//@ ignore-cross-compile + +// NOTE: this seems to be a host test, and testing on host `riscv64-gc-unknown-linux-gnu` reveals +// that this test is failing because of [MC: "error: A dwo section may not contain relocations" when +// building with fission + RISCV64 #56642](https://github.com/llvm/llvm-project/issues/56642). This +// test is ignored for now to unblock efforts to bring riscv64 targets to be exercised in CI, cf. +// [Enable riscv64gc-gnu testing #126641](https://github.com/rust-lang/rust/pull/126641). +//@ ignore-riscv64 (https://github.com/llvm/llvm-project/issues/56642) + +// FIXME(#135531): the `Makefile` version practically didn't test `-C split-debuginfo` on Windows +// at all, and lumped windows-msvc and windows-gnu together at that. +//@ ignore-windows-gnu + +#![deny(warnings)] + +use std::collections::BTreeSet; + +use run_make_support::rustc::Rustc; +use run_make_support::{ + cwd, has_extension, is_darwin, is_msvc, is_windows, llvm_dwarfdump, run_in_tmpdir, rustc, + shallow_find_directories, shallow_find_files, uname, +}; + +/// `-C debuginfo`. See <https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo>. +#[derive(Debug, PartialEq, Copy, Clone)] +enum DebuginfoLevel { + /// `-C debuginfo=0` or `-C debuginfo=none` aka no debuginfo at all, default. + None, + /// `-C debuginfo=2` aka full debuginfo, aliased via `-g`. + Full, + /// The cli flag is not explicitly provided; default. + Unspecified, +} + +impl DebuginfoLevel { + fn cli_value(&self) -> &'static str { + // `-Cdebuginfo=...` + match self { + DebuginfoLevel::None => "none", + DebuginfoLevel::Full => "2", + DebuginfoLevel::Unspecified => unreachable!(), + } + } +} + +/// `-C split-debuginfo`. See +/// <https://doc.rust-lang.org/rustc/codegen-options/index.html#split-debuginfo>. +/// +/// Note that all three options are supported on Linux and Apple platforms, packed is supported on +/// Windows-MSVC, and all other platforms support off. Attempting to use an unsupported option +/// requires using the nightly channel with the `-Z unstable-options` flag. +#[derive(Debug, PartialEq, Copy, Clone)] +enum SplitDebuginfo { + /// `-C split-debuginfo=off`. Default for platforms with ELF binaries and windows-gnu (not + /// Windows MSVC and not macOS). Typically DWARF debug information can be found in the final + /// artifact in sections of the executable. + /// + /// - Not supported on Windows MSVC. + /// - On macOS this options prevents the final execution of `dsymutil` to generate debuginfo. + Off, + /// `-C split-debuginfo=unpacked`. Debug information will be found in separate files for each + /// compilation unit (object file). + /// + /// - Not supported on Windows MSVC. + /// - On macOS this means the original object files will contain debug information. + /// - On other Unix platforms this means that `*.dwo` files will contain debug information. + Unpacked, + /// `-C split-debuginfo=packed`. Default for Windows MSVC and macOS. "Packed" here means that + /// all the debug information is packed into a separate file from the main executable. + /// + /// - On Windows MSVC this is a `*.pdb` file. + /// - On macOS this is a `*.dSYM` folder. + /// - On other platforms this is a `*.dwp` file. + Packed, + /// The cli flag is not explicitly provided; uses platform default. + Unspecified, +} + +impl SplitDebuginfo { + fn cli_value(&self) -> &'static str { + // `-Csplit-debuginfo=...` + match self { + SplitDebuginfo::Off => "off", + SplitDebuginfo::Unpacked => "unpacked", + SplitDebuginfo::Packed => "packed", + SplitDebuginfo::Unspecified => unreachable!(), + } + } +} + +/// `-Z split-dwarf-kind` +#[derive(Debug, PartialEq, Copy, Clone)] +enum SplitDwarfKind { + /// `-Zsplit-dwarf-kind=split` + Split, + /// `-Zsplit-dwarf-kind=single` + Single, + Unspecified, +} + +impl SplitDwarfKind { + fn cli_value(&self) -> &'static str { + // `-Zsplit-dwarf-kind=...` + match self { + SplitDwarfKind::Split => "split", + SplitDwarfKind::Single => "single", + SplitDwarfKind::Unspecified => unreachable!(), + } + } +} + +/// `-C linker-plugin-lto` +#[derive(Debug, PartialEq, Copy, Clone)] +enum LinkerPluginLto { + /// Pass `-C linker-plugin-lto`. + Yes, + /// Don't pass `-C linker-plugin-lto`. + Unspecified, +} + +/// `--remap-path-prefix` or not. +#[derive(Debug, Clone)] +enum RemapPathPrefix { + /// `--remap-path-prefix=$prefix=$remapped_prefix`. + Yes { remapped_prefix: &'static str }, + /// Don't pass `--remap-path-prefix`. + Unspecified, +} + +/// `-Zremap-path-scope`. See +/// <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/remap-path-scope.html#remap-path-scope>. +#[derive(Debug, Clone)] +enum RemapPathScope { + /// Comma-separated list of remap scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`. + Yes(&'static str), + Unspecified, +} + +/// Whether to pass `-Zunstable-options`. +#[derive(Debug, PartialEq, Copy, Clone)] +enum UnstableOptions { + Yes, + Unspecified, +} + +#[track_caller] +fn cwd_filenames() -> BTreeSet<String> { + let files = shallow_find_files(cwd(), |path| { + // Fiilter out source files + !has_extension(path, "rs") + }); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[track_caller] +fn cwd_dwo_filenames() -> BTreeSet<String> { + let files = shallow_find_files(cwd(), |path| has_extension(path, "dwo")); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[track_caller] +fn cwd_object_filenames() -> BTreeSet<String> { + let files = shallow_find_files(cwd(), |path| has_extension(path, "o")); + files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() +} + +#[must_use] +struct FileAssertions<'expected> { + expected_files: BTreeSet<&'expected str>, +} + +impl<'expected> FileAssertions<'expected> { + #[track_caller] + fn assert_on(self, found_files: &BTreeSet<String>) { + let found_files: BTreeSet<_> = found_files.iter().map(|f| f.as_str()).collect(); + assert!( + found_files.is_superset(&self.expected_files), + "expected {:?} to exist, but only found {:?}", + self.expected_files, + found_files + ); + + let unexpected_files: BTreeSet<_> = + found_files.difference(&self.expected_files).copied().collect(); + assert!(unexpected_files.is_empty(), "found unexpected files: {:?}", unexpected_files); + } +} + +/// Windows MSVC only supports packed debuginfo. +mod windows_msvc_tests { + use super::*; + + pub(crate) fn split_debuginfo(split_kind: SplitDebuginfo, level: DebuginfoLevel) { + // NOTE: `-C debuginfo` and other flags are not exercised here on Windows MSVC. + run_in_tmpdir(|| { + println!("checking: split_kind={:?} + level={:?}", split_kind, level); + match (split_kind, level) { + (SplitDebuginfo::Off, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .run_fail() + .assert_stderr_contains( + "error: `-Csplit-debuginfo=off` is unstable on this platform", + ); + } + (SplitDebuginfo::Unpacked, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .run_fail() + .assert_stderr_contains( + "error: `-Csplit-debuginfo=unpacked` is unstable on this platform", + ); + } + (SplitDebuginfo::Packed, _) => { + rustc().input("foo.rs").split_debuginfo(split_kind.cli_value()).run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo.exe", "foo.pdb"]) } + .assert_on(&found_files); + } + (split_kind, level) => { + panic!( + "split_kind={:?} + level={:?} is not handled on Windows MSVC", + split_kind, level + ) + } + } + }); + } +} + +mod darwin_tests { + use super::*; + + pub(crate) fn split_debuginfo(split_kind: SplitDebuginfo, level: DebuginfoLevel) { + run_in_tmpdir(|| { + println!("checking: split_kind={:?} + level={:?}", split_kind, level); + + let dsym_directories = + || shallow_find_directories(cwd(), |path| has_extension(path, "dSYM")); + + match (split_kind, level) { + (_, DebuginfoLevel::Unspecified) => { + rustc().input("foo.rs").run(); + let directories = + shallow_find_directories(cwd(), |path| has_extension(path, "dSYM")); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated when `-Cdebuginfo` is not specified" + ); + } + (_, DebuginfoLevel::None) => { + rustc().input("foo.rs").debuginfo(level.cli_value()).run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated when `-Cdebuginfo=none`" + ); + } + (SplitDebuginfo::Off, _) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated since we expect `-Csplit-debuginfo=off` to inhibit final debuginfo generation on macOS" + ); + } + (SplitDebuginfo::Unpacked, _) => { + rustc().input("foo.rs").split_debuginfo(split_kind.cli_value()).run(); + let directories = dsym_directories(); + assert!( + directories.is_empty(), + "expected no `*.dSYM` folder to be generated since we expect on macOS the object files to contain debuginfo instead" + ); + } + (SplitDebuginfo::Packed, DebuginfoLevel::Full) => { + rustc() + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let directories = shallow_find_directories(cwd(), |path| { + path.file_name().unwrap() == "foo.dSYM" + }); + assert_eq!(directories.len(), 1, "failed to find `foo.dSYM`"); + } + (SplitDebuginfo::Unspecified, DebuginfoLevel::Full) => { + rustc().input("foo.rs").debuginfo(level.cli_value()).run(); + let directories = shallow_find_directories(cwd(), |path| { + path.file_name().unwrap() == "foo.dSYM" + }); + assert_eq!(directories.len(), 1, "failed to find `foo.dSYM`"); + } + } + }); + } +} + +mod shared_linux_other_tests { + use std::path::PathBuf; + + use super::*; + + fn rustc(unstable_options: UnstableOptions) -> Rustc { + if unstable_options == UnstableOptions::Yes { + let mut rustc = run_make_support::rustc(); + rustc.arg("-Zunstable-options"); + rustc + } else { + run_make_support::rustc() + } + } + + #[derive(PartialEq)] + pub(crate) enum CrossCrateTest { + Yes, + No, + } + + pub(crate) fn split_debuginfo( + cross_crate_test: CrossCrateTest, + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + run_in_tmpdir(|| { + println!( + "checking: unstable_options={:?} + split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?}", + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope + ); + + match cross_crate_test { + CrossCrateTest::Yes => cross_crate_split_debuginfo( + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope, + ), + CrossCrateTest::No => simple_split_debuginfo( + unstable_options, + split_kind, + level, + split_dwarf_kind, + lto, + remap_path_prefix, + remap_path_scope, + ), + } + }); + } + + fn cross_crate_split_debuginfo( + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { + // packed-crosscrate-split + // - Debuginfo in `.dwo` files + // - (bar) `.rlib` file created, contains `.dwo` + // - (bar) `.o` deleted + // - (bar) `.dwo` deleted + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` deleted + // - (main) `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbar.rlib"]) } + .assert_on(&found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { + expected_files: BTreeSet::from(["libbar.rlib", "main", "main.dwp"]), + } + .assert_on(&found_files); + } + + // packed-crosscrate-single + // - Debuginfo in `.o` files + // - (bar) `.rlib` file created, contains `.o` + // - (bar) `.o` deleted + // - (bar) `.dwo` never created + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` never created + // - (main) `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbar.rlib"]) } + .assert_on(&found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let found_files = cwd_filenames(); + FileAssertions { + expected_files: BTreeSet::from(["libbar.rlib", "main", "main.dwp"]), + } + .assert_on(&found_files); + } + + // unpacked-crosscrate-split + // - Debuginfo in `.dwo` files + // - (bar) `.rlib` file created, contains `.dwo` + // - (bar) `.o` deleted + // - (bar) `.dwo` present + // - (bar) `.dwp` never created + // - (main) `.o` deleted + // - (main) `.dwo` present + // - (main) `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let bar_found_files = cwd_filenames(); + + let bar_dwo_files = cwd_dwo_filenames(); + assert_eq!(bar_dwo_files.len(), 1); + + let mut bar_expected_files = BTreeSet::new(); + bar_expected_files.extend(bar_dwo_files); + bar_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: bar_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&bar_found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let overall_found_files = cwd_filenames(); + + let overall_dwo_files = cwd_dwo_filenames(); + assert_eq!(overall_dwo_files.len(), 2); + + let mut overall_expected_files = BTreeSet::new(); + overall_expected_files.extend(overall_dwo_files); + overall_expected_files.insert("main".to_string()); + overall_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: overall_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&overall_found_files); + } + + // unpacked-crosscrate-single + // - Debuginfo in `.o` files + // - (bar) `.rlib` file created, contains `.o` + // - (bar) `.o` present + // - (bar) `.dwo` never created + // - (bar) `.dwp` never created + // - (main) `.o` present + // - (main) `.dwo` never created + // - (main) `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("bar.rs") + .crate_type("lib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let bar_found_files = cwd_filenames(); + + let bar_object_files = cwd_object_filenames(); + assert_eq!(bar_object_files.len(), 1); + + let mut bar_expected_files = BTreeSet::new(); + bar_expected_files.extend(bar_object_files); + bar_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: bar_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&bar_found_files); + + rustc(unstable_options) + .extern_("bar", "libbar.rlib") + .input("main.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + + let overall_found_files = cwd_filenames(); + + let overall_object_files = cwd_object_filenames(); + assert_eq!(overall_object_files.len(), 2); + + let mut overall_expected_files = BTreeSet::new(); + overall_expected_files.extend(overall_object_files); + overall_expected_files.insert("main".to_string()); + overall_expected_files.insert("libbar.rlib".to_string()); + + FileAssertions { + expected_files: overall_expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&overall_found_files); + } + + _ => {} + } + } + + fn simple_split_debuginfo( + unstable_options: UnstableOptions, + split_kind: SplitDebuginfo, + level: DebuginfoLevel, + split_dwarf_kind: SplitDwarfKind, + lto: LinkerPluginLto, + remap_path_prefix: RemapPathPrefix, + remap_path_scope: RemapPathScope, + ) { + match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { + // off (unspecified): + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unspecified, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options).input("foo.rs").debuginfo(level.cli_value()).run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo"]) }.assert_on(&found_files); + } + + // off: + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Off, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo"]) }.assert_on(&found_files); + } + + // packed-split: + // - Debuginfo in `.dwo` files + // - `.o` deleted + // - `.dwo` deleted + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + } + + // packed-single: + // - Debuginfo in `.o` files + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + } + + // packed-lto-split:: + // - `rmeta` file added to `rlib`, no object files are generated and thus no + // debuginfo is generated. + // - `.o` never created + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // packed-lto-single: + // - `rmeta` file added to `rlib`, no object files are generated and thus no + // debuginfo is generated + // - `.o` never created + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // packed-remapped-split: + // - Debuginfo in `.dwo` files + // - `.o` and binary refer to remapped `.dwo` paths which do not exist + // - `.o` deleted + // - `.dwo` deleted + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-single: + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-scope: + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "debuginfo"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // packed-remapped-wrong-scope: + // - `.o` and binary refer to un-remapped `.o` paths because remap path scope is + // macro. + // - `.o` deleted + // - `.dwo` never created + // - `.dwp` present + ( + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "macro"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + let found_files = cwd_filenames(); + FileAssertions { expected_files: BTreeSet::from(["foo", "foo.dwp"]) } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::NoRemap); + } + + // unpacked-split + // - Debuginfo in `.dwo` files + // - `.o` deleted + // - `.dwo` present + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + + let dwo_files = cwd_dwo_filenames(); + assert_eq!(dwo_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(dwo_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_str).collect(), + } + .assert_on(&found_files); + } + + // unpacked-single + // - Debuginfo in `.o` files + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .run(); + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_str).collect(), + } + .assert_on(&found_files); + } + + // unpacked-lto-split + // - `rmeta` file added to `rlib`, no object files are generated and thus no debuginfo + // is generated + // - `.o` not present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + + let found_files = cwd_filenames(); + + FileAssertions { expected_files: BTreeSet::from(["libbaz.rlib"]) } + .assert_on(&found_files); + } + + // unpacked-lto-single + // - rmeta file added to rlib, no object files are generated and thus no debuginfo is generated + // - `.o` present (bitcode) + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("baz.rs") + .crate_type("rlib") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .arg("-Clinker-plugin-lto") + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("libbaz.rlib".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + } + + // unpacked-remapped-split + // - Debuginfo in `.dwo` files + // - `.o` and binary refer to remapped `.dwo` paths which do not exist + // - `.o` deleted + // - `.dwo` present + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + + let found_files = cwd_filenames(); + + let dwo_files = cwd_dwo_filenames(); + assert_eq!(dwo_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(dwo_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-single + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Unspecified, + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-scope + // - Debuginfo in `.o` files + // - `.o` and binary refer to remapped `.o` paths which do not exist + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "debuginfo"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::Remapped); + } + + // unpacked-remapped-wrong-scope + // - Debuginfo in `.o` files + // - `.o` and binary refer to un-remapped `.o` paths because remap path scope is macro + // - `.o` present + // - `.dwo` never created + // - `.dwp` never created + ( + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix }, + RemapPathScope::Yes(scope @ "macro"), + ) => { + rustc(unstable_options) + .input("foo.rs") + .split_debuginfo(split_kind.cli_value()) + .debuginfo(level.cli_value()) + .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) + .remap_path_prefix(cwd(), remapped_prefix) + .arg(format!("-Zremap-path-scope={scope}")) + .run(); + + let found_files = cwd_filenames(); + + let object_files = cwd_object_filenames(); + assert_eq!(object_files.len(), 1); + + let mut expected_files = BTreeSet::new(); + expected_files.extend(object_files); + expected_files.insert("foo".to_string()); + + FileAssertions { + expected_files: expected_files.iter().map(String::as_ref).collect(), + } + .assert_on(&found_files); + + check_path_remap(cwd(), RemapExpectation::NoRemap); + } + + (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) => { + panic!( + "split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?} is not handled on linux/other", + split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope + ) + } + } + } + + #[derive(PartialEq)] + enum RemapExpectation { + Remapped, + NoRemap, + } + + #[track_caller] + fn check_path_remap(cwd_path: PathBuf, remap_expectation: RemapExpectation) { + let cwd_path = cwd_path.to_str().unwrap(); + let output = llvm_dwarfdump().input("foo").arg("--debug-info").run().stdout_utf8(); + let output_lines: Vec<_> = output.lines().collect(); + + // Look for `DW_AT_comp_dir` and `DW_AT_GNU_dwo_name` via `llvm-dwarfdump`. Note: space + // between uses tabs. + // + // ```text + // 0x0000000b: DW_TAG_compile_unit + // DW_AT_stmt_list (0x00000000) + // DW_AT_comp_dir ("/__MY_REMAPPED_PATH") # this could be e.g. /home/repos/rust/ if not remapped + // DW_AT_GNU_dwo_name ("foo.foo.fc848df41df7a00d-cgu.0.rcgu.dwo") + // ``` + // + // FIXME: this is very fragile because the output format can be load-bearing, but doing this + // via `object` + `gimli` is rather difficult. + let mut window = output_lines.windows(2); + while let Some([first_ln, second_ln]) = window.next() { + let first_ln = first_ln.trim(); + let second_ln = second_ln.trim(); + + if !second_ln.starts_with("DW_AT_GNU_dwo_name") { + continue; + } + + let Some((comp_dir_attr_name, comp_dir_attr_val)) = first_ln.split_once("\t") else { + continue; + }; + + println!("comp_dir_attr_name: `{}`", comp_dir_attr_name); + println!("cwd_path_string: `{}`", cwd_path); + + if comp_dir_attr_name != "DW_AT_comp_dir" { + continue; + } + + println!("comp_dir_attr_val: `{}`", comp_dir_attr_val); + + // Possibly `("/__MY_REMAPPED_PATH")` or `($cwd_path_string)`. + // + // FIXME: this check is insufficiently precise, it should probably also match on suffix + // (`.o` vs `.dwo` reference). But also, string matching is just very fragile. + let comp_dir_attr_val = comp_dir_attr_val.trim(); + + match remap_expectation { + RemapExpectation::Remapped => { + assert!( + !comp_dir_attr_val.contains(&cwd_path), + "unexpected non-remapped path found in `DW_AT_comp_dir`: {}", + comp_dir_attr_val + ); + } + RemapExpectation::NoRemap => { + assert!( + comp_dir_attr_val.contains(&cwd_path), + "failed to find un-remapped path in `DW_AT_comp_dir`: {}", + comp_dir_attr_val + ); + } + } + } + } +} + +fn main() { + // ENHANCEMENT: we are only checking that split-debuginfo is splitting is some way, shape or + // form, we do not sanity check the actual debuginfo artifacts on non-Linux! It may be possible + // to also sanity check the debuginfo artifacts, but I did not want to do that during the port + // to rmake.rs initially. + + // ENHANCEMENT: the Linux checks have significantly more coverage for interaction between `-C + // split-debuginfo` and other flags compared to windows-msvc or windows-gnu or darwin or some + // other non-linux targets. It would be cool if their test coverage could be improved. + + // NOTE: these combinations are not exhaustive, because while porting to rmake.rs initially I + // tried to preserve the existing test behavior closely. Notably, no attempt was made to + // exhaustively cover all cases in the 6-fold Cartesian product of `{,-Csplit=debuginfo=...}` x + // `{,-Cdebuginfo=...}` x `{,--remap-path-prefix}` x `{,-Zremap-path-scope=...}` x + // `{,-Zsplit-dwarf-kind=...}` x `{,-Clinker-plugin-lto}`. If you really want to, you can + // identify which combination isn't exercised with a 6-layers nested for loop iterating through + // each of the cli flag enum variants. + + if is_msvc() { + // FIXME: the windows-msvc test coverage is sparse at best. + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Unspecified); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Unspecified); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Unspecified); + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::None); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::None); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::None); + + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Full); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Full); + windows_msvc_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Full); + } else if is_windows() { + // FIXME(#135531): the `Makefile` version didn't test windows at all. I don't know about the + // intended behavior on windows-gnu to expand test coverage while porting this to rmake.rs, + // but the test coverage here really should be expanded since some windows-gnu targets are + // Tier 1. + } else if is_darwin() { + // FIXME: the darwin test coverage is sparse at best. + + // Expect no `.dSYM` generation if debuginfo is not requested (special case). + darwin_tests::split_debuginfo(SplitDebuginfo::Unspecified, DebuginfoLevel::Unspecified); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Unspecified); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Unspecified); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Unspecified); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::None); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::None); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::None); + + darwin_tests::split_debuginfo(SplitDebuginfo::Off, DebuginfoLevel::Full); + darwin_tests::split_debuginfo(SplitDebuginfo::Unpacked, DebuginfoLevel::Full); + darwin_tests::split_debuginfo(SplitDebuginfo::Packed, DebuginfoLevel::Full); + } else { + // Unix as well as the non-linux + non-windows + non-darwin targets. + + // FIXME: this `uname` check is very funny, it really should be refined (e.g. llvm bug + // <https://github.com/llvm/llvm-project/issues/56642> for riscv64 targets). + + // NOTE: some options are not stable on non-linux + non-windows + non-darwin targets... + let unstable_options = + if uname() == "Linux" { UnstableOptions::Unspecified } else { UnstableOptions::Yes }; + + // FIXME: we should add a test with scope `split-debuginfo,split-debuginfo-path` that greps + // the entire `.dwp` file for remapped paths (i.e. without going through objdump or + // readelf). See <https://github.com/rust-lang/rust/pull/118518#discussion_r1452180392>. + + use shared_linux_other_tests::CrossCrateTest; + + // unspecified `-Csplit-debuginfo` + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unspecified, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // off + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Off, + DebuginfoLevel::Full, + SplitDwarfKind::Unspecified, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-lto-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-lto-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // FIXME: the remapping tests probably need to be reworked, see + // <https://github.com/rust-lang/rust/pull/118518#discussion_r1452174338>. + + // packed-remapped-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // packed-remapped-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // packed-remapped-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("debuginfo"), + ); + + // packed-remapped-wrong-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("macro"), + ); + + // packed-crosscrate-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // packed-crosscrate-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Packed, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-lto-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-lto-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Yes, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + ); + + // unpacked-remapped-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("debuginfo"), + ); + + // unpacked-remapped-wrong-scope + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Yes("macro"), + ); + + // unpacked-crosscrate-split + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + + // unpacked-crosscrate-single + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + unstable_options, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Single, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + ); + } +} diff --git a/tests/ui/cenum_impl_drop_cast.rs b/tests/ui/cenum_impl_drop_cast.rs index 96e3d967e2c..f681434dd86 100644 --- a/tests/ui/cenum_impl_drop_cast.rs +++ b/tests/ui/cenum_impl_drop_cast.rs @@ -1,5 +1,3 @@ -#![deny(cenum_impl_drop_cast)] - enum E { A = 0, } @@ -14,5 +12,4 @@ fn main() { let e = E::A; let i = e as u32; //~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop` - //~| WARN this was previously accepted } diff --git a/tests/ui/cenum_impl_drop_cast.stderr b/tests/ui/cenum_impl_drop_cast.stderr index 541d15d021d..35c69f4b4b7 100644 --- a/tests/ui/cenum_impl_drop_cast.stderr +++ b/tests/ui/cenum_impl_drop_cast.stderr @@ -1,31 +1,8 @@ error: cannot cast enum `E` into integer `u32` because it implements `Drop` - --> $DIR/cenum_impl_drop_cast.rs:15:13 + --> $DIR/cenum_impl_drop_cast.rs:13:13 | LL | let i = e as u32; | ^^^^^^^^ - | - = 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 #73333 <https://github.com/rust-lang/rust/issues/73333> -note: the lint level is defined here - --> $DIR/cenum_impl_drop_cast.rs:1:9 - | -LL | #![deny(cenum_impl_drop_cast)] - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -Future incompatibility report: Future breakage diagnostic: -error: cannot cast enum `E` into integer `u32` because it implements `Drop` - --> $DIR/cenum_impl_drop_cast.rs:15:13 - | -LL | let i = e as u32; - | ^^^^^^^^ - | - = 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 #73333 <https://github.com/rust-lang/rust/issues/73333> -note: the lint level is defined here - --> $DIR/cenum_impl_drop_cast.rs:1:9 - | -LL | #![deny(cenum_impl_drop_cast)] - | ^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/issues/issue-40883.rs b/tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs index a4646d67c68..a4646d67c68 100644 --- a/tests/ui/issues/issue-40883.rs +++ b/tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs diff --git a/tests/ui/issues/issue-48838.rs b/tests/ui/enum/closure-in-enum-issue-48838.rs index 057a424dfef..057a424dfef 100644 --- a/tests/ui/issues/issue-48838.rs +++ b/tests/ui/enum/closure-in-enum-issue-48838.rs diff --git a/tests/ui/issues/issue-48838.stderr b/tests/ui/enum/closure-in-enum-issue-48838.stderr index 504ea3e8010..17e6c343334 100644 --- a/tests/ui/issues/issue-48838.stderr +++ b/tests/ui/enum/closure-in-enum-issue-48838.stderr @@ -1,11 +1,11 @@ error[E0308]: mismatched types - --> $DIR/issue-48838.rs:2:14 + --> $DIR/closure-in-enum-issue-48838.rs:2:14 | LL | Square = |x| x, | ^^^^^ expected `isize`, found closure | = note: expected type `isize` - found closure `{closure@$DIR/issue-48838.rs:2:14: 2:17}` + found closure `{closure@$DIR/closure-in-enum-issue-48838.rs:2:14: 2:17}` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-40350.rs b/tests/ui/enum/enum-inside-enum-issue-40350.rs index 50d74f27b63..50d74f27b63 100644 --- a/tests/ui/issues/issue-40350.rs +++ b/tests/ui/enum/enum-inside-enum-issue-40350.rs diff --git a/tests/ui/issues/issue-41272.rs b/tests/ui/expr/if/if-let-no-match-guards-issue-41272.rs index 255bbfe90a1..255bbfe90a1 100644 --- a/tests/ui/issues/issue-41272.rs +++ b/tests/ui/expr/if/if-let-no-match-guards-issue-41272.rs diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs new file mode 100644 index 00000000000..47198d51150 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dump.rs @@ -0,0 +1,15 @@ +//@ compile-flags: -Zverbose-internals + +#![feature(precise_capturing_in_traits, rustc_attrs)] +#![rustc_hidden_type_of_opaques] + +trait Foo { + fn hello(&self) -> impl Sized; +} + +fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { +//~^ ERROR <T as Foo>::{synthetic#0}<'s/#1> + x.hello() +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/dump.stderr b/tests/ui/impl-trait/in-trait/dump.stderr new file mode 100644 index 00000000000..95805840385 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dump.stderr @@ -0,0 +1,8 @@ +error: <T as Foo>::{synthetic#0}<'s/#1> + --> $DIR/dump.rs:10:35 + | +LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr index a26f9a1ff56..3848fcf61d9 100644 --- a/tests/ui/inference/issue-72616.stderr +++ b/tests/ui/inference/issue-72616.stderr @@ -26,7 +26,7 @@ LL | if String::from("a") == "a".try_into().unwrap() {} | ^^^^^^^^ | = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`: - - impl TryFrom<&str> for std::sys_common::net::LookupHost; + - impl TryFrom<&str> for std::sys::net::connection::socket::LookupHost; - impl<T, U> TryFrom<U> for T where U: Into<T>; = note: required for `&str` to implement `TryInto<_>` diff --git a/tests/ui/issues/issue-40408.rs b/tests/ui/lexer/floating-point-0e10-issue-40408.rs index a1c1c582181..a1c1c582181 100644 --- a/tests/ui/issues/issue-40408.rs +++ b/tests/ui/lexer/floating-point-0e10-issue-40408.rs diff --git a/tests/ui/issues/issue-40136.rs b/tests/ui/macros/const-expr-invocations-issue-40136.rs index d5ccebdc85d..d5ccebdc85d 100644 --- a/tests/ui/issues/issue-40136.rs +++ b/tests/ui/macros/const-expr-invocations-issue-40136.rs diff --git a/tests/ui/issues/issue-40845.rs b/tests/ui/macros/macros-in-trait-positions-issue-40845.rs index a4ede6adfa3..a4ede6adfa3 100644 --- a/tests/ui/issues/issue-40845.rs +++ b/tests/ui/macros/macros-in-trait-positions-issue-40845.rs diff --git a/tests/ui/issues/issue-40845.stderr b/tests/ui/macros/macros-in-trait-positions-issue-40845.stderr index 66bf053204c..5c1b5f51e44 100644 --- a/tests/ui/issues/issue-40845.stderr +++ b/tests/ui/macros/macros-in-trait-positions-issue-40845.stderr @@ -1,11 +1,11 @@ error: cannot find macro `m` in this scope - --> $DIR/issue-40845.rs:1:11 + --> $DIR/macros-in-trait-positions-issue-40845.rs:1:11 | LL | trait T { m!(); } | ^ error: cannot find macro `m` in this scope - --> $DIR/issue-40845.rs:4:10 + --> $DIR/macros-in-trait-positions-issue-40845.rs:4:10 | LL | impl S { m!(); } | ^ diff --git a/tests/ui/issues/issue-41213.rs b/tests/ui/match/enum-and-break-in-match-issue-41213.rs index 97f80a99a83..7c42a3629c9 100644 --- a/tests/ui/issues/issue-41213.rs +++ b/tests/ui/match/enum-and-break-in-match-issue-41213.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(dead_code)] enum A { A1, diff --git a/tests/ui/self/arbitrary_self_type_infinite_recursion.rs b/tests/ui/self/arbitrary_self_type_infinite_recursion.rs new file mode 100644 index 00000000000..6fbf35c0b86 --- /dev/null +++ b/tests/ui/self/arbitrary_self_type_infinite_recursion.rs @@ -0,0 +1,24 @@ +#![feature(arbitrary_self_types)] + +struct MySmartPtr<T>(T); + +impl<T> core::ops::Receiver for MySmartPtr<T> { + type Target = MySmartPtr<T>; +} + +struct Content; + +impl Content { + fn method(self: MySmartPtr<Self>) { // note self type + //~^ reached the recursion limit + //~| reached the recursion limit + //~| invalid `self` parameter type + } +} + +fn main() { + let p = MySmartPtr(Content); + p.method(); + //~^ reached the recursion limit + //~| no method named `method` +} diff --git a/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr new file mode 100644 index 00000000000..5e652efb364 --- /dev/null +++ b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr @@ -0,0 +1,47 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `MySmartPtr<Content>` + --> $DIR/arbitrary_self_type_infinite_recursion.rs:12:19 + | +LL | fn method(self: MySmartPtr<Self>) { // note self type + | ^^^^^^^^^^^^^^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`arbitrary_self_type_infinite_recursion`) + +error[E0055]: reached the recursion limit while auto-dereferencing `MySmartPtr<Content>` + --> $DIR/arbitrary_self_type_infinite_recursion.rs:12:19 + | +LL | fn method(self: MySmartPtr<Self>) { // note self type + | ^^^^^^^^^^^^^^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`arbitrary_self_type_infinite_recursion`) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0307]: invalid `self` parameter type: `MySmartPtr<Content>` + --> $DIR/arbitrary_self_type_infinite_recursion.rs:12:19 + | +LL | fn method(self: MySmartPtr<Self>) { // note self type + | ^^^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>` + +error[E0055]: reached the recursion limit while auto-dereferencing `MySmartPtr<Content>` + --> $DIR/arbitrary_self_type_infinite_recursion.rs:21:5 + | +LL | p.method(); + | ^^^^^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`arbitrary_self_type_infinite_recursion`) + +error[E0599]: no method named `method` found for struct `MySmartPtr` in the current scope + --> $DIR/arbitrary_self_type_infinite_recursion.rs:21:5 + | +LL | struct MySmartPtr<T>(T); + | -------------------- method `method` not found for this struct +... +LL | p.method(); + | ^^^^^^ method not found in `MySmartPtr<Content>` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0055, E0307, E0599. +For more information about an error, try `rustc --explain E0055`. diff --git a/tests/ui/issues/issue-40782.fixed b/tests/ui/suggestions/for-loop-missing-in.fixed index ff376b5a52c..ff376b5a52c 100644 --- a/tests/ui/issues/issue-40782.fixed +++ b/tests/ui/suggestions/for-loop-missing-in.fixed diff --git a/tests/ui/issues/issue-40782.rs b/tests/ui/suggestions/for-loop-missing-in.rs index 28c12aec665..28c12aec665 100644 --- a/tests/ui/issues/issue-40782.rs +++ b/tests/ui/suggestions/for-loop-missing-in.rs diff --git a/tests/ui/issues/issue-40782.stderr b/tests/ui/suggestions/for-loop-missing-in.stderr index 61498020238..61830b800a6 100644 --- a/tests/ui/issues/issue-40782.stderr +++ b/tests/ui/suggestions/for-loop-missing-in.stderr @@ -1,5 +1,5 @@ error: missing `in` in `for` loop - --> $DIR/issue-40782.rs:4:11 + --> $DIR/for-loop-missing-in.rs:4:11 | LL | for _i 0..2 { | ^ @@ -10,7 +10,7 @@ LL | for _i in 0..2 { | ++ error: missing `in` in `for` loop - --> $DIR/issue-40782.rs:6:12 + --> $DIR/for-loop-missing-in.rs:6:12 | LL | for _i of 0..2 { | ^^ diff --git a/tests/ui/suggestions/suggest-std-when-using-type.fixed b/tests/ui/suggestions/suggest-std-when-using-type.fixed index ebbb854175b..0547940f94d 100644 --- a/tests/ui/suggestions/suggest-std-when-using-type.fixed +++ b/tests/ui/suggestions/suggest-std-when-using-type.fixed @@ -1,8 +1,5 @@ //@ run-rustfix fn main() { let pi = std::f32::consts::PI; //~ ERROR ambiguous associated type - let bytes = "hello world".as_bytes(); - let string = std::str::from_utf8(bytes).unwrap(); - //~^ ERROR no function or associated item named `from_utf8` found - println!("{pi} {bytes:?} {string}"); + println!("{pi}"); } diff --git a/tests/ui/suggestions/suggest-std-when-using-type.rs b/tests/ui/suggestions/suggest-std-when-using-type.rs index 06aab63d688..cd55c5d13bd 100644 --- a/tests/ui/suggestions/suggest-std-when-using-type.rs +++ b/tests/ui/suggestions/suggest-std-when-using-type.rs @@ -1,8 +1,5 @@ //@ run-rustfix fn main() { let pi = f32::consts::PI; //~ ERROR ambiguous associated type - let bytes = "hello world".as_bytes(); - let string = str::from_utf8(bytes).unwrap(); - //~^ ERROR no function or associated item named `from_utf8` found - println!("{pi} {bytes:?} {string}"); + println!("{pi}"); } diff --git a/tests/ui/suggestions/suggest-std-when-using-type.stderr b/tests/ui/suggestions/suggest-std-when-using-type.stderr index 6f890b87b24..7f8545f461d 100644 --- a/tests/ui/suggestions/suggest-std-when-using-type.stderr +++ b/tests/ui/suggestions/suggest-std-when-using-type.stderr @@ -9,18 +9,6 @@ help: you are looking for the module in `std`, not the primitive type LL | let pi = std::f32::consts::PI; | +++++ -error[E0599]: no function or associated item named `from_utf8` found for type `str` in the current scope - --> $DIR/suggest-std-when-using-type.rs:5:23 - | -LL | let string = str::from_utf8(bytes).unwrap(); - | ^^^^^^^^^ function or associated item not found in `str` - | -help: you are looking for the module in `std`, not the primitive type - | -LL | let string = std::str::from_utf8(bytes).unwrap(); - | +++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0223, E0599. -For more information about an error, try `rustc --explain E0223`. +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-40827.rs b/tests/ui/trait-bounds/deep-level-Send-bound-check-issue-40827.rs index 6e42c506169..6e42c506169 100644 --- a/tests/ui/issues/issue-40827.rs +++ b/tests/ui/trait-bounds/deep-level-Send-bound-check-issue-40827.rs diff --git a/tests/ui/issues/issue-40827.stderr b/tests/ui/trait-bounds/deep-level-Send-bound-check-issue-40827.stderr index 7f5c578ae4f..7b59fe72f43 100644 --- a/tests/ui/issues/issue-40827.stderr +++ b/tests/ui/trait-bounds/deep-level-Send-bound-check-issue-40827.stderr @@ -1,5 +1,5 @@ error[E0277]: `Rc<Foo>` cannot be shared between threads safely - --> $DIR/issue-40827.rs:14:7 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:14:7 | LL | f(Foo(Arc::new(Bar::B(None)))); | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be shared between threads safely @@ -8,24 +8,24 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | = help: within `Bar`, the trait `Sync` is not implemented for `Rc<Foo>` note: required because it appears within the type `Bar` - --> $DIR/issue-40827.rs:6:6 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:6:6 | LL | enum Bar { | ^^^ = note: required for `Arc<Bar>` to implement `Send` note: required because it appears within the type `Foo` - --> $DIR/issue-40827.rs:4:8 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:4:8 | LL | struct Foo(Arc<Bar>); | ^^^ note: required by a bound in `f` - --> $DIR/issue-40827.rs:11:9 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:11:9 | LL | fn f<T: Send>(_: T) {} | ^^^^ required by this bound in `f` error[E0277]: `Rc<Foo>` cannot be sent between threads safely - --> $DIR/issue-40827.rs:14:7 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:14:7 | LL | f(Foo(Arc::new(Bar::B(None)))); | - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<Foo>` cannot be sent between threads safely @@ -34,18 +34,18 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | = help: within `Bar`, the trait `Send` is not implemented for `Rc<Foo>` note: required because it appears within the type `Bar` - --> $DIR/issue-40827.rs:6:6 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:6:6 | LL | enum Bar { | ^^^ = note: required for `Arc<Bar>` to implement `Send` note: required because it appears within the type `Foo` - --> $DIR/issue-40827.rs:4:8 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:4:8 | LL | struct Foo(Arc<Bar>); | ^^^ note: required by a bound in `f` - --> $DIR/issue-40827.rs:11:9 + --> $DIR/deep-level-Send-bound-check-issue-40827.rs:11:9 | LL | fn f<T: Send>(_: T) {} | ^^^^ required by this bound in `f` diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index 9e31fed9b18..376fa22ae19 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Znext-solver -//~^ ERROR cannot normalize `<T as Default>::Id: '_` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete @@ -14,6 +13,7 @@ impl<T> Default for T { // This will be fixed by #111994 fn intu(&self) -> &Self::Id { //~^ ERROR type annotations needed + //~| ERROR cannot normalize `<T as Default>::Id: '_` self //~ ERROR cannot satisfy } } diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index 2d0c503bc95..eeb101911c4 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-transmute.rs:3:12 + --> $DIR/specialization-transmute.rs:2:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,9 +9,13 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error: cannot normalize `<T as Default>::Id: '_` + --> $DIR/specialization-transmute.rs:14:5 + | +LL | fn intu(&self) -> &Self::Id { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:15:23 + --> $DIR/specialization-transmute.rs:14:23 | LL | fn intu(&self) -> &Self::Id { | ^^^^^^^^^ cannot infer type for reference `&<T as Default>::Id` diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs index 733be204354..e7fa60a2e3f 100644 --- a/tests/ui/traits/next-solver/unsound-region-obligation.rs +++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs @@ -1,4 +1,3 @@ -//~ ERROR the type `&'a ()` does not fulfill the required lifetime //@ compile-flags: -Znext-solver // Regression test for rust-lang/trait-system-refactor-initiative#59 @@ -8,6 +7,7 @@ trait StaticTy { impl StaticTy for () { type Item<'a> = &'a (); + //~^ ERROR the type `&'a ()` does not fulfill the required lifetime } fn main() {} diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr index fe96a184f43..dea3b62334c 100644 --- a/tests/ui/traits/next-solver/unsound-region-obligation.stderr +++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr @@ -1,4 +1,8 @@ error[E0477]: the type `&'a ()` does not fulfill the required lifetime + --> $DIR/unsound-region-obligation.rs:9:21 + | +LL | type Item<'a> = &'a (); + | ^^^^^^ | = note: type must satisfy the static lifetime diff --git a/tests/ui/type/pattern_types/signed_ranges.rs b/tests/ui/type/pattern_types/signed_ranges.rs new file mode 100644 index 00000000000..3725fbda729 --- /dev/null +++ b/tests/ui/type/pattern_types/signed_ranges.rs @@ -0,0 +1,24 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +type Sign = pattern_type!(u32 is -10..); +//~^ ERROR: cannot apply unary operator `-` + +type SignedChar = pattern_type!(char is -'A'..); +//~^ ERROR: cannot apply unary operator `-` + +fn main() { + match 42_u8 { + -10..253 => {} + //~^ ERROR `u8: Neg` is not satisfied + _ => {} + } + + match 'A' { + -'\0'..'a' => {} + //~^ ERROR `char: Neg` is not satisfied + _ => {} + } +} diff --git a/tests/ui/type/pattern_types/signed_ranges.stderr b/tests/ui/type/pattern_types/signed_ranges.stderr new file mode 100644 index 00000000000..79bf8501b63 --- /dev/null +++ b/tests/ui/type/pattern_types/signed_ranges.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/signed_ranges.rs:14:9 + | +LL | -10..253 => {} + | ^^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `char: Neg` is not satisfied + --> $DIR/signed_ranges.rs:20:9 + | +LL | -'\0'..'a' => {} + | ^^^^^ the trait `Neg` is not implemented for `char` + +error[E0600]: cannot apply unary operator `-` to type `u32` + --> $DIR/signed_ranges.rs:6:34 + | +LL | type Sign = pattern_type!(u32 is -10..); + | ^^^ cannot apply unary operator `-` + | + = note: unsigned values cannot be negated + +error[E0600]: cannot apply unary operator `-` to type `char` + --> $DIR/signed_ranges.rs:9:41 + | +LL | type SignedChar = pattern_type!(char is -'A'..); + | ^^^^ cannot apply unary operator `-` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0600. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/issues/issue-40610.rs b/tests/ui/typeck/coercion-check-for-addition-issue-40610.rs index c01233605b5..c01233605b5 100644 --- a/tests/ui/issues/issue-40610.rs +++ b/tests/ui/typeck/coercion-check-for-addition-issue-40610.rs diff --git a/tests/ui/issues/issue-40610.stderr b/tests/ui/typeck/coercion-check-for-addition-issue-40610.stderr index 1bd1c4dd57d..5e424862d97 100644 --- a/tests/ui/issues/issue-40610.stderr +++ b/tests/ui/typeck/coercion-check-for-addition-issue-40610.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `()` to `()` - --> $DIR/issue-40610.rs:4:8 + --> $DIR/coercion-check-for-addition-issue-40610.rs:4:8 | LL | () + f(&[1.0]); | -- ^ --------- () diff --git a/tests/ui/issues/issue-40861.rs b/tests/ui/typeck/coercion-check-for-indexing-expression-issue-40861.rs index d8a8384a544..d8a8384a544 100644 --- a/tests/ui/issues/issue-40861.rs +++ b/tests/ui/typeck/coercion-check-for-indexing-expression-issue-40861.rs diff --git a/tests/ui/issues/issue-40861.stderr b/tests/ui/typeck/coercion-check-for-indexing-expression-issue-40861.stderr index dec9af4b6d1..13bc0cd94f3 100644 --- a/tests/ui/issues/issue-40861.stderr +++ b/tests/ui/typeck/coercion-check-for-indexing-expression-issue-40861.stderr @@ -1,5 +1,5 @@ error[E0608]: cannot index into a value of type `()` - --> $DIR/issue-40861.rs:4:7 + --> $DIR/coercion-check-for-indexing-expression-issue-40861.rs:4:7 | LL | ()[f(&[1.0])]; | ^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-41139.rs b/tests/ui/typeck/unsized-rvalue-issue-41139.rs index 94c53216f50..94c53216f50 100644 --- a/tests/ui/issues/issue-41139.rs +++ b/tests/ui/typeck/unsized-rvalue-issue-41139.rs diff --git a/tests/ui/issues/issue-41139.stderr b/tests/ui/typeck/unsized-rvalue-issue-41139.stderr index d7b35245d8f..aba0423eeb3 100644 --- a/tests/ui/issues/issue-41139.stderr +++ b/tests/ui/typeck/unsized-rvalue-issue-41139.stderr @@ -1,5 +1,5 @@ error[E0618]: expected function, found `&dyn Fn() -> (dyn Trait + 'static)` - --> $DIR/issue-41139.rs:10:26 + --> $DIR/unsized-rvalue-issue-41139.rs:10:26 | LL | fn get_function<'a>() -> &'a dyn Fn() -> dyn Trait { | -------------------------------------------------- `get_function` defined here returns `&dyn Fn() -> (dyn Trait + 'static)` diff --git a/tests/ui/issues/issue-40749.rs b/tests/ui/wf/range-expr-root-of-constant-issue-40749.rs index 0a847853b12..0a847853b12 100644 --- a/tests/ui/issues/issue-40749.rs +++ b/tests/ui/wf/range-expr-root-of-constant-issue-40749.rs diff --git a/tests/ui/issues/issue-40749.stderr b/tests/ui/wf/range-expr-root-of-constant-issue-40749.stderr index f7770e00013..482773a3944 100644 --- a/tests/ui/issues/issue-40749.stderr +++ b/tests/ui/wf/range-expr-root-of-constant-issue-40749.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-40749.rs:2:9 + --> $DIR/range-expr-root-of-constant-issue-40749.rs:2:9 | LL | [0; ..10]; | ^^^^ expected `usize`, found `RangeTo<{integer}>` diff --git a/tests/ui/issues/issue-40235.rs b/tests/ui/while/while-let-scope-issue-40235.rs index 2bdbb2f229e..7d5dfc64a90 100644 --- a/tests/ui/issues/issue-40235.rs +++ b/tests/ui/while/while-let-scope-issue-40235.rs @@ -1,4 +1,4 @@ -//@ run-pass +//@ check-pass #![allow(unused_variables)] fn foo() {} |
