@@ -1978,19 +1978,76 @@ 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_fn_tys, target_hdr) = * ty. kind ( )
1999
+ && let target_sig = target_fn_tys. with ( target_hdr)
2000
+ && let Some ( target_sig) = target_sig. no_bound_vars ( )
2001
+ {
2002
+ let src_sig = self . infcx . instantiate_binder_with_fresh_vars (
2003
+ span,
2004
+ BoundRegionConversionTime :: HigherRankedType ,
2005
+ src_sig,
2006
+ ) ;
2007
+ let src_ty = Ty :: new_fn_ptr ( self . tcx ( ) , ty:: Binder :: dummy ( src_sig) ) ;
2008
+ self . prove_predicate (
2009
+ ty:: ClauseKind :: WellFormed ( src_ty. into ( ) ) ,
2010
+ location. to_locations ( ) ,
2011
+ ConstraintCategory :: Cast { unsize_to : None } ,
2012
+ ) ;
2013
+
2014
+ let src_ty = self . normalize ( src_ty, location) ;
2015
+ if let Err ( terr) = self . sub_types (
2016
+ src_ty,
2017
+ * ty,
2018
+ location. to_locations ( ) ,
2019
+ ConstraintCategory :: Cast { unsize_to : None } ,
2020
+ ) {
2021
+ span_mirbug ! (
2022
+ self ,
2023
+ rvalue,
2024
+ "equating {:?} with {:?} yields {:?}" ,
2025
+ target_sig,
2026
+ src_sig,
2027
+ terr
2028
+ ) ;
2029
+ } ;
2030
+ }
2031
+
2032
+ let src_ty = Ty :: new_fn_ptr ( tcx, src_sig) ;
2033
+ // HACK: We want to assert that the signature of the source fn is
2034
+ // well-formed, because we don't enforce that via the WF of FnDef
2035
+ // types normally. This should be removed when we improve the tracking
2036
+ // of implied bounds of fn signatures.
2037
+ self . prove_predicate (
2038
+ ty:: ClauseKind :: WellFormed ( src_ty. into ( ) ) ,
2039
+ location. to_locations ( ) ,
2040
+ ConstraintCategory :: Cast { unsize_to : None } ,
2041
+ ) ;
1982
2042
1983
2043
// The type that we see in the fcx is like
1984
2044
// `foo::<'a, 'b>`, where `foo` is the path to a
1985
2045
// function definition. When we extract the
1986
2046
// signature, it comes from the `fn_sig` query,
1987
2047
// 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
-
2048
+ let src_ty = self . normalize ( src_ty, location) ;
1992
2049
if let Err ( terr) = self . sub_types (
1993
- ty_fn_ptr_from ,
2050
+ src_ty ,
1994
2051
* ty,
1995
2052
location. to_locations ( ) ,
1996
2053
ConstraintCategory :: Cast { unsize_to : None } ,
@@ -1999,7 +2056,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1999
2056
self ,
2000
2057
rvalue,
2001
2058
"equating {:?} with {:?} yields {:?}" ,
2002
- ty_fn_ptr_from ,
2059
+ src_ty ,
2003
2060
ty,
2004
2061
terr
2005
2062
) ;
0 commit comments