@@ -18,13 +18,14 @@ use hir_def::{
18
18
generics:: { TypeParamProvenance , WherePredicate , WherePredicateTypeTarget } ,
19
19
path:: { GenericArg , Path , PathSegment , PathSegments } ,
20
20
resolver:: { HasResolver , Resolver , TypeNs } ,
21
- type_ref:: { TraitRef as HirTraitRef , TypeBound , TypeRef } ,
21
+ type_ref:: { TraitBoundModifier , TraitRef as HirTraitRef , TypeBound , TypeRef } ,
22
22
AdtId , AssocContainerId , AssocItemId , ConstId , ConstParamId , EnumId , EnumVariantId , FunctionId ,
23
23
GenericDefId , HasModule , ImplId , LocalFieldId , Lookup , StaticId , StructId , TraitId ,
24
24
TypeAliasId , TypeParamId , UnionId , VariantId ,
25
25
} ;
26
26
use hir_expand:: { name:: Name , ExpandResult } ;
27
27
use la_arena:: ArenaMap ;
28
+ use rustc_hash:: FxHashSet ;
28
29
use smallvec:: SmallVec ;
29
30
use stdx:: impl_from;
30
31
use syntax:: ast;
@@ -65,6 +66,8 @@ pub struct TyLoweringContext<'a> {
65
66
/// Splitting this up would be a possible fix.
66
67
opaque_type_data : RefCell < Vec < ReturnTypeImplTrait > > ,
67
68
expander : RefCell < Option < Expander > > ,
69
+ /// Keeps tracking types with explicit `?Sized` bounds.
70
+ unsized_types : RefCell < FxHashSet < Ty > > ,
68
71
}
69
72
70
73
impl < ' a > TyLoweringContext < ' a > {
@@ -83,6 +86,7 @@ impl<'a> TyLoweringContext<'a> {
83
86
type_param_mode,
84
87
opaque_type_data,
85
88
expander : RefCell :: new ( None ) ,
89
+ unsized_types : RefCell :: default ( ) ,
86
90
}
87
91
}
88
92
@@ -93,17 +97,20 @@ impl<'a> TyLoweringContext<'a> {
93
97
) -> T {
94
98
let opaque_ty_data_vec = self . opaque_type_data . replace ( Vec :: new ( ) ) ;
95
99
let expander = self . expander . replace ( None ) ;
100
+ let unsized_types = self . unsized_types . replace ( Default :: default ( ) ) ;
96
101
let new_ctx = Self {
97
102
in_binders : debruijn,
98
103
impl_trait_counter : Cell :: new ( self . impl_trait_counter . get ( ) ) ,
99
104
opaque_type_data : RefCell :: new ( opaque_ty_data_vec) ,
100
105
expander : RefCell :: new ( expander) ,
106
+ unsized_types : RefCell :: new ( unsized_types) ,
101
107
..* self
102
108
} ;
103
109
let result = f ( & new_ctx) ;
104
110
self . impl_trait_counter . set ( new_ctx. impl_trait_counter . get ( ) ) ;
105
111
self . opaque_type_data . replace ( new_ctx. opaque_type_data . into_inner ( ) ) ;
106
112
self . expander . replace ( new_ctx. expander . into_inner ( ) ) ;
113
+ self . unsized_types . replace ( new_ctx. unsized_types . into_inner ( ) ) ;
107
114
result
108
115
}
109
116
@@ -778,10 +785,27 @@ impl<'a> TyLoweringContext<'a> {
778
785
) -> impl Iterator < Item = QuantifiedWhereClause > + ' a {
779
786
let mut bindings = None ;
780
787
let trait_ref = match bound {
781
- TypeBound :: Path ( path) => {
788
+ TypeBound :: Path ( path, TraitBoundModifier :: None ) => {
782
789
bindings = self . lower_trait_ref_from_path ( path, Some ( self_ty) ) ;
783
790
bindings. clone ( ) . map ( WhereClause :: Implemented ) . map ( crate :: wrap_empty_binders)
784
791
}
792
+ TypeBound :: Path ( path, TraitBoundModifier :: Maybe ) => {
793
+ let sized_trait = self
794
+ . resolver
795
+ . krate ( )
796
+ . and_then ( |krate| self . db . lang_item ( krate, "sized" . into ( ) ) )
797
+ . and_then ( |lang_item| lang_item. as_trait ( ) ) ;
798
+ // Don't lower associated type bindings as the only possible relaxed trait bound
799
+ // `?Sized` has none of them.
800
+ // If we got another trait here ignore the bound completely.
801
+ let trait_id = self
802
+ . lower_trait_ref_from_path ( path, Some ( self_ty. clone ( ) ) )
803
+ . map ( |trait_ref| trait_ref. hir_trait_id ( ) ) ;
804
+ if trait_id == sized_trait {
805
+ self . unsized_types . borrow_mut ( ) . insert ( self_ty) ;
806
+ }
807
+ None
808
+ }
785
809
TypeBound :: ForLifetime ( _, path) => {
786
810
// FIXME Don't silently drop the hrtb lifetimes here
787
811
bindings = self . lower_trait_ref_from_path ( path, Some ( self_ty) ) ;
@@ -804,8 +828,10 @@ impl<'a> TyLoweringContext<'a> {
804
828
trait_ref : TraitRef ,
805
829
) -> impl Iterator < Item = QuantifiedWhereClause > + ' a {
806
830
let last_segment = match bound {
807
- TypeBound :: Path ( path) | TypeBound :: ForLifetime ( _, path) => path. segments ( ) . last ( ) ,
808
- TypeBound :: Error | TypeBound :: Lifetime ( _) => None ,
831
+ TypeBound :: Path ( path, TraitBoundModifier :: None ) | TypeBound :: ForLifetime ( _, path) => path. segments ( ) . last ( ) ,
832
+ TypeBound :: Path ( _, TraitBoundModifier :: Maybe )
833
+ | TypeBound :: Error
834
+ | TypeBound :: Lifetime ( _) => None ,
809
835
} ;
810
836
last_segment
811
837
. into_iter ( )
@@ -1053,10 +1079,40 @@ pub(crate) fn generic_predicates_query(
1053
1079
let ctx =
1054
1080
TyLoweringContext :: new ( db, & resolver) . with_type_param_mode ( TypeParamLoweringMode :: Variable ) ;
1055
1081
let generics = generics ( db. upcast ( ) , def) ;
1056
- resolver
1082
+
1083
+ let mut predicates = resolver
1057
1084
. where_predicates_in_scope ( )
1058
1085
. flat_map ( |pred| ctx. lower_where_predicate ( pred, false ) . map ( |p| make_binders ( & generics, p) ) )
1059
- . collect ( )
1086
+ . collect :: < Vec < _ > > ( ) ;
1087
+
1088
+ // Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
1089
+ // Exception is Self of a trait.
1090
+ let is_trait_def = matches ! ( def, GenericDefId :: TraitId ( ..) ) ;
1091
+ let explicitly_unsized_tys = ctx. unsized_types . into_inner ( ) ;
1092
+ let subtsts = generics. bound_vars_subst ( DebruijnIndex :: INNERMOST ) ;
1093
+ let generic_args = & subtsts. as_slice ( & Interner ) [ is_trait_def as usize ..] ;
1094
+ let sized_trait = resolver
1095
+ . krate ( )
1096
+ . and_then ( |krate| db. lang_item ( krate, "sized" . into ( ) ) )
1097
+ . and_then ( |lang_item| lang_item. as_trait ( ) . map ( to_chalk_trait_id) ) ;
1098
+ let sized_predicates = sized_trait
1099
+ . into_iter ( )
1100
+ . flat_map ( |sized_trait| {
1101
+ let implicitly_sized_tys = generic_args
1102
+ . iter ( )
1103
+ . filter_map ( |generic_arg| generic_arg. ty ( & Interner ) )
1104
+ . filter ( |& self_ty| !explicitly_unsized_tys. contains ( self_ty) ) ;
1105
+ implicitly_sized_tys. map ( move |self_ty| {
1106
+ WhereClause :: Implemented ( TraitRef {
1107
+ trait_id : sized_trait,
1108
+ substitution : Substitution :: from1 ( & Interner , self_ty. clone ( ) ) ,
1109
+ } )
1110
+ } )
1111
+ } )
1112
+ . map ( |p| make_binders ( & generics, crate :: wrap_empty_binders ( p) ) ) ;
1113
+
1114
+ predicates. extend ( sized_predicates) ;
1115
+ predicates. into ( )
1060
1116
}
1061
1117
1062
1118
/// Resolve the default type params from generics
0 commit comments