@@ -1187,6 +1187,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1187
1187
has_custom_message : bool ,
1188
1188
) -> bool {
1189
1189
let span = obligation. cause . span ;
1190
+ let param_env = obligation. param_env ;
1191
+
1192
+ let mk_result = |trait_pred_and_new_ty| {
1193
+ let obligation =
1194
+ self . mk_trait_obligation_with_new_self_ty ( param_env, trait_pred_and_new_ty) ;
1195
+ self . predicate_must_hold_modulo_regions ( & obligation)
1196
+ } ;
1190
1197
1191
1198
let code = match obligation. cause . code ( ) {
1192
1199
ObligationCauseCode :: FunctionArg { parent_code, .. } => parent_code,
@@ -1195,6 +1202,76 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1195
1202
c @ ObligationCauseCode :: WhereClauseInExpr ( _, _, hir_id, _)
1196
1203
if self . tcx . hir_span ( * hir_id) . lo ( ) == span. lo ( ) =>
1197
1204
{
1205
+ // `hir_id` corresponds to the HIR node that introduced a `where`-clause obligation.
1206
+ // If that obligation comes from a type in an associated method call, we need
1207
+ // special handling here.
1208
+ if let hir:: Node :: Expr ( expr) = self . tcx . parent_hir_node ( * hir_id)
1209
+ && let hir:: ExprKind :: Call ( base, _) = expr. kind
1210
+ && let hir:: ExprKind :: Path ( hir:: QPath :: TypeRelative ( ty, segment) ) = base. kind
1211
+ && let hir:: Node :: Expr ( outer) = self . tcx . parent_hir_node ( expr. hir_id )
1212
+ && let hir:: ExprKind :: AddrOf ( hir:: BorrowKind :: Ref , mtbl, _) = outer. kind
1213
+ && ty. span == span
1214
+ {
1215
+ // We've encountered something like `&str::from("")`, where the intended code
1216
+ // was likely `<&str>::from("")`. The former is interpreted as "call method
1217
+ // `from` on `str` and borrow the result", while the latter means "call method
1218
+ // `from` on `&str`".
1219
+
1220
+ let trait_pred_and_imm_ref = poly_trait_pred. map_bound ( |p| {
1221
+ ( p, Ty :: new_imm_ref ( self . tcx , self . tcx . lifetimes . re_static , p. self_ty ( ) ) )
1222
+ } ) ;
1223
+ let trait_pred_and_mut_ref = poly_trait_pred. map_bound ( |p| {
1224
+ ( p, Ty :: new_mut_ref ( self . tcx , self . tcx . lifetimes . re_static , p. self_ty ( ) ) )
1225
+ } ) ;
1226
+
1227
+ let imm_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_imm_ref) ;
1228
+ let mut_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_mut_ref) ;
1229
+ let sugg_msg = |pre : & str | {
1230
+ format ! (
1231
+ "you likely meant to call the associated function `{FN}` for type \
1232
+ `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \
1233
+ type `{TY}`",
1234
+ FN = segment. ident,
1235
+ TY = poly_trait_pred. self_ty( ) ,
1236
+ )
1237
+ } ;
1238
+ match ( imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) {
1239
+ ( true , _, hir:: Mutability :: Not ) | ( _, true , hir:: Mutability :: Mut ) => {
1240
+ err. multipart_suggestion_verbose (
1241
+ sugg_msg ( mtbl. prefix_str ( ) ) ,
1242
+ vec ! [
1243
+ ( outer. span. shrink_to_lo( ) , "<" . to_string( ) ) ,
1244
+ ( span. shrink_to_hi( ) , ">" . to_string( ) ) ,
1245
+ ] ,
1246
+ Applicability :: MachineApplicable ,
1247
+ ) ;
1248
+ }
1249
+ ( true , _, hir:: Mutability :: Mut ) => {
1250
+ // There's an associated function found on the immutable borrow of the
1251
+ err. multipart_suggestion_verbose (
1252
+ sugg_msg ( "mut " ) ,
1253
+ vec ! [
1254
+ ( outer. span. shrink_to_lo( ) . until( span) , "<&" . to_string( ) ) ,
1255
+ ( span. shrink_to_hi( ) , ">" . to_string( ) ) ,
1256
+ ] ,
1257
+ Applicability :: MachineApplicable ,
1258
+ ) ;
1259
+ }
1260
+ ( _, true , hir:: Mutability :: Not ) => {
1261
+ err. multipart_suggestion_verbose (
1262
+ sugg_msg ( "" ) ,
1263
+ vec ! [
1264
+ ( outer. span. shrink_to_lo( ) . until( span) , "<&mut " . to_string( ) ) ,
1265
+ ( span. shrink_to_hi( ) , ">" . to_string( ) ) ,
1266
+ ] ,
1267
+ Applicability :: MachineApplicable ,
1268
+ ) ;
1269
+ }
1270
+ _ => { }
1271
+ }
1272
+ // If we didn't return early here, we would instead suggest `&&str::from("")`.
1273
+ return false ;
1274
+ }
1198
1275
c
1199
1276
}
1200
1277
c if matches ! (
@@ -1220,8 +1297,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1220
1297
never_suggest_borrow. push ( def_id) ;
1221
1298
}
1222
1299
1223
- let param_env = obligation. param_env ;
1224
-
1225
1300
// Try to apply the original trait bound by borrowing.
1226
1301
let mut try_borrowing = |old_pred : ty:: PolyTraitPredicate < ' tcx > ,
1227
1302
blacklist : & [ DefId ] |
@@ -1243,11 +1318,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1243
1318
)
1244
1319
} ) ;
1245
1320
1246
- let mk_result = |trait_pred_and_new_ty| {
1247
- let obligation =
1248
- self . mk_trait_obligation_with_new_self_ty ( param_env, trait_pred_and_new_ty) ;
1249
- self . predicate_must_hold_modulo_regions ( & obligation)
1250
- } ;
1251
1321
let imm_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_imm_ref) ;
1252
1322
let mut_ref_self_ty_satisfies_pred = mk_result ( trait_pred_and_mut_ref) ;
1253
1323
0 commit comments