Skip to content

Commit

Permalink
Auto merge of rust-lang#135465 - jhpratt:rollup-7p93bct, r=jhpratt
Browse files Browse the repository at this point in the history
Rollup of 10 pull requests

Successful merges:

 - rust-lang#134498 (Fix cycle error only occurring with -Zdump-mir)
 - rust-lang#134977 (Detect `mut arg: &Ty` meant to be `arg: &mut Ty` and provide structured suggestion)
 - rust-lang#135390 (Re-added regression test for rust-lang#122638)
 - rust-lang#135393 (uefi: helpers: Introduce OwnedDevicePath)
 - rust-lang#135440 (rm unnecessary `OpaqueTypeDecl` wrapper)
 - rust-lang#135441 (Make sure to mark `IMPL_TRAIT_REDUNDANT_CAPTURES` as `Allow` in edition 2024)
 - rust-lang#135444 (Update books)
 - rust-lang#135450 (Fix emscripten-wasm-eh with unwind=abort)
 - rust-lang#135452 (bootstrap: fix outdated feature name in comment)
 - rust-lang#135454 (llvm: Allow sized-word rather than ymmword in tests)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 14, 2025
2 parents 1ab85fb + 9fdebf6 commit 35c2908
Show file tree
Hide file tree
Showing 34 changed files with 492 additions and 83 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
let opaque_types = infcx
.take_opaque_types()
.into_iter()
.map(|(opaque_type_key, decl)| {
let hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
.map(|(opaque_type_key, hidden_type)| {
let hidden_type = infcx.resolve_vars_if_possible(hidden_type);
register_member_constraints(
typeck,
&mut member_constraints,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2451,10 +2451,10 @@ fn add_order_independent_options(
}

if sess.target.os == "emscripten" {
cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
"-sDISABLE_EXCEPTION_CATCHING=1"
} else if sess.opts.unstable_opts.emscripten_wasm_eh {
cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
"-fwasm-exceptions"
} else if sess.panic_strategy() == PanicStrategy::Abort {
"-sDISABLE_EXCEPTION_CATCHING=1"
} else {
"-sDISABLE_EXCEPTION_CATCHING=0"
});
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,9 @@ fn check_opaque_meets_bounds<'tcx>(
} else {
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
for (mut key, mut ty) in infcx.take_opaque_types() {
ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
ty.ty = infcx.resolve_vars_if_possible(ty.ty);
key = infcx.resolve_vars_if_possible(key);
sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
sanity_check_found_hidden_type(tcx, key, ty)?;
}
Ok(())
}
Expand Down Expand Up @@ -1873,7 +1873,7 @@ pub(super) fn check_coroutine_obligations(
// Check that any hidden types found when checking these stalled coroutine obligations
// are valid.
for (key, ty) in infcx.take_opaque_types() {
let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type);
let hidden_type = infcx.resolve_vars_if_possible(ty);
let key = infcx.resolve_vars_if_possible(key);
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
}
Expand Down
95 changes: 95 additions & 0 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

self.annotate_expected_due_to_let_ty(err, expr, error);
self.annotate_loop_expected_due_to_inference(err, expr, error);
if self.annotate_mut_binding_to_immutable_binding(err, expr, error) {
return;
}

// FIXME(#73154): For now, we do leak check when coercing function
// pointers in typeck, instead of only during borrowck. This can lead
Expand Down Expand Up @@ -795,6 +798,98 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// Detect the following case
///
/// ```text
/// fn change_object(mut a: &Ty) {
/// let a = Ty::new();
/// b = a;
/// }
/// ```
///
/// where the user likely meant to modify the value behind there reference, use `a` as an out
/// parameter, instead of mutating the local binding. When encountering this we suggest:
///
/// ```text
/// fn change_object(a: &'_ mut Ty) {
/// let a = Ty::new();
/// *b = a;
/// }
/// ```
fn annotate_mut_binding_to_immutable_binding(
&self,
err: &mut Diag<'_>,
expr: &hir::Expr<'_>,
error: Option<TypeError<'tcx>>,
) -> bool {
if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error
&& let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()

// The difference between the expected and found values is one level of borrowing.
&& self.can_eq(self.param_env, *inner, found)

// We have an `ident = expr;` assignment.
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
self.tcx.parent_hir_node(expr.hir_id)
&& rhs.hir_id == expr.hir_id

// We are assigning to some binding.
&& let hir::ExprKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: hir::def::Res::Local(hir_id), .. },
)) = lhs.kind
&& let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id)

// The pattern we have is an fn argument.
&& let hir::Node::Param(hir::Param { ty_span, .. }) =
self.tcx.parent_hir_node(pat.hir_id)
&& let item = self.tcx.hir().get_parent_item(pat.hir_id)
&& let item = self.tcx.hir_owner_node(item)
&& let Some(fn_decl) = item.fn_decl()

// We have a mutable binding in the argument.
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind

// Look for the type corresponding to the argument pattern we have in the argument list.
&& let Some(ty_sugg) = fn_decl
.inputs
.iter()
.filter_map(|ty| {
if ty.span == *ty_span
&& let hir::TyKind::Ref(lt, x) = ty.kind
{
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
Some((
x.ty.span.shrink_to_lo(),
format!(
"{}mut ",
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }
),
))
} else {
None
}
})
.next()
{
let sugg = vec![
ty_sugg,
(pat.span.until(ident.span), String::new()),
(lhs.span.shrink_to_lo(), "*".to_string()),
];
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
// assignment from `ident = val;` to `*ident = val;`.
err.multipart_suggestion_verbose(
"you might have meant to mutate the pointed at value being passed in, instead of \
changing the reference in the local binding",
sugg,
Applicability::MaybeIncorrect,
);
return true;
}
false
}

fn annotate_alternative_method_deref(
&self,
err: &mut Diag<'_>,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
// types or by using this function at the end of writeback and running it as a
// fixpoint.
let opaque_types = self.fcx.infcx.clone_opaque_types();
for (opaque_type_key, decl) in opaque_types {
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
for (opaque_type_key, hidden_type) in opaque_types {
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);

if !self.fcx.next_trait_solver() {
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ impl<'tcx> InferCtxt<'tcx> {
.opaque_type_storage
.opaque_types
.iter()
.map(|(k, v)| (*k, v.hidden_type.ty))
.map(|(k, v)| (*k, v.ty))
.collect()
}

fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.hidden_type.ty)).collect()
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
}

/// Given the (canonicalized) result to a canonical query,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
pub fn iter_opaque_types(
&self,
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
self.opaque_type_storage.opaque_types.iter().map(|(&k, v)| (k, v.hidden_type))
self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
}
}

Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,9 @@ use crate::traits::{self, Obligation, PredicateObligations};

mod table;

pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>;
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};

/// Information about the opaque types whose values we
/// are inferring in this function (these are the `impl Trait` that
/// appear in the return type).
#[derive(Clone, Debug)]
pub struct OpaqueTypeDecl<'tcx> {
/// The hidden types that have been inferred for this opaque type.
/// There can be multiple, but they are all `lub`ed together at the end
/// to obtain the canonical hidden type.
pub hidden_type: OpaqueHiddenType<'tcx>,
}

impl<'tcx> InferCtxt<'tcx> {
/// This is a backwards compatibility hack to prevent breaking changes from
/// lazy TAIT around RPIT handling.
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_infer/src/infer/opaque_types/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@ use rustc_middle::bug;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
use tracing::instrument;

use super::{OpaqueTypeDecl, OpaqueTypeMap};
use super::OpaqueTypeMap;
use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};

#[derive(Default, Debug, Clone)]
pub(crate) struct OpaqueTypeStorage<'tcx> {
/// Opaque types found in explicit return types and their
/// associated fresh inference variable. Writeback resolves these
/// variables to get the concrete type, which can be used to
/// 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
/// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.
pub opaque_types: OpaqueTypeMap<'tcx>,
}

impl<'tcx> OpaqueTypeStorage<'tcx> {
#[instrument(level = "debug")]
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
if let Some(idx) = idx {
self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
pub(crate) fn remove(
&mut self,
key: OpaqueTypeKey<'tcx>,
prev: Option<OpaqueHiddenType<'tcx>>,
) {
if let Some(prev) = prev {
*self.opaque_types.get_mut(&key).unwrap() = prev;
} else {
// FIXME(#120456) - is `swap_remove` correct?
match self.opaque_types.swap_remove(&key) {
Expand Down Expand Up @@ -59,13 +63,12 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
key: OpaqueTypeKey<'tcx>,
hidden_type: OpaqueHiddenType<'tcx>,
) -> Option<Ty<'tcx>> {
if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
let prev = std::mem::replace(entry, hidden_type);
self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
return Some(prev.ty);
}
let decl = OpaqueTypeDecl { hidden_type };
self.storage.opaque_types.insert(key, decl);
self.storage.opaque_types.insert(key, hidden_type);
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
None
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ declare_lint! {
/// To fix this, remove the `use<'a>`, since the lifetime is already captured
/// since it is in scope.
pub IMPL_TRAIT_REDUNDANT_CAPTURES,
Warn,
Allow,
"redundant precise-capturing `use<...>` syntax on an `impl Trait`",
}

Expand Down
24 changes: 15 additions & 9 deletions compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,16 +1555,22 @@ pub fn write_allocations<'tcx>(
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
}
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
write_allocation_track_relocs(w, alloc)?;
write!(w, " (static: {}", tcx.def_path_str(did))?;
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)
&& tcx.hir().body_const_context(body.source.def_id()).is_some()
{
// Statics may be cyclic and evaluating them too early
// in the MIR pipeline may cause cycle errors even though
// normal compilation is fine.
write!(w, ")")?;
} else {
match tcx.eval_static_initializer(did) {
Ok(alloc) => {
write!(w, ", ")?;
write_allocation_track_relocs(w, alloc)?;
}
Err(_) => write!(w, ", error during initializer evaluation)")?,
}
Err(_) => write!(
w,
" (static: {}, error during initializer evaluation)",
tcx.def_path_str(did)
)?,
}
}
Some(GlobalAlloc::Static(did)) => {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,9 @@ passes_unused_assign = value assigned to `{$name}` is never read
passes_unused_assign_passed = value passed to `{$name}` is never read
.help = maybe it is overwritten before being read?
passes_unused_assign_suggestion =
you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
.help = did you mean to capture by reference instead?
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1787,9 +1787,26 @@ pub(crate) struct IneffectiveUnstableImpl;

#[derive(LintDiagnostic)]
#[diag(passes_unused_assign)]
#[help]
pub(crate) struct UnusedAssign {
pub name: String,
#[subdiagnostic]
pub suggestion: Option<UnusedAssignSuggestion>,
#[help]
pub help: bool,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(passes_unused_assign_suggestion, applicability = "maybe-incorrect")]
pub(crate) struct UnusedAssignSuggestion {
pub pre: &'static str,
#[suggestion_part(code = "{pre}mut ")]
pub ty_span: Span,
#[suggestion_part(code = "")]
pub ty_ref_span: Span,
#[suggestion_part(code = "*")]
pub ident_span: Span,
#[suggestion_part(code = "")]
pub expr_ref_span: Span,
}

#[derive(LintDiagnostic)]
Expand Down
Loading

0 comments on commit 35c2908

Please sign in to comment.