@@ -181,6 +181,7 @@ fn compare_method_predicate_entailment<'tcx>(
181
181
} ) ;
182
182
183
183
// Create mapping from trait method to impl method.
184
+ let impl_def_id = impl_m. container_id ( tcx) ;
184
185
let trait_to_impl_args = GenericArgs :: identity_for_item ( tcx, impl_m. def_id ) . rebase_onto (
185
186
tcx,
186
187
impl_m. container_id ( tcx) ,
@@ -204,6 +205,24 @@ fn compare_method_predicate_entailment<'tcx>(
204
205
trait_m_predicates. instantiate_own ( tcx, trait_to_impl_args) . map ( |( predicate, _) | predicate) ,
205
206
) ;
206
207
208
+ // FIXME(effects): This should be replaced with a more dedicated method.
209
+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
210
+ if check_const_if_const {
211
+ // Augment the hybrid param-env with the const conditions
212
+ // of the impl header and the trait method.
213
+ hybrid_preds. extend (
214
+ tcx. const_conditions ( impl_def_id)
215
+ . instantiate_identity ( tcx)
216
+ . into_iter ( )
217
+ . chain (
218
+ tcx. const_conditions ( trait_m. def_id ) . instantiate_own ( tcx, trait_to_impl_args) ,
219
+ )
220
+ . map ( |( trait_ref, _) | {
221
+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
222
+ } ) ,
223
+ ) ;
224
+ }
225
+
207
226
let normalize_cause = traits:: ObligationCause :: misc ( impl_m_span, impl_m_def_id) ;
208
227
let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
209
228
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
@@ -230,6 +249,34 @@ fn compare_method_predicate_entailment<'tcx>(
230
249
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
231
250
}
232
251
252
+ // If we're within a const implementation, we need to make sure that the method
253
+ // does not assume stronger `~const` bounds than the trait definition.
254
+ //
255
+ // This registers the `~const` bounds of the impl method, which we will prove
256
+ // using the hybrid param-env that we earlier augmented with the const conditions
257
+ // from the impl header and trait method declaration.
258
+ if check_const_if_const {
259
+ for ( const_condition, span) in
260
+ tcx. const_conditions ( impl_m. def_id ) . instantiate_own_identity ( )
261
+ {
262
+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
263
+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
264
+
265
+ let cause =
266
+ ObligationCause :: new ( span, impl_m_def_id, ObligationCauseCode :: CompareImplItem {
267
+ impl_item_def_id : impl_m_def_id,
268
+ trait_item_def_id : trait_m. def_id ,
269
+ kind : impl_m. kind ,
270
+ } ) ;
271
+ ocx. register_obligation ( traits:: Obligation :: new (
272
+ tcx,
273
+ cause,
274
+ param_env,
275
+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
276
+ ) ) ;
277
+ }
278
+ }
279
+
233
280
// We now need to check that the signature of the impl method is
234
281
// compatible with that of the trait method. We do this by
235
282
// checking that `impl_fty <: trait_fty`.
@@ -1846,17 +1893,20 @@ fn compare_type_predicate_entailment<'tcx>(
1846
1893
trait_ty : ty:: AssocItem ,
1847
1894
impl_trait_ref : ty:: TraitRef < ' tcx > ,
1848
1895
) -> Result < ( ) , ErrorGuaranteed > {
1896
+ let impl_def_id = impl_ty. container_id ( tcx) ;
1849
1897
let trait_to_impl_args = GenericArgs :: identity_for_item ( tcx, impl_ty. def_id ) . rebase_onto (
1850
1898
tcx,
1851
- impl_ty . container_id ( tcx ) ,
1899
+ impl_def_id ,
1852
1900
impl_trait_ref. args ,
1853
1901
) ;
1854
1902
1855
1903
let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
1856
1904
let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
1857
1905
1858
1906
let impl_ty_own_bounds = impl_ty_predicates. instantiate_own_identity ( ) ;
1859
- if impl_ty_own_bounds. len ( ) == 0 {
1907
+ let impl_ty_own_const_conditions =
1908
+ tcx. const_conditions ( impl_ty. def_id ) . instantiate_own_identity ( ) ;
1909
+ if impl_ty_own_bounds. len ( ) == 0 && impl_ty_own_const_conditions. len ( ) == 0 {
1860
1910
// Nothing to check.
1861
1911
return Ok ( ( ) ) ;
1862
1912
}
@@ -1881,6 +1931,23 @@ fn compare_type_predicate_entailment<'tcx>(
1881
1931
let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
1882
1932
let normalize_cause = ObligationCause :: misc ( impl_ty_span, impl_ty_def_id) ;
1883
1933
1934
+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
1935
+ if check_const_if_const {
1936
+ // Augment the hybrid param-env with the const conditions
1937
+ // of the impl header and the trait assoc type.
1938
+ hybrid_preds. extend (
1939
+ tcx. const_conditions ( impl_ty_predicates. parent . unwrap ( ) )
1940
+ . instantiate_identity ( tcx)
1941
+ . into_iter ( )
1942
+ . chain (
1943
+ tcx. const_conditions ( trait_ty. def_id ) . instantiate_own ( tcx, trait_to_impl_args) ,
1944
+ )
1945
+ . map ( |( trait_ref, _) | {
1946
+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
1947
+ } ) ,
1948
+ ) ;
1949
+ }
1950
+
1884
1951
let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
1885
1952
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
1886
1953
debug ! ( caller_bounds=?param_env. caller_bounds( ) ) ;
@@ -1901,6 +1968,27 @@ fn compare_type_predicate_entailment<'tcx>(
1901
1968
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
1902
1969
}
1903
1970
1971
+ if check_const_if_const {
1972
+ // Validate the const conditions of the impl associated type.
1973
+ for ( const_condition, span) in impl_ty_own_const_conditions {
1974
+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_ty_def_id) ;
1975
+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
1976
+
1977
+ let cause =
1978
+ ObligationCause :: new ( span, impl_ty_def_id, ObligationCauseCode :: CompareImplItem {
1979
+ impl_item_def_id : impl_ty_def_id,
1980
+ trait_item_def_id : trait_ty. def_id ,
1981
+ kind : impl_ty. kind ,
1982
+ } ) ;
1983
+ ocx. register_obligation ( traits:: Obligation :: new (
1984
+ tcx,
1985
+ cause,
1986
+ param_env,
1987
+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
1988
+ ) ) ;
1989
+ }
1990
+ }
1991
+
1904
1992
// Check that all obligations are satisfied by the implementation's
1905
1993
// version.
1906
1994
let errors = ocx. select_all_or_error ( ) ;
@@ -1983,14 +2071,30 @@ pub(super) fn check_type_bounds<'tcx>(
1983
2071
ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
1984
2072
} ;
1985
2073
1986
- let obligations: Vec < _ > = tcx
2074
+ let mut obligations: Vec < _ > = tcx
1987
2075
. explicit_item_bounds ( trait_ty. def_id )
1988
2076
. iter_instantiated_copied ( tcx, rebased_args)
1989
2077
. map ( |( concrete_ty_bound, span) | {
1990
2078
debug ! ( ?concrete_ty_bound) ;
1991
2079
traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
1992
2080
} )
1993
2081
. collect ( ) ;
2082
+
2083
+ // Only in a const implementation do we need to check that the `~const` item bounds hold.
2084
+ if tcx. constness ( container_id) == hir:: Constness :: Const {
2085
+ obligations. extend (
2086
+ tcx. implied_const_bounds ( trait_ty. def_id )
2087
+ . iter_instantiated_copied ( tcx, rebased_args)
2088
+ . map ( |( c, span) | {
2089
+ traits:: Obligation :: new (
2090
+ tcx,
2091
+ mk_cause ( span) ,
2092
+ param_env,
2093
+ c. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
2094
+ )
2095
+ } ) ,
2096
+ ) ;
2097
+ }
1994
2098
debug ! ( item_bounds=?obligations) ;
1995
2099
1996
2100
// Normalize predicates with the assumption that the GAT may always normalize
0 commit comments