Skip to content

Commit 38814fc

Browse files
committed
small refactor
1 parent 2e3221a commit 38814fc

File tree

1 file changed

+96
-95
lines changed
  • compiler/rustc_mir_build/src/thir/cx

1 file changed

+96
-95
lines changed

compiler/rustc_mir_build/src/thir/cx/expr.rs

+96-95
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::thir::cx::region::Scope;
12
use crate::thir::cx::Cx;
23
use crate::thir::util::UserAnnotatedTyHelpers;
34
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -158,6 +159,100 @@ impl<'tcx> Cx<'tcx> {
158159
Expr { temp_lifetime, ty: adjustment.target, span, kind }
159160
}
160161

162+
fn mirror_expr_cast(
163+
&mut self,
164+
source: &'tcx hir::Expr<'tcx>,
165+
temp_lifetime: Option<Scope>,
166+
span: Span,
167+
) -> ExprKind<'tcx> {
168+
let tcx = self.tcx;
169+
170+
// Check to see if this cast is a "coercion cast", where the cast is actually done
171+
// using a coercion (or is a no-op).
172+
if self.typeck_results().is_coercion_cast(source.hir_id) {
173+
// Convert the lexpr to a vexpr.
174+
ExprKind::Use { source: self.mirror_expr(source) }
175+
} else if self.typeck_results().expr_ty(source).is_region_ptr() {
176+
// Special cased so that we can type check that the element
177+
// type of the source matches the pointed to type of the
178+
// destination.
179+
ExprKind::Pointer {
180+
source: self.mirror_expr(source),
181+
cast: PointerCast::ArrayToPointer,
182+
}
183+
} else {
184+
// check whether this is casting an enum variant discriminant
185+
// to prevent cycles, we refer to the discriminant initializer
186+
// which is always an integer and thus doesn't need to know the
187+
// enum's layout (or its tag type) to compute it during const eval
188+
// Example:
189+
// enum Foo {
190+
// A,
191+
// B = A as isize + 4,
192+
// }
193+
// The correct solution would be to add symbolic computations to miri,
194+
// so we wouldn't have to compute and store the actual value
195+
196+
let hir::ExprKind::Path(ref qpath) = source.kind else {
197+
return ExprKind::Cast { source: self.mirror_expr(source)};
198+
};
199+
200+
let res = self.typeck_results().qpath_res(qpath, source.hir_id);
201+
let (discr_did, discr_offset, discr_ty, substs) = {
202+
let ty = self.typeck_results().node_type(source.hir_id);
203+
let ty::Adt(adt_def, substs) = ty.kind() else {
204+
return ExprKind::Cast { source: self.mirror_expr(source)};
205+
};
206+
let Res::Def(
207+
DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
208+
variant_ctor_id,
209+
) = res else {
210+
return ExprKind::Cast { source: self.mirror_expr(source)};
211+
};
212+
213+
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
214+
let (d, o) = adt_def.discriminant_def_for_variant(idx);
215+
use rustc_middle::ty::util::IntTypeExt;
216+
let ty = adt_def.repr().discr_type();
217+
let ty = ty.to_ty(tcx);
218+
(d, o, ty, substs)
219+
};
220+
221+
let param_env_ty = self.param_env.and(discr_ty);
222+
let size = tcx
223+
.layout_of(param_env_ty)
224+
.unwrap_or_else(|e| {
225+
panic!("could not compute layout for {:?}: {:?}", param_env_ty, e)
226+
})
227+
.size;
228+
229+
let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap();
230+
let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
231+
let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
232+
233+
let source = match discr_did {
234+
Some(did) => {
235+
// in case we are offsetting from a computed discriminant
236+
// and not the beginning of discriminants (which is always `0`)
237+
238+
let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None };
239+
let lhs =
240+
self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
241+
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
242+
self.thir.exprs.push(Expr {
243+
temp_lifetime,
244+
ty: discr_ty,
245+
span: span,
246+
kind: bin,
247+
})
248+
}
249+
None => offset,
250+
};
251+
252+
ExprKind::Cast { source }
253+
}
254+
}
255+
161256
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
162257
let tcx = self.tcx;
163258
let expr_ty = self.typeck_results().expr_ty(expr);
@@ -604,101 +699,7 @@ impl<'tcx> Cx<'tcx> {
604699
expr, cast_ty.hir_id, user_ty,
605700
);
606701

607-
// Check to see if this cast is a "coercion cast", where the cast is actually done
608-
// using a coercion (or is a no-op).
609-
let cast = if self.typeck_results().is_coercion_cast(source.hir_id) {
610-
// Convert the lexpr to a vexpr.
611-
ExprKind::Use { source: self.mirror_expr(source) }
612-
} else if self.typeck_results().expr_ty(source).is_region_ptr() {
613-
// Special cased so that we can type check that the element
614-
// type of the source matches the pointed to type of the
615-
// destination.
616-
ExprKind::Pointer {
617-
source: self.mirror_expr(source),
618-
cast: PointerCast::ArrayToPointer,
619-
}
620-
} else {
621-
// check whether this is casting an enum variant discriminant
622-
// to prevent cycles, we refer to the discriminant initializer
623-
// which is always an integer and thus doesn't need to know the
624-
// enum's layout (or its tag type) to compute it during const eval
625-
// Example:
626-
// enum Foo {
627-
// A,
628-
// B = A as isize + 4,
629-
// }
630-
// The correct solution would be to add symbolic computations to miri,
631-
// so we wouldn't have to compute and store the actual value
632-
let var = if let hir::ExprKind::Path(ref qpath) = source.kind {
633-
let res = self.typeck_results().qpath_res(qpath, source.hir_id);
634-
self.typeck_results().node_type(source.hir_id).ty_adt_def().and_then(
635-
|adt_def| match res {
636-
Res::Def(
637-
DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
638-
variant_ctor_id,
639-
) => {
640-
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
641-
let (d, o) = adt_def.discriminant_def_for_variant(idx);
642-
use rustc_middle::ty::util::IntTypeExt;
643-
let ty = adt_def.repr().discr_type();
644-
let ty = ty.to_ty(tcx);
645-
Some((d, o, ty))
646-
}
647-
_ => None,
648-
},
649-
)
650-
} else {
651-
None
652-
};
653-
debug!(?var);
654-
let substs = self.typeck_results.node_substs(source.hir_id);
655-
debug!(?substs);
656-
657-
let source = if let Some((did, offset, var_ty)) = var {
658-
let param_env_ty = self.param_env.and(var_ty);
659-
let size = tcx
660-
.layout_of(param_env_ty)
661-
.unwrap_or_else(|e| {
662-
panic!("could not compute layout for {:?}: {:?}", param_env_ty, e)
663-
})
664-
.size;
665-
let lit = ScalarInt::try_from_uint(offset as u128, size).unwrap();
666-
let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
667-
let offset = self.thir.exprs.push(Expr {
668-
temp_lifetime,
669-
ty: var_ty,
670-
span: expr.span,
671-
kind,
672-
});
673-
match did {
674-
Some(did) => {
675-
// in case we are offsetting from a computed discriminant
676-
// and not the beginning of discriminants (which is always `0`)
677-
678-
let kind =
679-
ExprKind::NamedConst { def_id: did, substs, user_ty: None };
680-
let lhs = self.thir.exprs.push(Expr {
681-
temp_lifetime,
682-
ty: var_ty,
683-
span: expr.span,
684-
kind,
685-
});
686-
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
687-
self.thir.exprs.push(Expr {
688-
temp_lifetime,
689-
ty: var_ty,
690-
span: expr.span,
691-
kind: bin,
692-
})
693-
}
694-
None => offset,
695-
}
696-
} else {
697-
self.mirror_expr(source)
698-
};
699-
700-
ExprKind::Cast { source: source }
701-
};
702+
let cast = self.mirror_expr_cast(*source, temp_lifetime, expr.span);
702703

703704
if let Some(user_ty) = user_ty {
704705
// NOTE: Creating a new Expr and wrapping a Cast inside of it may be

0 commit comments

Comments
 (0)