@@ -187,48 +187,64 @@ fn compare_method_predicate_entailment<'tcx>(
187187 let impl_to_placeholder_args = GenericArgs :: identity_for_item ( tcx, impl_m. def_id ) ;
188188
189189 // Create mapping from trait to placeholder.
190+ let impl_def_id = impl_m. container_id ( tcx) ;
190191 let trait_to_placeholder_args =
191- impl_to_placeholder_args. rebase_onto ( tcx, impl_m . container_id ( tcx ) , trait_to_impl_args) ;
192+ impl_to_placeholder_args. rebase_onto ( tcx, impl_def_id , trait_to_impl_args) ;
192193 debug ! ( "compare_impl_method: trait_to_placeholder_args={:?}" , trait_to_placeholder_args) ;
193194
194195 let impl_m_predicates = tcx. predicates_of ( impl_m. def_id ) ;
195196 let trait_m_predicates = tcx. predicates_of ( trait_m. def_id ) ;
196197
197- // Create obligations for each predicate declared by the impl
198- // definition in the context of the trait's parameter
199- // environment. We can't just use `impl_env.caller_bounds`,
200- // however, because we want to replace all late-bound regions with
201- // region variables.
202- let impl_predicates = tcx. predicates_of ( impl_m_predicates. parent . unwrap ( ) ) ;
203- let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) ;
204-
205- debug ! ( "compare_impl_method: impl_bounds={:?}" , hybrid_preds) ;
206-
207198 // This is the only tricky bit of the new way we check implementation methods
208199 // We need to build a set of predicates where only the method-level bounds
209200 // are from the trait and we assume all other bounds from the implementation
210201 // to be previously satisfied.
211202 //
212203 // We then register the obligations from the impl_m and check to see
213204 // if all constraints hold.
214- hybrid_preds. predicates . extend (
205+ let impl_predicates = tcx. predicates_of ( impl_m_predicates. parent . unwrap ( ) ) ;
206+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
207+ hybrid_preds. extend (
215208 trait_m_predicates
216209 . instantiate_own ( tcx, trait_to_placeholder_args)
217210 . map ( |( predicate, _) | predicate) ,
218211 ) ;
219212
213+ // FIXME(effects): This should be replaced with a more dedicated method.
214+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
215+ if check_const_if_const {
216+ // Augment the hybrid param-env with the const conditions
217+ // of the impl header and the trait method.
218+ hybrid_preds. extend (
219+ tcx. const_conditions ( impl_def_id)
220+ . instantiate_identity ( tcx)
221+ . into_iter ( )
222+ . chain (
223+ tcx. const_conditions ( trait_m. def_id )
224+ . instantiate_own ( tcx, trait_to_placeholder_args) ,
225+ )
226+ . map ( |( trait_ref, _) | {
227+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
228+ } ) ,
229+ ) ;
230+ }
231+
220232 // Construct trait parameter environment and then shift it into the placeholder viewpoint.
221233 // The key step here is to update the caller_bounds's predicates to be
222234 // the new hybrid bounds we computed.
223235 let normalize_cause = traits:: ObligationCause :: misc ( impl_m_span, impl_m_def_id) ;
224- let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds. predicates ) , Reveal :: UserFacing ) ;
236+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
225237 let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
226238
227239 let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
228240 let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
229241
230242 debug ! ( "compare_impl_method: caller_bounds={:?}" , param_env. caller_bounds( ) ) ;
231243
244+ // Create obligations for each predicate declared by the impl
245+ // definition in the context of the hybrid param-env. This makes
246+ // sure that the impl's method's where clauses are not more
247+ // restrictive than the trait's method (and the impl itself).
232248 let impl_m_own_bounds = impl_m_predicates. instantiate_own ( tcx, impl_to_placeholder_args) ;
233249 for ( predicate, span) in impl_m_own_bounds {
234250 let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
@@ -243,6 +259,34 @@ fn compare_method_predicate_entailment<'tcx>(
243259 ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
244260 }
245261
262+ // If we're within a const implementation, we need to make sure that the method
263+ // does not assume stronger `~const` bounds than the trait definition.
264+ //
265+ // This registers the `~const` bounds of the impl method, which we will prove
266+ // using the hybrid param-env that we earlier augmented with the const conditions
267+ // from the impl header and trait method declaration.
268+ if check_const_if_const {
269+ for ( const_condition, span) in
270+ tcx. const_conditions ( impl_m. def_id ) . instantiate_own ( tcx, impl_to_placeholder_args)
271+ {
272+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
273+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
274+
275+ let cause =
276+ ObligationCause :: new ( span, impl_m_def_id, ObligationCauseCode :: CompareImplItem {
277+ impl_item_def_id : impl_m_def_id,
278+ trait_item_def_id : trait_m. def_id ,
279+ kind : impl_m. kind ,
280+ } ) ;
281+ ocx. register_obligation ( traits:: Obligation :: new (
282+ tcx,
283+ cause,
284+ param_env,
285+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
286+ ) ) ;
287+ }
288+ }
289+
246290 // We now need to check that the signature of the impl method is
247291 // compatible with that of the trait method. We do this by
248292 // checking that `impl_fty <: trait_fty`.
@@ -1759,14 +1803,14 @@ fn compare_const_predicate_entailment<'tcx>(
17591803 // The predicates declared by the impl definition, the trait and the
17601804 // associated const in the trait are assumed.
17611805 let impl_predicates = tcx. predicates_of ( impl_ct_predicates. parent . unwrap ( ) ) ;
1762- let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) ;
1763- hybrid_preds. predicates . extend (
1806+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1807+ hybrid_preds. extend (
17641808 trait_ct_predicates
17651809 . instantiate_own ( tcx, trait_to_impl_args)
17661810 . map ( |( predicate, _) | predicate) ,
17671811 ) ;
17681812
1769- let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds. predicates ) , Reveal :: UserFacing ) ;
1813+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
17701814 let param_env = traits:: normalize_param_env_or_error (
17711815 tcx,
17721816 param_env,
@@ -1871,14 +1915,16 @@ fn compare_type_predicate_entailment<'tcx>(
18711915 impl_trait_ref : ty:: TraitRef < ' tcx > ,
18721916) -> Result < ( ) , ErrorGuaranteed > {
18731917 let impl_args = GenericArgs :: identity_for_item ( tcx, impl_ty. def_id ) ;
1874- let trait_to_impl_args =
1875- impl_args. rebase_onto ( tcx, impl_ty . container_id ( tcx ) , impl_trait_ref. args ) ;
1918+ let impl_def_id = impl_ty . container_id ( tcx ) ;
1919+ let trait_to_impl_args = impl_args. rebase_onto ( tcx, impl_def_id , impl_trait_ref. args ) ;
18761920
18771921 let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
18781922 let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
18791923
18801924 let impl_ty_own_bounds = impl_ty_predicates. instantiate_own ( tcx, impl_args) ;
1881- if impl_ty_own_bounds. len ( ) == 0 {
1925+ let impl_ty_own_const_conditions =
1926+ tcx. const_conditions ( impl_ty. def_id ) . instantiate_own ( tcx, impl_args) ;
1927+ if impl_ty_own_bounds. len ( ) == 0 && impl_ty_own_const_conditions. len ( ) == 0 {
18821928 // Nothing to check.
18831929 return Ok ( ( ) ) ;
18841930 }
@@ -1892,18 +1938,35 @@ fn compare_type_predicate_entailment<'tcx>(
18921938 // The predicates declared by the impl definition, the trait and the
18931939 // associated type in the trait are assumed.
18941940 let impl_predicates = tcx. predicates_of ( impl_ty_predicates. parent . unwrap ( ) ) ;
1895- let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) ;
1896- hybrid_preds. predicates . extend (
1941+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1942+ hybrid_preds. extend (
18971943 trait_ty_predicates
18981944 . instantiate_own ( tcx, trait_to_impl_args)
18991945 . map ( |( predicate, _) | predicate) ,
19001946 ) ;
19011947
1948+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
1949+ if check_const_if_const {
1950+ // Augment the hybrid param-env with the const conditions
1951+ // of the impl header and the trait assoc type.
1952+ hybrid_preds. extend (
1953+ tcx. const_conditions ( impl_ty_predicates. parent . unwrap ( ) )
1954+ . instantiate_identity ( tcx)
1955+ . into_iter ( )
1956+ . chain (
1957+ tcx. const_conditions ( trait_ty. def_id ) . instantiate_own ( tcx, trait_to_impl_args) ,
1958+ )
1959+ . map ( |( trait_ref, _) | {
1960+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
1961+ } ) ,
1962+ ) ;
1963+ }
1964+
19021965 debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
19031966
19041967 let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
19051968 let normalize_cause = ObligationCause :: misc ( impl_ty_span, impl_ty_def_id) ;
1906- let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds. predicates ) , Reveal :: UserFacing ) ;
1969+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
19071970 let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
19081971 let infcx = tcx. infer_ctxt ( ) . build ( ) ;
19091972 let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
@@ -1923,6 +1986,27 @@ fn compare_type_predicate_entailment<'tcx>(
19231986 ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
19241987 }
19251988
1989+ if check_const_if_const {
1990+ // Validate the const conditions of the impl associated type.
1991+ for ( const_condition, span) in impl_ty_own_const_conditions {
1992+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_ty_def_id) ;
1993+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
1994+
1995+ let cause =
1996+ ObligationCause :: new ( span, impl_ty_def_id, ObligationCauseCode :: CompareImplItem {
1997+ impl_item_def_id : impl_ty_def_id,
1998+ trait_item_def_id : trait_ty. def_id ,
1999+ kind : impl_ty. kind ,
2000+ } ) ;
2001+ ocx. register_obligation ( traits:: Obligation :: new (
2002+ tcx,
2003+ cause,
2004+ param_env,
2005+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
2006+ ) ) ;
2007+ }
2008+ }
2009+
19262010 // Check that all obligations are satisfied by the implementation's
19272011 // version.
19282012 let errors = ocx. select_all_or_error ( ) ;
@@ -2005,14 +2089,30 @@ pub(super) fn check_type_bounds<'tcx>(
20052089 ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
20062090 } ;
20072091
2008- let obligations: Vec < _ > = tcx
2092+ let mut obligations: Vec < _ > = tcx
20092093 . explicit_item_bounds ( trait_ty. def_id )
20102094 . iter_instantiated_copied ( tcx, rebased_args)
20112095 . map ( |( concrete_ty_bound, span) | {
20122096 debug ! ( "check_type_bounds: concrete_ty_bound = {:?}" , concrete_ty_bound) ;
20132097 traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
20142098 } )
20152099 . collect ( ) ;
2100+
2101+ // Only in a const implementation do we need to check that the `~const` item bounds hold.
2102+ if tcx. constness ( container_id) == hir:: Constness :: Const {
2103+ obligations. extend (
2104+ tcx. implied_const_bounds ( trait_ty. def_id )
2105+ . iter_instantiated_copied ( tcx, rebased_args)
2106+ . map ( |( c, span) | {
2107+ traits:: Obligation :: new (
2108+ tcx,
2109+ mk_cause ( span) ,
2110+ param_env,
2111+ c. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
2112+ )
2113+ } ) ,
2114+ ) ;
2115+ }
20162116 debug ! ( "check_type_bounds: item_bounds={:?}" , obligations) ;
20172117
20182118 // Normalize predicates with the assumption that the GAT may always normalize
0 commit comments