@@ -187,48 +187,63 @@ 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
+ 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, _) | {
226
+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
227
+ } ) ,
228
+ ) ;
229
+ }
230
+
220
231
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
221
232
// The key step here is to update the caller_bounds's predicates to be
222
233
// the new hybrid bounds we computed.
223
234
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 ) ;
235
+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
225
236
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
226
237
227
238
let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
228
239
let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
229
240
230
241
debug ! ( "compare_impl_method: caller_bounds={:?}" , param_env. caller_bounds( ) ) ;
231
242
243
+ // Create obligations for each predicate declared by the impl
244
+ // definition in the context of the hybrid param-env. This makes
245
+ // sure that the impl's method's where clauses are not more
246
+ // restrictive than the trait's method (and the impl itself).
232
247
let impl_m_own_bounds = impl_m_predicates. instantiate_own ( tcx, impl_to_placeholder_args) ;
233
248
for ( predicate, span) in impl_m_own_bounds {
234
249
let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
@@ -243,6 +258,34 @@ fn compare_method_predicate_entailment<'tcx>(
243
258
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
244
259
}
245
260
261
+ // If we're within a const implementation, we need to make sure that the method
262
+ // does not assume stronger `~const` bounds than the trait definition.
263
+ //
264
+ // This registers the `~const` bounds of the impl method, which we will prove
265
+ // using the hybrid param-env that we earlier augmented with the const conditions
266
+ // from the impl header and trait method declaration.
267
+ if check_const_if_const {
268
+ for ( const_condition, span) in
269
+ tcx. const_conditions ( impl_m. def_id ) . instantiate_own ( tcx, impl_to_placeholder_args)
270
+ {
271
+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
272
+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
273
+
274
+ let cause =
275
+ ObligationCause :: new ( span, impl_m_def_id, ObligationCauseCode :: CompareImplItem {
276
+ impl_item_def_id : impl_m_def_id,
277
+ trait_item_def_id : trait_m. def_id ,
278
+ kind : impl_m. kind ,
279
+ } ) ;
280
+ ocx. register_obligation ( traits:: Obligation :: new (
281
+ tcx,
282
+ cause,
283
+ param_env,
284
+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
285
+ ) ) ;
286
+ }
287
+ }
288
+
246
289
// We now need to check that the signature of the impl method is
247
290
// compatible with that of the trait method. We do this by
248
291
// checking that `impl_fty <: trait_fty`.
@@ -1759,14 +1802,14 @@ fn compare_const_predicate_entailment<'tcx>(
1759
1802
// The predicates declared by the impl definition, the trait and the
1760
1803
// associated const in the trait are assumed.
1761
1804
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 (
1805
+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1806
+ hybrid_preds. extend (
1764
1807
trait_ct_predicates
1765
1808
. instantiate_own ( tcx, trait_to_impl_args)
1766
1809
. map ( |( predicate, _) | predicate) ,
1767
1810
) ;
1768
1811
1769
- let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds. predicates ) , Reveal :: UserFacing ) ;
1812
+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
1770
1813
let param_env = traits:: normalize_param_env_or_error (
1771
1814
tcx,
1772
1815
param_env,
@@ -1871,14 +1914,16 @@ fn compare_type_predicate_entailment<'tcx>(
1871
1914
impl_trait_ref : ty:: TraitRef < ' tcx > ,
1872
1915
) -> Result < ( ) , ErrorGuaranteed > {
1873
1916
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 ) ;
1917
+ let impl_def_id = impl_ty . container_id ( tcx ) ;
1918
+ let trait_to_impl_args = impl_args. rebase_onto ( tcx, impl_def_id , impl_trait_ref. args ) ;
1876
1919
1877
1920
let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
1878
1921
let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
1879
1922
1880
1923
let impl_ty_own_bounds = impl_ty_predicates. instantiate_own ( tcx, impl_args) ;
1881
- if impl_ty_own_bounds. len ( ) == 0 {
1924
+ let impl_ty_own_const_conditions =
1925
+ tcx. const_conditions ( impl_ty. def_id ) . instantiate_own ( tcx, impl_args) ;
1926
+ if impl_ty_own_bounds. len ( ) == 0 && impl_ty_own_const_conditions. len ( ) == 0 {
1882
1927
// Nothing to check.
1883
1928
return Ok ( ( ) ) ;
1884
1929
}
@@ -1892,18 +1937,33 @@ fn compare_type_predicate_entailment<'tcx>(
1892
1937
// The predicates declared by the impl definition, the trait and the
1893
1938
// associated type in the trait are assumed.
1894
1939
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 (
1940
+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) . predicates ;
1941
+ hybrid_preds. extend (
1897
1942
trait_ty_predicates
1898
1943
. instantiate_own ( tcx, trait_to_impl_args)
1899
1944
. map ( |( predicate, _) | predicate) ,
1900
1945
) ;
1901
1946
1947
+ let check_const_if_const = tcx. constness ( impl_def_id) == hir:: Constness :: Const ;
1948
+ if check_const_if_const {
1949
+ hybrid_preds. extend (
1950
+ tcx. const_conditions ( impl_ty_predicates. parent . unwrap ( ) )
1951
+ . instantiate_identity ( tcx)
1952
+ . into_iter ( )
1953
+ . chain (
1954
+ tcx. const_conditions ( trait_ty. def_id ) . instantiate_own ( tcx, trait_to_impl_args) ,
1955
+ )
1956
+ . map ( |( trait_ref, _) | {
1957
+ trait_ref. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe )
1958
+ } ) ,
1959
+ ) ;
1960
+ }
1961
+
1902
1962
debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
1903
1963
1904
1964
let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
1905
1965
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 ) ;
1966
+ let param_env = ty:: ParamEnv :: new ( tcx. mk_clauses ( & hybrid_preds) , Reveal :: UserFacing ) ;
1907
1967
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
1908
1968
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
1909
1969
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
@@ -1923,6 +1983,27 @@ fn compare_type_predicate_entailment<'tcx>(
1923
1983
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
1924
1984
}
1925
1985
1986
+ if check_const_if_const {
1987
+ // Validate the const conditions of the impl method.
1988
+ for ( const_condition, span) in impl_ty_own_const_conditions {
1989
+ let normalize_cause = traits:: ObligationCause :: misc ( span, impl_ty_def_id) ;
1990
+ let const_condition = ocx. normalize ( & normalize_cause, param_env, const_condition) ;
1991
+
1992
+ let cause =
1993
+ ObligationCause :: new ( span, impl_ty_def_id, ObligationCauseCode :: CompareImplItem {
1994
+ impl_item_def_id : impl_ty_def_id,
1995
+ trait_item_def_id : trait_ty. def_id ,
1996
+ kind : impl_ty. kind ,
1997
+ } ) ;
1998
+ ocx. register_obligation ( traits:: Obligation :: new (
1999
+ tcx,
2000
+ cause,
2001
+ param_env,
2002
+ const_condition. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
2003
+ ) ) ;
2004
+ }
2005
+ }
2006
+
1926
2007
// Check that all obligations are satisfied by the implementation's
1927
2008
// version.
1928
2009
let errors = ocx. select_all_or_error ( ) ;
@@ -2005,14 +2086,30 @@ pub(super) fn check_type_bounds<'tcx>(
2005
2086
ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
2006
2087
} ;
2007
2088
2008
- let obligations: Vec < _ > = tcx
2089
+ let mut obligations: Vec < _ > = tcx
2009
2090
. explicit_item_bounds ( trait_ty. def_id )
2010
2091
. iter_instantiated_copied ( tcx, rebased_args)
2011
2092
. map ( |( concrete_ty_bound, span) | {
2012
2093
debug ! ( "check_type_bounds: concrete_ty_bound = {:?}" , concrete_ty_bound) ;
2013
2094
traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
2014
2095
} )
2015
2096
. collect ( ) ;
2097
+
2098
+ // Only in a const implementation do we need to check that the `~const` item bounds hold.
2099
+ if tcx. constness ( container_id) == hir:: Constness :: Const {
2100
+ obligations. extend (
2101
+ tcx. implied_const_bounds ( trait_ty. def_id )
2102
+ . iter_instantiated_copied ( tcx, rebased_args)
2103
+ . map ( |( c, span) | {
2104
+ traits:: Obligation :: new (
2105
+ tcx,
2106
+ mk_cause ( span) ,
2107
+ param_env,
2108
+ c. to_host_effect_clause ( tcx, ty:: HostPolarity :: Maybe ) ,
2109
+ )
2110
+ } ) ,
2111
+ ) ;
2112
+ }
2016
2113
debug ! ( "check_type_bounds: item_bounds={:?}" , obligations) ;
2017
2114
2018
2115
// Normalize predicates with the assumption that the GAT may always normalize
0 commit comments