@@ -187,48 +187,61 @@ 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, _) | trait_ref. to_host_effect ( tcx, ty:: HostPolarity :: Maybe ) ) ,
226
+ ) ;
227
+ }
228
+
220
229
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
221
230
// The key step here is to update the caller_bounds's predicates to be
222
231
// the new hybrid bounds we computed.
223
232
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 ) ;
225
234
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
226
235
227
236
let infcx = & tcx. infer_ctxt ( ) . build ( ) ;
228
237
let ocx = ObligationCtxt :: new_with_diagnostics ( infcx) ;
229
238
230
239
debug ! ( "compare_impl_method: caller_bounds={:?}" , param_env. caller_bounds( ) ) ;
231
240
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).
232
245
let impl_m_own_bounds = impl_m_predicates. instantiate_own ( tcx, impl_to_placeholder_args) ;
233
246
for ( predicate, span) in impl_m_own_bounds {
234
247
let normalize_cause = traits:: ObligationCause :: misc ( span, impl_m_def_id) ;
@@ -243,6 +256,34 @@ fn compare_method_predicate_entailment<'tcx>(
243
256
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
244
257
}
245
258
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
+
246
287
// We now need to check that the signature of the impl method is
247
288
// compatible with that of the trait method. We do this by
248
289
// checking that `impl_fty <: trait_fty`.
@@ -1759,14 +1800,14 @@ fn compare_const_predicate_entailment<'tcx>(
1759
1800
// The predicates declared by the impl definition, the trait and the
1760
1801
// associated const in the trait are assumed.
1761
1802
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 (
1764
1805
trait_ct_predicates
1765
1806
. instantiate_own ( tcx, trait_to_impl_args)
1766
1807
. map ( |( predicate, _) | predicate) ,
1767
1808
) ;
1768
1809
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 ) ;
1770
1811
let param_env = traits:: normalize_param_env_or_error (
1771
1812
tcx,
1772
1813
param_env,
@@ -1871,14 +1912,16 @@ fn compare_type_predicate_entailment<'tcx>(
1871
1912
impl_trait_ref : ty:: TraitRef < ' tcx > ,
1872
1913
) -> Result < ( ) , ErrorGuaranteed > {
1873
1914
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 ) ;
1876
1917
1877
1918
let impl_ty_predicates = tcx. predicates_of ( impl_ty. def_id ) ;
1878
1919
let trait_ty_predicates = tcx. predicates_of ( trait_ty. def_id ) ;
1879
1920
1880
1921
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 {
1882
1925
// Nothing to check.
1883
1926
return Ok ( ( ) ) ;
1884
1927
}
@@ -1892,18 +1935,31 @@ fn compare_type_predicate_entailment<'tcx>(
1892
1935
// The predicates declared by the impl definition, the trait and the
1893
1936
// associated type in the trait are assumed.
1894
1937
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 (
1897
1940
trait_ty_predicates
1898
1941
. instantiate_own ( tcx, trait_to_impl_args)
1899
1942
. map ( |( predicate, _) | predicate) ,
1900
1943
) ;
1901
1944
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
+
1902
1958
debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
1903
1959
1904
1960
let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
1905
1961
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 ) ;
1907
1963
let param_env = traits:: normalize_param_env_or_error ( tcx, param_env, normalize_cause) ;
1908
1964
let infcx = tcx. infer_ctxt ( ) . build ( ) ;
1909
1965
let ocx = ObligationCtxt :: new_with_diagnostics ( & infcx) ;
@@ -1923,6 +1979,27 @@ fn compare_type_predicate_entailment<'tcx>(
1923
1979
ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, param_env, predicate) ) ;
1924
1980
}
1925
1981
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
+
1926
2003
// Check that all obligations are satisfied by the implementation's
1927
2004
// version.
1928
2005
let errors = ocx. select_all_or_error ( ) ;
@@ -2005,14 +2082,30 @@ pub(super) fn check_type_bounds<'tcx>(
2005
2082
ObligationCause :: new ( impl_ty_span, impl_ty_def_id, code)
2006
2083
} ;
2007
2084
2008
- let obligations: Vec < _ > = tcx
2085
+ let mut obligations: Vec < _ > = tcx
2009
2086
. explicit_item_bounds ( trait_ty. def_id )
2010
2087
. iter_instantiated_copied ( tcx, rebased_args)
2011
2088
. map ( |( concrete_ty_bound, span) | {
2012
2089
debug ! ( "check_type_bounds: concrete_ty_bound = {:?}" , concrete_ty_bound) ;
2013
2090
traits:: Obligation :: new ( tcx, mk_cause ( span) , param_env, concrete_ty_bound)
2014
2091
} )
2015
2092
. 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
+ }
2016
2109
debug ! ( "check_type_bounds: item_bounds={:?}" , obligations) ;
2017
2110
2018
2111
// Normalize predicates with the assumption that the GAT may always normalize
0 commit comments