@@ -76,7 +76,7 @@ fn check_method_is_structurally_compatible<'tcx>(
7676 Ok ( ( ) )
7777}
7878
79- /// This function is best explained by example. Consider a trait with it's implementation:
79+ /// This function is best explained by example. Consider a trait with its implementation:
8080///
8181/// ```rust
8282/// trait Trait<'t, T> {
@@ -120,7 +120,7 @@ fn check_method_is_structurally_compatible<'tcx>(
120120/// types:
121121///
122122/// ```rust,ignore (pseudo-Rust)
123- /// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
123+ /// <'b> fn(t: &'i0 U0, m: &'b N0 ) -> Foo
124124/// ```
125125///
126126/// We now want to extract and substitute the type of the *trait*
@@ -137,7 +137,7 @@ fn check_method_is_structurally_compatible<'tcx>(
137137/// Applying this to the trait method type yields:
138138///
139139/// ```rust,ignore (pseudo-Rust)
140- /// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
140+ /// <'a> fn(t: &'i0 U0, m: &'a N0 ) -> Foo
141141/// ```
142142///
143143/// This type is also the same but the name of the bound region (`'a`
@@ -262,8 +262,6 @@ fn compare_method_predicate_entailment<'tcx>(
262262 // type.
263263
264264 // Compute placeholder form of impl and trait method tys.
265- let tcx = infcx. tcx ;
266-
267265 let mut wf_tys = FxIndexSet :: default ( ) ;
268266
269267 let unnormalized_impl_sig = infcx. instantiate_binder_with_fresh_vars (
@@ -1669,19 +1667,19 @@ fn compare_synthetic_generics<'tcx>(
16691667/// ```rust,ignore (pseudo-Rust)
16701668/// trait Foo {
16711669/// fn foo<const N: u8>();
1672- /// type bar <const N: u8>;
1670+ /// type Bar <const N: u8>;
16731671/// fn baz<const N: u32>();
1674- /// type blah <T>;
1672+ /// type Blah <T>;
16751673/// }
16761674///
16771675/// impl Foo for () {
16781676/// fn foo<const N: u64>() {}
16791677/// //~^ error
1680- /// type bar <const N: u64> {}
1678+ /// type Bar <const N: u64> = ();
16811679/// //~^ error
16821680/// fn baz<T>() {}
16831681/// //~^ error
1684- /// type blah <const N: i64> = u32;
1682+ /// type Blah <const N: i64> = u32;
16851683/// //~^ error
16861684/// }
16871685/// ```
@@ -1770,35 +1768,52 @@ pub(super) fn compare_impl_const_raw(
17701768 let trait_const_item = tcx. associated_item ( trait_const_item_def) ;
17711769 let impl_trait_ref =
17721770 tcx. impl_trait_ref ( impl_const_item. container_id ( tcx) ) . unwrap ( ) . subst_identity ( ) ;
1773- debug ! ( "compare_const_impl(impl_trait_ref={:?})" , impl_trait_ref) ;
17741771
1775- let impl_c_span = tcx. def_span ( impl_const_item_def. to_def_id ( ) ) ;
1772+ debug ! ( "compare_impl_const(impl_trait_ref={:?})" , impl_trait_ref) ;
1773+
1774+ compare_number_of_generics ( tcx, impl_const_item, trait_const_item, false ) ?;
1775+ compare_generic_param_kinds ( tcx, impl_const_item, trait_const_item, false ) ?;
1776+ compare_const_predicate_entailment ( tcx, impl_const_item, trait_const_item, impl_trait_ref)
1777+ }
1778+
1779+ /// The equivalent of [compare_method_predicate_entailment], but for associated constants
1780+ /// instead of associated functions.
1781+ // FIXME(generic_consts): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
1782+ // FIXME(fmease): This can probably be simplified by a lot.
1783+ fn compare_const_predicate_entailment < ' tcx > (
1784+ tcx : TyCtxt < ' tcx > ,
1785+ impl_ct : ty:: AssocItem ,
1786+ trait_ct : ty:: AssocItem ,
1787+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
1788+ ) -> Result < ( ) , ErrorGuaranteed > {
1789+ let impl_ct_def_id = impl_ct. def_id . expect_local ( ) ;
1790+ let impl_ct_span = tcx. def_span ( impl_ct_def_id) ;
17761791
17771792 let infcx = tcx. infer_ctxt ( ) . build ( ) ;
1778- let param_env = tcx. param_env ( impl_const_item_def . to_def_id ( ) ) ;
1793+ let param_env = tcx. param_env ( impl_ct . def_id ) ;
17791794 let ocx = ObligationCtxt :: new ( & infcx) ;
17801795
17811796 // The below is for the most part highly similar to the procedure
17821797 // for methods above. It is simpler in many respects, especially
17831798 // because we shouldn't really have to deal with lifetimes or
17841799 // predicates. In fact some of this should probably be put into
17851800 // shared functions because of DRY violations...
1786- let trait_to_impl_substs = impl_trait_ref. substs ;
1801+ let impl_substs = InternalSubsts :: identity_for_item ( tcx, impl_ct. def_id ) ;
1802+ let trait_to_impl_substs =
1803+ impl_substs. rebase_onto ( tcx, impl_ct. container_id ( tcx) , impl_trait_ref. substs ) ;
17871804
17881805 // Create a parameter environment that represents the implementation's
17891806 // method.
17901807 // Compute placeholder form of impl and trait const tys.
1791- let impl_ty = tcx. type_of ( impl_const_item_def. to_def_id ( ) ) . subst_identity ( ) ;
1792- let trait_ty = tcx. type_of ( trait_const_item_def) . subst ( tcx, trait_to_impl_substs) ;
1793- let mut cause = ObligationCause :: new (
1794- impl_c_span,
1795- impl_const_item_def,
1796- ObligationCauseCode :: CompareImplItemObligation {
1797- impl_item_def_id : impl_const_item_def,
1798- trait_item_def_id : trait_const_item_def,
1799- kind : impl_const_item. kind ,
1800- } ,
1801- ) ;
1808+ let impl_ty = tcx. type_of ( impl_ct_def_id) . subst_identity ( ) ;
1809+
1810+ let trait_ty = tcx. type_of ( trait_ct. def_id ) . subst ( tcx, trait_to_impl_substs) ;
1811+ let code = ObligationCauseCode :: CompareImplItemObligation {
1812+ impl_item_def_id : impl_ct_def_id,
1813+ trait_item_def_id : trait_ct. def_id ,
1814+ kind : impl_ct. kind ,
1815+ } ;
1816+ let mut cause = ObligationCause :: new ( impl_ct_span, impl_ct_def_id, code. clone ( ) ) ;
18021817
18031818 // There is no "body" here, so just pass dummy id.
18041819 let impl_ty = ocx. normalize ( & cause, param_env, impl_ty) ;
@@ -1818,20 +1833,20 @@ pub(super) fn compare_impl_const_raw(
18181833 ) ;
18191834
18201835 // Locate the Span containing just the type of the offending impl
1821- let ( ty, _) = tcx. hir ( ) . expect_impl_item ( impl_const_item_def ) . expect_const ( ) ;
1836+ let ( ty, _) = tcx. hir ( ) . expect_impl_item ( impl_ct_def_id ) . expect_const ( ) ;
18221837 cause. span = ty. span ;
18231838
18241839 let mut diag = struct_span_err ! (
18251840 tcx. sess,
18261841 cause. span,
18271842 E0326 ,
18281843 "implemented const `{}` has an incompatible type for trait" ,
1829- trait_const_item . name
1844+ trait_ct . name
18301845 ) ;
18311846
1832- let trait_c_span = trait_const_item_def . as_local ( ) . map ( |trait_c_def_id | {
1847+ let trait_c_span = trait_ct . def_id . as_local ( ) . map ( |trait_ct_def_id | {
18331848 // Add a label to the Span containing just the type of the const
1834- let ( ty, _) = tcx. hir ( ) . expect_trait_item ( trait_c_def_id ) . expect_const ( ) ;
1849+ let ( ty, _) = tcx. hir ( ) . expect_trait_item ( trait_ct_def_id ) . expect_const ( ) ;
18351850 ty. span
18361851 } ) ;
18371852
@@ -1850,6 +1865,46 @@ pub(super) fn compare_impl_const_raw(
18501865 return Err ( diag. emit ( ) ) ;
18511866 } ;
18521867
1868+ let impl_ct_predicates = tcx. predicates_of ( impl_ct. def_id ) ;
1869+ let trait_ct_predicates = tcx. predicates_of ( trait_ct. def_id ) ;
1870+
1871+ // FIXME(generic_consts): Is this correct? We already have an ocx...
1872+ check_region_bounds_on_impl_item ( tcx, impl_ct, trait_ct, false ) ?;
1873+
1874+ // FIXME(generic_consts): It'd be nice if we added a fast-path if the own bounds are empty
1875+ // similar to cmp_impl_ty_pred_entail without intro'ing unsoundness.
1876+ let impl_ct_own_bounds = impl_ct_predicates. instantiate_own ( tcx, impl_substs) ;
1877+
1878+ // The predicates declared by the impl definition, the trait and the
1879+ // associated const in the trait are assumed.
1880+ let impl_predicates = tcx. predicates_of ( impl_ct_predicates. parent . unwrap ( ) ) ;
1881+ let mut hybrid_preds = impl_predicates. instantiate_identity ( tcx) ;
1882+ hybrid_preds. predicates . extend (
1883+ trait_ct_predicates
1884+ . instantiate_own ( tcx, trait_to_impl_substs)
1885+ . map ( |( predicate, _) | predicate) ,
1886+ ) ;
1887+
1888+ let hybrid_param_env = ty:: ParamEnv :: new (
1889+ tcx. mk_clauses ( & hybrid_preds. predicates ) ,
1890+ Reveal :: UserFacing ,
1891+ hir:: Constness :: Const ,
1892+ ) ;
1893+ let hybrid_param_env = traits:: normalize_param_env_or_error (
1894+ tcx,
1895+ hybrid_param_env,
1896+ ObligationCause :: misc ( impl_ct_span, impl_ct_def_id) ,
1897+ ) ;
1898+
1899+ // FIXME(generic_consts): Is this correct? We already have an ocx...
1900+ for ( predicate, span) in impl_ct_own_bounds {
1901+ let cause = ObligationCause :: misc ( span, impl_ct_def_id) ;
1902+ let predicate = ocx. normalize ( & cause, hybrid_param_env, predicate) ;
1903+
1904+ let cause = ObligationCause :: new ( span, impl_ct_def_id, code. clone ( ) ) ;
1905+ ocx. register_obligation ( traits:: Obligation :: new ( tcx, cause, hybrid_param_env, predicate) ) ;
1906+ }
1907+
18531908 // Check that all obligations are satisfied by the implementation's
18541909 // version.
18551910 let errors = ocx. select_all_or_error ( ) ;
@@ -1858,7 +1913,7 @@ pub(super) fn compare_impl_const_raw(
18581913 }
18591914
18601915 let outlives_env = OutlivesEnvironment :: new ( param_env) ;
1861- ocx. resolve_regions_and_report_errors ( impl_const_item_def , & outlives_env)
1916+ ocx. resolve_regions_and_report_errors ( impl_ct_def_id , & outlives_env)
18621917}
18631918
18641919pub ( super ) fn compare_impl_ty < ' tcx > (
@@ -1900,7 +1955,7 @@ fn compare_type_predicate_entailment<'tcx>(
19001955 return Ok ( ( ) ) ;
19011956 }
19021957
1903- // This `HirId ` should be used for the `body_id` field on each
1958+ // This `DefId ` should be used for the `body_id` field on each
19041959 // `ObligationCause` (and the `FnCtxt`). This is what
19051960 // `regionck_item` expects.
19061961 let impl_ty_def_id = impl_ty. def_id . expect_local ( ) ;
@@ -1919,7 +1974,7 @@ fn compare_type_predicate_entailment<'tcx>(
19191974 debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
19201975
19211976 let impl_ty_span = tcx. def_span ( impl_ty_def_id) ;
1922- let normalize_cause = traits :: ObligationCause :: misc ( impl_ty_span, impl_ty_def_id) ;
1977+ let normalize_cause = ObligationCause :: misc ( impl_ty_span, impl_ty_def_id) ;
19231978 let param_env = ty:: ParamEnv :: new (
19241979 tcx. mk_clauses ( & hybrid_preds. predicates ) ,
19251980 Reveal :: UserFacing ,
@@ -1968,7 +2023,7 @@ fn compare_type_predicate_entailment<'tcx>(
19682023///
19692024/// trait X { type Y: Copy } impl X for T { type Y = S; }
19702025///
1971- /// We are able to normalize `<T as X>::U ` to `S`, and so when we check the
2026+ /// We are able to normalize `<T as X>::Y ` to `S`, and so when we check the
19722027/// impl is well-formed we have to prove `S: Copy`.
19732028///
19742029/// For default associated types the normalization is not possible (the value
0 commit comments