Skip to content

Commit 743ce3b

Browse files
committed
thir building: use typing_env directly
1 parent d9efd17 commit 743ce3b

File tree

3 files changed

+101
-120
lines changed

3 files changed

+101
-120
lines changed

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

Lines changed: 88 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -237,88 +237,88 @@ impl<'tcx> Cx<'tcx> {
237237
///
238238
/// Dealing with user type annotations is left to the caller.
239239
fn mirror_expr_cast(
240-
&mut self,
241-
source: &'tcx hir::Expr<'tcx>,
242-
temp_lifetime: TempLifetime,
243-
span: Span,
244-
) -> ExprKind<'tcx> {
245-
let tcx = self.tcx;
246-
247-
// Check to see if this cast is a "coercion cast", where the cast is actually done
248-
// using a coercion (or is a no-op).
249-
if self.typeck_results().is_coercion_cast(source.hir_id) {
250-
// Convert the lexpr to a vexpr.
251-
ExprKind::Use { source: self.mirror_expr(source) }
252-
} else if self.typeck_results().expr_ty(source).is_ref() {
253-
// Special cased so that we can type check that the element
254-
// type of the source matches the pointed to type of the
255-
// destination.
256-
ExprKind::PointerCoercion {
257-
source: self.mirror_expr(source),
258-
cast: PointerCoercion::ArrayToPointer,
259-
is_from_as_cast: true,
260-
}
261-
} else if let hir::ExprKind::Path(ref qpath) = source.kind
262-
&& let res = self.typeck_results().qpath_res(qpath, source.hir_id)
263-
&& let ty = self.typeck_results().node_type(source.hir_id)
264-
&& let ty::Adt(adt_def, args) = ty.kind()
265-
&& let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res
266-
{
267-
// Check whether this is casting an enum variant discriminant.
268-
// To prevent cycles, we refer to the discriminant initializer,
269-
// which is always an integer and thus doesn't need to know the
270-
// enum's layout (or its tag type) to compute it during const eval.
271-
// Example:
272-
// enum Foo {
273-
// A,
274-
// B = A as isize + 4,
275-
// }
276-
// The correct solution would be to add symbolic computations to miri,
277-
// so we wouldn't have to compute and store the actual value
278-
279-
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
280-
let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx);
281-
282-
use rustc_middle::ty::util::IntTypeExt;
283-
let ty = adt_def.repr().discr_type();
284-
let discr_ty = ty.to_ty(tcx);
285-
286-
let size = tcx
287-
.layout_of(self.typing_env().as_query_input(discr_ty))
288-
.unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}"))
289-
.size;
290-
291-
let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
292-
if overflowing {
293-
// An erroneous enum with too many variants for its repr will emit E0081 and E0370
294-
self.tcx.dcx().span_delayed_bug(
295-
source.span,
296-
"overflowing enum wasn't rejected by hir analysis",
297-
);
240+
&mut self,
241+
source: &'tcx hir::Expr<'tcx>,
242+
temp_lifetime: TempLifetime,
243+
span: Span,
244+
) -> ExprKind<'tcx> {
245+
let tcx = self.tcx;
246+
247+
// Check to see if this cast is a "coercion cast", where the cast is actually done
248+
// using a coercion (or is a no-op).
249+
if self.typeck_results().is_coercion_cast(source.hir_id) {
250+
// Convert the lexpr to a vexpr.
251+
ExprKind::Use { source: self.mirror_expr(source) }
252+
} else if self.typeck_results().expr_ty(source).is_ref() {
253+
// Special cased so that we can type check that the element
254+
// type of the source matches the pointed to type of the
255+
// destination.
256+
ExprKind::PointerCoercion {
257+
source: self.mirror_expr(source),
258+
cast: PointerCoercion::ArrayToPointer,
259+
is_from_as_cast: true,
260+
}
261+
} else if let hir::ExprKind::Path(ref qpath) = source.kind
262+
&& let res = self.typeck_results().qpath_res(qpath, source.hir_id)
263+
&& let ty = self.typeck_results().node_type(source.hir_id)
264+
&& let ty::Adt(adt_def, args) = ty.kind()
265+
&& let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res
266+
{
267+
// Check whether this is casting an enum variant discriminant.
268+
// To prevent cycles, we refer to the discriminant initializer,
269+
// which is always an integer and thus doesn't need to know the
270+
// enum's layout (or its tag type) to compute it during const eval.
271+
// Example:
272+
// enum Foo {
273+
// A,
274+
// B = A as isize + 4,
275+
// }
276+
// The correct solution would be to add symbolic computations to miri,
277+
// so we wouldn't have to compute and store the actual value
278+
279+
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
280+
let (discr_did, discr_offset) = adt_def.discriminant_def_for_variant(idx);
281+
282+
use rustc_middle::ty::util::IntTypeExt;
283+
let ty = adt_def.repr().discr_type();
284+
let discr_ty = ty.to_ty(tcx);
285+
286+
let size = tcx
287+
.layout_of(self.typing_env.as_query_input(discr_ty))
288+
.unwrap_or_else(|e| panic!("could not compute layout for {discr_ty:?}: {e:?}"))
289+
.size;
290+
291+
let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size);
292+
if overflowing {
293+
// An erroneous enum with too many variants for its repr will emit E0081 and E0370
294+
self.tcx.dcx().span_delayed_bug(
295+
source.span,
296+
"overflowing enum wasn't rejected by hir analysis",
297+
);
298+
}
299+
let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
300+
let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
301+
302+
let source = match discr_did {
303+
// in case we are offsetting from a computed discriminant
304+
// and not the beginning of discriminants (which is always `0`)
305+
Some(did) => {
306+
let kind = ExprKind::NamedConst { def_id: did, args, user_ty: None };
307+
let lhs =
308+
self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
309+
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
310+
self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind: bin })
298311
}
299-
let kind = ExprKind::NonHirLiteral { lit, user_ty: None };
300-
let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
301-
302-
let source = match discr_did {
303-
// in case we are offsetting from a computed discriminant
304-
// and not the beginning of discriminants (which is always `0`)
305-
Some(did) => {
306-
let kind = ExprKind::NamedConst { def_id: did, args, user_ty: None };
307-
let lhs =
308-
self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind });
309-
let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
310-
self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind: bin })
311-
}
312-
None => offset,
313-
};
312+
None => offset,
313+
};
314314

315-
ExprKind::Cast { source }
316-
} else {
317-
// Default to `ExprKind::Cast` for all explicit casts.
318-
// MIR building then picks the right MIR casts based on the types.
319-
ExprKind::Cast { source: self.mirror_expr(source) }
320-
}
315+
ExprKind::Cast { source }
316+
} else {
317+
// Default to `ExprKind::Cast` for all explicit casts.
318+
// MIR building then picks the right MIR casts based on the types.
319+
ExprKind::Cast { source: self.mirror_expr(source) }
321320
}
321+
}
322322

323323
#[instrument(level = "debug", skip(self), ret)]
324324
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
@@ -1040,7 +1040,7 @@ impl<'tcx> Cx<'tcx> {
10401040
// but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics
10411041
Res::Def(DefKind::Static { .. }, id) => {
10421042
// this is &raw for extern static or static mut, and & for other statics
1043-
let ty = self.tcx.static_ptr_ty(id, self.typing_env());
1043+
let ty = self.tcx.static_ptr_ty(id, self.typing_env);
10441044
let (temp_lifetime, backwards_incompatible) = self
10451045
.rvalue_scopes
10461046
.temporary_scope(self.region_scope_tree, expr.hir_id.local_id);
@@ -1240,14 +1240,14 @@ impl<'tcx> Cx<'tcx> {
12401240

12411241
/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
12421242
fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
1243-
fields
1244-
.iter()
1245-
.map(|field| FieldExpr {
1246-
name: self.typeck_results.field_index(field.hir_id),
1247-
expr: self.mirror_expr(field.expr),
1248-
})
1249-
.collect()
1250-
}
1243+
fields
1244+
.iter()
1245+
.map(|field| FieldExpr {
1246+
name: self.typeck_results.field_index(field.hir_id),
1247+
expr: self.mirror_expr(field.expr),
1248+
})
1249+
.collect()
1250+
}
12511251
}
12521252

12531253
trait ToBorrowKind {

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

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_hir::lang_items::LangItem;
1212
use rustc_middle::bug;
1313
use rustc_middle::middle::region;
1414
use rustc_middle::thir::*;
15-
use rustc_middle::ty::solve::Reveal;
1615
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
1716
use tracing::instrument;
1817

@@ -57,7 +56,7 @@ struct Cx<'tcx> {
5756
tcx: TyCtxt<'tcx>,
5857
thir: Thir<'tcx>,
5958

60-
param_env: ty::ParamEnv<'tcx>,
59+
typing_env: ty::TypingEnv<'tcx>,
6160

6261
region_scope_tree: &'tcx region::ScopeTree,
6362
typeck_results: &'tcx ty::TypeckResults<'tcx>,
@@ -98,7 +97,9 @@ impl<'tcx> Cx<'tcx> {
9897
Cx {
9998
tcx,
10099
thir: Thir::new(body_type),
101-
param_env: tcx.param_env(def),
100+
// FIXME(#132279): We're in a body, we should use a typing
101+
// mode which reveals the opaque types defined by that body.
102+
typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
102103
region_scope_tree: tcx.region_scope_tree(def),
103104
typeck_results,
104105
rvalue_scopes: &typeck_results.rvalue_scopes,
@@ -110,20 +111,9 @@ impl<'tcx> Cx<'tcx> {
110111
}
111112
}
112113

113-
fn typing_mode(&self) -> ty::TypingMode<'tcx> {
114-
debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
115-
// FIXME(#132279): In case we're in a body, we should use a typing
116-
// mode which reveals the opaque types defined by that body.
117-
ty::TypingMode::non_body_analysis()
118-
}
119-
120-
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
121-
ty::TypingEnv { typing_mode: self.typing_mode(), param_env: self.param_env }
122-
}
123-
124114
#[instrument(level = "debug", skip(self))]
125115
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
126-
pat_from_hir(self.tcx, self.typing_env(), self.typeck_results(), p)
116+
pat_from_hir(self.tcx, self.typing_env, self.typeck_results(), p)
127117
}
128118

129119
fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e
77
use rustc_hir::def::*;
88
use rustc_hir::def_id::LocalDefId;
99
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
10-
use rustc_infer::traits::Reveal;
1110
use rustc_middle::bug;
1211
use rustc_middle::middle::limits::get_limit_size;
1312
use rustc_middle::thir::visit::Visitor;
@@ -39,7 +38,8 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
3938
tcx,
4039
thir: &*thir,
4140
typeck_results,
42-
param_env: tcx.param_env(def_id),
41+
// FIXME(#132279): We're in a body, should handle opaques.
42+
typing_env: ty::TypingEnv::non_body_analysis(tcx, def_id),
4343
lint_level: tcx.local_def_id_to_hir_id(def_id),
4444
let_source: LetSource::None,
4545
pattern_arena: &pattern_arena,
@@ -86,7 +86,7 @@ enum LetSource {
8686

8787
struct MatchVisitor<'p, 'tcx> {
8888
tcx: TyCtxt<'tcx>,
89-
param_env: ty::ParamEnv<'tcx>,
89+
typing_env: ty::TypingEnv<'tcx>,
9090
typeck_results: &'tcx ty::TypeckResults<'tcx>,
9191
thir: &'p Thir<'tcx>,
9292
lint_level: HirId,
@@ -192,15 +192,6 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
192192
}
193193

194194
impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
195-
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
196-
// FIXME(#132279): We're in a body, should handle opaques.
197-
debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
198-
ty::TypingEnv {
199-
typing_mode: ty::TypingMode::non_body_analysis(),
200-
param_env: self.param_env,
201-
}
202-
}
203-
204195
#[instrument(level = "trace", skip(self, f))]
205196
fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) {
206197
let old_let_source = self.let_source;
@@ -391,7 +382,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
391382
PatCtxt {
392383
tcx: self.tcx,
393384
typeck_results: self.typeck_results,
394-
param_env: self.param_env,
385+
typing_env: self.typing_env,
395386
module: self.tcx.parent_module(self.lint_level).to_def_id(),
396387
dropless_arena: self.dropless_arena,
397388
match_lint_level: self.lint_level,
@@ -745,8 +736,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
745736
.variant(*variant_index)
746737
.inhabited_predicate(self.tcx, *adt)
747738
.instantiate(self.tcx, args);
748-
variant_inhabited.apply(self.tcx, cx.typing_env(), cx.module)
749-
&& !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env())
739+
variant_inhabited.apply(self.tcx, cx.typing_env, cx.module)
740+
&& !variant_inhabited.apply_ignore_module(self.tcx, cx.typing_env)
750741
} else {
751742
false
752743
};
@@ -785,7 +776,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
785776
return;
786777
};
787778

788-
let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
779+
let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env);
789780

790781
let sess = cx.tcx.sess;
791782

@@ -1149,7 +1140,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
11491140
}
11501141

11511142
if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
1152-
if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env()) {
1143+
if !sub_ty.is_inhabited_from(cx.tcx, cx.module, cx.typing_env) {
11531144
err.note("references are always considered inhabited");
11541145
}
11551146
}

0 commit comments

Comments
 (0)