@@ -1978,19 +1978,75 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1978
1978
1979
1979
match cast_kind {
1980
1980
CastKind :: PointerCoercion ( PointerCoercion :: ReifyFnPointer ) => {
1981
- let fn_sig = op. ty ( body, tcx) . fn_sig ( tcx) ;
1981
+ let src_sig = op. ty ( body, tcx) . fn_sig ( tcx) ;
1982
+
1983
+ // HACK: This shouldn't be necessary... We can remove this when we actually
1984
+ // get binders with where clauses, then elaborate implied bounds into that
1985
+ // binder, and implement a higher-ranked subtyping algorithm that actually
1986
+ // respects these implied bounds.
1987
+ //
1988
+ // This protects against the case where we are casting from a higher-ranked
1989
+ // fn item to a non-higher-ranked fn pointer, where the cast throws away
1990
+ // implied bounds that would've needed to be checked at the call site. This
1991
+ // only works when we're casting to a non-higher-ranked fn ptr, since we
1992
+ // need to instantiate the higher-ranked signature with *infer* vars, not
1993
+ // placeholders.
1994
+ //
1995
+ // We check that this signature is WF before subtyping the signature with
1996
+ // the target fn sig.
1997
+ if src_sig. has_bound_regions ( )
1998
+ && let ty:: FnPtr ( target_sig) = * ty. kind ( )
1999
+ && let Some ( target_sig) = target_sig. no_bound_vars ( )
2000
+ {
2001
+ let src_sig = self . infcx . instantiate_binder_with_fresh_vars (
2002
+ span,
2003
+ BoundRegionConversionTime :: HigherRankedType ,
2004
+ src_sig,
2005
+ ) ;
2006
+ let src_ty = Ty :: new_fn_ptr ( self . tcx ( ) , ty:: Binder :: dummy ( src_sig) ) ;
2007
+ self . prove_predicate (
2008
+ ty:: ClauseKind :: WellFormed ( src_ty. into ( ) ) ,
2009
+ location. to_locations ( ) ,
2010
+ ConstraintCategory :: Cast { unsize_to : None } ,
2011
+ ) ;
2012
+
2013
+ let src_ty = self . normalize ( src_ty, location) ;
2014
+ if let Err ( terr) = self . sub_types (
2015
+ src_ty,
2016
+ * ty,
2017
+ location. to_locations ( ) ,
2018
+ ConstraintCategory :: Cast { unsize_to : None } ,
2019
+ ) {
2020
+ span_mirbug ! (
2021
+ self ,
2022
+ rvalue,
2023
+ "equating {:?} with {:?} yields {:?}" ,
2024
+ target_sig,
2025
+ src_sig,
2026
+ terr
2027
+ ) ;
2028
+ } ;
2029
+ }
2030
+
2031
+ let src_ty = Ty :: new_fn_ptr ( tcx, src_sig) ;
2032
+ // HACK: We want to assert that the signature of the source fn is
2033
+ // well-formed, because we don't enforce that via the WF of FnDef
2034
+ // types normally. This should be removed when we improve the tracking
2035
+ // of implied bounds of fn signatures.
2036
+ self . prove_predicate (
2037
+ ty:: ClauseKind :: WellFormed ( src_ty. into ( ) ) ,
2038
+ location. to_locations ( ) ,
2039
+ ConstraintCategory :: Cast { unsize_to : None } ,
2040
+ ) ;
1982
2041
1983
2042
// The type that we see in the fcx is like
1984
2043
// `foo::<'a, 'b>`, where `foo` is the path to a
1985
2044
// function definition. When we extract the
1986
2045
// signature, it comes from the `fn_sig` query,
1987
2046
// and hence may contain unnormalized results.
1988
- let fn_sig = self . normalize ( fn_sig, location) ;
1989
-
1990
- let ty_fn_ptr_from = Ty :: new_fn_ptr ( tcx, fn_sig) ;
1991
-
2047
+ let src_ty = self . normalize ( src_ty, location) ;
1992
2048
if let Err ( terr) = self . sub_types (
1993
- ty_fn_ptr_from ,
2049
+ src_ty ,
1994
2050
* ty,
1995
2051
location. to_locations ( ) ,
1996
2052
ConstraintCategory :: Cast { unsize_to : None } ,
@@ -1999,7 +2055,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1999
2055
self ,
2000
2056
rvalue,
2001
2057
"equating {:?} with {:?} yields {:?}" ,
2002
- ty_fn_ptr_from ,
2058
+ src_ty ,
2003
2059
ty,
2004
2060
terr
2005
2061
) ;
0 commit comments