1212//! be considered a bug.
1313
1414use crate :: paths:: { PathNS , lookup_path} ;
15+ use rustc_ast:: { LitFloatType , LitIntType , LitKind } ;
1516use rustc_hir:: def:: { DefKind , Res } ;
1617use rustc_hir:: def_id:: DefId ;
1718use rustc_hir:: intravisit:: { InferKind , Visitor , VisitorExt , walk_qpath, walk_ty} ;
@@ -24,30 +25,32 @@ mod certainty;
2425use certainty:: { Certainty , Meet , join, meet} ;
2526
2627pub fn expr_type_is_certain ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
27- expr_type_certainty ( cx, expr) . is_certain ( )
28+ expr_type_certainty ( cx, expr, false ) . is_certain ( )
2829}
2930
30- fn expr_type_certainty ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> Certainty {
31+ /// Determine the type certainty of `expr`. `in_arg` indicates that the expression happens within
32+ /// the evaluation of a function or method call argument.
33+ fn expr_type_certainty ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , in_arg : bool ) -> Certainty {
3134 let certainty = match & expr. kind {
3235 ExprKind :: Unary ( _, expr)
3336 | ExprKind :: Field ( expr, _)
3437 | ExprKind :: Index ( expr, _, _)
35- | ExprKind :: AddrOf ( _, _, expr) => expr_type_certainty ( cx, expr) ,
38+ | ExprKind :: AddrOf ( _, _, expr) => expr_type_certainty ( cx, expr, in_arg ) ,
3639
37- ExprKind :: Array ( exprs) => join ( exprs. iter ( ) . map ( |expr| expr_type_certainty ( cx, expr) ) ) ,
40+ ExprKind :: Array ( exprs) => join ( exprs. iter ( ) . map ( |expr| expr_type_certainty ( cx, expr, in_arg ) ) ) ,
3841
3942 ExprKind :: Call ( callee, args) => {
40- let lhs = expr_type_certainty ( cx, callee) ;
43+ let lhs = expr_type_certainty ( cx, callee, false ) ;
4144 let rhs = if type_is_inferable_from_arguments ( cx, expr) {
42- meet ( args. iter ( ) . map ( |arg| expr_type_certainty ( cx, arg) ) )
45+ meet ( args. iter ( ) . map ( |arg| expr_type_certainty ( cx, arg, true ) ) )
4346 } else {
4447 Certainty :: Uncertain
4548 } ;
4649 lhs. join_clearing_def_ids ( rhs)
4750 } ,
4851
4952 ExprKind :: MethodCall ( method, receiver, args, _) => {
50- let mut receiver_type_certainty = expr_type_certainty ( cx, receiver) ;
53+ let mut receiver_type_certainty = expr_type_certainty ( cx, receiver, false ) ;
5154 // Even if `receiver_type_certainty` is `Certain(Some(..))`, the `Self` type in the method
5255 // identified by `type_dependent_def_id(..)` can differ. This can happen as a result of a `deref`,
5356 // for example. So update the `DefId` in `receiver_type_certainty` (if any).
@@ -59,24 +62,48 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty {
5962 let lhs = path_segment_certainty ( cx, receiver_type_certainty, method, false ) ;
6063 let rhs = if type_is_inferable_from_arguments ( cx, expr) {
6164 meet (
62- std:: iter:: once ( receiver_type_certainty) . chain ( args. iter ( ) . map ( |arg| expr_type_certainty ( cx, arg) ) ) ,
65+ std:: iter:: once ( receiver_type_certainty)
66+ . chain ( args. iter ( ) . map ( |arg| expr_type_certainty ( cx, arg, true ) ) ) ,
6367 )
6468 } else {
6569 Certainty :: Uncertain
6670 } ;
6771 lhs. join ( rhs)
6872 } ,
6973
70- ExprKind :: Tup ( exprs) => meet ( exprs. iter ( ) . map ( |expr| expr_type_certainty ( cx, expr) ) ) ,
74+ ExprKind :: Tup ( exprs) => meet ( exprs. iter ( ) . map ( |expr| expr_type_certainty ( cx, expr, in_arg ) ) ) ,
7175
72- ExprKind :: Binary ( _, lhs, rhs) => expr_type_certainty ( cx, lhs) . meet ( expr_type_certainty ( cx, rhs) ) ,
76+ ExprKind :: Binary ( _, lhs, rhs) => {
77+ // If one of the side of the expression is uncertain, the certainty will come from the other side,
78+ // with no information on the type.
79+ match (
80+ expr_type_certainty ( cx, lhs, in_arg) ,
81+ expr_type_certainty ( cx, rhs, in_arg) ,
82+ ) {
83+ ( Certainty :: Uncertain , Certainty :: Certain ( _) ) | ( Certainty :: Certain ( _) , Certainty :: Uncertain ) => {
84+ Certainty :: Certain ( None )
85+ } ,
86+ ( l, r) => l. meet ( r) ,
87+ }
88+ } ,
7389
74- ExprKind :: Lit ( _) => Certainty :: Certain ( None ) ,
90+ ExprKind :: Lit ( lit) => {
91+ if !in_arg
92+ && matches ! (
93+ lit. node,
94+ LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed )
95+ )
96+ {
97+ Certainty :: Uncertain
98+ } else {
99+ Certainty :: Certain ( None )
100+ }
101+ } ,
75102
76103 ExprKind :: Cast ( _, ty) => type_certainty ( cx, ty) ,
77104
78105 ExprKind :: If ( _, if_expr, Some ( else_expr) ) => {
79- expr_type_certainty ( cx, if_expr) . join ( expr_type_certainty ( cx, else_expr) )
106+ expr_type_certainty ( cx, if_expr, in_arg ) . join ( expr_type_certainty ( cx, else_expr, in_arg ) )
80107 } ,
81108
82109 ExprKind :: Path ( qpath) => qpath_certainty ( cx, qpath, false ) ,
@@ -248,7 +275,7 @@ fn path_segment_certainty(
248275 let lhs = local. ty . map_or ( Certainty :: Uncertain , |ty| type_certainty ( cx, ty) ) ;
249276 let rhs = local
250277 . init
251- . map_or ( Certainty :: Uncertain , |init| expr_type_certainty ( cx, init) ) ;
278+ . map_or ( Certainty :: Uncertain , |init| expr_type_certainty ( cx, init, false ) ) ;
252279 let certainty = lhs. join ( rhs) ;
253280 if resolves_to_type {
254281 certainty
0 commit comments