1
+ use rustc_data_structures:: fx:: FxHashMap ;
2
+ use rustc_errors:: ErrorGuaranteed ;
3
+ use rustc_span:: def_id:: { DefId , LocalDefId } ;
4
+ use rustc_span:: Span ;
5
+
1
6
use crate :: error:: ConstNotUsedTraitAlias ;
7
+ use crate :: error:: OpaqueHiddenTypeMismatch ;
2
8
use crate :: ty:: fold:: { TypeFolder , TypeSuperFoldable } ;
3
9
use crate :: ty:: subst:: { GenericArg , GenericArgKind } ;
4
- use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
5
- use rustc_data_structures:: fx:: FxHashMap ;
6
- use rustc_span:: def_id:: DefId ;
7
- use rustc_span:: Span ;
10
+ use crate :: ty:: { self , InternalSubsts , SubstsRef , Ty , TyCtxt , TypeFoldable , TypeMismatchReason } ;
11
+
12
+ #[ derive( Copy , Clone , Debug , TypeFoldable , TypeVisitable , HashStable , TyEncodable , TyDecodable ) ]
13
+ pub struct OpaqueHiddenType < ' tcx > {
14
+ /// The span of this particular definition of the opaque type. So
15
+ /// for example:
16
+ ///
17
+ /// ```ignore (incomplete snippet)
18
+ /// type Foo = impl Baz;
19
+ /// fn bar() -> Foo {
20
+ /// // ^^^ This is the span we are looking for!
21
+ /// }
22
+ /// ```
23
+ ///
24
+ /// In cases where the fn returns `(impl Trait, impl Trait)` or
25
+ /// other such combinations, the result is currently
26
+ /// over-approximated, but better than nothing.
27
+ pub span : Span ,
28
+
29
+ /// The type variable that represents the value of the opaque type
30
+ /// that we require. In other words, after we compile this function,
31
+ /// we will be created a constraint like:
32
+ /// ```ignore (pseudo-rust)
33
+ /// Foo<'a, T> = ?C
34
+ /// ```
35
+ /// where `?C` is the value of this type variable. =) It may
36
+ /// naturally refer to the type and lifetime parameters in scope
37
+ /// in this function, though ultimately it should only reference
38
+ /// those that are arguments to `Foo` in the constraint above. (In
39
+ /// other words, `?C` should not include `'b`, even though it's a
40
+ /// lifetime parameter on `foo`.)
41
+ pub ty : Ty < ' tcx > ,
42
+ }
43
+
44
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , HashStable , TyEncodable , TyDecodable , Lift ) ]
45
+ #[ derive( TypeFoldable , TypeVisitable ) ]
46
+ pub struct OpaqueTypeKey < ' tcx > {
47
+ pub def_id : LocalDefId ,
48
+ pub substs : SubstsRef < ' tcx > ,
49
+ }
8
50
9
51
/// Converts generic params of a TypeFoldable from one
10
52
/// item's generics to another. Usually from a function's generics
11
53
/// list to the opaque type's own generics.
12
- pub ( super ) struct ReverseMapper < ' tcx > {
54
+ struct ReverseMapper < ' tcx > {
13
55
tcx : TyCtxt < ' tcx > ,
14
56
map : FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > ,
15
57
/// see call sites to fold_kind_no_missing_regions_error
@@ -26,6 +68,54 @@ pub(super) struct ReverseMapper<'tcx> {
26
68
span : Span ,
27
69
}
28
70
71
+ impl < ' tcx > OpaqueHiddenType < ' tcx > {
72
+ pub fn report_mismatch ( & self , other : & Self , tcx : TyCtxt < ' tcx > ) -> ErrorGuaranteed {
73
+ // Found different concrete types for the opaque type.
74
+ let sub_diag = if self . span == other. span {
75
+ TypeMismatchReason :: ConflictType { span : self . span }
76
+ } else {
77
+ TypeMismatchReason :: PreviousUse { span : self . span }
78
+ } ;
79
+ tcx. sess . emit_err ( OpaqueHiddenTypeMismatch {
80
+ self_ty : self . ty ,
81
+ other_ty : other. ty ,
82
+ other_span : other. span ,
83
+ sub : sub_diag,
84
+ } )
85
+ }
86
+
87
+ #[ instrument( level = "debug" , skip( tcx) , ret) ]
88
+ pub fn remap_generic_params_to_declaration_params (
89
+ self ,
90
+ opaque_type_key : OpaqueTypeKey < ' tcx > ,
91
+ tcx : TyCtxt < ' tcx > ,
92
+ // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
93
+ ignore_errors : bool ,
94
+ ) -> Self {
95
+ let OpaqueTypeKey { def_id, substs } = opaque_type_key;
96
+
97
+ // Use substs to build up a reverse map from regions to their
98
+ // identity mappings. This is necessary because of `impl
99
+ // Trait` lifetimes are computed by replacing existing
100
+ // lifetimes with 'static and remapping only those used in the
101
+ // `impl Trait` return type, resulting in the parameters
102
+ // shifting.
103
+ let id_substs = InternalSubsts :: identity_for_item ( tcx, def_id) ;
104
+ debug ! ( ?id_substs) ;
105
+
106
+ // This zip may have several times the same lifetime in `substs` paired with a different
107
+ // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
108
+ // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
109
+ let map = substs. iter ( ) . zip ( id_substs) . collect ( ) ;
110
+ debug ! ( "map = {:#?}" , map) ;
111
+
112
+ // Convert the type from the function into a type valid outside
113
+ // the function, by replacing invalid regions with 'static,
114
+ // after producing an error for each of them.
115
+ self . fold_with ( & mut ReverseMapper :: new ( tcx, map, self . span , ignore_errors) )
116
+ }
117
+ }
118
+
29
119
impl < ' tcx > ReverseMapper < ' tcx > {
30
120
pub ( super ) fn new (
31
121
tcx : TyCtxt < ' tcx > ,
0 commit comments