Skip to content

Commit 35c2908

Browse files
committed
Auto merge of #135465 - jhpratt:rollup-7p93bct, r=jhpratt
Rollup of 10 pull requests Successful merges: - #134498 (Fix cycle error only occurring with -Zdump-mir) - #134977 (Detect `mut arg: &Ty` meant to be `arg: &mut Ty` and provide structured suggestion) - #135390 (Re-added regression test for #122638) - #135393 (uefi: helpers: Introduce OwnedDevicePath) - #135440 (rm unnecessary `OpaqueTypeDecl` wrapper) - #135441 (Make sure to mark `IMPL_TRAIT_REDUNDANT_CAPTURES` as `Allow` in edition 2024) - #135444 (Update books) - #135450 (Fix emscripten-wasm-eh with unwind=abort) - #135452 (bootstrap: fix outdated feature name in comment) - #135454 (llvm: Allow sized-word rather than ymmword in tests) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1ab85fb + 9fdebf6 commit 35c2908

34 files changed

+492
-83
lines changed

compiler/rustc_borrowck/src/type_check/opaque_types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
2525
let opaque_types = infcx
2626
.take_opaque_types()
2727
.into_iter()
28-
.map(|(opaque_type_key, decl)| {
29-
let hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
28+
.map(|(opaque_type_key, hidden_type)| {
29+
let hidden_type = infcx.resolve_vars_if_possible(hidden_type);
3030
register_member_constraints(
3131
typeck,
3232
&mut member_constraints,

compiler/rustc_codegen_ssa/src/back/link.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2451,10 +2451,10 @@ fn add_order_independent_options(
24512451
}
24522452

24532453
if sess.target.os == "emscripten" {
2454-
cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort {
2455-
"-sDISABLE_EXCEPTION_CATCHING=1"
2456-
} else if sess.opts.unstable_opts.emscripten_wasm_eh {
2454+
cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
24572455
"-fwasm-exceptions"
2456+
} else if sess.panic_strategy() == PanicStrategy::Abort {
2457+
"-sDISABLE_EXCEPTION_CATCHING=1"
24582458
} else {
24592459
"-sDISABLE_EXCEPTION_CATCHING=0"
24602460
});

compiler/rustc_hir_analysis/src/check/check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,9 @@ fn check_opaque_meets_bounds<'tcx>(
436436
} else {
437437
// Check that any hidden types found during wf checking match the hidden types that `type_of` sees.
438438
for (mut key, mut ty) in infcx.take_opaque_types() {
439-
ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty);
439+
ty.ty = infcx.resolve_vars_if_possible(ty.ty);
440440
key = infcx.resolve_vars_if_possible(key);
441-
sanity_check_found_hidden_type(tcx, key, ty.hidden_type)?;
441+
sanity_check_found_hidden_type(tcx, key, ty)?;
442442
}
443443
Ok(())
444444
}
@@ -1873,7 +1873,7 @@ pub(super) fn check_coroutine_obligations(
18731873
// Check that any hidden types found when checking these stalled coroutine obligations
18741874
// are valid.
18751875
for (key, ty) in infcx.take_opaque_types() {
1876-
let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type);
1876+
let hidden_type = infcx.resolve_vars_if_possible(ty);
18771877
let key = infcx.resolve_vars_if_possible(key);
18781878
sanity_check_found_hidden_type(tcx, key, hidden_type)?;
18791879
}

compiler/rustc_hir_typeck/src/demand.rs

+95
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8585

8686
self.annotate_expected_due_to_let_ty(err, expr, error);
8787
self.annotate_loop_expected_due_to_inference(err, expr, error);
88+
if self.annotate_mut_binding_to_immutable_binding(err, expr, error) {
89+
return;
90+
}
8891

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

801+
/// Detect the following case
802+
///
803+
/// ```text
804+
/// fn change_object(mut a: &Ty) {
805+
/// let a = Ty::new();
806+
/// b = a;
807+
/// }
808+
/// ```
809+
///
810+
/// where the user likely meant to modify the value behind there reference, use `a` as an out
811+
/// parameter, instead of mutating the local binding. When encountering this we suggest:
812+
///
813+
/// ```text
814+
/// fn change_object(a: &'_ mut Ty) {
815+
/// let a = Ty::new();
816+
/// *b = a;
817+
/// }
818+
/// ```
819+
fn annotate_mut_binding_to_immutable_binding(
820+
&self,
821+
err: &mut Diag<'_>,
822+
expr: &hir::Expr<'_>,
823+
error: Option<TypeError<'tcx>>,
824+
) -> bool {
825+
if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error
826+
&& let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
827+
828+
// The difference between the expected and found values is one level of borrowing.
829+
&& self.can_eq(self.param_env, *inner, found)
830+
831+
// We have an `ident = expr;` assignment.
832+
&& let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
833+
self.tcx.parent_hir_node(expr.hir_id)
834+
&& rhs.hir_id == expr.hir_id
835+
836+
// We are assigning to some binding.
837+
&& let hir::ExprKind::Path(hir::QPath::Resolved(
838+
None,
839+
hir::Path { res: hir::def::Res::Local(hir_id), .. },
840+
)) = lhs.kind
841+
&& let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id)
842+
843+
// The pattern we have is an fn argument.
844+
&& let hir::Node::Param(hir::Param { ty_span, .. }) =
845+
self.tcx.parent_hir_node(pat.hir_id)
846+
&& let item = self.tcx.hir().get_parent_item(pat.hir_id)
847+
&& let item = self.tcx.hir_owner_node(item)
848+
&& let Some(fn_decl) = item.fn_decl()
849+
850+
// We have a mutable binding in the argument.
851+
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
852+
853+
// Look for the type corresponding to the argument pattern we have in the argument list.
854+
&& let Some(ty_sugg) = fn_decl
855+
.inputs
856+
.iter()
857+
.filter_map(|ty| {
858+
if ty.span == *ty_span
859+
&& let hir::TyKind::Ref(lt, x) = ty.kind
860+
{
861+
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
862+
Some((
863+
x.ty.span.shrink_to_lo(),
864+
format!(
865+
"{}mut ",
866+
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }
867+
),
868+
))
869+
} else {
870+
None
871+
}
872+
})
873+
.next()
874+
{
875+
let sugg = vec![
876+
ty_sugg,
877+
(pat.span.until(ident.span), String::new()),
878+
(lhs.span.shrink_to_lo(), "*".to_string()),
879+
];
880+
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
881+
// assignment from `ident = val;` to `*ident = val;`.
882+
err.multipart_suggestion_verbose(
883+
"you might have meant to mutate the pointed at value being passed in, instead of \
884+
changing the reference in the local binding",
885+
sugg,
886+
Applicability::MaybeIncorrect,
887+
);
888+
return true;
889+
}
890+
false
891+
}
892+
798893
fn annotate_alternative_method_deref(
799894
&self,
800895
err: &mut Diag<'_>,

compiler/rustc_hir_typeck/src/writeback.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -562,9 +562,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
562562
// types or by using this function at the end of writeback and running it as a
563563
// fixpoint.
564564
let opaque_types = self.fcx.infcx.clone_opaque_types();
565-
for (opaque_type_key, decl) in opaque_types {
566-
let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
567-
let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
565+
for (opaque_type_key, hidden_type) in opaque_types {
566+
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
567+
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
568568

569569
if !self.fcx.next_trait_solver() {
570570
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()

compiler/rustc_infer/src/infer/canonical/query_response.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,12 @@ impl<'tcx> InferCtxt<'tcx> {
155155
.opaque_type_storage
156156
.opaque_types
157157
.iter()
158-
.map(|(k, v)| (*k, v.hidden_type.ty))
158+
.map(|(k, v)| (*k, v.ty))
159159
.collect()
160160
}
161161

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

166166
/// Given the (canonicalized) result to a canonical query,

compiler/rustc_infer/src/infer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
234234
pub fn iter_opaque_types(
235235
&self,
236236
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
237-
self.opaque_type_storage.opaque_types.iter().map(|(&k, v)| (k, v.hidden_type))
237+
self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
238238
}
239239
}
240240

compiler/rustc_infer/src/infer/opaque_types/mod.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,9 @@ use crate::traits::{self, Obligation, PredicateObligations};
1919

2020
mod table;
2121

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

25-
/// Information about the opaque types whose values we
26-
/// are inferring in this function (these are the `impl Trait` that
27-
/// appear in the return type).
28-
#[derive(Clone, Debug)]
29-
pub struct OpaqueTypeDecl<'tcx> {
30-
/// The hidden types that have been inferred for this opaque type.
31-
/// There can be multiple, but they are all `lub`ed together at the end
32-
/// to obtain the canonical hidden type.
33-
pub hidden_type: OpaqueHiddenType<'tcx>,
34-
}
35-
3625
impl<'tcx> InferCtxt<'tcx> {
3726
/// This is a backwards compatibility hack to prevent breaking changes from
3827
/// lazy TAIT around RPIT handling.

compiler/rustc_infer/src/infer/opaque_types/table.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,27 @@ use rustc_middle::bug;
33
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
44
use tracing::instrument;
55

6-
use super::{OpaqueTypeDecl, OpaqueTypeMap};
6+
use super::OpaqueTypeMap;
77
use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
88

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

1818
impl<'tcx> OpaqueTypeStorage<'tcx> {
1919
#[instrument(level = "debug")]
20-
pub(crate) fn remove(&mut self, key: OpaqueTypeKey<'tcx>, idx: Option<OpaqueHiddenType<'tcx>>) {
21-
if let Some(idx) = idx {
22-
self.opaque_types.get_mut(&key).unwrap().hidden_type = idx;
20+
pub(crate) fn remove(
21+
&mut self,
22+
key: OpaqueTypeKey<'tcx>,
23+
prev: Option<OpaqueHiddenType<'tcx>>,
24+
) {
25+
if let Some(prev) = prev {
26+
*self.opaque_types.get_mut(&key).unwrap() = prev;
2327
} else {
2428
// FIXME(#120456) - is `swap_remove` correct?
2529
match self.opaque_types.swap_remove(&key) {
@@ -59,13 +63,12 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
5963
key: OpaqueTypeKey<'tcx>,
6064
hidden_type: OpaqueHiddenType<'tcx>,
6165
) -> Option<Ty<'tcx>> {
62-
if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
63-
let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
66+
if let Some(entry) = self.storage.opaque_types.get_mut(&key) {
67+
let prev = std::mem::replace(entry, hidden_type);
6468
self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
6569
return Some(prev.ty);
6670
}
67-
let decl = OpaqueTypeDecl { hidden_type };
68-
self.storage.opaque_types.insert(key, decl);
71+
self.storage.opaque_types.insert(key, hidden_type);
6972
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
7073
None
7174
}

compiler/rustc_lint/src/impl_trait_overcaptures.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ declare_lint! {
9999
/// To fix this, remove the `use<'a>`, since the lifetime is already captured
100100
/// since it is in scope.
101101
pub IMPL_TRAIT_REDUNDANT_CAPTURES,
102-
Warn,
102+
Allow,
103103
"redundant precise-capturing `use<...>` syntax on an `impl Trait`",
104104
}
105105

compiler/rustc_middle/src/mir/pretty.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -1555,16 +1555,22 @@ pub fn write_allocations<'tcx>(
15551555
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
15561556
}
15571557
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
1558-
match tcx.eval_static_initializer(did) {
1559-
Ok(alloc) => {
1560-
write!(w, " (static: {}, ", tcx.def_path_str(did))?;
1561-
write_allocation_track_relocs(w, alloc)?;
1558+
write!(w, " (static: {}", tcx.def_path_str(did))?;
1559+
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)
1560+
&& tcx.hir().body_const_context(body.source.def_id()).is_some()
1561+
{
1562+
// Statics may be cyclic and evaluating them too early
1563+
// in the MIR pipeline may cause cycle errors even though
1564+
// normal compilation is fine.
1565+
write!(w, ")")?;
1566+
} else {
1567+
match tcx.eval_static_initializer(did) {
1568+
Ok(alloc) => {
1569+
write!(w, ", ")?;
1570+
write_allocation_track_relocs(w, alloc)?;
1571+
}
1572+
Err(_) => write!(w, ", error during initializer evaluation)")?,
15621573
}
1563-
Err(_) => write!(
1564-
w,
1565-
" (static: {}, error during initializer evaluation)",
1566-
tcx.def_path_str(did)
1567-
)?,
15681574
}
15691575
}
15701576
Some(GlobalAlloc::Static(did)) => {

compiler/rustc_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ passes_unused_assign = value assigned to `{$name}` is never read
799799
passes_unused_assign_passed = value passed to `{$name}` is never read
800800
.help = maybe it is overwritten before being read?
801801
802+
passes_unused_assign_suggestion =
803+
you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
804+
802805
passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read
803806
.help = did you mean to capture by reference instead?
804807

compiler/rustc_passes/src/errors.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1787,9 +1787,26 @@ pub(crate) struct IneffectiveUnstableImpl;
17871787

17881788
#[derive(LintDiagnostic)]
17891789
#[diag(passes_unused_assign)]
1790-
#[help]
17911790
pub(crate) struct UnusedAssign {
17921791
pub name: String,
1792+
#[subdiagnostic]
1793+
pub suggestion: Option<UnusedAssignSuggestion>,
1794+
#[help]
1795+
pub help: bool,
1796+
}
1797+
1798+
#[derive(Subdiagnostic)]
1799+
#[multipart_suggestion(passes_unused_assign_suggestion, applicability = "maybe-incorrect")]
1800+
pub(crate) struct UnusedAssignSuggestion {
1801+
pub pre: &'static str,
1802+
#[suggestion_part(code = "{pre}mut ")]
1803+
pub ty_span: Span,
1804+
#[suggestion_part(code = "")]
1805+
pub ty_ref_span: Span,
1806+
#[suggestion_part(code = "*")]
1807+
pub ident_span: Span,
1808+
#[suggestion_part(code = "")]
1809+
pub expr_ref_span: Span,
17931810
}
17941811

17951812
#[derive(LintDiagnostic)]

0 commit comments

Comments
 (0)