@@ -34,6 +34,58 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TyVarFinder<'a, 'tcx> {
34
34
}
35
35
}
36
36
37
+ fn find_questionable_call (
38
+ path : InferredPath < ' tcx > ,
39
+ fcx : & FnCtxt < ' a , ' tcx > ,
40
+ ) -> Option < Vec < Ty < ' tcx > > > {
41
+ let tcx = fcx. tcx ;
42
+ let ty = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
43
+ debug ! ( "post_fallback: Fully resolved ty: {:?}" , ty) ;
44
+
45
+ let ty = ty. unwrap_or_else ( || bug ! ( "Missing ty in path: {:?}" , path) ) ;
46
+
47
+ if let ty:: FnDef ( _, substs) = ty. kind {
48
+ debug ! ( "Got substs: {:?}" , substs) ;
49
+ let mut args_inhabited = true ;
50
+
51
+ for arg in & * path. args . unwrap ( ) {
52
+ let resolved_arg = fcx. infcx . resolve_vars_if_possible ( arg) ;
53
+
54
+ if resolved_arg. conservative_is_privately_uninhabited ( tcx) {
55
+ debug ! ( "post_fallback: Arg is uninhabited: {:?}" , resolved_arg) ;
56
+ args_inhabited = false ;
57
+ break ;
58
+ } else {
59
+ debug ! ( "post_fallback: Arg is inhabited: {:?}" , resolved_arg) ;
60
+ }
61
+ }
62
+
63
+ if !args_inhabited {
64
+ debug ! ( "post_fallback: Not all arguments are inhabited" ) ;
65
+ return None ;
66
+ }
67
+
68
+ for ( subst_ty, vars) in substs. types ( ) . zip ( path. unresolved_vars . into_iter ( ) ) {
69
+ let resolved_subst = fcx. infcx . resolve_vars_if_possible ( & subst_ty) ;
70
+ if resolved_subst. conservative_is_privately_uninhabited ( tcx) {
71
+ debug ! ( "post_fallback: Subst is uninhabited: {:?}" , resolved_subst) ;
72
+ if !vars. is_empty ( ) {
73
+ debug ! ( "Found fallback vars: {:?}" , vars) ;
74
+ debug ! (
75
+ "post_fallback: All arguments are inhabited, at least one subst is not inhabited!"
76
+ ) ;
77
+ return Some ( vars) ;
78
+ } else {
79
+ debug ! ( "No fallback vars" )
80
+ }
81
+ } else {
82
+ debug ! ( "post_fallback: Subst is inhabited: {:?}" , resolved_subst) ;
83
+ }
84
+ }
85
+ }
86
+ return None ;
87
+ }
88
+
37
89
impl < ' tcx > NeverCompatHandler < ' tcx > {
38
90
pub fn pre_fallback ( fcx : & FnCtxt < ' a , ' tcx > ) -> NeverCompatHandler < ' tcx > {
39
91
let unresolved_paths: FxHashMap < HirId , InferredPath < ' tcx > > = fcx
@@ -88,132 +140,75 @@ impl<'tcx> NeverCompatHandler<'tcx> {
88
140
let tcx = fcx. tcx ;
89
141
for ( call_id, path) in self . unresolved_paths {
90
142
debug ! (
91
- "Resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
143
+ "post_fallback: resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
92
144
path. span,
93
145
path. ty,
94
146
tcx. hir( ) . get( call_id) ,
95
147
tcx. hir( ) . get( tcx. hir( ) . get_parent_node( call_id) ) ,
96
148
path
97
149
) ;
98
150
99
- let ty = fcx. infcx . resolve_vars_if_possible ( & path. ty ) ;
100
- debug ! ( "Fully resolved ty: {:?}" , ty) ;
101
-
102
- let ty = ty. unwrap_or_else ( || bug ! ( "Missing ty in path: {:?}" , path) ) ;
103
-
104
- if let ty:: FnDef ( _, substs) = ty. kind {
105
- debug ! ( "Got substs: {:?}" , substs) ;
106
- let mut args_inhabited = true ;
107
- let mut uninhabited_subst = None ;
108
-
109
- for arg in & * path. args . unwrap ( ) {
110
- let resolved_arg = fcx. infcx . resolve_vars_if_possible ( arg) ;
111
-
112
- if resolved_arg. conservative_is_privately_uninhabited ( tcx) {
113
- debug ! ( "Arg is uninhabited: {:?}" , resolved_arg) ;
114
- args_inhabited = false ;
115
- break ;
116
- } else {
117
- debug ! ( "Arg is inhabited: {:?}" , resolved_arg) ;
118
- }
119
- }
120
-
121
- for ( subst_ty, vars) in substs. types ( ) . zip ( path. unresolved_vars . into_iter ( ) ) {
122
- let resolved_subst = fcx. infcx . resolve_vars_if_possible ( & subst_ty) ;
123
- if resolved_subst. conservative_is_privately_uninhabited ( tcx) {
124
- debug ! ( "Subst is uninhabited: {:?}" , resolved_subst) ;
125
- if !vars. is_empty ( ) {
126
- debug ! ( "Found fallback vars: {:?}" , vars) ;
127
- uninhabited_subst = Some ( vars) ;
128
- break ;
129
- } else {
130
- debug ! ( "No fallback vars" )
131
- }
132
- } else {
133
- debug ! ( "Subst is inhabited: {:?}" , resolved_subst) ;
134
- }
135
- }
136
-
137
- if let ( true , Some ( vars) ) = ( args_inhabited, uninhabited_subst) {
138
- debug ! ( "All arguments are inhabited, at least one subst is not inhabited!" ) ;
139
-
140
- let mut best_diverging_var = None ;
141
- let mut best_var = None ;
142
-
143
- for var in vars {
144
- for diverging_var in & self . unconstrained_diverging {
145
- match ( & var. kind , & diverging_var. kind ) {
146
- (
147
- ty:: Infer ( ty:: InferTy :: TyVar ( vid1) ) ,
148
- ty:: Infer ( ty:: InferTy :: TyVar ( vid2) ) ,
149
- ) => {
150
- if fcx
151
- . infcx
152
- . type_variables
153
- . borrow_mut ( )
154
- . sub_unified ( * vid1, * vid2)
155
- {
156
- debug ! (
157
- "Type variable {:?} is equal to diverging var {:?}" ,
158
- var, diverging_var
159
- ) ;
160
-
161
- debug ! (
162
- "Var origin: {:?}" ,
163
- fcx. infcx. type_variables. borrow( ) . var_origin( * vid1)
164
- ) ;
165
- best_var = Some ( vid1) ;
166
- best_diverging_var = Some ( vid2) ;
167
- }
151
+ let span = path. span ;
152
+ if let Some ( vars) = find_questionable_call ( path, fcx) {
153
+ let mut best_diverging_var = None ;
154
+ let mut best_var = None ;
155
+
156
+ for var in vars {
157
+ for diverging_var in & self . unconstrained_diverging {
158
+ match ( & var. kind , & diverging_var. kind ) {
159
+ (
160
+ ty:: Infer ( ty:: InferTy :: TyVar ( vid1) ) ,
161
+ ty:: Infer ( ty:: InferTy :: TyVar ( vid2) ) ,
162
+ ) => {
163
+ if fcx. infcx . type_variables . borrow_mut ( ) . sub_unified ( * vid1, * vid2) {
164
+ debug ! (
165
+ "Type variable {:?} is equal to diverging var {:?}" ,
166
+ var, diverging_var
167
+ ) ;
168
+
169
+ debug ! (
170
+ "Var origin: {:?}" ,
171
+ fcx. infcx. type_variables. borrow( ) . var_origin( * vid1)
172
+ ) ;
173
+ best_var = Some ( vid1) ;
174
+ best_diverging_var = Some ( vid2) ;
168
175
}
169
- _ => bug ! (
170
- "Unexpected types: var={:?} diverging_var={:?}" ,
171
- var,
172
- diverging_var
173
- ) ,
174
176
}
177
+ _ => bug ! (
178
+ "Unexpected types: var={:?} diverging_var={:?}" ,
179
+ var,
180
+ diverging_var
181
+ ) ,
175
182
}
176
183
}
184
+ }
177
185
178
- let var_origin =
179
- * fcx. infcx . type_variables . borrow ( ) . var_origin ( * best_var. unwrap ( ) ) ;
180
- let diverging_var_span = fcx
181
- . infcx
182
- . type_variables
183
- . borrow ( )
184
- . var_origin ( * best_diverging_var. unwrap ( ) )
185
- . span ;
186
-
187
- let mut err = tcx. sess . struct_span_warn (
188
- path. span ,
189
- "Fallback to `!` may introduce undefined behavior" ,
190
- ) ;
191
-
192
- match var_origin. kind {
193
- TypeVariableOriginKind :: TypeParameterDefinition ( name, did) => {
194
- err. span_note (
195
- var_origin. span ,
196
- & format ! ( "the type parameter {} here was inferred to `!`" , name) ,
197
- ) ;
198
- if let Some ( did) = did {
199
- err. span_note (
200
- fcx. tcx . def_span ( did) ,
201
- "(type parameter defined here)" ,
202
- ) ;
203
- }
204
- }
205
- _ => {
206
- err. span_note ( var_origin. span , "the type here was inferred to `!`" ) ;
186
+ let var_origin = * fcx. infcx . type_variables . borrow ( ) . var_origin ( * best_var. unwrap ( ) ) ;
187
+ let diverging_var_span =
188
+ fcx. infcx . type_variables . borrow ( ) . var_origin ( * best_diverging_var. unwrap ( ) ) . span ;
189
+
190
+ let mut err = tcx
191
+ . sess
192
+ . struct_span_warn ( span, "Fallback to `!` may introduce undefined behavior" ) ;
193
+
194
+ match var_origin. kind {
195
+ TypeVariableOriginKind :: TypeParameterDefinition ( name, did) => {
196
+ err. span_note (
197
+ var_origin. span ,
198
+ & format ! ( "the type parameter {} here was inferred to `!`" , name) ,
199
+ ) ;
200
+ if let Some ( did) = did {
201
+ err. span_note ( fcx. tcx . def_span ( did) , "(type parameter defined here)" ) ;
207
202
}
208
203
}
204
+ _ => {
205
+ err. span_note ( var_origin. span , "the type here was inferred to `!`" ) ;
206
+ }
207
+ }
209
208
210
- err. span_note (
211
- diverging_var_span,
212
- "... due to this expression evaluating to `!`" ,
213
- )
209
+ err. span_note ( diverging_var_span, "... due to this expression evaluating to `!`" )
214
210
. note ( "If you want the `!` type to be used here, add explicit type annotations" )
215
211
. emit ( ) ;
216
- }
217
212
}
218
213
}
219
214
}
0 commit comments