]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | //! Values computed by queries that use MIR. |
2 | ||
923072b8 | 3 | use crate::mir::{Body, ConstantKind, Promoted}; |
5e7ed085 | 4 | use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; |
f2b60f7d | 5 | use rustc_data_structures::fx::FxHashSet; |
17df50a5 | 6 | use rustc_data_structures::vec_map::VecMap; |
5e7ed085 | 7 | use rustc_errors::ErrorGuaranteed; |
dfeec247 | 8 | use rustc_hir as hir; |
3dfed10e | 9 | use rustc_hir::def_id::{DefId, LocalDefId}; |
dfeec247 XL |
10 | use rustc_index::bit_set::BitMatrix; |
11 | use rustc_index::vec::IndexVec; | |
3dfed10e | 12 | use rustc_span::Span; |
dfeec247 XL |
13 | use rustc_target::abi::VariantIdx; |
14 | use smallvec::SmallVec; | |
f035d41b XL |
15 | use std::cell::Cell; |
16 | use std::fmt::{self, Debug}; | |
dfeec247 XL |
17 | |
18 | use super::{Field, SourceInfo}; | |
19 | ||
5869c6ff | 20 | #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] |
dfeec247 | 21 | pub enum UnsafetyViolationKind { |
cdc7bbd5 | 22 | /// Unsafe operation outside `unsafe`. |
dfeec247 | 23 | General, |
f9f354fc XL |
24 | /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block. |
25 | /// Has to be handled as a lint for backwards compatibility. | |
f9f354fc | 26 | UnsafeFn, |
dfeec247 XL |
27 | } |
28 | ||
5869c6ff | 29 | #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] |
3dfed10e XL |
30 | pub enum UnsafetyViolationDetails { |
31 | CallToUnsafeFunction, | |
32 | UseOfInlineAssembly, | |
33 | InitializingTypeWith, | |
34 | CastOfPointerToInt, | |
3dfed10e XL |
35 | UseOfMutableStatic, |
36 | UseOfExternStatic, | |
37 | DerefOfRawPointer, | |
3dfed10e XL |
38 | AccessToUnionField, |
39 | MutationOfLayoutConstrainedField, | |
40 | BorrowOfLayoutConstrainedField, | |
41 | CallToFunctionWith, | |
42 | } | |
43 | ||
44 | impl UnsafetyViolationDetails { | |
45 | pub fn description_and_note(&self) -> (&'static str, &'static str) { | |
46 | use UnsafetyViolationDetails::*; | |
47 | match self { | |
48 | CallToUnsafeFunction => ( | |
49 | "call to unsafe function", | |
50 | "consult the function's documentation for information on how to avoid undefined \ | |
51 | behavior", | |
52 | ), | |
53 | UseOfInlineAssembly => ( | |
54 | "use of inline assembly", | |
55 | "inline assembly is entirely unchecked and can cause undefined behavior", | |
56 | ), | |
57 | InitializingTypeWith => ( | |
58 | "initializing type with `rustc_layout_scalar_valid_range` attr", | |
59 | "initializing a layout restricted type's field with a value outside the valid \ | |
60 | range is undefined behavior", | |
61 | ), | |
62 | CastOfPointerToInt => { | |
63 | ("cast of pointer to int", "casting pointers to integers in constants") | |
64 | } | |
3dfed10e XL |
65 | UseOfMutableStatic => ( |
66 | "use of mutable static", | |
67 | "mutable statics can be mutated by multiple threads: aliasing violations or data \ | |
68 | races will cause undefined behavior", | |
69 | ), | |
70 | UseOfExternStatic => ( | |
71 | "use of extern static", | |
72 | "extern statics are not controlled by the Rust type system: invalid data, \ | |
73 | aliasing violations or data races will cause undefined behavior", | |
74 | ), | |
75 | DerefOfRawPointer => ( | |
76 | "dereference of raw pointer", | |
17df50a5 | 77 | "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \ |
3dfed10e XL |
78 | and cause data races: all of these are undefined behavior", |
79 | ), | |
3dfed10e XL |
80 | AccessToUnionField => ( |
81 | "access to union field", | |
82 | "the field may not be properly initialized: using uninitialized data will cause \ | |
83 | undefined behavior", | |
84 | ), | |
85 | MutationOfLayoutConstrainedField => ( | |
86 | "mutation of layout constrained field", | |
87 | "mutating layout constrained fields cannot statically be checked for valid values", | |
88 | ), | |
89 | BorrowOfLayoutConstrainedField => ( | |
90 | "borrow of layout constrained field with interior mutability", | |
91 | "references to fields of layout constrained fields lose the constraints. Coupled \ | |
92 | with interior mutability, the field can be changed to invalid values", | |
93 | ), | |
94 | CallToFunctionWith => ( | |
95 | "call to function with `#[target_feature]`", | |
96 | "can only be called if the required target features are available", | |
97 | ), | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
5869c6ff | 102 | #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] |
dfeec247 XL |
103 | pub struct UnsafetyViolation { |
104 | pub source_info: SourceInfo, | |
f9f354fc | 105 | pub lint_root: hir::HirId, |
dfeec247 | 106 | pub kind: UnsafetyViolationKind, |
3dfed10e | 107 | pub details: UnsafetyViolationDetails, |
dfeec247 XL |
108 | } |
109 | ||
5e7ed085 FG |
110 | #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] |
111 | pub enum UnusedUnsafe { | |
112 | /// `unsafe` block contains no unsafe operations | |
113 | /// > ``unnecessary `unsafe` block`` | |
114 | Unused, | |
115 | /// `unsafe` block nested under another (used) `unsafe` block | |
116 | /// > ``… because it's nested under this `unsafe` block`` | |
117 | InUnsafeBlock(hir::HirId), | |
5e7ed085 FG |
118 | } |
119 | ||
120 | #[derive(TyEncodable, TyDecodable, HashStable, Debug)] | |
dfeec247 XL |
121 | pub struct UnsafetyCheckResult { |
122 | /// Violations that are propagated *upwards* from this function. | |
5e7ed085 FG |
123 | pub violations: Vec<UnsafetyViolation>, |
124 | ||
125 | /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. | |
f2b60f7d | 126 | pub used_unsafe_blocks: FxHashSet<hir::HirId>, |
5e7ed085 FG |
127 | |
128 | /// This is `Some` iff the item is not a closure. | |
129 | pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>, | |
dfeec247 XL |
130 | } |
131 | ||
132 | rustc_index::newtype_index! { | |
133 | pub struct GeneratorSavedLocal { | |
134 | derive [HashStable] | |
135 | DEBUG_FORMAT = "_{}", | |
136 | } | |
137 | } | |
138 | ||
139 | /// The layout of generator state. | |
064997fb | 140 | #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] |
dfeec247 XL |
141 | pub struct GeneratorLayout<'tcx> { |
142 | /// The type of every local stored inside the generator. | |
143 | pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>, | |
144 | ||
145 | /// Which of the above fields are in each variant. Note that one field may | |
146 | /// be stored in multiple variants. | |
147 | pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>, | |
148 | ||
f035d41b XL |
149 | /// The source that led to each variant being created (usually, a yield or |
150 | /// await). | |
151 | pub variant_source_info: IndexVec<VariantIdx, SourceInfo>, | |
152 | ||
dfeec247 XL |
153 | /// Which saved locals are storage-live at the same time. Locals that do not |
154 | /// have conflicts with each other are allowed to overlap in the computed | |
155 | /// layout. | |
156 | pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>, | |
157 | } | |
158 | ||
f035d41b XL |
159 | impl Debug for GeneratorLayout<'_> { |
160 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
161 | /// Prints an iterator of (key, value) tuples as a map. | |
162 | struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>); | |
163 | impl<'a, K, V> MapPrinter<'a, K, V> { | |
164 | fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self { | |
165 | Self(Cell::new(Some(Box::new(iter)))) | |
166 | } | |
167 | } | |
168 | impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { | |
169 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
170 | fmt.debug_map().entries(self.0.take().unwrap()).finish() | |
171 | } | |
172 | } | |
173 | ||
174 | /// Prints the generator variant name. | |
175 | struct GenVariantPrinter(VariantIdx); | |
176 | impl From<VariantIdx> for GenVariantPrinter { | |
177 | fn from(idx: VariantIdx) -> Self { | |
178 | GenVariantPrinter(idx) | |
179 | } | |
180 | } | |
181 | impl Debug for GenVariantPrinter { | |
182 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
183 | let variant_name = ty::GeneratorSubsts::variant_name(self.0); | |
184 | if fmt.alternate() { | |
185 | write!(fmt, "{:9}({:?})", variant_name, self.0) | |
186 | } else { | |
187 | write!(fmt, "{}", variant_name) | |
188 | } | |
189 | } | |
190 | } | |
191 | ||
192 | /// Forces its contents to print in regular mode instead of alternate mode. | |
193 | struct OneLinePrinter<T>(T); | |
194 | impl<T: Debug> Debug for OneLinePrinter<T> { | |
195 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
196 | write!(fmt, "{:?}", self.0) | |
197 | } | |
198 | } | |
199 | ||
200 | fmt.debug_struct("GeneratorLayout") | |
201 | .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) | |
202 | .field( | |
203 | "variant_fields", | |
204 | &MapPrinter::new( | |
205 | self.variant_fields | |
206 | .iter_enumerated() | |
207 | .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), | |
208 | ), | |
209 | ) | |
210 | .field("storage_conflicts", &self.storage_conflicts) | |
211 | .finish() | |
212 | } | |
213 | } | |
214 | ||
3dfed10e | 215 | #[derive(Debug, TyEncodable, TyDecodable, HashStable)] |
dfeec247 | 216 | pub struct BorrowCheckResult<'tcx> { |
74b04a01 | 217 | /// All the opaque types that are restricted to concrete types |
3dfed10e | 218 | /// by this function. Unlike the value in `TypeckResults`, this has |
74b04a01 | 219 | /// unerased regions. |
064997fb | 220 | pub concrete_opaque_types: VecMap<LocalDefId, OpaqueHiddenType<'tcx>>, |
dfeec247 XL |
221 | pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, |
222 | pub used_mut_upvars: SmallVec<[Field; 8]>, | |
5e7ed085 | 223 | pub tainted_by_errors: Option<ErrorGuaranteed>, |
dfeec247 XL |
224 | } |
225 | ||
226 | /// The result of the `mir_const_qualif` query. | |
227 | /// | |
5e7ed085 | 228 | /// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in |
c295e0f8 | 229 | /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each |
dfeec247 | 230 | /// `Qualif`. |
3dfed10e | 231 | #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] |
dfeec247 XL |
232 | pub struct ConstQualifs { |
233 | pub has_mut_interior: bool, | |
234 | pub needs_drop: bool, | |
3c0e092e | 235 | pub needs_non_const_drop: bool, |
f9f354fc | 236 | pub custom_eq: bool, |
5e7ed085 | 237 | pub tainted_by_errors: Option<ErrorGuaranteed>, |
dfeec247 XL |
238 | } |
239 | ||
240 | /// After we borrow check a closure, we are left with various | |
241 | /// requirements that we have inferred between the free regions that | |
242 | /// appear in the closure's signature or on its field types. These | |
243 | /// requirements are then verified and proved by the closure's | |
244 | /// creating function. This struct encodes those requirements. | |
245 | /// | |
ba9703b0 XL |
246 | /// The requirements are listed as being between various `RegionVid`. The 0th |
247 | /// region refers to `'static`; subsequent region vids refer to the free | |
248 | /// regions that appear in the closure (or generator's) type, in order of | |
249 | /// appearance. (This numbering is actually defined by the `UniversalRegions` | |
250 | /// struct in the NLL region checker. See for example | |
251 | /// `UniversalRegions::closure_mapping`.) Note the free regions in the | |
252 | /// closure's signature and captures are erased. | |
dfeec247 XL |
253 | /// |
254 | /// Example: If type check produces a closure with the closure substs: | |
255 | /// | |
256 | /// ```text | |
257 | /// ClosureSubsts = [ | |
ba9703b0 XL |
258 | /// 'a, // From the parent. |
259 | /// 'b, | |
260 | /// i8, // the "closure kind" | |
261 | /// for<'x> fn(&'<erased> &'x u32) -> &'x u32, // the "closure signature" | |
262 | /// &'<erased> String, // some upvar | |
dfeec247 XL |
263 | /// ] |
264 | /// ``` | |
265 | /// | |
ba9703b0 | 266 | /// We would "renumber" each free region to a unique vid, as follows: |
dfeec247 XL |
267 | /// |
268 | /// ```text | |
269 | /// ClosureSubsts = [ | |
ba9703b0 XL |
270 | /// '1, // From the parent. |
271 | /// '2, | |
272 | /// i8, // the "closure kind" | |
273 | /// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" | |
274 | /// &'4 String, // some upvar | |
dfeec247 XL |
275 | /// ] |
276 | /// ``` | |
277 | /// | |
278 | /// Now the code might impose a requirement like `'1: '2`. When an | |
279 | /// instance of the closure is created, the corresponding free regions | |
280 | /// can be extracted from its type and constrained to have the given | |
281 | /// outlives relationship. | |
282 | /// | |
ba9703b0 XL |
283 | /// In some cases, we have to record outlives requirements between types and |
284 | /// regions as well. In that case, if those types include any regions, those | |
285 | /// regions are recorded using their external names (`ReStatic`, | |
286 | /// `ReEarlyBound`, `ReFree`). We use these because in a query response we | |
287 | /// cannot use `ReVar` (which is what we use internally within the rest of the | |
288 | /// NLL code). | |
3dfed10e | 289 | #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] |
dfeec247 XL |
290 | pub struct ClosureRegionRequirements<'tcx> { |
291 | /// The number of external regions defined on the closure. In our | |
292 | /// example above, it would be 3 -- one for `'static`, then `'1` | |
293 | /// and `'2`. This is just used for a sanity check later on, to | |
294 | /// make sure that the number of regions we see at the callsite | |
295 | /// matches. | |
296 | pub num_external_vids: usize, | |
297 | ||
298 | /// Requirements between the various free regions defined in | |
299 | /// indices. | |
300 | pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>, | |
301 | } | |
302 | ||
303 | /// Indicates an outlives-constraint between a type or between two | |
304 | /// free regions declared on the closure. | |
3dfed10e | 305 | #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] |
dfeec247 XL |
306 | pub struct ClosureOutlivesRequirement<'tcx> { |
307 | // This region or type ... | |
308 | pub subject: ClosureOutlivesSubject<'tcx>, | |
309 | ||
310 | // ... must outlive this one. | |
311 | pub outlived_free_region: ty::RegionVid, | |
312 | ||
313 | // If not, report an error here ... | |
314 | pub blame_span: Span, | |
315 | ||
316 | // ... due to this reason. | |
923072b8 | 317 | pub category: ConstraintCategory<'tcx>, |
dfeec247 XL |
318 | } |
319 | ||
c295e0f8 | 320 | // Make sure this enum doesn't unintentionally grow |
923072b8 FG |
321 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
322 | rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); | |
c295e0f8 | 323 | |
dfeec247 XL |
324 | /// Outlives-constraints can be categorized to determine whether and why they |
325 | /// are interesting (for error reporting). Order of variants indicates sort | |
326 | /// order of the category, thereby influencing diagnostic output. | |
327 | /// | |
c295e0f8 | 328 | /// See also `rustc_const_eval::borrow_check::constraints`. |
dfeec247 | 329 | #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] |
f2b60f7d | 330 | #[derive(TyEncodable, TyDecodable, HashStable, Lift, TypeVisitable, TypeFoldable)] |
923072b8 | 331 | pub enum ConstraintCategory<'tcx> { |
f035d41b | 332 | Return(ReturnConstraint), |
dfeec247 XL |
333 | Yield, |
334 | UseAsConst, | |
335 | UseAsStatic, | |
336 | TypeAnnotation, | |
337 | Cast, | |
338 | ||
339 | /// A constraint that came from checking the body of a closure. | |
340 | /// | |
341 | /// We try to get the category that the closure used when reporting this. | |
342 | ClosureBounds, | |
923072b8 FG |
343 | |
344 | /// Contains the function type if available. | |
345 | CallArgument(Option<Ty<'tcx>>), | |
dfeec247 XL |
346 | CopyBound, |
347 | SizedBound, | |
348 | Assignment, | |
c295e0f8 XL |
349 | /// A constraint that came from a usage of a variable (e.g. in an ADT expression |
350 | /// like `Foo { field: my_val }`) | |
351 | Usage, | |
dfeec247 | 352 | OpaqueType, |
5099ac24 | 353 | ClosureUpvar(Field), |
dfeec247 | 354 | |
c295e0f8 XL |
355 | /// A constraint from a user-written predicate |
356 | /// with the provided span, written on the item | |
357 | /// with the given `DefId` | |
358 | Predicate(Span), | |
359 | ||
dfeec247 XL |
360 | /// A "boring" constraint (caused by the given location) is one that |
361 | /// the user probably doesn't want to see described in diagnostics, | |
362 | /// because it is kind of an artifact of the type system setup. | |
dfeec247 XL |
363 | Boring, |
364 | // Boring and applicable everywhere. | |
365 | BoringNoLocation, | |
366 | ||
367 | /// A constraint that doesn't correspond to anything the user sees. | |
368 | Internal, | |
369 | } | |
370 | ||
f035d41b | 371 | #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] |
f2b60f7d | 372 | #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] |
f035d41b XL |
373 | pub enum ReturnConstraint { |
374 | Normal, | |
5099ac24 | 375 | ClosureUpvar(Field), |
f035d41b XL |
376 | } |
377 | ||
dfeec247 XL |
378 | /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing |
379 | /// that must outlive some region. | |
3dfed10e | 380 | #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] |
dfeec247 XL |
381 | pub enum ClosureOutlivesSubject<'tcx> { |
382 | /// Subject is a type, typically a type parameter, but could also | |
383 | /// be a projection. Indicates a requirement like `T: 'a` being | |
384 | /// passed to the caller, where the type here is `T`. | |
385 | /// | |
386 | /// The type here is guaranteed not to contain any free regions at | |
387 | /// present. | |
388 | Ty(Ty<'tcx>), | |
389 | ||
390 | /// Subject is a free region from the closure. Indicates a requirement | |
391 | /// like `'a: 'b` being passed to the caller; the region here is `'a`. | |
392 | Region(ty::RegionVid), | |
393 | } | |
394 | ||
923072b8 | 395 | /// The constituent parts of a type level constant of kind ADT or array. |
dfeec247 XL |
396 | #[derive(Copy, Clone, Debug, HashStable)] |
397 | pub struct DestructuredConst<'tcx> { | |
f035d41b | 398 | pub variant: Option<VariantIdx>, |
5099ac24 | 399 | pub fields: &'tcx [ty::Const<'tcx>], |
dfeec247 | 400 | } |
f035d41b | 401 | |
923072b8 FG |
402 | /// The constituent parts of a mir constant of kind ADT or array. |
403 | #[derive(Copy, Clone, Debug, HashStable)] | |
404 | pub struct DestructuredMirConstant<'tcx> { | |
405 | pub variant: Option<VariantIdx>, | |
406 | pub fields: &'tcx [ConstantKind<'tcx>], | |
407 | } | |
408 | ||
f035d41b | 409 | /// Coverage information summarized from a MIR if instrumented for source code coverage (see |
5099ac24 | 410 | /// compiler option `-Cinstrument-coverage`). This information is generated by the |
f035d41b | 411 | /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. |
3dfed10e | 412 | #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] |
f035d41b | 413 | pub struct CoverageInfo { |
f035d41b XL |
414 | /// The total number of coverage region counters added to the MIR `Body`. |
415 | pub num_counters: u32, | |
3dfed10e XL |
416 | |
417 | /// The total number of coverage region counter expressions added to the MIR `Body`. | |
418 | pub num_expressions: u32, | |
419 | } | |
420 | ||
29967ef6 XL |
421 | /// Shims which make dealing with `WithOptConstParam` easier. |
422 | /// | |
423 | /// For more information on why this is needed, consider looking | |
424 | /// at the docs for `WithOptConstParam` itself. | |
3dfed10e | 425 | impl<'tcx> TyCtxt<'tcx> { |
29967ef6 | 426 | #[inline] |
3dfed10e XL |
427 | pub fn mir_const_qualif_opt_const_arg( |
428 | self, | |
429 | def: ty::WithOptConstParam<LocalDefId>, | |
430 | ) -> ConstQualifs { | |
431 | if let Some(param_did) = def.const_param_did { | |
432 | self.mir_const_qualif_const_arg((def.did, param_did)) | |
433 | } else { | |
434 | self.mir_const_qualif(def.did) | |
435 | } | |
436 | } | |
437 | ||
29967ef6 XL |
438 | #[inline] |
439 | pub fn promoted_mir_opt_const_arg( | |
3dfed10e XL |
440 | self, |
441 | def: ty::WithOptConstParam<DefId>, | |
442 | ) -> &'tcx IndexVec<Promoted, Body<'tcx>> { | |
443 | if let Some((did, param_did)) = def.as_const_arg() { | |
444 | self.promoted_mir_of_const_arg((did, param_did)) | |
445 | } else { | |
446 | self.promoted_mir(def.did) | |
447 | } | |
448 | } | |
29967ef6 | 449 | |
5869c6ff XL |
450 | #[inline] |
451 | pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> { | |
452 | if let Some((did, param_did)) = def.as_const_arg() { | |
453 | self.mir_for_ctfe_of_const_arg((did, param_did)) | |
454 | } else { | |
455 | self.mir_for_ctfe(def.did) | |
456 | } | |
457 | } | |
f035d41b | 458 | } |