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