@@ -6,7 +6,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
6
6
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
7
7
use rustc_middle:: ty:: { TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
8
8
use rustc_span:: Span ;
9
- use rustc_type_ir :: AliasKind ;
9
+ use rustc_trait_selection :: traits :: check_substs_compatible ;
10
10
use std:: ops:: ControlFlow ;
11
11
12
12
use crate :: errors:: { DuplicateArg , NotParam } ;
@@ -36,6 +36,15 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
36
36
self . tcx . def_span ( self . item )
37
37
}
38
38
39
+ fn parent_trait_ref ( & self ) -> Option < ty:: TraitRef < ' tcx > > {
40
+ let parent = self . parent ( ) ?;
41
+ if matches ! ( self . tcx. def_kind( parent) , DefKind :: Impl { .. } ) {
42
+ Some ( self . tcx . impl_trait_ref ( parent) ?. subst_identity ( ) )
43
+ } else {
44
+ None
45
+ }
46
+ }
47
+
39
48
fn parent ( & self ) -> Option < LocalDefId > {
40
49
match self . tcx . def_kind ( self . item ) {
41
50
DefKind :: Fn => None ,
@@ -56,7 +65,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
56
65
#[ instrument( skip( self ) , ret, level = "trace" ) ]
57
66
fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < ErrorGuaranteed > {
58
67
match t. kind ( ) {
59
- ty:: Alias ( AliasKind :: Opaque , alias_ty) if alias_ty. def_id . is_local ( ) => {
68
+ ty:: Alias ( ty :: Opaque , alias_ty) if alias_ty. def_id . is_local ( ) => {
60
69
if !self . seen . insert ( alias_ty. def_id . expect_local ( ) ) {
61
70
return ControlFlow :: Continue ( ( ) ) ;
62
71
}
@@ -98,37 +107,48 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
98
107
}
99
108
}
100
109
}
101
- ty:: Alias ( AliasKind :: Projection , alias_ty) => {
102
- if let Some ( parent) = self . parent ( ) {
103
- trace ! ( ?alias_ty) ;
104
- let ( trait_ref, own_substs) = alias_ty. trait_ref_and_own_substs ( self . tcx ) ;
105
-
106
- trace ! ( ?trait_ref, ?own_substs) ;
107
- // This avoids having to do normalization of `Self::AssocTy` by only
108
- // supporting the case of a method defining opaque types from assoc types
109
- // in the same impl block.
110
- if trait_ref. self_ty ( ) == self . tcx . type_of ( parent) . subst_identity ( ) {
111
- for assoc in self . tcx . associated_items ( parent) . in_definition_order ( ) {
110
+ ty:: Alias ( ty:: Projection , alias_ty) => {
111
+ // This avoids having to do normalization of `Self::AssocTy` by only
112
+ // supporting the case of a method defining opaque types from assoc types
113
+ // in the same impl block.
114
+ if let Some ( parent_trait_ref) = self . parent_trait_ref ( ) {
115
+ // If the trait ref of the associated item and the impl differs,
116
+ // then we can't use the impl's identity substitutions below, so
117
+ // just skip.
118
+ if alias_ty. trait_ref ( self . tcx ) == parent_trait_ref {
119
+ let parent = self . parent ( ) . expect ( "we should have a parent here" ) ;
120
+
121
+ for & assoc in self . tcx . associated_items ( parent) . in_definition_order ( ) {
112
122
trace ! ( ?assoc) ;
113
- if assoc. trait_item_def_id == Some ( alias_ty. def_id ) {
114
- // We reconstruct the generic args of the associated type within the impl
115
- // from the impl's generics and the generic args passed to the type via the
116
- // projection.
117
- let substs = ty:: InternalSubsts :: identity_for_item (
118
- self . tcx ,
119
- parent. to_def_id ( ) ,
123
+ if assoc. trait_item_def_id != Some ( alias_ty. def_id ) {
124
+ continue ;
125
+ }
126
+
127
+ // If the type is further specializable, then the type_of
128
+ // is not actually correct below.
129
+ if !assoc. defaultness ( self . tcx ) . is_final ( ) {
130
+ continue ;
131
+ }
132
+
133
+ let impl_substs = alias_ty. substs . rebase_onto (
134
+ self . tcx ,
135
+ parent_trait_ref. def_id ,
136
+ ty:: InternalSubsts :: identity_for_item ( self . tcx , parent) ,
137
+ ) ;
138
+
139
+ if !check_substs_compatible ( self . tcx , assoc, impl_substs) {
140
+ self . tcx . sess . delay_span_bug (
141
+ self . tcx . def_span ( assoc. def_id ) ,
142
+ "item had incorrect substs" ,
120
143
) ;
121
- trace ! ( ?substs) ;
122
- let substs: Vec < _ > =
123
- substs. iter ( ) . chain ( own_substs. iter ( ) . copied ( ) ) . collect ( ) ;
124
- trace ! ( ?substs) ;
125
- // Find opaque types in this associated type.
126
- return self
127
- . tcx
128
- . type_of ( assoc. def_id )
129
- . subst ( self . tcx , & substs)
130
- . visit_with ( self ) ;
144
+ return ControlFlow :: Continue ( ( ) ) ;
131
145
}
146
+
147
+ return self
148
+ . tcx
149
+ . type_of ( assoc. def_id )
150
+ . subst ( self . tcx , impl_substs)
151
+ . visit_with ( self ) ;
132
152
}
133
153
}
134
154
}
0 commit comments