Auto merge of #149166 - Zalathar:rollup-fyrwtcb, r=Zalathar

Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#148990 (Exhaustively specify names and stability of `--print` values)
 - rust-lang/rust#149127 (unwrap ret ty of `iter::ArrayChunks::into_remainder` )
 - rust-lang/rust#149134 (std: sys: net: uefi: Implement read_vectored)
 - rust-lang/rust#149135 (Constify `residual_into_try_type`)
 - rust-lang/rust#149160 (Check for intrinsic to fn ptr casts in unified coercions)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-11-21 03:46:25 +00:00
commit e22dab387f
14 changed files with 403 additions and 205 deletions

View file

@ -1291,14 +1291,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Closure(..) => {
Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.safety()))
}
ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
ty::FnDef(def_id, ..) => {
// Intrinsics are not coercible to function pointers
if self.tcx.intrinsic(def_id).is_some() {
return Err(TypeError::IntrinsicCast);
}
Adjust::Pointer(PointerCoercion::ReifyFnPointer)
}
_ => span_bug!(cause.span, "should not try to coerce a {prev_ty} to a fn pointer"),
};
let next_adjustment = match new_ty.kind() {
ty::Closure(..) => {
Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.safety()))
}
ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
ty::FnDef(def_id, ..) => {
// Intrinsics are not coercible to function pointers
if self.tcx.intrinsic(def_id).is_some() {
return Err(TypeError::IntrinsicCast);
}
Adjust::Pointer(PointerCoercion::ReifyFnPointer)
}
_ => span_bug!(new.span, "should not try to coerce a {new_ty} to a fn pointer"),
};
for expr in exprs.iter().map(|e| e.as_coercion_site()) {

View file

@ -36,6 +36,7 @@ use tracing::debug;
pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues};
use crate::config::native_libs::parse_native_libs;
pub use crate::config::print_request::{PrintKind, PrintRequest};
use crate::errors::FileWriteFail;
pub use crate::options::*;
use crate::search_paths::SearchPath;
@ -45,37 +46,9 @@ use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};
mod cfg;
mod externs;
mod native_libs;
mod print_request;
pub mod sigpipe;
pub const PRINT_KINDS: &[(&str, PrintKind)] = &[
// tidy-alphabetical-start
("all-target-specs-json", PrintKind::AllTargetSpecsJson),
("calling-conventions", PrintKind::CallingConventions),
("cfg", PrintKind::Cfg),
("check-cfg", PrintKind::CheckCfg),
("code-models", PrintKind::CodeModels),
("crate-name", PrintKind::CrateName),
("crate-root-lint-levels", PrintKind::CrateRootLintLevels),
("deployment-target", PrintKind::DeploymentTarget),
("file-names", PrintKind::FileNames),
("host-tuple", PrintKind::HostTuple),
("link-args", PrintKind::LinkArgs),
("native-static-libs", PrintKind::NativeStaticLibs),
("relocation-models", PrintKind::RelocationModels),
("split-debuginfo", PrintKind::SplitDebuginfo),
("stack-protector-strategies", PrintKind::StackProtectorStrategies),
("supported-crate-types", PrintKind::SupportedCrateTypes),
("sysroot", PrintKind::Sysroot),
("target-cpus", PrintKind::TargetCPUs),
("target-features", PrintKind::TargetFeatures),
("target-libdir", PrintKind::TargetLibdir),
("target-list", PrintKind::TargetList),
("target-spec-json", PrintKind::TargetSpecJson),
("target-spec-json-schema", PrintKind::TargetSpecJsonSchema),
("tls-models", PrintKind::TlsModels),
// tidy-alphabetical-end
];
/// The different settings that the `-C strip` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Strip {
@ -1015,42 +988,6 @@ impl ExternEntry {
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct PrintRequest {
pub kind: PrintKind,
pub out: OutFileName,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PrintKind {
// tidy-alphabetical-start
AllTargetSpecsJson,
CallingConventions,
Cfg,
CheckCfg,
CodeModels,
CrateName,
CrateRootLintLevels,
DeploymentTarget,
FileNames,
HostTuple,
LinkArgs,
NativeStaticLibs,
RelocationModels,
SplitDebuginfo,
StackProtectorStrategies,
SupportedCrateTypes,
Sysroot,
TargetCPUs,
TargetFeatures,
TargetLibdir,
TargetList,
TargetSpecJson,
TargetSpecJsonSchema,
TlsModels,
// tidy-alphabetical-end
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
pub struct NextSolverConfig {
/// Whether the new trait solver should be enabled in coherence.
@ -1798,14 +1735,6 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE
)
});
static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
format!(
"Compiler information to print on stdout (or to a file)\n\
INFO may be one of <{}>.",
PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::<Vec<_>>().join("|")
)
});
static EMIT_HELP: LazyLock<String> = LazyLock::new(|| {
let mut result =
String::from("Comma separated list of types of output for the compiler to emit.\n");
@ -1872,7 +1801,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "<NAME>"),
opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST),
opt(Stable, Multi, "", "emit", &EMIT_HELP, "<TYPE>[=<FILE>]"),
opt(Stable, Multi, "", "print", &PRINT_HELP, "<INFO>[=<FILE>]"),
opt(Stable, Multi, "", "print", &print_request::PRINT_HELP, "<INFO>[=<FILE>]"),
opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
opt(Stable, Opt, "o", "", "Write output to FILENAME", "<FILENAME>"),
@ -2320,108 +2249,6 @@ fn should_override_cgus_and_disable_thinlto(
(disable_local_thinlto, codegen_units)
}
fn collect_print_requests(
early_dcx: &EarlyDiagCtxt,
cg: &mut CodegenOptions,
unstable_opts: &UnstableOptions,
matches: &getopts::Matches,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_deref() == Some("help") {
prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout });
cg.target_cpu = None;
};
if cg.target_feature == "help" {
prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout });
cg.target_feature = String::new();
}
// We disallow reusing the same path in multiple prints, such as `--print
// cfg=output.txt --print link-args=output.txt`, because outputs are printed
// by disparate pieces of the compiler, and keeping track of which files
// need to be overwritten vs appended to is annoying.
let mut printed_paths = FxHashSet::default();
prints.extend(matches.opt_strs("print").into_iter().map(|req| {
let (req, out) = split_out_file_name(&req);
let kind = if let Some((print_name, print_kind)) =
PRINT_KINDS.iter().find(|&&(name, _)| name == req)
{
check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind));
*print_kind
} else {
let is_nightly = nightly_options::match_is_nightly_build(matches);
emit_unknown_print_request_help(early_dcx, req, is_nightly)
};
let out = out.unwrap_or(OutFileName::Stdout);
if let OutFileName::Real(path) = &out {
if !printed_paths.insert(path.clone()) {
early_dcx.early_fatal(format!(
"cannot print multiple outputs to the same path: {}",
path.display(),
));
}
}
PrintRequest { kind, out }
}));
prints
}
fn check_print_request_stability(
early_dcx: &EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
(print_name, print_kind): (&str, PrintKind),
) {
if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options {
early_dcx.early_fatal(format!(
"the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \
print option"
));
}
}
fn is_print_request_stable(print_kind: PrintKind) -> bool {
match print_kind {
PrintKind::AllTargetSpecsJson
| PrintKind::CheckCfg
| PrintKind::CrateRootLintLevels
| PrintKind::SupportedCrateTypes
| PrintKind::TargetSpecJson
| PrintKind::TargetSpecJsonSchema => false,
_ => true,
}
}
fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
let prints = PRINT_KINDS
.iter()
.filter_map(|(name, kind)| {
// If we're not on nightly, we don't want to print unstable options
if !is_nightly && !is_print_request_stable(*kind) {
None
} else {
Some(format!("`{name}`"))
}
})
.collect::<Vec<_>>();
let prints = prints.join(", ");
let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
#[allow(rustc::diagnostic_outside_of_impl)]
diag.help(format!("valid print requests are: {prints}"));
if req == "lints" {
diag.help(format!("use `-Whelp` to print a list of lints"));
}
diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"));
diag.emit()
}
pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
match matches.opt_str("target") {
Some(target) if target.ends_with(".json") => {
@ -2846,7 +2673,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
));
}
let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
let prints = print_request::collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
// -Zretpoline-external-thunk also requires -Zretpoline
if unstable_opts.retpoline_external_thunk {

View file

@ -0,0 +1,222 @@
//! Code for dealing with `--print` requests.
use std::fmt;
use std::sync::LazyLock;
use rustc_data_structures::fx::FxHashSet;
use crate::EarlyDiagCtxt;
use crate::config::{
CodegenOptions, OutFileName, UnstableOptions, nightly_options, split_out_file_name,
};
use crate::macros::AllVariants;
#[derive(Clone, PartialEq, Debug)]
pub struct PrintRequest {
pub kind: PrintKind,
pub out: OutFileName,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(AllVariants)]
pub enum PrintKind {
// tidy-alphabetical-start
AllTargetSpecsJson,
CallingConventions,
Cfg,
CheckCfg,
CodeModels,
CrateName,
CrateRootLintLevels,
DeploymentTarget,
FileNames,
HostTuple,
LinkArgs,
NativeStaticLibs,
RelocationModels,
SplitDebuginfo,
StackProtectorStrategies,
SupportedCrateTypes,
Sysroot,
TargetCPUs,
TargetFeatures,
TargetLibdir,
TargetList,
TargetSpecJson,
TargetSpecJsonSchema,
TlsModels,
// tidy-alphabetical-end
}
impl PrintKind {
/// FIXME: rust-analyzer doesn't support `#![feature(macro_derive)]` yet
/// (<https://github.com/rust-lang/rust-analyzer/issues/21043>), which breaks autocomplete.
/// Work around that by aliasing the trait constant to a regular constant.
const ALL_VARIANTS: &[Self] = <Self as AllVariants>::ALL_VARIANTS;
fn name(self) -> &'static str {
use PrintKind::*;
match self {
// tidy-alphabetical-start
AllTargetSpecsJson => "all-target-specs-json",
CallingConventions => "calling-conventions",
Cfg => "cfg",
CheckCfg => "check-cfg",
CodeModels => "code-models",
CrateName => "crate-name",
CrateRootLintLevels => "crate-root-lint-levels",
DeploymentTarget => "deployment-target",
FileNames => "file-names",
HostTuple => "host-tuple",
LinkArgs => "link-args",
NativeStaticLibs => "native-static-libs",
RelocationModels => "relocation-models",
SplitDebuginfo => "split-debuginfo",
StackProtectorStrategies => "stack-protector-strategies",
SupportedCrateTypes => "supported-crate-types",
Sysroot => "sysroot",
TargetCPUs => "target-cpus",
TargetFeatures => "target-features",
TargetLibdir => "target-libdir",
TargetList => "target-list",
TargetSpecJson => "target-spec-json",
TargetSpecJsonSchema => "target-spec-json-schema",
TlsModels => "tls-models",
// tidy-alphabetical-end
}
}
fn is_stable(self) -> bool {
use PrintKind::*;
match self {
// Stable values:
CallingConventions
| Cfg
| CodeModels
| CrateName
| DeploymentTarget
| FileNames
| HostTuple
| LinkArgs
| NativeStaticLibs
| RelocationModels
| SplitDebuginfo
| StackProtectorStrategies
| Sysroot
| TargetCPUs
| TargetFeatures
| TargetLibdir
| TargetList
| TlsModels => true,
// Unstable values:
AllTargetSpecsJson => false,
CheckCfg => false,
CrateRootLintLevels => false,
SupportedCrateTypes => false,
TargetSpecJson => false,
TargetSpecJsonSchema => false,
}
}
fn from_str(s: &str) -> Option<Self> {
Self::ALL_VARIANTS.iter().find(|kind| kind.name() == s).copied()
}
}
impl fmt::Display for PrintKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name().fmt(f)
}
}
pub(crate) static PRINT_HELP: LazyLock<String> = LazyLock::new(|| {
let print_kinds =
PrintKind::ALL_VARIANTS.iter().map(|kind| kind.name()).collect::<Vec<_>>().join("|");
format!(
"Compiler information to print on stdout (or to a file)\n\
INFO may be one of <{print_kinds}>.",
)
});
pub(crate) fn collect_print_requests(
early_dcx: &EarlyDiagCtxt,
cg: &mut CodegenOptions,
unstable_opts: &UnstableOptions,
matches: &getopts::Matches,
) -> Vec<PrintRequest> {
let mut prints = Vec::<PrintRequest>::new();
if cg.target_cpu.as_deref() == Some("help") {
prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout });
cg.target_cpu = None;
};
if cg.target_feature == "help" {
prints.push(PrintRequest { kind: PrintKind::TargetFeatures, out: OutFileName::Stdout });
cg.target_feature = String::new();
}
// We disallow reusing the same path in multiple prints, such as `--print
// cfg=output.txt --print link-args=output.txt`, because outputs are printed
// by disparate pieces of the compiler, and keeping track of which files
// need to be overwritten vs appended to is annoying.
let mut printed_paths = FxHashSet::default();
prints.extend(matches.opt_strs("print").into_iter().map(|req| {
let (req, out) = split_out_file_name(&req);
let kind = if let Some(print_kind) = PrintKind::from_str(req) {
check_print_request_stability(early_dcx, unstable_opts, print_kind);
print_kind
} else {
let is_nightly = nightly_options::match_is_nightly_build(matches);
emit_unknown_print_request_help(early_dcx, req, is_nightly)
};
let out = out.unwrap_or(OutFileName::Stdout);
if let OutFileName::Real(path) = &out {
if !printed_paths.insert(path.clone()) {
early_dcx.early_fatal(format!(
"cannot print multiple outputs to the same path: {}",
path.display(),
));
}
}
PrintRequest { kind, out }
}));
prints
}
fn check_print_request_stability(
early_dcx: &EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
print_kind: PrintKind,
) {
if !print_kind.is_stable() && !unstable_opts.unstable_options {
early_dcx.early_fatal(format!(
"the `-Z unstable-options` flag must also be passed to enable the `{print_kind}` print option"
));
}
}
fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! {
let prints = PrintKind::ALL_VARIANTS
.iter()
// If we're not on nightly, we don't want to print unstable options
.filter(|kind| is_nightly || kind.is_stable())
.map(|kind| format!("`{kind}`"))
.collect::<Vec<_>>()
.join(", ");
let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`"));
#[allow(rustc::diagnostic_outside_of_impl)]
diag.help(format!("valid print requests are: {prints}"));
if req == "lints" {
diag.help(format!("use `-Whelp` to print a list of lints"));
}
diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"));
diag.emit()
}

View file

@ -2,6 +2,7 @@
#![allow(internal_features)]
#![feature(default_field_values)]
#![feature(iter_intersperse)]
#![feature(macro_derive)]
#![feature(rustc_attrs)]
// To generate CodegenOptionsTargetModifiers and UnstableOptionsTargetModifiers enums
// with macro_rules, it is necessary to use recursive mechanic ("Incremental TT Munchers").
@ -20,6 +21,7 @@ pub mod code_stats;
pub mod config;
pub mod cstore;
pub mod filesearch;
mod macros;
mod options;
pub mod search_paths;

View file

@ -0,0 +1,27 @@
/// Derivable trait for enums with no fields (i.e. C-style enums) that want to
/// allow iteration over a list of all variant values.
pub(crate) trait AllVariants: Copy + 'static {
const ALL_VARIANTS: &[Self];
}
macro_rules! AllVariantsDerive {
derive() (
$(#[$meta:meta])*
$vis:vis enum $Type:ident {
$(
$(#[$varmeta:meta])*
$Variant:ident $( = $value:literal )?
), *$(,)?
}
) => {
impl $crate::macros::AllVariants for $Type {
const ALL_VARIANTS: &[$Type] = &[
$( $Type::$Variant, )*
];
}
};
}
// For some reason the compiler won't allow `pub(crate) use AllVariants` due
// to a conflict with the trait of the same name, but will allow this form.
pub(crate) use AllVariantsDerive as AllVariants;

View file

@ -40,17 +40,17 @@ where
/// # // Also serves as a regression test for https://github.com/rust-lang/rust/issues/123333
/// # #![feature(iter_array_chunks)]
/// let x = [1,2,3,4,5].into_iter().array_chunks::<2>();
/// let mut rem = x.into_remainder().unwrap();
/// let mut rem = x.into_remainder();
/// assert_eq!(rem.next(), Some(5));
/// assert_eq!(rem.next(), None);
/// ```
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
#[inline]
pub fn into_remainder(mut self) -> Option<array::IntoIter<I::Item, N>> {
pub fn into_remainder(mut self) -> array::IntoIter<I::Item, N> {
if self.remainder.is_none() {
while let Some(_) = self.next() {}
}
self.remainder
self.remainder.unwrap_or_default()
}
}

View file

@ -3523,7 +3523,7 @@ pub trait Iterator {
/// assert_eq!(iter.next(), Some(['l', 'o']));
/// assert_eq!(iter.next(), Some(['r', 'e']));
/// assert_eq!(iter.next(), None);
/// assert_eq!(iter.into_remainder().unwrap().as_slice(), &['m']);
/// assert_eq!(iter.into_remainder().as_slice(), &['m']);
/// ```
///
/// ```

View file

@ -371,11 +371,14 @@ pub const trait Residual<O>: Sized {
/// but importantly not on the contextual type the way it would be if
/// we called `<_ as FromResidual>::from_residual(r)` directly.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
#[rustc_const_unstable(feature = "const_try_residual", issue = "91285")]
// needs to be `pub` to avoid `private type` errors
#[expect(unreachable_pub)]
#[inline] // FIXME: force would be nice, but fails -- see #148915
#[lang = "into_try_type"]
pub fn residual_into_try_type<R: Residual<O>, O>(r: R) -> <R as Residual<O>>::TryType {
pub const fn residual_into_try_type<R: [const] Residual<O>, O>(
r: R,
) -> <R as Residual<O>>::TryType {
FromResidual::from_residual(r)
}

View file

@ -18,10 +18,10 @@ fn test_iterator_array_chunks_clone_and_drop() {
assert_eq!(count.get(), 3);
let mut it2 = it.clone();
assert_eq!(count.get(), 3);
assert_eq!(it.into_remainder().unwrap().len(), 2);
assert_eq!(it.into_remainder().len(), 2);
assert_eq!(count.get(), 5);
assert!(it2.next().is_none());
assert_eq!(it2.into_remainder().unwrap().len(), 2);
assert_eq!(it2.into_remainder().len(), 2);
assert_eq!(count.get(), 7);
}
@ -31,7 +31,7 @@ fn test_iterator_array_chunks_remainder() {
assert_eq!(it.next(), Some([0, 1, 2, 3]));
assert_eq!(it.next(), Some([4, 5, 6, 7]));
assert_eq!(it.next(), None);
assert_eq!(it.into_remainder().unwrap().as_slice(), &[8, 9, 10]);
assert_eq!(it.into_remainder().as_slice(), &[8, 9, 10]);
}
#[test]
@ -89,7 +89,7 @@ fn test_iterator_array_chunks_next_and_next_back() {
assert_eq!(it.next(), None);
assert_eq!(it.next_back(), None);
assert_eq!(it.next(), None);
assert_eq!(it.into_remainder().unwrap().as_slice(), &[9, 10]);
assert_eq!(it.into_remainder().as_slice(), &[9, 10]);
}
#[test]
@ -102,7 +102,7 @@ fn test_iterator_array_chunks_rev_remainder() {
assert_eq!(it.next(), None);
assert_eq!(it.next(), None);
}
assert_eq!(it.into_remainder().unwrap().as_slice(), &[8, 9, 10]);
assert_eq!(it.into_remainder().as_slice(), &[8, 9, 10]);
}
#[test]

View file

@ -69,12 +69,11 @@ impl TcpStream {
}
pub fn read_vectored(&self, buf: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
// FIXME: UEFI does support vectored read, so implement that.
crate::io::default_read_vectored(|b| self.read(b), buf)
self.inner.read_vectored(buf, self.read_timeout()?)
}
pub fn is_read_vectored(&self) -> bool {
false
true
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {

View file

@ -1,5 +1,5 @@
use super::tcp4;
use crate::io::{self, IoSlice};
use crate::io::{self, IoSlice, IoSliceMut};
use crate::net::SocketAddr;
use crate::ptr::NonNull;
use crate::sys::{helpers, unsupported};
@ -44,6 +44,16 @@ impl Tcp {
}
}
pub(crate) fn read_vectored(
&self,
buf: &mut [IoSliceMut<'_>],
timeout: Option<Duration>,
) -> io::Result<usize> {
match self {
Self::V4(client) => client.read_vectored(buf, timeout),
}
}
pub(crate) fn ttl(&self) -> io::Result<u32> {
match self {
Self::V4(client) => client.get_mode_data().map(|x| x.time_to_live.into()),

View file

@ -1,7 +1,7 @@
use r_efi::efi::{self, Status};
use r_efi::protocols::tcp4;
use crate::io::{self, IoSlice};
use crate::io::{self, IoSlice, IoSliceMut};
use crate::net::SocketAddrV4;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicBool, Ordering};
@ -193,30 +193,74 @@ impl Tcp4 {
}
pub(crate) fn read(&self, buf: &mut [u8], timeout: Option<Duration>) -> io::Result<usize> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
let data_len = u32::try_from(buf.len()).unwrap_or(u32::MAX);
let fragment = tcp4::FragmentData {
fragment_length: data_len,
fragment_buffer: buf.as_mut_ptr().cast::<crate::ffi::c_void>(),
};
let mut tx_data = tcp4::ReceiveData {
let mut rx_data = tcp4::ReceiveData {
urgent_flag: r_efi::efi::Boolean::FALSE,
data_length: data_len,
fragment_count: 1,
fragment_table: [fragment],
};
let protocol = self.protocol.as_ptr();
let mut token = tcp4::IoToken {
completion_token,
packet: tcp4::IoTokenPacket {
rx_data: (&raw mut tx_data).cast::<tcp4::ReceiveData<0>>(),
},
self.read_inner((&raw mut rx_data).cast(), timeout).map(|_| data_len as usize)
}
pub(crate) fn read_vectored(
&self,
buf: &[IoSliceMut<'_>],
timeout: Option<Duration>,
) -> io::Result<usize> {
let mut data_length = 0u32;
let mut fragment_count = 0u32;
// Calculate how many IoSlice in buf can be transmitted.
for i in buf {
// IoSlice length is always <= u32::MAX in UEFI.
match data_length.checked_add(u32::try_from(i.len()).expect("value is stored as a u32"))
{
Some(x) => data_length = x,
None => break,
}
fragment_count += 1;
}
let rx_data_size = size_of::<tcp4::ReceiveData<0>>()
+ size_of::<tcp4::FragmentData>() * (fragment_count as usize);
let mut rx_data = helpers::UefiBox::<tcp4::ReceiveData>::new(rx_data_size)?;
rx_data.write(tcp4::ReceiveData {
urgent_flag: r_efi::efi::Boolean::FALSE,
data_length,
fragment_count,
fragment_table: [],
});
unsafe {
// SAFETY: IoSlice and FragmentData are guaranteed to have same layout.
crate::ptr::copy_nonoverlapping(
buf.as_ptr().cast(),
(*rx_data.as_mut_ptr()).fragment_table.as_mut_ptr(),
fragment_count as usize,
);
};
self.read_inner(rx_data.as_mut_ptr(), timeout).map(|_| data_length as usize)
}
pub(crate) fn read_inner(
&self,
rx_data: *mut tcp4::ReceiveData,
timeout: Option<Duration>,
) -> io::Result<()> {
let evt = unsafe { self.create_evt() }?;
let completion_token =
tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS };
let protocol = self.protocol.as_ptr();
let mut token = tcp4::IoToken { completion_token, packet: tcp4::IoTokenPacket { rx_data } };
let r = unsafe { ((*protocol).receive)(protocol, &mut token) };
if r.is_error() {
return Err(io::Error::from_raw_os_error(r.as_usize()));
@ -227,7 +271,7 @@ impl Tcp4 {
if completion_token.status.is_error() {
Err(io::Error::from_raw_os_error(completion_token.status.as_usize()))
} else {
Ok(data_len as usize)
Ok(())
}
}

View file

@ -0,0 +1,25 @@
// Regression test for #149143.
// The compiler did not check for a coercion from intrinsics
// to fn ptrs in all possible code paths that could lead to such a coercion.
// This caused an ICE during a later sanity check.
use std::mem::transmute;
fn main() {
unsafe {
let f = if true { transmute } else { safe_transmute };
//~^ ERROR `if` and `else` have incompatible type
let _: i64 = f(5i64);
}
unsafe {
let f = if true { safe_transmute } else { transmute };
//~^ ERROR `if` and `else` have incompatible type
let _: i64 = f(5i64);
}
}
unsafe fn safe_transmute<A, B>(x: A) -> B {
panic!()
}

View file

@ -0,0 +1,27 @@
error[E0308]: `if` and `else` have incompatible types
--> $DIR/intrinsic-in-unifying-coercion-149143.rs:10:46
|
LL | let f = if true { transmute } else { safe_transmute };
| --------- ^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
| |
| expected because of this
|
= note: expected fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
found fn item `unsafe fn(_) -> _ {safe_transmute::<_, _>}`
= note: different fn items have unique types, even if their signatures are the same
error[E0308]: `if` and `else` have incompatible types
--> $DIR/intrinsic-in-unifying-coercion-149143.rs:16:51
|
LL | let f = if true { safe_transmute } else { transmute };
| -------------- ^^^^^^^^^ cannot coerce intrinsics to function pointers
| |
| expected because of this
|
= note: expected fn item `unsafe fn(_) -> _ {safe_transmute::<_, _>}`
found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
= note: different fn items have unique types, even if their signatures are the same
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.