@@ -10,9 +10,9 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
10
10
use rustc_hir as hir;
11
11
use rustc_hir:: intravisit:: { walk_body, walk_expr, walk_ty, FnKind , NestedVisitorMap , Visitor } ;
12
12
use rustc_hir:: {
13
- BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericParamKind , HirId , ImplItem ,
14
- ImplItemKind , Item , ItemKind , Lifetime , Lit , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind ,
15
- TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
13
+ BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericBounds , GenericParamKind , HirId ,
14
+ ImplItem , ImplItemKind , Item , ItemKind , Lifetime , Lit , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt ,
15
+ StmtKind , SyntheticTyParamKind , TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
16
16
} ;
17
17
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
18
18
use rustc_middle:: hir:: map:: Map ;
@@ -678,17 +678,30 @@ impl Types {
678
678
// details.
679
679
return ;
680
680
}
681
+
682
+ // When trait objects or opaque types have lifetime or auto-trait bounds,
683
+ // we need to add parentheses to avoid a syntax error due to its ambiguity.
684
+ // Originally reported as the issue #3128.
685
+ let inner_snippet = snippet( cx, inner. span, ".." ) ;
686
+ let suggestion = match & inner. kind {
687
+ TyKind :: TraitObject ( bounds, lt_bound) if bounds. len( ) > 1 || !lt_bound. is_elided( ) => {
688
+ format!( "&{}({})" , ltopt, & inner_snippet)
689
+ } ,
690
+ TyKind :: Path ( qpath)
691
+ if get_bounds_if_impl_trait( cx, qpath, inner. hir_id)
692
+ . map_or( false , |bounds| bounds. len( ) > 1 ) =>
693
+ {
694
+ format!( "&{}({})" , ltopt, & inner_snippet)
695
+ } ,
696
+ _ => format!( "&{}{}" , ltopt, & inner_snippet) ,
697
+ } ;
681
698
span_lint_and_sugg(
682
699
cx,
683
700
BORROWED_BOX ,
684
701
hir_ty. span,
685
702
"you seem to be trying to use `&Box<T>`. Consider using just `&T`" ,
686
703
"try" ,
687
- format!(
688
- "&{}{}" ,
689
- ltopt,
690
- & snippet( cx, inner. span, ".." )
691
- ) ,
704
+ suggestion,
692
705
// To make this `MachineApplicable`, at least one needs to check if it isn't a trait item
693
706
// because the trait impls of it will break otherwise;
694
707
// and there may be other cases that result in invalid code.
@@ -721,6 +734,21 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool {
721
734
false
722
735
}
723
736
737
+ fn get_bounds_if_impl_trait < ' tcx > ( cx : & LateContext < ' tcx > , qpath : & QPath < ' _ > , id : HirId ) -> Option < GenericBounds < ' tcx > > {
738
+ if_chain ! {
739
+ if let Some ( did) = qpath_res( cx, qpath, id) . opt_def_id( ) ;
740
+ if let Some ( node) = cx. tcx. hir( ) . get_if_local( did) ;
741
+ if let Node :: GenericParam ( generic_param) = node;
742
+ if let GenericParamKind :: Type { synthetic, .. } = generic_param. kind;
743
+ if synthetic == Some ( SyntheticTyParamKind :: ImplTrait ) ;
744
+ then {
745
+ Some ( generic_param. bounds)
746
+ } else {
747
+ None
748
+ }
749
+ }
750
+ }
751
+
724
752
declare_clippy_lint ! {
725
753
/// **What it does:** Checks for binding a unit value.
726
754
///
0 commit comments