@@ -187,48 +187,61 @@ 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+ hybrid_preds. extend (
218+ tcx. const_conditions ( impl_def_id)
219+ . instantiate_identity ( tcx)
220+ . into_iter ( )
221+ . chain (
222+ tcx. const_conditions ( trait_m. def_id )
223+ . instantiate_own ( tcx, trait_to_placeholder_args) ,
224+ )
225+ . map ( |( trait_ref, _) | trait_ref. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ) ,
226+ ) ;
227+ }
228+
220229 // Construct trait parameter environment and then shift it into the placeholder viewpoint.
221230 // The key step here is to update the caller_bounds's predicates to be
222231 // the new hybrid bounds we computed.
223232 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 ) ;
233+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
225234 let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
226235
227236 let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
228237 let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
229238
230239 debug ! ( "compare_impl_method: caller_bounds={:?}" , param_env. caller_bounds( ) ) ;
231240
241+ // Create obligations for each predicate declared by the impl
242+ // definition in the context of the hybrid param-env. This makes
243+ // sure that the impl's method's where clauses are not more
244+ // restrictive than the trait's method (and the impl itself).
232245 let impl_m_own_bounds = impl_m_predicates. instantiate_own ( tcx, impl_to_placeholder_args) ;
233246 for ( predicate, span) in impl_m_own_bounds {
234247 let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
@@ -243,6 +256,34 @@ fn compare_method_predicate_entailment<'tcx>(
243256 ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
244257 }
245258
259+ // If we're within a const implementation, we need to make sure that the method
260+ // does not assume stronger `~const` bounds than the trait definition.
261+ //
262+ // This registers the `~const` bounds of the impl method, which we will prove
263+ // using the hybrid param-env that we earlier augmented with the const conditions
264+ // from the impl header and trait method declaration.
265+ if check_const_if_const {
266+ for ( const_condition, span) in
267+ tcx. const_conditions ( impl_m. def_id ) . instantiate_own ( tcx, impl_to_placeholder_args)
268+ {
269+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
270+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
271+
272+ let cause =
273+ ObligationCause :: new ( span, impl_m_def_id, ObligationCauseCode :: CompareImplItem {
274+ impl_item_def_id : impl_m_def_id,
275+ trait_item_def_id : trait_m. def_id ,
276+ kind : impl_m. kind ,
277+ } ) ;
278+ ocx. register_obligation ( traits:: Obligation :: new (
279+ tcx,
280+ cause,
281+ param_env,
282+ const_condition. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ,
283+ ) ) ;
284+ }
285+ }
286+
246287 // We now need to check that the signature of the impl method is
247288 // compatible with that of the trait method. We do this by
248289 // checking that `impl_fty <: trait_fty`.
@@ -1759,14 +1800,14 @@ fn compare_const_predicate_entailment<'tcx>(
17591800 // The predicates declared by the impl definition, the trait and the
17601801 // associated const in the trait are assumed.
17611802 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 (
1803+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1804+ hybrid_preds. extend (
17641805 trait_ct_predicates
17651806 . instantiate_own ( tcx, trait_to_impl_args)
17661807 . map ( |( predicate, _) | predicate) ,
17671808 ) ;
17681809
1769- let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds. predicates ) , Reveal :: UserFacing ) ;
1810+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
17701811 let param_env = traits:: normalize_param_env_or_error (
17711812 tcx,
17721813 param_env,
@@ -1871,14 +1912,16 @@ fn compare_type_predicate_entailment<'tcx>(
18711912 impl_trait_ref : ty:: TraitRef < ' tcx > ,
18721913) -> Result < ( ) , ErrorGuaranteed > {
18731914 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 ) ;
1915+ let impl_def_id = impl_ty . container_id ( tcx ) ;
1916+ let trait_to_impl_args = impl_args. rebase_onto ( tcx, impl_def_id , impl_trait_ref. args ) ;
18761917
18771918 let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
18781919 let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
18791920
18801921 let impl_ty_own_bounds = impl_ty_predicates. instantiate_own ( tcx, impl_args) ;
1881- if impl_ty_own_bounds. len ( ) == 0 {
1922+ let impl_ty_own_const_conditions =
1923+ tcx. const_conditions ( impl_ty. def_id ) . instantiate_own ( tcx, impl_args) ;
1924+ if impl_ty_own_bounds. len ( ) == 0 && impl_ty_own_const_conditions. len ( ) == 0 {
18821925 // Nothing to check.
18831926 return Ok ( ( ) ) ;
18841927 }
@@ -1892,18 +1935,31 @@ fn compare_type_predicate_entailment<'tcx>(
18921935 // The predicates declared by the impl definition, the trait and the
18931936 // associated type in the trait are assumed.
18941937 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 (
1938+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1939+ hybrid_preds. extend (
18971940 trait_ty_predicates
18981941 . instantiate_own ( tcx, trait_to_impl_args)
18991942 . map ( |( predicate, _) | predicate) ,
19001943 ) ;
19011944
1945+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
1946+ if check_const_if_const {
1947+ hybrid_preds. extend (
1948+ tcx. const_conditions ( impl_ty_predicates. parent . unwrap ( ) )
1949+ . instantiate_identity ( tcx)
1950+ . into_iter ( )
1951+ . chain (
1952+ tcx. const_conditions ( trait_ty. def_id ) . instantiate_own ( tcx, trait_to_impl_args) ,
1953+ )
1954+ . map ( |( trait_ref, _) | trait_ref. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ) ,
1955+ ) ;
1956+ }
1957+
19021958 debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
19031959
19041960 let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
19051961 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 ) ;
1962+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
19071963 let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
19081964 let infcx = tcx. infer_ctxt ( ) . build ( ) ;
19091965 let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
@@ -1923,6 +1979,27 @@ fn compare_type_predicate_entailment<'tcx>(
19231979 ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
19241980 }
19251981
1982+ if check_const_if_const {
1983+ // Validate the const conditions of the impl method.
1984+ for ( const_condition, span) in impl_ty_own_const_conditions {
1985+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_ty_def_id) ;
1986+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
1987+
1988+ let cause =
1989+ ObligationCause :: new ( span, impl_ty_def_id, ObligationCauseCode :: CompareImplItem {
1990+ impl_item_def_id : impl_ty_def_id,
1991+ trait_item_def_id : trait_ty. def_id ,
1992+ kind : impl_ty. kind ,
1993+ } ) ;
1994+ ocx. register_obligation ( traits:: Obligation :: new (
1995+ tcx,
1996+ cause,
1997+ param_env,
1998+ const_condition. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ,
1999+ ) ) ;
2000+ }
2001+ }
2002+
19262003 // Check that all obligations are satisfied by the implementation's
19272004 // version.
19282005 let errors = ocx. select_all_or_error ( ) ;
@@ -2005,14 +2082,30 @@ pub(super) fn check_type_bounds<'tcx>(
20052082 ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
20062083 } ;
20072084
2008- let obligations: Vec < _ > = tcx
2085+ let mut obligations: Vec < _ > = tcx
20092086 . explicit_item_bounds ( trait_ty. def_id )
20102087 . iter_instantiated_copied ( tcx, rebased_args)
20112088 . map ( |( concrete_ty_bound, span) | {
20122089 debug ! ( "check_type_bounds: concrete_ty_bound = {:?}" , concrete_ty_bound) ;
20132090 traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
20142091 } )
20152092 . collect ( ) ;
2093+
2094+ // Only in a const implementation do we need to check that the `~const` item bounds hold.
2095+ if tcx. constness ( container_id) == hir:: Constness :: Const {
2096+ obligations. extend (
2097+ tcx. implied_const_bounds ( trait_ty. def_id )
2098+ . iter_instantiated_copied ( tcx, rebased_args)
2099+ . map ( |( c, span) | {
2100+ traits:: Obligation :: new (
2101+ tcx,
2102+ mk_cause ( span) ,
2103+ param_env,
2104+ c. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ,
2105+ )
2106+ } ) ,
2107+ ) ;
2108+ }
20162109 debug ! ( "check_type_bounds: item_bounds={:?}" , obligations) ;
20172110
20182111 // Normalize predicates with the assumption that the GAT may always normalize
0 commit comments