]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/opaque_types.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / opaque_types.rs
CommitLineData
487cf647
FG
1use crate::error::ConstNotUsedTraitAlias;
2use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
3use crate::ty::subst::{GenericArg, GenericArgKind};
4use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
2b03887a 5use rustc_data_structures::fx::FxHashMap;
9ffffee4 6use rustc_span::def_id::DefId;
2b03887a
FG
7use rustc_span::Span;
8
9/// Converts generic params of a TypeFoldable from one
10/// item's generics to another. Usually from a function's generics
11/// list to the opaque type's own generics.
12pub(super) struct ReverseMapper<'tcx> {
13 tcx: TyCtxt<'tcx>,
14 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
15 /// see call sites to fold_kind_no_missing_regions_error
16 /// for an explanation of this field.
17 do_not_error: bool,
18
19 /// We do not want to emit any errors in typeck because
20 /// the spans in typeck are subpar at the moment.
21 /// Borrowck will do the same work again (this time with
22 /// lifetime information) and thus report better errors.
23 ignore_errors: bool,
24
25 /// Span of function being checked.
26 span: Span,
27}
28
29impl<'tcx> ReverseMapper<'tcx> {
30 pub(super) fn new(
31 tcx: TyCtxt<'tcx>,
32 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
33 span: Span,
34 ignore_errors: bool,
35 ) -> Self {
36 Self { tcx, map, do_not_error: false, ignore_errors, span }
37 }
38
39 fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
40 assert!(!self.do_not_error);
41 self.do_not_error = true;
42 let kind = kind.fold_with(self);
43 self.do_not_error = false;
44 kind
45 }
46
47 fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
48 assert!(!self.do_not_error);
49 kind.fold_with(self)
50 }
9ffffee4
FG
51
52 fn fold_closure_substs(
53 &mut self,
54 def_id: DefId,
55 substs: ty::SubstsRef<'tcx>,
56 ) -> ty::SubstsRef<'tcx> {
57 // I am a horrible monster and I pray for death. When
58 // we encounter a closure here, it is always a closure
59 // from within the function that we are currently
60 // type-checking -- one that is now being encapsulated
61 // in an opaque type. Ideally, we would
62 // go through the types/lifetimes that it references
63 // and treat them just like we would any other type,
64 // which means we would error out if we find any
65 // reference to a type/region that is not in the
66 // "reverse map".
67 //
68 // **However,** in the case of closures, there is a
69 // somewhat subtle (read: hacky) consideration. The
70 // problem is that our closure types currently include
71 // all the lifetime parameters declared on the
72 // enclosing function, even if they are unused by the
73 // closure itself. We can't readily filter them out,
74 // so here we replace those values with `'empty`. This
75 // can't really make a difference to the rest of the
76 // compiler; those regions are ignored for the
77 // outlives relation, and hence don't affect trait
78 // selection or auto traits, and they are erased
79 // during codegen.
80
81 let generics = self.tcx.generics_of(def_id);
82 self.tcx.mk_substs_from_iter(substs.iter().enumerate().map(|(index, kind)| {
83 if index < generics.parent_count {
84 // Accommodate missing regions in the parent kinds...
85 self.fold_kind_no_missing_regions_error(kind)
86 } else {
87 // ...but not elsewhere.
88 self.fold_kind_normally(kind)
89 }
90 }))
91 }
2b03887a
FG
92}
93
9ffffee4
FG
94impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
95 fn interner(&self) -> TyCtxt<'tcx> {
2b03887a
FG
96 self.tcx
97 }
98
99 #[instrument(skip(self), level = "debug")]
100 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
101 match *r {
102 // Ignore bound regions and `'static` regions that appear in the
103 // type, we only need to remap regions that reference lifetimes
104 // from the function declaration.
105 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
106 ty::ReLateBound(..) | ty::ReStatic => return r,
107
108 // If regions have been erased (by writeback), don't try to unerase
109 // them.
110 ty::ReErased => return r,
111
9ffffee4
FG
112 ty::ReError(_) => return r,
113
2b03887a
FG
114 // The regions that we expect from borrow checking.
115 ty::ReEarlyBound(_) | ty::ReFree(_) => {}
116
117 ty::RePlaceholder(_) | ty::ReVar(_) => {
118 // All of the regions in the type should either have been
119 // erased by writeback, or mapped back to named regions by
120 // borrow checking.
121 bug!("unexpected region kind in opaque type: {:?}", r);
122 }
123 }
124
125 match self.map.get(&r.into()).map(|k| k.unpack()) {
126 Some(GenericArgKind::Lifetime(r1)) => r1,
127 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
128 None if self.do_not_error => self.tcx.lifetimes.re_static,
129 None => {
9ffffee4
FG
130 let e = self
131 .tcx
2b03887a
FG
132 .sess
133 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
134 .span_label(
135 self.span,
136 format!(
137 "lifetime `{}` is part of concrete type but not used in \
9ffffee4 138 parameter list of the `impl Trait` type alias",
2b03887a
FG
139 r
140 ),
141 )
142 .emit();
143
9ffffee4 144 self.interner().mk_re_error(e)
2b03887a
FG
145 }
146 }
147 }
148
149 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
150 match *ty.kind() {
151 ty::Closure(def_id, substs) => {
9ffffee4 152 let substs = self.fold_closure_substs(def_id, substs);
2b03887a
FG
153 self.tcx.mk_closure(def_id, substs)
154 }
155
156 ty::Generator(def_id, substs, movability) => {
9ffffee4 157 let substs = self.fold_closure_substs(def_id, substs);
2b03887a
FG
158 self.tcx.mk_generator(def_id, substs, movability)
159 }
160
9ffffee4
FG
161 ty::GeneratorWitnessMIR(def_id, substs) => {
162 let substs = self.fold_closure_substs(def_id, substs);
163 self.tcx.mk_generator_witness_mir(def_id, substs)
164 }
165
2b03887a
FG
166 ty::Param(param) => {
167 // Look it up in the substitution list.
168 match self.map.get(&ty.into()).map(|k| k.unpack()) {
169 // Found it in the substitution list; replace with the parameter from the
170 // opaque type.
171 Some(GenericArgKind::Type(t1)) => t1,
172 Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
173 None => {
174 debug!(?param, ?self.map);
175 if !self.ignore_errors {
176 self.tcx
177 .sess
178 .struct_span_err(
179 self.span,
49aad941 180 format!(
2b03887a
FG
181 "type parameter `{}` is part of concrete type but not \
182 used in parameter list for the `impl Trait` type alias",
183 ty
184 ),
185 )
186 .emit();
187 }
188
9ffffee4 189 self.interner().ty_error_misc()
2b03887a
FG
190 }
191 }
192 }
193
194 _ => ty.super_fold_with(self),
195 }
196 }
197
198 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
199 trace!("checking const {:?}", ct);
200 // Find a const parameter
201 match ct.kind() {
202 ty::ConstKind::Param(..) => {
203 // Look it up in the substitution list.
204 match self.map.get(&ct.into()).map(|k| k.unpack()) {
205 // Found it in the substitution list, replace with the parameter from the
206 // opaque type.
207 Some(GenericArgKind::Const(c1)) => c1,
208 Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
209 None => {
49aad941
FG
210 let guar = self
211 .tcx
212 .sess
213 .create_err(ConstNotUsedTraitAlias {
2b03887a
FG
214 ct: ct.to_string(),
215 span: self.span,
49aad941
FG
216 })
217 .emit_unless(self.ignore_errors);
2b03887a 218
49aad941 219 self.interner().const_error(ct.ty(), guar)
2b03887a
FG
220 }
221 }
222 }
223
224 _ => ct,
225 }
226 }
227}