Skip to content

Commit

Permalink
Auto merge of rust-lang#133329 - jhpratt:rollup-8ndpkzx, r=jhpratt
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Nov 22, 2024
2 parents 2cf7908 + aac0327 commit 5d83144
Show file tree
Hide file tree
Showing 145 changed files with 1,219 additions and 609 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ impl AddAssign for Size {
#[cfg(feature = "nightly")]
impl Step for Size {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
u64::steps_between(&start.bytes(), &end.bytes())
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fn minimum_deployment_target(target: &Target) -> OSVersion {
}

/// Name of the environment variable used to fetch the deployment target on the given OS.
fn deployment_target_env_var(os: &str) -> &'static str {
pub fn deployment_target_env_var(os: &str) -> &'static str {
match os {
"macos" => "MACOSX_DEPLOYMENT_TARGET",
"ios" => "IPHONEOS_DEPLOYMENT_TARGET",
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1117,14 +1117,14 @@ fn link_natively(
let stripcmd = "rust-objcopy";
match (strip, crate_type) {
(Strip::Debuginfo, _) => {
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-S"])
}
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-x"])
}
(Strip::Symbols, _) => {
strip_symbols_with_external_utility(sess, stripcmd, out_filename, None)
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[])
}
(Strip::None, _) => {}
}
Expand All @@ -1141,7 +1141,7 @@ fn link_natively(
match strip {
// Always preserve the symbol table (-x).
Strip::Debuginfo => {
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-x"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &["-x"])
}
// Strip::Symbols is handled via the --strip-all linker option.
Strip::Symbols => {}
Expand All @@ -1158,11 +1158,15 @@ fn link_natively(
match strip {
Strip::Debuginfo => {
// FIXME: AIX's strip utility only offers option to strip line number information.
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-l"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[
"-X32_64", "-l",
])
}
Strip::Symbols => {
// Must be noted this option might remove symbol __aix_rust_metadata and thus removes .info section which contains metadata.
strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-r"))
strip_symbols_with_external_utility(sess, stripcmd, out_filename, &[
"-X32_64", "-r",
])
}
Strip::None => {}
}
Expand All @@ -1181,12 +1185,10 @@ fn strip_symbols_with_external_utility(
sess: &Session,
util: &str,
out_filename: &Path,
option: Option<&str>,
options: &[&str],
) {
let mut cmd = Command::new(util);
if let Some(option) = option {
cmd.arg(option);
}
cmd.args(options);

let mut new_path = sess.get_tools_search_paths(false);
if let Some(path) = env::var_os("PATH") {
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,8 +875,9 @@ fn print_crate_info(
DeploymentTarget => {
if sess.target.is_like_osx {
println_info!(
"deployment_target={}",
apple::pretty_version(apple::deployment_target(sess))
"{}={}",
apple::deployment_target_env_var(&sess.target.os),
apple::pretty_version(apple::deployment_target(sess)),
)
} else {
#[allow(rustc::diagnostic_outside_of_impl)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ fn report_unexpected_variant_res(
.with_code(err_code);
match res {
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
let patterns_url = "https://doc.rust-lang.org/book/ch19-00-patterns.html";
err.with_span_label(span, "`fn` calls are not allowed in patterns")
.with_help(format!("for more information, visit {patterns_url}"))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_index_macros/src/newtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl Parse for Newtype {
#gate_rustc_only
impl ::std::iter::Step for #name {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as ::std::iter::Step>::steps_between(
&Self::index(*start),
&Self::index(*end),
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
mir_build_moved = value is moved into `{$name}` here
Expand Down Expand Up @@ -338,6 +338,13 @@ mir_build_unreachable_pattern = unreachable pattern
.unreachable_covered_by_catchall = matches any value
.unreachable_covered_by_one = matches all the relevant values
.unreachable_covered_by_many = multiple earlier patterns match some of the same values
.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
.unreachable_pattern_wanted_const = you might have meant to pattern match against the value of {$is_typo ->
[true] similarly named constant
*[false] constant
} `{$const_name}` instead of introducing a new catch-all binding
.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
.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
.suggestion = remove the match arm
mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default
Expand Down
22 changes: 22 additions & 0 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,14 @@ pub(crate) struct UnreachablePattern<'tcx> {
pub(crate) uninhabited_note: Option<()>,
#[label(mir_build_unreachable_covered_by_catchall)]
pub(crate) covered_by_catchall: Option<Span>,
#[subdiagnostic]
pub(crate) wanted_constant: Option<WantedConstant>,
#[note(mir_build_unreachable_pattern_const_reexport_accessible)]
pub(crate) accessible_constant: Option<Span>,
#[note(mir_build_unreachable_pattern_const_inaccessible)]
pub(crate) inaccessible_constant: Option<Span>,
#[note(mir_build_unreachable_pattern_let_binding)]
pub(crate) pattern_let_binding: Option<Span>,
#[label(mir_build_unreachable_covered_by_one)]
pub(crate) covered_by_one: Option<Span>,
#[note(mir_build_unreachable_covered_by_many)]
Expand All @@ -602,6 +610,20 @@ pub(crate) struct UnreachablePattern<'tcx> {
pub(crate) suggest_remove: Option<Span>,
}

#[derive(Subdiagnostic)]
#[suggestion(
mir_build_unreachable_pattern_wanted_const,
code = "{const_path}",
applicability = "machine-applicable"
)]
pub(crate) struct WantedConstant {
#[primary_span]
pub(crate) span: Span,
pub(crate) is_typo: bool,
pub(crate) const_name: String,
pub(crate) const_path: String,
}

#[derive(Diagnostic)]
#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)]
pub(crate) struct ConstPatternDependsOnGenericParameter {
Expand Down
164 changes: 163 additions & 1 deletion compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::Reveal;
use rustc_lint::Level;
use rustc_middle::bug;
use rustc_middle::middle::limits::get_limit_size;
use rustc_middle::thir::visit::Visitor;
Expand All @@ -22,8 +24,10 @@ use rustc_pattern_analysis::rustc::{
use rustc_session::lint::builtin::{
BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::{Span, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::instrument;

use crate::errors::*;
Expand Down Expand Up @@ -969,6 +973,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
covered_by_one: None,
covered_by_many: None,
covered_by_many_n_more_count: 0,
wanted_constant: None,
accessible_constant: None,
inaccessible_constant: None,
pattern_let_binding: None,
suggest_remove: None,
};
match explanation.covered_by.as_slice() {
Expand All @@ -991,7 +999,10 @@ fn report_unreachable_pattern<'p, 'tcx>(
});
}
[covering_pat] if pat_is_catchall(covering_pat) => {
lint.covered_by_catchall = Some(covering_pat.data().span);
// A binding pattern that matches all, a single binding name.
let pat = covering_pat.data();
lint.covered_by_catchall = Some(pat.span);
find_fallback_pattern_typo(cx, hir_id, pat, &mut lint);
}
[covering_pat] => {
lint.covered_by_one = Some(covering_pat.data().span);
Expand Down Expand Up @@ -1024,6 +1035,157 @@ fn report_unreachable_pattern<'p, 'tcx>(
cx.tcx.emit_node_span_lint(UNREACHABLE_PATTERNS, hir_id, pat_span, lint);
}

/// Detect typos that were meant to be a `const` but were interpreted as a new pattern binding.
fn find_fallback_pattern_typo<'tcx>(
cx: &PatCtxt<'_, 'tcx>,
hir_id: HirId,
pat: &Pat<'tcx>,
lint: &mut UnreachablePattern<'_>,
) {
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(UNREACHABLE_PATTERNS, hir_id) {
// This is because we use `with_no_trimmed_paths` later, so if we never emit the lint we'd
// ICE. At the same time, we don't really need to do all of this if we won't emit anything.
return;
}
if let PatKind::Binding { name, subpattern: None, ty, .. } = pat.kind {
// See if the binding might have been a `const` that was mistyped or out of scope.
let mut accessible = vec![];
let mut accessible_path = vec![];
let mut inaccessible = vec![];
let mut imported = vec![];
let mut imported_spans = vec![];
let infcx = cx.tcx.infer_ctxt().build(ty::TypingMode::non_body_analysis());
let parent = cx.tcx.hir().get_parent_item(hir_id);

for item in cx.tcx.hir_crate_items(()).free_items() {
if let DefKind::Use = cx.tcx.def_kind(item.owner_id) {
// Look for consts being re-exported.
let item = cx.tcx.hir().expect_item(item.owner_id.def_id);
let use_name = item.ident.name;
let hir::ItemKind::Use(path, _) = item.kind else {
continue;
};
for res in &path.res {
if let Res::Def(DefKind::Const, id) = res
&& infcx.can_eq(cx.param_env, ty, cx.tcx.type_of(id).instantiate_identity())
{
if cx.tcx.visibility(id).is_accessible_from(parent, cx.tcx) {
// The original const is accessible, suggest using it directly.
let item_name = cx.tcx.item_name(*id);
accessible.push(item_name);
accessible_path.push(with_no_trimmed_paths!(cx.tcx.def_path_str(id)));
} else if cx
.tcx
.visibility(item.owner_id)
.is_accessible_from(parent, cx.tcx)
{
// The const is accessible only through the re-export, point at
// the `use`.
imported.push(use_name);
imported_spans.push(item.ident.span);
}
}
}
}
if let DefKind::Const = cx.tcx.def_kind(item.owner_id)
&& infcx.can_eq(
cx.param_env,
ty,
cx.tcx.type_of(item.owner_id).instantiate_identity(),
)
{
// Look for local consts.
let item_name = cx.tcx.item_name(item.owner_id.into());
let vis = cx.tcx.visibility(item.owner_id);
if vis.is_accessible_from(parent, cx.tcx) {
accessible.push(item_name);
let path = if item_name == name {
// We know that the const wasn't in scope because it has the exact
// same name, so we suggest the full path.
with_no_trimmed_paths!(cx.tcx.def_path_str(item.owner_id))
} else {
// The const is likely just typoed, and nothing else.
cx.tcx.def_path_str(item.owner_id)
};
accessible_path.push(path);
} else if name == item_name {
// The const exists somewhere in this crate, but it can't be imported
// from this pattern's scope. We'll just point at its definition.
inaccessible.push(cx.tcx.def_span(item.owner_id));
}
}
}
if let Some((i, &const_name)) =
accessible.iter().enumerate().find(|(_, &const_name)| const_name == name)
{
// The pattern name is an exact match, so the pattern needed to be imported.
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: false,
const_name: const_name.to_string(),
const_path: accessible_path[i].clone(),
});
} else if let Some(name) = find_best_match_for_name(&accessible, name, None) {
// The pattern name is likely a typo.
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: true,
const_name: name.to_string(),
const_path: name.to_string(),
});
} else if let Some(i) =
imported.iter().enumerate().find(|(_, &const_name)| const_name == name).map(|(i, _)| i)
{
// The const with the exact name wasn't re-exported from an import in this
// crate, we point at the import.
lint.accessible_constant = Some(imported_spans[i]);
} else if let Some(name) = find_best_match_for_name(&imported, name, None) {
// The typoed const wasn't re-exported by an import in this crate, we suggest
// the right name (which will likely require another follow up suggestion).
lint.wanted_constant = Some(WantedConstant {
span: pat.span,
is_typo: true,
const_path: name.to_string(),
const_name: name.to_string(),
});
} else if !inaccessible.is_empty() {
for span in inaccessible {
// The const with the exact name match isn't accessible, we just point at it.
lint.inaccessible_constant = Some(span);
}
} else {
// Look for local bindings for people that might have gotten confused with how
// `let` and `const` works.
for (_, node) in cx.tcx.hir().parent_iter(hir_id) {
match node {
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(let_stmt), .. }) => {
if let hir::PatKind::Binding(_, _, binding_name, _) = let_stmt.pat.kind {
if name == binding_name.name {
lint.pattern_let_binding = Some(binding_name.span);
}
}
}
hir::Node::Block(hir::Block { stmts, .. }) => {
for stmt in *stmts {
if let hir::StmtKind::Let(let_stmt) = stmt.kind {
if let hir::PatKind::Binding(_, _, binding_name, _) =
let_stmt.pat.kind
{
if name == binding_name.name {
lint.pattern_let_binding = Some(binding_name.span);
}
}
}
}
}
hir::Node::Item(_) => break,
_ => {}
}
}
}
}
}

/// Report unreachable arms, if any.
fn report_arm_reachability<'p, 'tcx>(
cx: &PatCtxt<'p, 'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ parse_unexpected_expr_in_pat =
}, found an expression
.label = not a pattern
.note = arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
.note = arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
Expand Down
11 changes: 1 addition & 10 deletions compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,16 +590,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
}

fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
// if the const impl is derived using the `derive_const` attribute,
// then it would be "stable" at least for the impl.
// We gate usages of it using `feature(const_trait_impl)` anyways
// so there is no unstable leakage
if self.tcx.is_automatically_derived(def_id.to_def_id()) {
return;
}

let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|| self.tcx.is_const_trait_impl(def_id.to_def_id());
let is_const = self.tcx.is_const_fn(def_id.to_def_id());

// Reachable const fn must have a stability attribute.
if is_const
Expand Down
Loading

0 comments on commit 5d83144

Please sign in to comment.