@@ -187,48 +187,64 @@ fn compare_method_predicate_entailment<'tcx>(
187
187
let impl_to_placeholder_args = GenericArgs :: identity_for_item ( tcx, impl_m. def_id ) ;
188
188
189
189
// Create mapping from trait to placeholder.
190
+ let impl_def_id = impl_m. container_id ( tcx) ;
190
191
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) ;
192
193
debug ! ( "compare_impl_method: trait_to_placeholder_args={:?}" , trait_to_placeholder_args) ;
193
194
194
195
let impl_m_predicates = tcx. predicates_of ( impl_m. def_id ) ;
195
196
let trait_m_predicates = tcx. predicates_of ( trait_m. def_id ) ;
196
197
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
-
207
198
// This is the only tricky bit of the new way we check implementation methods
208
199
// We need to build a set of predicates where only the method-level bounds
209
200
// are from the trait and we assume all other bounds from the implementation
210
201
// to be previously satisfied.
211
202
//
212
203
// We then register the obligations from the impl_m and check to see
213
204
// 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 (
215
208
trait_m_predicates
216
209
. instantiate_own ( tcx, trait_to_placeholder_args)
217
210
. map ( |( predicate, _) | predicate) ,
218
211
) ;
219
212
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
+
220
232
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
221
233
// The key step here is to update the caller_bounds's predicates to be
222
234
// the new hybrid bounds we computed.
223
235
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 ) ;
225
237
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
226
238
227
239
let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
228
240
let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
229
241
230
242
debug ! ( "compare_impl_method: caller_bounds={:?}" , param_env. caller_bounds( ) ) ;
231
243
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).
232
248
let impl_m_own_bounds = impl_m_predicates. instantiate_own ( tcx, impl_to_placeholder_args) ;
233
249
for ( predicate, span) in impl_m_own_bounds {
234
250
let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
@@ -243,6 +259,34 @@ fn compare_method_predicate_entailment<'tcx>(
243
259
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
244
260
}
245
261
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
+
246
290
// We now need to check that the signature of the impl method is
247
291
// compatible with that of the trait method. We do this by
248
292
// checking that `impl_fty <: trait_fty`.
@@ -1759,14 +1803,14 @@ fn compare_const_predicate_entailment<'tcx>(
1759
1803
// The predicates declared by the impl definition, the trait and the
1760
1804
// associated const in the trait are assumed.
1761
1805
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 (
1764
1808
trait_ct_predicates
1765
1809
. instantiate_own ( tcx, trait_to_impl_args)
1766
1810
. map ( |( predicate, _) | predicate) ,
1767
1811
) ;
1768
1812
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 ) ;
1770
1814
let param_env = traits:: normalize_param_env_or_error (
1771
1815
tcx,
1772
1816
param_env,
@@ -1871,14 +1915,16 @@ fn compare_type_predicate_entailment<'tcx>(
1871
1915
impl_trait_ref : ty:: TraitRef < ' tcx > ,
1872
1916
) -> Result < ( ) , ErrorGuaranteed > {
1873
1917
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 ) ;
1876
1920
1877
1921
let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
1878
1922
let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
1879
1923
1880
1924
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 {
1882
1928
// Nothing to check.
1883
1929
return Ok ( ( ) ) ;
1884
1930
}
@@ -1892,18 +1938,35 @@ fn compare_type_predicate_entailment<'tcx>(
1892
1938
// The predicates declared by the impl definition, the trait and the
1893
1939
// associated type in the trait are assumed.
1894
1940
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 (
1897
1943
trait_ty_predicates
1898
1944
. instantiate_own ( tcx, trait_to_impl_args)
1899
1945
. map ( |( predicate, _) | predicate) ,
1900
1946
) ;
1901
1947
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
+
1902
1965
debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
1903
1966
1904
1967
let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
1905
1968
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 ) ;
1907
1970
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
1908
1971
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
1909
1972
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
@@ -1923,6 +1986,27 @@ fn compare_type_predicate_entailment<'tcx>(
1923
1986
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
1924
1987
}
1925
1988
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
+
1926
2010
// Check that all obligations are satisfied by the implementation's
1927
2011
// version.
1928
2012
let errors = ocx. select_all_or_error ( ) ;
@@ -2005,14 +2089,30 @@ pub(super) fn check_type_bounds<'tcx>(
2005
2089
ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
2006
2090
} ;
2007
2091
2008
- let obligations: Vec < _ > = tcx
2092
+ let mut obligations: Vec < _ > = tcx
2009
2093
. explicit_item_bounds ( trait_ty. def_id )
2010
2094
. iter_instantiated_copied ( tcx, rebased_args)
2011
2095
. map ( |( concrete_ty_bound, span) | {
2012
2096
debug ! ( "check_type_bounds: concrete_ty_bound = {:?}" , concrete_ty_bound) ;
2013
2097
traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
2014
2098
} )
2015
2099
. 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
+ }
2016
2116
debug ! ( "check_type_bounds: item_bounds={:?}" , obligations) ;
2017
2117
2018
2118
// Normalize predicates with the assumption that the GAT may always normalize
0 commit comments