@@ -15,14 +15,14 @@ use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError};
15
15
use rustc_hir as hir;
16
16
use rustc_hir:: def:: { CtorOf , DefKind , Namespace , Res } ;
17
17
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
18
- use rustc_hir:: intravisit:: { walk_generics, Visitor as _ } ;
18
+ use rustc_hir:: intravisit:: { self , walk_generics, Visitor } ;
19
19
use rustc_hir:: lang_items:: LangItem ;
20
20
use rustc_hir:: { Constness , GenericArg , GenericArgs } ;
21
21
use rustc_middle:: ty:: subst:: { self , InternalSubsts , Subst , SubstsRef } ;
22
22
use rustc_middle:: ty:: GenericParamDefKind ;
23
23
use rustc_middle:: ty:: { self , Const , DefIdTree , Ty , TyCtxt , TypeFoldable } ;
24
24
use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
25
- use rustc_span:: symbol:: { Ident , Symbol } ;
25
+ use rustc_span:: symbol:: { kw , Ident , Symbol } ;
26
26
use rustc_span:: { Span , DUMMY_SP } ;
27
27
use rustc_target:: spec:: abi;
28
28
use rustc_trait_selection:: traits;
@@ -285,8 +285,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
285
285
// region with the current anon region binding (in other words,
286
286
// whatever & would get replaced with).
287
287
debug ! (
288
- "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
289
- generic_args={:?})",
288
+ "create_substs_for_ast_path(def_id={:?}, self_ty={:?}, generic_args={:?})" ,
290
289
def_id, self_ty, generic_args
291
290
) ;
292
291
@@ -316,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
316
315
infer_args,
317
316
) ;
318
317
319
- let is_object = self_ty. map_or ( false , |ty| ty == self . tcx ( ) . types . trait_object_dummy_self ) ;
318
+ let is_object = self_ty. map_or ( false , |ty| ty == tcx. types . trait_object_dummy_self ) ;
320
319
let default_needs_object_self = |param : & ty:: GenericParamDef | {
321
320
if let GenericParamDefKind :: Type { has_default, .. } = param. kind {
322
321
if is_object && has_default {
@@ -356,14 +355,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
356
355
( GenericParamDefKind :: Lifetime , GenericArg :: Lifetime ( lt) ) => {
357
356
self . ast_region_to_region ( & lt, Some ( param) ) . into ( )
358
357
}
359
- ( GenericParamDefKind :: Type { .. } , GenericArg :: Type ( ty) ) => {
360
- if let ( hir:: TyKind :: Infer , false ) = ( & ty . kind , self . allow_ty_infer ( ) ) {
358
+ ( GenericParamDefKind :: Type { .. } , GenericArg :: Type ( ty) ) => match & ty . kind {
359
+ hir:: TyKind :: Infer if ! self . allow_ty_infer ( ) => {
361
360
inferred_params. push ( ty. span ) ;
362
361
tcx. ty_error ( ) . into ( )
363
- } else {
364
- self . ast_ty_to_ty ( & ty) . into ( )
365
362
}
366
- }
363
+ hir:: TyKind :: Path ( hir:: QPath :: TypeRelative (
364
+ hir:: Ty {
365
+ kind :
366
+ hir:: TyKind :: Path (
367
+ hir:: QPath :: Resolved (
368
+ None ,
369
+ hir:: Path { res : res @ Res :: SelfTy ( Some ( _) , None ) , .. } ,
370
+ ) ,
371
+ ..,
372
+ ) ,
373
+ ..
374
+ } ,
375
+ segment,
376
+ ) ) if Some ( tcx. types . self_param ) == self_ty => {
377
+ // Handle `trait A: B<Self::C> { type C; }` to avoid cycle error.
378
+ // See `super_predicates_of_skip_self_param` for more information.
379
+ self . associated_path_to_ty (
380
+ ty. hir_id ,
381
+ ty. span ,
382
+ tcx. types . self_param ,
383
+ * res,
384
+ segment,
385
+ false ,
386
+ true ,
387
+ )
388
+ . map ( |( ty, _, _) | ty)
389
+ . unwrap_or_else ( |_| tcx. ty_error ( ) )
390
+ . into ( )
391
+ }
392
+ _ => self . ast_ty_to_ty ( & ty) . into ( ) ,
393
+ } ,
367
394
( GenericParamDefKind :: Const , GenericArg :: Const ( ct) ) => {
368
395
ty:: Const :: from_opt_const_arg_anon_const (
369
396
tcx,
@@ -527,7 +554,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
527
554
) -> GenericArgCountResult {
528
555
let trait_def_id = trait_ref. trait_def_id ( ) . unwrap_or_else ( || FatalError . raise ( ) ) ;
529
556
530
- debug ! ( "instantiate_poly_trait_ref({:?}, def_id={:?})" , trait_ref, trait_def_id) ;
557
+ debug ! (
558
+ "instantiate_poly_trait_ref({:?}, def_id={:?}, self_ty={:?})" ,
559
+ trait_ref, trait_def_id, self_ty
560
+ ) ;
531
561
532
562
self . prohibit_generics ( trait_ref. path . segments . split_last ( ) . unwrap ( ) . 1 ) ;
533
563
@@ -704,9 +734,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
704
734
if tpb. path . res != Res :: Def ( DefKind :: Trait , kind_id) {
705
735
tcx. sess . span_warn (
706
736
span,
707
- "default bound relaxed for a type parameter, but \
708
- this does nothing because the given bound is not \
709
- a default; only `?Sized` is supported",
737
+ "default bound relaxed for a type parameter, but this does nothing \
738
+ because the given bound is not a default; only `?Sized` is supported",
710
739
) ;
711
740
}
712
741
}
@@ -741,15 +770,61 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
741
770
param_ty : Ty < ' tcx > ,
742
771
ast_bounds : & [ hir:: GenericBound < ' _ > ] ,
743
772
bounds : & mut Bounds < ' tcx > ,
773
+ skip_self_param_evaluation : bool ,
744
774
) {
745
775
let mut trait_bounds = Vec :: new ( ) ;
746
776
let mut region_bounds = Vec :: new ( ) ;
747
777
778
+ /// Walk each bound to see if they reference an associated type of `Self` without
779
+ /// specifying a trait (using a Resolved path `Self::Foo` instead of fully qualified path
780
+ /// `<Self as Bar>::Foo`) and if so, skip them if `skip_self_param_evaluation` is `true`.
781
+ /// This way, we avoid cycle errors and are able to resolve the associated type
782
+ /// successfully.
783
+ struct SelfFinder ( bool ) ;
784
+
785
+ impl < ' v > Visitor < ' v > for SelfFinder {
786
+ type Map = intravisit:: ErasedMap < ' v > ;
787
+
788
+ fn nested_visit_map ( & mut self ) -> intravisit:: NestedVisitorMap < Self :: Map > {
789
+ intravisit:: NestedVisitorMap :: None
790
+ }
791
+
792
+ fn visit_ty ( & mut self , t : & ' v hir:: Ty < ' v > ) {
793
+ if let hir:: TyKind :: Path ( hir:: QPath :: TypeRelative (
794
+ hir:: Ty {
795
+ kind :
796
+ hir:: TyKind :: Path (
797
+ hir:: QPath :: Resolved (
798
+ None ,
799
+ hir:: Path { res : Res :: SelfTy ( Some ( _) , None ) , .. } ,
800
+ ) ,
801
+ ..,
802
+ ) ,
803
+ ..
804
+ } ,
805
+ _,
806
+ ) ) = t. kind
807
+ {
808
+ self . 0 = true ;
809
+ }
810
+ intravisit:: walk_ty ( self , t)
811
+ }
812
+ }
813
+
748
814
let constness = self . default_constness_for_trait_bounds ( ) ;
749
815
for ast_bound in ast_bounds {
750
816
match * ast_bound {
751
- hir:: GenericBound :: Trait ( ref b, hir:: TraitBoundModifier :: None ) => {
752
- trait_bounds. push ( ( b, constness) )
817
+ hir:: GenericBound :: Trait ( ref b, modif @ hir:: TraitBoundModifier :: None ) => {
818
+ let mut visitor = SelfFinder ( false ) ;
819
+ visitor. visit_poly_trait_ref ( b, modif) ;
820
+
821
+ let is_self_param = match param_ty. kind {
822
+ ty:: Param ( param) if param. name == kw:: SelfUpper => true ,
823
+ _ => false ,
824
+ } ;
825
+ if !( visitor. 0 && skip_self_param_evaluation && is_self_param) {
826
+ trait_bounds. push ( ( b, constness) )
827
+ }
753
828
}
754
829
hir:: GenericBound :: Trait ( ref b, hir:: TraitBoundModifier :: MaybeConst ) => {
755
830
trait_bounds. push ( ( b, Constness :: NotConst ) )
@@ -794,10 +869,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
794
869
ast_bounds : & [ hir:: GenericBound < ' _ > ] ,
795
870
sized_by_default : SizedByDefault ,
796
871
span : Span ,
872
+ skip_self_param_evaluation : bool ,
797
873
) -> Bounds < ' tcx > {
798
874
let mut bounds = Bounds :: default ( ) ;
799
875
800
- self . add_bounds ( param_ty, ast_bounds, & mut bounds) ;
876
+ self . add_bounds ( param_ty, ast_bounds, & mut bounds, skip_self_param_evaluation ) ;
801
877
bounds. trait_bounds . sort_by_key ( |( t, _, _) | t. def_id ( ) ) ;
802
878
803
879
bounds. implicitly_sized = if let SizedByDefault :: Yes = sized_by_default {
@@ -969,7 +1045,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
969
1045
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
970
1046
// parameter to have a skipped binder.
971
1047
let param_ty = tcx. mk_projection ( assoc_ty. def_id , candidate. skip_binder ( ) . substs ) ;
972
- self . add_bounds ( param_ty, ast_bounds, bounds) ;
1048
+ self . add_bounds ( param_ty, ast_bounds, bounds, false ) ;
973
1049
}
974
1050
}
975
1051
Ok ( ( ) )
@@ -996,7 +1072,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
996
1072
997
1073
let mut bounds = Bounds :: default ( ) ;
998
1074
let mut potential_assoc_types = Vec :: new ( ) ;
999
- let dummy_self = self . tcx ( ) . types . trait_object_dummy_self ;
1075
+ let dummy_self = tcx. types . trait_object_dummy_self ;
1000
1076
for trait_bound in trait_bounds. iter ( ) . rev ( ) {
1001
1077
if let GenericArgCountResult {
1002
1078
correct :
@@ -1274,15 +1350,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1274
1350
err. emit ( ) ;
1275
1351
}
1276
1352
1277
- // Search for a bound on a type parameter which includes the associated item
1278
- // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
1279
- // This function will fail if there are no suitable bounds or there is
1280
- // any ambiguity.
1353
+ /// Search for a bound on a type parameter which includes the associated item
1354
+ /// given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter
1355
+ /// This function will fail if there are no suitable bounds or there is
1356
+ /// any ambiguity.
1357
+ ///
1358
+ /// See `super_predicates_of_skip_self_param` for the behavior when `skip_self_param_evaluation`
1359
+ /// is `true`.
1281
1360
fn find_bound_for_assoc_item (
1282
1361
& self ,
1283
1362
ty_param_def_id : LocalDefId ,
1284
1363
assoc_name : Ident ,
1285
1364
span : Span ,
1365
+ skip_self_param_evaluation : bool ,
1286
1366
) -> Result < ty:: PolyTraitRef < ' tcx > , ErrorReported > {
1287
1367
let tcx = self . tcx ( ) ;
1288
1368
@@ -1300,9 +1380,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1300
1380
let param_name = tcx. hir ( ) . ty_param_name ( param_hir_id) ;
1301
1381
self . one_bound_for_assoc_type (
1302
1382
|| {
1303
- traits:: transitive_bounds (
1383
+ traits:: supertraits_maybe_skip_self_param_users (
1304
1384
tcx,
1305
1385
predicates. iter ( ) . filter_map ( |( p, _) | p. to_opt_poly_trait_ref ( ) ) ,
1386
+ skip_self_param_evaluation,
1306
1387
)
1307
1388
} ,
1308
1389
|| param_name. to_string ( ) ,
@@ -1432,12 +1513,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1432
1513
Ok ( bound)
1433
1514
}
1434
1515
1435
- // Create a type from a path to an associated type.
1436
- // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
1437
- // and item_segment is the path segment for `D`. We return a type and a def for
1438
- // the whole path.
1439
- // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
1440
- // parameter or `Self`.
1516
+ /// Create a type from a path to an associated type.
1517
+ /// For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
1518
+ /// and `item_segment` is the path segment for `D`. We return a type and a def for
1519
+ /// the whole path.
1520
+ /// Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
1521
+ /// parameter or `Self`.
1522
+ ///
1523
+ /// When `dont_recurse` is `true`, and we are evaluation a path rooted in `Self`, we will skip
1524
+ /// super-traits that reference `Self` to avoid cycle errors. See
1525
+ /// `super_predicates_of_skip_self_param` for more information.
1441
1526
pub fn associated_path_to_ty (
1442
1527
& self ,
1443
1528
hir_ref_id : hir:: HirId ,
@@ -1446,6 +1531,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1446
1531
qself_res : Res ,
1447
1532
assoc_segment : & hir:: PathSegment < ' _ > ,
1448
1533
permit_variants : bool ,
1534
+ dont_recurse : bool ,
1449
1535
) -> Result < ( Ty < ' tcx > , DefKind , DefId ) , ErrorReported > {
1450
1536
let tcx = self . tcx ( ) ;
1451
1537
let assoc_ident = assoc_segment. ident ;
@@ -1494,10 +1580,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1494
1580
|| None ,
1495
1581
) ?
1496
1582
}
1497
- (
1498
- & ty:: Param ( _) ,
1499
- Res :: SelfTy ( Some ( param_did) , None ) | Res :: Def ( DefKind :: TyParam , param_did) ,
1500
- ) => self . find_bound_for_assoc_item ( param_did. expect_local ( ) , assoc_ident, span) ?,
1583
+ ( & ty:: Param ( _) , Res :: SelfTy ( Some ( param_did) , None ) ) => self . find_bound_for_assoc_item (
1584
+ param_did. expect_local ( ) ,
1585
+ assoc_ident,
1586
+ span,
1587
+ dont_recurse,
1588
+ ) ?,
1589
+ ( & ty:: Param ( _) , Res :: Def ( DefKind :: TyParam , param_did) ) => {
1590
+ self . find_bound_for_assoc_item ( param_did. expect_local ( ) , assoc_ident, span, false ) ?
1591
+ }
1501
1592
_ => {
1502
1593
if variant_resolution. is_some ( ) {
1503
1594
// Variant in type position
@@ -2036,9 +2127,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2036
2127
} else {
2037
2128
Res :: Err
2038
2129
} ;
2039
- self . associated_path_to_ty ( ast_ty. hir_id , ast_ty. span , ty, res, segment, false )
2040
- . map ( |( ty, _, _) | ty)
2041
- . unwrap_or_else ( |_| tcx. ty_error ( ) )
2130
+ self . associated_path_to_ty (
2131
+ ast_ty. hir_id ,
2132
+ ast_ty. span ,
2133
+ ty,
2134
+ res,
2135
+ segment,
2136
+ false ,
2137
+ false ,
2138
+ )
2139
+ . map ( |( ty, _, _) | ty)
2140
+ . unwrap_or_else ( |_| tcx. ty_error ( ) )
2042
2141
}
2043
2142
hir:: TyKind :: Path ( hir:: QPath :: LangItem ( lang_item, span) ) => {
2044
2143
let def_id = tcx. require_lang_item ( lang_item, Some ( span) ) ;
0 commit comments