Skip to content

Commit 5d83144

Browse files
committed
Auto merge of rust-lang#133329 - jhpratt:rollup-8ndpkzx, r=jhpratt
Rollup of 13 pull requests Successful merges: - rust-lang#130867 (distinguish overflow and unimplemented in Step::steps_between) - rust-lang#131859 (Update TRPL to add new Chapter 17: Async and Await) - rust-lang#132090 (Stop being so bail-y in candidate assembly) - rust-lang#132658 (Detect const in pattern with typo) - rust-lang#133041 (Print name of env var in `--print=deployment-target`) - rust-lang#133102 (aarch64 softfloat target: always pass floats in int registers) - rust-lang#133159 (Don't allow `-Zunstable-options` to take a value ) - rust-lang#133217 ([AIX] Add option -X32_64 to the "strip" command) - rust-lang#133237 (Minimally constify `Add`) - rust-lang#133238 (re-export `is_loongarch_feature_detected`) - rust-lang#133286 (Re-delay a resolve `bug` related to `Self`-ctor in patterns) - rust-lang#133301 (Add code example for `wrapping_neg` method for signed integers) - rust-lang#133313 (Use arc4random of libc for RTEMS target) Failed merges: - rust-lang#133215 (Fix missing submodule in `./x vendor`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2cf7908 + aac0327 commit 5d83144

File tree

145 files changed

+1219
-609
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

145 files changed

+1219
-609
lines changed

compiler/rustc_abi/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ impl AddAssign for Size {
638638
#[cfg(feature = "nightly")]
639639
impl Step for Size {
640640
#[inline]
641-
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
641+
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
642642
u64::steps_between(&start.bytes(), &end.bytes())
643643
}
644644

compiler/rustc_codegen_ssa/src/back/apple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ fn minimum_deployment_target(target: &Target) -> OSVersion {
9797
}
9898

9999
/// Name of the environment variable used to fetch the deployment target on the given OS.
100-
fn deployment_target_env_var(os: &str) -> &'static str {
100+
pub fn deployment_target_env_var(os: &str) -> &'static str {
101101
match os {
102102
"macos" => "MACOSX_DEPLOYMENT_TARGET",
103103
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",

compiler/rustc_codegen_ssa/src/back/link.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1117,14 +1117,14 @@ fn link_natively(
11171117
let stripcmd = "rust-objcopy";
11181118
match (strip, crate_type) {
11191119
(Strip::Debuginfo, _) => {
1120-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S"))
1120+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-S"])
11211121
}
11221122
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
11231123
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
1124-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x"))
1124+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-x"])
11251125
}
11261126
(Strip::Symbols, _) => {
1127-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, None)
1127+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[])
11281128
}
11291129
(Strip::None, _) => {}
11301130
}
@@ -1141,7 +1141,7 @@ fn link_natively(
11411141
match strip {
11421142
// Always preserve the symbol table (-x).
11431143
Strip::Debuginfo => {
1144-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x"))
1144+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-x"])
11451145
}
11461146
// Strip::Symbols is handled via the --strip-all linker option.
11471147
Strip::Symbols => {}
@@ -1158,11 +1158,15 @@ fn link_natively(
11581158
match strip {
11591159
Strip::Debuginfo => {
11601160
// FIXME: AIX's strip utility only offers option to strip line number information.
1161-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-l"))
1161+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[
1162+
"-X32_64", "-l",
1163+
])
11621164
}
11631165
Strip::Symbols => {
11641166
// Must be noted this option might remove symbol __aix_rust_metadata and thus removes .info section which contains metadata.
1165-
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-r"))
1167+
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[
1168+
"-X32_64", "-r",
1169+
])
11661170
}
11671171
Strip::None => {}
11681172
}
@@ -1181,12 +1185,10 @@ fn strip_symbols_with_external_utility(
11811185
sess: &Session,
11821186
util: &str,
11831187
out_filename: &Path,
1184-
option: Option<&str>,
1188+
options: &[&str],
11851189
) {
11861190
let mut cmd = Command::new(util);
1187-
if let Some(option) = option {
1188-
cmd.arg(option);
1189-
}
1191+
cmd.args(options);
11901192

11911193
let mut new_path = sess.get_tools_search_paths(false);
11921194
if let Some(path) = env::var_os("PATH") {

compiler/rustc_driver_impl/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -875,8 +875,9 @@ fn print_crate_info(
875875
DeploymentTarget => {
876876
if sess.target.is_like_osx {
877877
println_info!(
878-
"deployment_target={}",
879-
apple::pretty_version(apple::deployment_target(sess))
878+
"{}={}",
879+
apple::deployment_target_env_var(&sess.target.os),
880+
apple::pretty_version(apple::deployment_target(sess)),
880881
)
881882
} else {
882883
#[allow(rustc::diagnostic_outside_of_impl)]

compiler/rustc_hir_typeck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ fn report_unexpected_variant_res(
364364
.with_code(err_code);
365365
match res {
366366
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
367-
let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
367+
let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html";
368368
err.with_span_label(span, "`fn` calls are not allowed in patterns")
369369
.with_help(format!("for more information, visit {patterns_url}"))
370370
}

compiler/rustc_index_macros/src/newtype.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl Parse for Newtype {
122122
#gate_rustc_only
123123
impl ::std::iter::Step for #name {
124124
#[inline]
125-
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
125+
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
126126
<usize as ::std::iter::Step>::steps_between(
127127
&Self::index(*start),
128128
&Self::index(*end),

compiler/rustc_mir_build/messages.ftl

+8-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
203203
204204
mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
205205
206-
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
206+
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
207207
208208
mir_build_moved = value is moved into `{$name}` here
209209
@@ -338,6 +338,13 @@ mir_build_unreachable_pattern = unreachable pattern
338338
.unreachable_covered_by_catchall = matches any value
339339
.unreachable_covered_by_one = matches all the relevant values
340340
.unreachable_covered_by_many = multiple earlier patterns match some of the same values
341+
.unreachable_pattern_const_reexport_accessible = there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope
342+
.unreachable_pattern_wanted_const = you might have meant to pattern match against the value of {$is_typo ->
343+
[true] similarly named constant
344+
*[false] constant
345+
} `{$const_name}` instead of introducing a new catch-all binding
346+
.unreachable_pattern_const_inaccessible = there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope
347+
.unreachable_pattern_let_binding = there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings
341348
.suggestion = remove the match arm
342349
343350
mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default

compiler/rustc_mir_build/src/errors.rs

+22
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,14 @@ pub(crate) struct UnreachablePattern<'tcx> {
593593
pub(crate) uninhabited_note: Option<()>,
594594
#[label(mir_build_unreachable_covered_by_catchall)]
595595
pub(crate) covered_by_catchall: Option<Span>,
596+
#[subdiagnostic]
597+
pub(crate) wanted_constant: Option<WantedConstant>,
598+
#[note(mir_build_unreachable_pattern_const_reexport_accessible)]
599+
pub(crate) accessible_constant: Option<Span>,
600+
#[note(mir_build_unreachable_pattern_const_inaccessible)]
601+
pub(crate) inaccessible_constant: Option<Span>,
602+
#[note(mir_build_unreachable_pattern_let_binding)]
603+
pub(crate) pattern_let_binding: Option<Span>,
596604
#[label(mir_build_unreachable_covered_by_one)]
597605
pub(crate) covered_by_one: Option<Span>,
598606
#[note(mir_build_unreachable_covered_by_many)]
@@ -602,6 +610,20 @@ pub(crate) struct UnreachablePattern<'tcx> {
602610
pub(crate) suggest_remove: Option<Span>,
603611
}
604612

613+
#[derive(Subdiagnostic)]
614+
#[suggestion(
615+
mir_build_unreachable_pattern_wanted_const,
616+
code = "{const_path}",
617+
applicability = "machine-applicable"
618+
)]
619+
pub(crate) struct WantedConstant {
620+
#[primary_span]
621+
pub(crate) span: Span,
622+
pub(crate) is_typo: bool,
623+
pub(crate) const_name: String,
624+
pub(crate) const_path: String,
625+
}
626+
605627
#[derive(Diagnostic)]
606628
#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
607629
pub(crate) struct ConstPatternDependsOnGenericParameter {

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+163-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e
77
use rustc_hir::def::*;
88
use rustc_hir::def_id::LocalDefId;
99
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
10+
use rustc_infer::infer::TyCtxtInferExt;
1011
use rustc_infer::traits::Reveal;
12+
use rustc_lint::Level;
1113
use rustc_middle::bug;
1214
use rustc_middle::middle::limits::get_limit_size;
1315
use rustc_middle::thir::visit::Visitor;
@@ -22,8 +24,10 @@ use rustc_pattern_analysis::rustc::{
2224
use rustc_session::lint::builtin::{
2325
BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
2426
};
27+
use rustc_span::edit_distance::find_best_match_for_name;
2528
use rustc_span::hygiene::DesugaringKind;
2629
use rustc_span::{Span, sym};
30+
use rustc_trait_selection::infer::InferCtxtExt;
2731
use tracing::instrument;
2832

2933
use crate::errors::*;
@@ -969,6 +973,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
969973
covered_by_one: None,
970974
covered_by_many: None,
971975
covered_by_many_n_more_count: 0,
976+
wanted_constant: None,
977+
accessible_constant: None,
978+
inaccessible_constant: None,
979+
pattern_let_binding: None,
972980
suggest_remove: None,
973981
};
974982
match explanation.covered_by.as_slice() {
@@ -991,7 +999,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
991999
});
9921000
}
9931001
[covering_pat] if pat_is_catchall(covering_pat) => {
994-
lint.covered_by_catchall = Some(covering_pat.data().span);
1002+
// A binding pattern that matches all, a single binding name.
1003+
let pat = covering_pat.data();
1004+
lint.covered_by_catchall = Some(pat.span);
1005+
find_fallback_pattern_typo(cx, hir_id, pat, &mut lint);
9951006
}
9961007
[covering_pat] => {
9971008
lint.covered_by_one = Some(covering_pat.data().span);
@@ -1024,6 +1035,157 @@ fn report_unreachable_pattern<'p, 'tcx>(
10241035
cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint);
10251036
}
10261037

1038+
/// Detect typos that were meant to be a `const` but were interpreted as a new pattern binding.
1039+
fn find_fallback_pattern_typo<'tcx>(
1040+
cx: &PatCtxt<'_, 'tcx>,
1041+
hir_id: HirId,
1042+
pat: &Pat<'tcx>,
1043+
lint: &mut UnreachablePattern<'_>,
1044+
) {
1045+
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) {
1046+
// This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd
1047+
// ICE. At the same time, we don't really need to do all of this if we won't emit anything.
1048+
return;
1049+
}
1050+
if let PatKind::Binding { name, subpattern: None, ty, .. } = pat.kind {
1051+
// See if the binding might have been a `const` that was mistyped or out of scope.
1052+
let mut accessible = vec![];
1053+
let mut accessible_path = vec![];
1054+
let mut inaccessible = vec![];
1055+
let mut imported = vec![];
1056+
let mut imported_spans = vec![];
1057+
let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::non_body_analysis());
1058+
let parent = cx.tcx.hir().get_parent_item(hir_id);
1059+
1060+
for item in cx.tcx.hir_crate_items(()).free_items() {
1061+
if let DefKind::Use = cx.tcx.def_kind(item.owner_id) {
1062+
// Look for consts being re-exported.
1063+
let item = cx.tcx.hir().expect_item(item.owner_id.def_id);
1064+
let use_name = item.ident.name;
1065+
let hir::ItemKind::Use(path, _) = item.kind else {
1066+
continue;
1067+
};
1068+
for res in &path.res {
1069+
if let Res::Def(DefKind::Const, id) = res
1070+
&& infcx.can_eq(cx.param_env, ty, cx.tcx.type_of(id).instantiate_identity())
1071+
{
1072+
if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
1073+
// The original const is accessible, suggest using it directly.
1074+
let item_name = cx.tcx.item_name(*id);
1075+
accessible.push(item_name);
1076+
accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
1077+
} else if cx
1078+
.tcx
1079+
.visibility(item.owner_id)
1080+
.is_accessible_from(parent, cx.tcx)
1081+
{
1082+
// The const is accessible only through the re-export, point at
1083+
// the `use`.
1084+
imported.push(use_name);
1085+
imported_spans.push(item.ident.span);
1086+
}
1087+
}
1088+
}
1089+
}
1090+
if let DefKind::Const = cx.tcx.def_kind(item.owner_id)
1091+
&& infcx.can_eq(
1092+
cx.param_env,
1093+
ty,
1094+
cx.tcx.type_of(item.owner_id).instantiate_identity(),
1095+
)
1096+
{
1097+
// Look for local consts.
1098+
let item_name = cx.tcx.item_name(item.owner_id.into());
1099+
let vis = cx.tcx.visibility(item.owner_id);
1100+
if vis.is_accessible_from(parent, cx.tcx) {
1101+
accessible.push(item_name);
1102+
let path = if item_name == name {
1103+
// We know that the const wasn't in scope because it has the exact
1104+
// same name, so we suggest the full path.
1105+
with_no_trimmed_paths!(cx.tcx.def_path_str(item.owner_id))
1106+
} else {
1107+
// The const is likely just typoed, and nothing else.
1108+
cx.tcx.def_path_str(item.owner_id)
1109+
};
1110+
accessible_path.push(path);
1111+
} else if name == item_name {
1112+
// The const exists somewhere in this crate, but it can't be imported
1113+
// from this pattern's scope. We'll just point at its definition.
1114+
inaccessible.push(cx.tcx.def_span(item.owner_id));
1115+
}
1116+
}
1117+
}
1118+
if let Some((i, &const_name)) =
1119+
accessible.iter().enumerate().find(|(_, &const_name)| const_name == name)
1120+
{
1121+
// The pattern name is an exact match, so the pattern needed to be imported.
1122+
lint.wanted_constant = Some(WantedConstant {
1123+
span: pat.span,
1124+
is_typo: false,
1125+
const_name: const_name.to_string(),
1126+
const_path: accessible_path[i].clone(),
1127+
});
1128+
} else if let Some(name) = find_best_match_for_name(&accessible, name, None) {
1129+
// The pattern name is likely a typo.
1130+
lint.wanted_constant = Some(WantedConstant {
1131+
span: pat.span,
1132+
is_typo: true,
1133+
const_name: name.to_string(),
1134+
const_path: name.to_string(),
1135+
});
1136+
} else if let Some(i) =
1137+
imported.iter().enumerate().find(|(_, &const_name)| const_name == name).map(|(i, _)| i)
1138+
{
1139+
// The const with the exact name wasn't re-exported from an import in this
1140+
// crate, we point at the import.
1141+
lint.accessible_constant = Some(imported_spans[i]);
1142+
} else if let Some(name) = find_best_match_for_name(&imported, name, None) {
1143+
// The typoed const wasn't re-exported by an import in this crate, we suggest
1144+
// the right name (which will likely require another follow up suggestion).
1145+
lint.wanted_constant = Some(WantedConstant {
1146+
span: pat.span,
1147+
is_typo: true,
1148+
const_path: name.to_string(),
1149+
const_name: name.to_string(),
1150+
});
1151+
} else if !inaccessible.is_empty() {
1152+
for span in inaccessible {
1153+
// The const with the exact name match isn't accessible, we just point at it.
1154+
lint.inaccessible_constant = Some(span);
1155+
}
1156+
} else {
1157+
// Look for local bindings for people that might have gotten confused with how
1158+
// `let` and `const` works.
1159+
for (_, node) in cx.tcx.hir().parent_iter(hir_id) {
1160+
match node {
1161+
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(let_stmt), .. }) => {
1162+
if let hir::PatKind::Binding(_, _, binding_name, _) = let_stmt.pat.kind {
1163+
if name == binding_name.name {
1164+
lint.pattern_let_binding = Some(binding_name.span);
1165+
}
1166+
}
1167+
}
1168+
hir::Node::Block(hir::Block { stmts, .. }) => {
1169+
for stmt in *stmts {
1170+
if let hir::StmtKind::Let(let_stmt) = stmt.kind {
1171+
if let hir::PatKind::Binding(_, _, binding_name, _) =
1172+
let_stmt.pat.kind
1173+
{
1174+
if name == binding_name.name {
1175+
lint.pattern_let_binding = Some(binding_name.span);
1176+
}
1177+
}
1178+
}
1179+
}
1180+
}
1181+
hir::Node::Item(_) => break,
1182+
_ => {}
1183+
}
1184+
}
1185+
}
1186+
}
1187+
}
1188+
10271189
/// Report unreachable arms, if any.
10281190
fn report_arm_reachability<'p, 'tcx>(
10291191
cx: &PatCtxt<'p, 'tcx>,

compiler/rustc_parse/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ parse_unexpected_expr_in_pat =
827827
}, found an expression
828828
829829
.label = not a pattern
830-
.note = arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
830+
.note = arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
831831
832832
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
833833

compiler/rustc_passes/src/stability.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -590,16 +590,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
590590
}
591591

592592
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
593-
// if the const impl is derived using the `derive_const` attribute,
594-
// then it would be "stable" at least for the impl.
595-
// We gate usages of it using `feature(const_trait_impl)` anyways
596-
// so there is no unstable leakage
597-
if self.tcx.is_automatically_derived(def_id.to_def_id()) {
598-
return;
599-
}
600-
601-
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
602-
|| self.tcx.is_const_trait_impl(def_id.to_def_id());
593+
let is_const = self.tcx.is_const_fn(def_id.to_def_id());
603594

604595
// Reachable const fn must have a stability attribute.
605596
if is_const

0 commit comments

Comments
 (0)