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:
commit
e22dab387f
14 changed files with 403 additions and 205 deletions
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
222
compiler/rustc_session/src/config/print_request.rs
Normal file
222
compiler/rustc_session/src/config/print_request.rs
Normal 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()
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
27
compiler/rustc_session/src/macros.rs
Normal file
27
compiler/rustc_session/src/macros.rs
Normal 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;
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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']);
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
25
tests/ui/coercion/intrinsic-in-unifying-coercion-149143.rs
Normal file
25
tests/ui/coercion/intrinsic-in-unifying-coercion-149143.rs
Normal 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!()
|
||||
}
|
||||
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue