@@ -76,7 +76,7 @@ fn check_method_is_structurally_compatible<'tcx>(
76
76
Ok ( ( ) )
77
77
}
78
78
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:
80
80
///
81
81
/// ```rust
82
82
/// trait Trait<'t, T> {
@@ -120,7 +120,7 @@ fn check_method_is_structurally_compatible<'tcx>(
120
120
/// types:
121
121
///
122
122
/// ```rust,ignore (pseudo-Rust)
123
- /// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
123
+ /// <'b> fn(t: &'i0 U0, m: &'b N0 ) -> Foo
124
124
/// ```
125
125
///
126
126
/// We now want to extract and substitute the type of the *trait*
@@ -137,7 +137,7 @@ fn check_method_is_structurally_compatible<'tcx>(
137
137
/// Applying this to the trait method type yields:
138
138
///
139
139
/// ```rust,ignore (pseudo-Rust)
140
- /// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
140
+ /// <'a> fn(t: &'i0 U0, m: &'a N0 ) -> Foo
141
141
/// ```
142
142
///
143
143
/// This type is also the same but the name of the bound region (`'a`
@@ -262,8 +262,6 @@ fn compare_method_predicate_entailment<'tcx>(
262
262
// type.
263
263
264
264
// Compute placeholder form of impl and trait method tys.
265
- let tcx = infcx. tcx ;
266
-
267
265
let mut wf_tys = FxIndexSet :: default ( ) ;
268
266
269
267
let unnormalized_impl_sig = infcx. instantiate_binder_with_fresh_vars (
@@ -1669,19 +1667,19 @@ fn compare_synthetic_generics<'tcx>(
1669
1667
/// ```rust,ignore (pseudo-Rust)
1670
1668
/// trait Foo {
1671
1669
/// fn foo<const N: u8>();
1672
- /// type bar <const N: u8>;
1670
+ /// type Bar <const N: u8>;
1673
1671
/// fn baz<const N: u32>();
1674
- /// type blah <T>;
1672
+ /// type Blah <T>;
1675
1673
/// }
1676
1674
///
1677
1675
/// impl Foo for () {
1678
1676
/// fn foo<const N: u64>() {}
1679
1677
/// //~^ error
1680
- /// type bar <const N: u64> {}
1678
+ /// type Bar <const N: u64> = ();
1681
1679
/// //~^ error
1682
1680
/// fn baz<T>() {}
1683
1681
/// //~^ error
1684
- /// type blah <const N: i64> = u32;
1682
+ /// type Blah <const N: i64> = u32;
1685
1683
/// //~^ error
1686
1684
/// }
1687
1685
/// ```
@@ -1770,35 +1768,52 @@ pub(super) fn compare_impl_const_raw(
1770
1768
let trait_const_item = tcx. associated_item ( trait_const_item_def) ;
1771
1769
let impl_trait_ref =
1772
1770
tcx. impl_trait_ref ( impl_const_item. container_id ( tcx) ) . unwrap ( ) . subst_identity ( ) ;
1773
- debug ! ( "compare_const_impl(impl_trait_ref={:?})" , impl_trait_ref) ;
1774
1771
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) ;
1776
1791
1777
1792
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 ) ;
1779
1794
let ocx = ObligationCtxt :: new ( & infcx) ;
1780
1795
1781
1796
// The below is for the most part highly similar to the procedure
1782
1797
// for methods above. It is simpler in many respects, especially
1783
1798
// because we shouldn't really have to deal with lifetimes or
1784
1799
// predicates. In fact some of this should probably be put into
1785
1800
// 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 ) ;
1787
1804
1788
1805
// Create a parameter environment that represents the implementation's
1789
1806
// method.
1790
1807
// 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 ( ) ) ;
1802
1817
1803
1818
// There is no "body" here, so just pass dummy id.
1804
1819
let impl_ty = ocx. normalize ( & cause, param_env, impl_ty) ;
@@ -1818,20 +1833,20 @@ pub(super) fn compare_impl_const_raw(
1818
1833
) ;
1819
1834
1820
1835
// 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 ( ) ;
1822
1837
cause. span = ty. span ;
1823
1838
1824
1839
let mut diag = struct_span_err ! (
1825
1840
tcx. sess,
1826
1841
cause. span,
1827
1842
E0326 ,
1828
1843
"implemented const `{}` has an incompatible type for trait" ,
1829
- trait_const_item . name
1844
+ trait_ct . name
1830
1845
) ;
1831
1846
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 | {
1833
1848
// 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 ( ) ;
1835
1850
ty. span
1836
1851
} ) ;
1837
1852
@@ -1850,6 +1865,46 @@ pub(super) fn compare_impl_const_raw(
1850
1865
return Err ( diag. emit ( ) ) ;
1851
1866
} ;
1852
1867
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
+
1853
1908
// Check that all obligations are satisfied by the implementation's
1854
1909
// version.
1855
1910
let errors = ocx. select_all_or_error ( ) ;
@@ -1858,7 +1913,7 @@ pub(super) fn compare_impl_const_raw(
1858
1913
}
1859
1914
1860
1915
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)
1862
1917
}
1863
1918
1864
1919
pub ( super ) fn compare_impl_ty < ' tcx > (
@@ -1900,7 +1955,7 @@ fn compare_type_predicate_entailment<'tcx>(
1900
1955
return Ok ( ( ) ) ;
1901
1956
}
1902
1957
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
1904
1959
// `ObligationCause` (and the `FnCtxt`). This is what
1905
1960
// `regionck_item` expects.
1906
1961
let impl_ty_def_id = impl_ty. def_id . expect_local ( ) ;
@@ -1919,7 +1974,7 @@ fn compare_type_predicate_entailment<'tcx>(
1919
1974
debug ! ( "compare_type_predicate_entailment: bounds={:?}" , hybrid_preds) ;
1920
1975
1921
1976
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) ;
1923
1978
let param_env = ty:: ParamEnv :: new (
1924
1979
tcx. mk_clauses ( & hybrid_preds. predicates ) ,
1925
1980
Reveal :: UserFacing ,
@@ -1968,7 +2023,7 @@ fn compare_type_predicate_entailment<'tcx>(
1968
2023
///
1969
2024
/// trait X { type Y: Copy } impl X for T { type Y = S; }
1970
2025
///
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
1972
2027
/// impl is well-formed we have to prove `S: Copy`.
1973
2028
///
1974
2029
/// For default associated types the normalization is not possible (the value
0 commit comments