1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Normalizes MIR in `TypingMode::PostAnalysis` mode, most notably revealing
//! its opaques. We also only normalize specializable associated items once in
//! `PostAnalysis` mode.
// `#![no_std]`: these arrive with the standard prelude and name no path, so a `std::`
// search cannot see them - and a `#[derive]` can use them without the name appearing
// in this file at all, which is why they are not trimmed by inspection.
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
use crate::rustc_middle::mir::visit::*;
use crate::rustc_middle::mir::*;
use crate::rustc_middle::ty::{self, Ty, TyCtxt};
use crate::rustc_mir_transform::PassPolicy;
pub(super) struct PostAnalysisNormalize;
impl<'tcx> crate::rustc_mir_transform::MirPass<'tcx> for PostAnalysisNormalize {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// FIXME(#132279): This is used during the phase transition from analysis
// to runtime, so we have to manually specify the correct typing mode.
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
}
fn policy(&self, _sess: &crate::rustc_session::Session) -> PassPolicy {
// Reveals opaque types and normalizes MIR while transitioning to the runtime dialect.
PassPolicy::Required
}
}
struct PostAnalysisNormalizeVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
#[inline]
fn visit_place(
&mut self,
place: &mut Place<'tcx>,
_context: PlaceContext,
_location: Location,
) {
if !self.tcx.next_trait_solver_globally() {
// `OpaqueCast` projections are only needed if there are opaque types on which projections
// are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their
// hidden types, so we don't need these projections anymore.
//
// Performance optimization: don't reintern if there is no `OpaqueCast` to remove.
if place.projection.iter().any(|elem| matches!(elem, ProjectionElem::OpaqueCast(_))) {
place.projection = self.tcx.mk_place_elems(
&place
.projection
.into_iter()
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
.collect::<Vec<_>>(),
);
};
}
self.super_place(place, _context, _location);
}
#[inline]
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(c) = self.tcx.try_normalize_erasing_regions(
self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, constant.const_),
) {
constant.const_ = c;
}
self.super_const_operand(constant, location);
}
#[inline]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(t) = self.tcx.try_normalize_erasing_regions(
self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, *ty),
) {
*ty = t;
}
}
#[inline]
fn visit_args(&mut self, args: &mut ty::GenericArgsRef<'tcx>, _: Location) {
if let Ok(a) = self.tcx.try_normalize_erasing_regions(
self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, *args),
) {
*args = a;
}
}
}