1 use crate::error::ConstNotUsedTraitAlias;
2 use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
3 use crate::ty::subst::{GenericArg, GenericArgKind};
4 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
5 use rustc_data_structures::fx::FxHashMap;
8 /// Converts generic params of a TypeFoldable from one
9 /// item's generics to another. Usually from a function's generics
10 /// list to the opaque type's own generics.
11 pub(super) struct ReverseMapper<'tcx> {
13 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
14 /// see call sites to fold_kind_no_missing_regions_error
15 /// for an explanation of this field.
18 /// We do not want to emit any errors in typeck because
19 /// the spans in typeck are subpar at the moment.
20 /// Borrowck will do the same work again (this time with
21 /// lifetime information) and thus report better errors.
24 /// Span of function being checked.
28 impl<'tcx> ReverseMapper<'tcx> {
31 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
35 Self { tcx, map, do_not_error: false, ignore_errors, span }
38 fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
39 assert!(!self.do_not_error);
40 self.do_not_error = true;
41 let kind = kind.fold_with(self);
42 self.do_not_error = false;
46 fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
47 assert!(!self.do_not_error);
52 impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
53 fn tcx(&self) -> TyCtxt<'tcx> {
57 #[instrument(skip(self), level = "debug")]
58 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
60 // Ignore bound regions and `'static` regions that appear in the
61 // type, we only need to remap regions that reference lifetimes
62 // from the function declaration.
63 // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
64 ty::ReLateBound(..) | ty::ReStatic => return r,
66 // If regions have been erased (by writeback), don't try to unerase
68 ty::ReErased => return r,
70 // The regions that we expect from borrow checking.
71 ty::ReEarlyBound(_) | ty::ReFree(_) => {}
73 ty::RePlaceholder(_) | ty::ReVar(_) => {
74 // All of the regions in the type should either have been
75 // erased by writeback, or mapped back to named regions by
77 bug!("unexpected region kind in opaque type: {:?}", r);
81 match self.map.get(&r.into()).map(|k| k.unpack()) {
82 Some(GenericArgKind::Lifetime(r1)) => r1,
83 Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
84 None if self.do_not_error => self.tcx.lifetimes.re_static,
88 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
92 "lifetime `{}` is part of concrete type but not used in \
93 parameter list of the `impl Trait` type alias",
99 self.tcx().lifetimes.re_static
104 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
106 ty::Closure(def_id, substs) => {
107 // I am a horrible monster and I pray for death. When
108 // we encounter a closure here, it is always a closure
109 // from within the function that we are currently
110 // type-checking -- one that is now being encapsulated
111 // in an opaque type. Ideally, we would
112 // go through the types/lifetimes that it references
113 // and treat them just like we would any other type,
114 // which means we would error out if we find any
115 // reference to a type/region that is not in the
118 // **However,** in the case of closures, there is a
119 // somewhat subtle (read: hacky) consideration. The
120 // problem is that our closure types currently include
121 // all the lifetime parameters declared on the
122 // enclosing function, even if they are unused by the
123 // closure itself. We can't readily filter them out,
124 // so here we replace those values with `'empty`. This
125 // can't really make a difference to the rest of the
126 // compiler; those regions are ignored for the
127 // outlives relation, and hence don't affect trait
128 // selection or auto traits, and they are erased
131 let generics = self.tcx.generics_of(def_id);
132 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
133 if index < generics.parent_count {
134 // Accommodate missing regions in the parent kinds...
135 self.fold_kind_no_missing_regions_error(kind)
137 // ...but not elsewhere.
138 self.fold_kind_normally(kind)
142 self.tcx.mk_closure(def_id, substs)
145 ty::Generator(def_id, substs, movability) => {
146 let generics = self.tcx.generics_of(def_id);
147 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
148 if index < generics.parent_count {
149 // Accommodate missing regions in the parent kinds...
150 self.fold_kind_no_missing_regions_error(kind)
152 // ...but not elsewhere.
153 self.fold_kind_normally(kind)
157 self.tcx.mk_generator(def_id, substs, movability)
160 ty::Param(param) => {
161 // Look it up in the substitution list.
162 match self.map.get(&ty.into()).map(|k| k.unpack()) {
163 // Found it in the substitution list; replace with the parameter from the
165 Some(GenericArgKind::Type(t1)) => t1,
166 Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
168 debug!(?param, ?self.map);
169 if !self.ignore_errors {
175 "type parameter `{}` is part of concrete type but not \
176 used in parameter list for the `impl Trait` type alias",
183 self.tcx().ty_error()
188 _ => ty.super_fold_with(self),
192 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
193 trace!("checking const {:?}", ct);
194 // Find a const parameter
196 ty::ConstKind::Param(..) => {
197 // Look it up in the substitution list.
198 match self.map.get(&ct.into()).map(|k| k.unpack()) {
199 // Found it in the substitution list, replace with the parameter from the
201 Some(GenericArgKind::Const(c1)) => c1,
202 Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
204 if !self.ignore_errors {
205 self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
211 self.tcx().const_error(ct.ty())