@@ -34,6 +34,58 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TyVarFinder<'a, 'tcx> {
3434 }
3535}
3636
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+
3789impl < ' tcx > NeverCompatHandler < ' tcx > {
3890 pub fn pre_fallback ( fcx : & FnCtxt < ' a , ' tcx > ) -> NeverCompatHandler < ' tcx > {
3991 let unresolved_paths: FxHashMap < HirId , InferredPath < ' tcx > > = fcx
@@ -88,132 +140,75 @@ impl<'tcx> NeverCompatHandler<'tcx> {
88140 let tcx = fcx. tcx ;
89141 for ( call_id, path) in self . unresolved_paths {
90142 debug ! (
91- "Resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
143+ "post_fallback: resolved ty: {:?} at span {:?} : expr={:?} parent={:?} path={:?}" ,
92144 path. span,
93145 path. ty,
94146 tcx. hir( ) . get( call_id) ,
95147 tcx. hir( ) . get( tcx. hir( ) . get_parent_node( call_id) ) ,
96148 path
97149 ) ;
98150
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) ;
168175 }
169- _ => bug ! (
170- "Unexpected types: var={:?} diverging_var={:?}" ,
171- var,
172- diverging_var
173- ) ,
174176 }
177+ _ => bug ! (
178+ "Unexpected types: var={:?} diverging_var={:?}" ,
179+ var,
180+ diverging_var
181+ ) ,
175182 }
176183 }
184+ }
177185
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)" ) ;
207202 }
208203 }
204+ _ => {
205+ err. span_note ( var_origin. span , "the type here was inferred to `!`" ) ;
206+ }
207+ }
209208
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 `!`" )
214210 . note ( "If you want the `!` type to be used here, add explicit type annotations" )
215211 . emit ( ) ;
216- }
217212 }
218213 }
219214 }
0 commit comments