Skip to content
Open
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// whether or not the right-hand side is a place expression
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
opt_match_place: Some((opt_match_place, match_span)),
binding_mode: _,
opt_ty_info: _,
pat_span: _,
..
})) = *local_decl.local_info()
{
let stmt_source_info = self.body.source_info(location);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
binding_mode: BindingMode(ByRef::No, Mutability::Not),
opt_ty_info: Some(sp),
opt_match_place: _,
pat_span: _,
..
})) => {
if suggest {
err.span_note(sp, "the binding is already a mutable borrow");
Expand Down Expand Up @@ -751,6 +750,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
opt_ty_info: _,
opt_match_place: _,
pat_span,
introductions: _,
})) => pat_span,
_ => local_decl.source_info.span,
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
tcx.ensure_ok().check_transmutes(def_id);
}
tcx.ensure_ok().has_ffi_unwind_calls(def_id);
tcx.ensure_ok().check_liveness(def_id);

// If we need to codegen, ensure that we emit all errors from
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering
Expand Down
33 changes: 18 additions & 15 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,9 @@ pub struct VarBindingForm<'tcx> {
pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
/// The span of the pattern in which this variable was bound.
pub pat_span: Span,
/// A binding can be introduced multiple times, with or patterns:
/// `Foo::A { x } | Foo::B { z: x }`. This stores information for each of those introductions.
pub introductions: Vec<VarBindingIntroduction>,
}

#[derive(Clone, Debug, TyEncodable, TyDecodable)]
Expand All @@ -891,7 +894,15 @@ pub enum BindingForm<'tcx> {
/// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
ImplicitSelf(ImplicitSelfKind),
/// Reference used in a guard expression to ensure immutability.
RefForGuard,
RefForGuard(Local),
}

#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct VarBindingIntroduction {
/// Where this additional introduction happened.
pub span: Span,
/// Is that introduction a shorthand struct pattern, i.e. `Foo { x }`.
pub is_shorthand: bool,
}

mod binding_form_impl {
Expand All @@ -906,7 +917,7 @@ mod binding_form_impl {
match self {
Var(binding) => binding.hash_stable(hcx, hasher),
ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
RefForGuard => (),
RefForGuard(local) => local.hash_stable(hcx, hasher),
}
}
}
Expand Down Expand Up @@ -1088,12 +1099,8 @@ impl<'tcx> LocalDecl<'tcx> {
matches!(
self.local_info(),
LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: BindingMode(ByRef::No, _),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
| BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
)
)
}
Expand All @@ -1105,12 +1112,8 @@ impl<'tcx> LocalDecl<'tcx> {
matches!(
self.local_info(),
LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: BindingMode(ByRef::No, _),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}) | BindingForm::ImplicitSelf(_),
BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
| BindingForm::ImplicitSelf(_),
)
)
}
Expand All @@ -1126,7 +1129,7 @@ impl<'tcx> LocalDecl<'tcx> {
/// expression that is used to access said variable for the guard of the
/// match arm.
pub fn is_ref_for_guard(&self) -> bool {
matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard))
matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard(_)))
}

/// Returns `Some` if this is a reference to a static item that is used to
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl<'tcx> PlaceTy<'tcx> {
impl<V, T> ProjectionElem<V, T> {
/// Returns `true` if the target of this projection may refer to a different region of memory
/// than the base.
fn is_indirect(&self) -> bool {
pub fn is_indirect(&self) -> bool {
match self {
Self::Deref => true,

Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,8 +1195,10 @@ rustc_queries! {
desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) }
}

query check_liveness(key: LocalDefId) {
desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key) }
query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
arena_cache
desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
}

/// Return the live symbols in the crate for dead code check.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,8 @@ pub enum PatKind<'tcx> {
/// (The same binding can occur multiple times in different branches of
/// an or-pattern, but only one of them will be primary.)
is_primary: bool,
/// Is this binding a shorthand struct pattern, i.e. `Foo { a }`?
is_shorthand: bool,
},

/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
)
}
},
HirProjectionKind::UnwrapUnsafeBinder => {
curr_string = format!("unwrap_binder!({curr_string})");
}
// Just change the type to the hidden type, so we can actually project.
HirProjectionKind::OpaqueCast => {}
proj => bug!("{:?} unexpected because it isn't captured", proj),
}
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
mir_build_union_pattern = cannot use unions in constant patterns
.label = can't use a `union` here

mir_build_unreachable_due_to_uninhabited = unreachable {$descr}
.label = unreachable {$descr}
.label_orig = any code following this expression is unreachable
.note = this expression has type `{$ty}`, which is uninhabited

mir_build_unreachable_making_this_unreachable = collectively making this unreachable

mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/builder/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
node,
span,
false,
OutsideGuard,
ScheduleDrops::Yes,
);
Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_mir_build/src/builder/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,18 +390,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
args,
unwind: UnwindAction::Continue,
destination,
// The presence or absence of a return edge affects control-flow sensitive
// MIR checks and ultimately whether code is accepted or not. We can only
// omit the return edge if a return type is visibly uninhabited to a module
// that makes the call.
target: expr
.ty
.is_inhabited_from(
this.tcx,
this.parent_module,
this.infcx.typing_env(this.param_env),
)
.then_some(success),
target: Some(success),
call_source: if from_hir_call {
CallSource::Normal
} else {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl<'tcx> MatchPairTree<'tcx> {
None
}

PatKind::Binding { mode, var, ref subpattern, .. } => {
PatKind::Binding { mode, var, is_shorthand, ref subpattern, .. } => {
// In order to please the borrow checker, when lowering a pattern
// like `x @ subpat` we must establish any bindings in `subpat`
// before establishing the binding for `x`.
Expand Down Expand Up @@ -209,6 +209,7 @@ impl<'tcx> MatchPairTree<'tcx> {
source,
var_id: var,
binding_mode: mode,
is_shorthand,
}));
}

Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_mir_build/src/builder/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
var,
irrefutable_pat.span,
false,
OutsideGuard,
ScheduleDrops::Yes,
);
Expand Down Expand Up @@ -608,6 +609,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
var,
irrefutable_pat.span,
false,
OutsideGuard,
ScheduleDrops::Yes,
);
Expand Down Expand Up @@ -739,6 +741,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pattern,
&ProjectedUserTypesNode::None,
&mut |this, name, mode, var, span, ty, user_tys| {
let saved_scope = this.source_scope;
this.set_correct_source_scope_for_arg(var.0, saved_scope, span);
let vis_scope = *visibility_scope
.get_or_insert_with(|| this.new_source_scope(scope_span, LintLevel::Inherited));
let source_info = SourceInfo { span, scope: this.source_scope };
Expand All @@ -756,6 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place.map(|(x, y)| (x.cloned(), y)),
pattern.span,
);
this.source_scope = saved_scope;
},
);
if let Some(guard_expr) = guard {
Expand Down Expand Up @@ -799,6 +804,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block: BasicBlock,
var: LocalVarId,
span: Span,
is_shorthand: bool,
for_guard: ForGuard,
schedule_drop: ScheduleDrops,
) -> Place<'tcx> {
Expand All @@ -812,6 +818,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
{
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
}
let local_info = self.local_decls[local_id].local_info.as_mut().unwrap_crate_local();
if let LocalInfo::User(BindingForm::Var(var_info)) = &mut **local_info {
var_info.introductions.push(VarBindingIntroduction { span, is_shorthand });
}
Place::from(local_id)
}

Expand Down Expand Up @@ -1217,6 +1227,7 @@ struct Binding<'tcx> {
source: Place<'tcx>,
var_id: LocalVarId,
binding_mode: BindingMode,
is_shorthand: bool,
}

/// Indicates that the type of `source` must be a subtype of the
Expand Down Expand Up @@ -2725,6 +2736,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
binding.var_id,
binding.span,
binding.is_shorthand,
RefWithinGuard,
ScheduleDrops::Yes,
);
Expand All @@ -2742,6 +2754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
binding.var_id,
binding.span,
binding.is_shorthand,
OutsideGuard,
ScheduleDrops::Yes,
);
Expand Down Expand Up @@ -2775,6 +2788,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block,
binding.var_id,
binding.span,
binding.is_shorthand,
OutsideGuard,
schedule_drops,
);
Expand Down Expand Up @@ -2827,6 +2841,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_ty_info: None,
opt_match_place,
pat_span,
introductions: Vec::new(),
},
)))),
};
Expand All @@ -2849,7 +2864,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
user_ty: None,
source_info,
local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(
BindingForm::RefForGuard,
BindingForm::RefForGuard(for_arm_body),
))),
});
if self.should_emit_debug_info_for_binding(name, var_id) {
Expand Down
Loading
Loading