6
6
use std:: sync:: Arc ;
7
7
8
8
use chalk_ir:: cast:: Cast ;
9
- use hir_def:: lang_item:: LangItem ;
9
+ use hir_def:: {
10
+ lang_item:: { LangItem , LangItemTarget } ,
11
+ AdtId ,
12
+ } ;
10
13
use hir_expand:: name:: name;
11
14
use limit:: Limit ;
12
15
@@ -76,7 +79,7 @@ pub(crate) fn autoderef_step(
76
79
table : & mut InferenceTable < ' _ > ,
77
80
ty : Ty ,
78
81
) -> Option < ( AutoderefKind , Ty ) > {
79
- if let Some ( derefed) = builtin_deref ( & ty) {
82
+ if let Some ( derefed) = builtin_deref ( table , & ty, false ) {
80
83
Some ( ( AutoderefKind :: Builtin , table. resolve_ty_shallow ( derefed) ) )
81
84
} else {
82
85
Some ( ( AutoderefKind :: Overloaded , deref_by_trait ( table, ty) ?) )
@@ -99,26 +102,41 @@ pub fn autoderef(
99
102
v. into_iter ( )
100
103
}
101
104
102
- pub ( crate ) fn deref ( table : & mut InferenceTable < ' _ > , ty : Ty ) -> Option < Ty > {
103
- let _p = profile:: span ( "deref" ) ;
104
- autoderef_step ( table, ty) . map ( |( _, ty) | ty)
105
- }
106
-
107
- fn builtin_deref ( ty : & Ty ) -> Option < & Ty > {
105
+ pub ( crate ) fn builtin_deref < ' ty > (
106
+ table : & mut InferenceTable < ' _ > ,
107
+ ty : & ' ty Ty ,
108
+ explicit : bool ,
109
+ ) -> Option < & ' ty Ty > {
108
110
match ty. kind ( Interner ) {
109
- TyKind :: Ref ( .., ty) | TyKind :: Raw ( .., ty) => Some ( ty) ,
111
+ TyKind :: Ref ( .., ty) => Some ( ty) ,
112
+ // FIXME: Maybe accept this but diagnose if its not explicit?
113
+ TyKind :: Raw ( .., ty) if explicit => Some ( ty) ,
114
+ & TyKind :: Adt ( chalk_ir:: AdtId ( AdtId :: StructId ( strukt) ) , ref substs) => {
115
+ if Some ( strukt)
116
+ == table
117
+ . db
118
+ . lang_item ( table. trait_env . krate , LangItem :: OwnedBox )
119
+ . and_then ( LangItemTarget :: as_struct)
120
+ {
121
+ substs. at ( Interner , 0 ) . ty ( Interner )
122
+ } else {
123
+ None
124
+ }
125
+ }
110
126
_ => None ,
111
127
}
112
128
}
113
129
114
- fn deref_by_trait ( table : & mut InferenceTable < ' _ > , ty : Ty ) -> Option < Ty > {
130
+ pub ( crate ) fn deref_by_trait (
131
+ table @ & mut InferenceTable { db, .. } : & mut InferenceTable < ' _ > ,
132
+ ty : Ty ,
133
+ ) -> Option < Ty > {
115
134
let _p = profile:: span ( "deref_by_trait" ) ;
116
135
if table. resolve_ty_shallow ( & ty) . inference_var ( Interner ) . is_some ( ) {
117
136
// don't try to deref unknown variables
118
137
return None ;
119
138
}
120
139
121
- let db = table. db ;
122
140
let deref_trait =
123
141
db. lang_item ( table. trait_env . krate , LangItem :: Deref ) . and_then ( |l| l. as_trait ( ) ) ?;
124
142
let target = db. trait_data ( deref_trait) . associated_type_by_name ( & name ! [ Target ] ) ?;
0 commit comments