Skip to content

Commit 909bfa3

Browse files
authored
Rollup merge of #112410 - compiler-errors:writeback, r=lcnr
Do `fix_*_builtin_expr` hacks on the writeback results During writeback, we do `fix_{scalar,index}_builtin_expr` so that during MIR build we generate built-in MIR instructions instead of method calls for certain built-in arithmetic operations. We do this by checking the types of these built-in operations are scalar types, and remove the method def-id to essentially mark the operation as built-in and not "overloaded". For lazy norm and the new trait solver, this is a problem, because we don't actually normalize all the types we end up seeing in the typeck results until they're copied over writeback's copy of the typeck results. To fix this, delay these fixup calls until after this normalization has been done. This doesn't affect the old trait solver, but does simplify the code a bit IMO, since we can remove a few sets of calls to `resolve_vars_if_possible` and some `borrow_mut`s. r? `@lcnr`
2 parents c71daaa + 8efcb28 commit 909bfa3

File tree

2 files changed

+46
-48
lines changed

2 files changed

+46
-48
lines changed

compiler/rustc_hir_typeck/src/writeback.rs

+35-48
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use rustc_middle::mir::FakeReadCause;
1414
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
1515
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
1616
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
17-
use rustc_middle::ty::TypeckResults;
1817
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
1918
use rustc_span::symbol::sym;
2019
use rustc_span::Span;
@@ -148,31 +147,25 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
148147
fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr<'_>) {
149148
match e.kind {
150149
hir::ExprKind::Unary(hir::UnOp::Neg | hir::UnOp::Not, inner) => {
151-
let inner_ty = self.fcx.node_ty(inner.hir_id);
152-
let inner_ty = self.fcx.resolve_vars_if_possible(inner_ty);
150+
let inner_ty = self.typeck_results.node_type(inner.hir_id);
153151

154152
if inner_ty.is_scalar() {
155-
let mut typeck_results = self.fcx.typeck_results.borrow_mut();
156-
typeck_results.type_dependent_defs_mut().remove(e.hir_id);
157-
typeck_results.node_substs_mut().remove(e.hir_id);
153+
self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
154+
self.typeck_results.node_substs_mut().remove(e.hir_id);
158155
}
159156
}
160157
hir::ExprKind::Binary(ref op, lhs, rhs) | hir::ExprKind::AssignOp(ref op, lhs, rhs) => {
161-
let lhs_ty = self.fcx.node_ty(lhs.hir_id);
162-
let lhs_ty = self.fcx.resolve_vars_if_possible(lhs_ty);
163-
164-
let rhs_ty = self.fcx.node_ty(rhs.hir_id);
165-
let rhs_ty = self.fcx.resolve_vars_if_possible(rhs_ty);
158+
let lhs_ty = self.typeck_results.node_type(lhs.hir_id);
159+
let rhs_ty = self.typeck_results.node_type(rhs.hir_id);
166160

167161
if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
168-
let mut typeck_results = self.fcx.typeck_results.borrow_mut();
169-
typeck_results.type_dependent_defs_mut().remove(e.hir_id);
170-
typeck_results.node_substs_mut().remove(e.hir_id);
162+
self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
163+
self.typeck_results.node_substs_mut().remove(e.hir_id);
171164

172165
match e.kind {
173166
hir::ExprKind::Binary(..) => {
174167
if !op.node.is_by_value() {
175-
let mut adjustments = typeck_results.adjustments_mut();
168+
let mut adjustments = self.typeck_results.adjustments_mut();
176169
if let Some(a) = adjustments.get_mut(lhs.hir_id) {
177170
a.pop();
178171
}
@@ -182,7 +175,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
182175
}
183176
}
184177
hir::ExprKind::AssignOp(..)
185-
if let Some(a) = typeck_results.adjustments_mut().get_mut(lhs.hir_id) =>
178+
if let Some(a) = self.typeck_results.adjustments_mut().get_mut(lhs.hir_id) =>
186179
{
187180
a.pop();
188181
}
@@ -200,16 +193,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
200193
// if they are not we don't modify the expr, hence we bypass the ICE
201194
fn is_builtin_index(
202195
&mut self,
203-
typeck_results: &TypeckResults<'tcx>,
204196
e: &hir::Expr<'_>,
205197
base_ty: Ty<'tcx>,
206198
index_ty: Ty<'tcx>,
207199
) -> bool {
208-
if let Some(elem_ty) = base_ty.builtin_index() {
209-
let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;};
210-
let resolved_exp_ty = self.resolve(exp_ty, &e.span);
211-
212-
elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize
200+
if let Some(elem_ty) = base_ty.builtin_index()
201+
&& let Some(exp_ty) = self.typeck_results.expr_ty_opt(e)
202+
{
203+
elem_ty == exp_ty && index_ty == self.fcx.tcx.types.usize
213204
} else {
214205
false
215206
}
@@ -221,38 +212,34 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
221212
// usize-ish
222213
fn fix_index_builtin_expr(&mut self, e: &hir::Expr<'_>) {
223214
if let hir::ExprKind::Index(ref base, ref index) = e.kind {
224-
let mut typeck_results = self.fcx.typeck_results.borrow_mut();
225-
226215
// All valid indexing looks like this; might encounter non-valid indexes at this point.
227-
let base_ty = typeck_results
228-
.expr_ty_adjusted_opt(base)
229-
.map(|t| self.fcx.resolve_vars_if_possible(t).kind());
216+
let base_ty = self.typeck_results.expr_ty_adjusted_opt(base);
230217
if base_ty.is_none() {
231218
// When encountering `return [0][0]` outside of a `fn` body we can encounter a base
232219
// that isn't in the type table. We assume more relevant errors have already been
233220
// emitted, so we delay an ICE if none have. (#64638)
234221
self.tcx().sess.delay_span_bug(e.span, format!("bad base: `{:?}`", base));
235222
}
236-
if let Some(ty::Ref(_, base_ty, _)) = base_ty {
237-
let index_ty = typeck_results.expr_ty_adjusted_opt(index).unwrap_or_else(|| {
238-
// When encountering `return [0][0]` outside of a `fn` body we would attempt
239-
// to access an nonexistent index. We assume that more relevant errors will
240-
// already have been emitted, so we only gate on this with an ICE if no
241-
// error has been emitted. (#64638)
242-
self.fcx.tcx.ty_error_with_message(
243-
e.span,
244-
format!("bad index {:?} for base: `{:?}`", index, base),
245-
)
246-
});
247-
let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
248-
let resolved_base_ty = self.resolve(*base_ty, &base.span);
249-
250-
if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) {
223+
if let Some(base_ty) = base_ty
224+
&& let ty::Ref(_, base_ty_inner, _) = *base_ty.kind()
225+
{
226+
let index_ty =
227+
self.typeck_results.expr_ty_adjusted_opt(index).unwrap_or_else(|| {
228+
// When encountering `return [0][0]` outside of a `fn` body we would attempt
229+
// to access an nonexistent index. We assume that more relevant errors will
230+
// already have been emitted, so we only gate on this with an ICE if no
231+
// error has been emitted. (#64638)
232+
self.fcx.tcx.ty_error_with_message(
233+
e.span,
234+
format!("bad index {:?} for base: `{:?}`", index, base),
235+
)
236+
});
237+
if self.is_builtin_index(e, base_ty_inner, index_ty) {
251238
// Remove the method call record
252-
typeck_results.type_dependent_defs_mut().remove(e.hir_id);
253-
typeck_results.node_substs_mut().remove(e.hir_id);
239+
self.typeck_results.type_dependent_defs_mut().remove(e.hir_id);
240+
self.typeck_results.node_substs_mut().remove(e.hir_id);
254241

255-
if let Some(a) = typeck_results.adjustments_mut().get_mut(base.hir_id) {
242+
if let Some(a) = self.typeck_results.adjustments_mut().get_mut(base.hir_id) {
256243
// Discard the need for a mutable borrow
257244

258245
// Extra adjustment made when indexing causes a drop
@@ -283,9 +270,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
283270

284271
impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
285272
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
286-
self.fix_scalar_builtin_expr(e);
287-
self.fix_index_builtin_expr(e);
288-
289273
match e.kind {
290274
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
291275
let body = self.fcx.tcx.hir().body(body);
@@ -314,6 +298,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
314298

315299
self.visit_node_id(e.span, e.hir_id);
316300
intravisit::walk_expr(self, e);
301+
302+
self.fix_scalar_builtin_expr(e);
303+
self.fix_index_builtin_expr(e);
317304
}
318305

319306
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
const fn foo() {
5+
let mut x = [1, 2, 3];
6+
// We need to fix up `<<[i32; 3] as Index<usize>>::Output as AddAssign>`
7+
// to be treated like a built-in operation.
8+
x[1] += 5;
9+
}
10+
11+
fn main() {}

0 commit comments

Comments
 (0)