@@ -93,6 +93,7 @@ use rustc_attr_data_structures::{AttributeKind, find_attr};
9393use rustc_data_structures:: fx:: FxHashMap ;
9494use rustc_data_structures:: packed:: Pu128 ;
9595use rustc_data_structures:: unhash:: UnindexMap ;
96+ use rustc_errors:: Applicability ;
9697use rustc_hir:: LangItem :: { OptionNone , OptionSome , ResultErr , ResultOk } ;
9798use rustc_hir:: def:: { DefKind , Res } ;
9899use rustc_hir:: def_id:: { DefId , LocalDefId , LocalModDefId } ;
@@ -104,7 +105,7 @@ use rustc_hir::{
104105 CoroutineKind , Destination , Expr , ExprField , ExprKind , FnDecl , FnRetTy , GenericArg , GenericArgs , HirId , Impl ,
105106 ImplItem , ImplItemKind , Item , ItemKind , LangItem , LetStmt , MatchSource , Mutability , Node , OwnerId , OwnerNode ,
106107 Param , Pat , PatExpr , PatExprKind , PatKind , Path , PathSegment , QPath , Stmt , StmtKind , TraitFn , TraitItem ,
107- TraitItemKind , TraitRef , TyKind , UnOp , def,
108+ TraitItemKind , TraitRef , TyKind , UnOp , UsePath , def,
108109} ;
109110use rustc_lexer:: { TokenKind , tokenize} ;
110111use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
@@ -121,12 +122,13 @@ use rustc_middle::ty::{
121122use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
122123use rustc_span:: source_map:: SourceMap ;
123124use rustc_span:: symbol:: { Ident , Symbol , kw} ;
124- use rustc_span:: { InnerSpan , Span } ;
125+ use rustc_span:: { BytePos , InnerSpan , Span } ;
125126use source:: walk_span_to_context;
126127use visitors:: { Visitable , for_each_unconsumed_temporary} ;
127128
128129use crate :: consts:: { ConstEvalCtxt , Constant , mir_to_const} ;
129130use crate :: higher:: Range ;
131+ use crate :: source:: { snippet, snippet_with_applicability} ;
130132use crate :: ty:: { adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type} ;
131133use crate :: visitors:: for_each_expr_without_closures;
132134
@@ -3471,3 +3473,55 @@ pub fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
34713473 None
34723474 }
34733475}
3476+
3477+ /// Returns true for `...prelude::...` imports.
3478+ pub fn is_prelude_import ( segments : & [ PathSegment < ' _ > ] ) -> bool {
3479+ segments
3480+ . iter ( )
3481+ . any ( |ps| ps. ident . as_str ( ) . contains ( sym:: prelude. as_str ( ) ) )
3482+ }
3483+
3484+ pub fn import_span_and_sugg (
3485+ cx : & LateContext < ' _ > ,
3486+ use_path : & UsePath < ' _ > ,
3487+ item : & Item < ' _ > ,
3488+ ) -> ( Span , String , Applicability ) {
3489+ let used_imports = cx. tcx . names_imported_by_glob_use ( item. owner_id . def_id ) ;
3490+
3491+ let mut applicability = Applicability :: MachineApplicable ;
3492+ let import_source_snippet = snippet_with_applicability ( cx, use_path. span , ".." , & mut applicability) ;
3493+ let ( span, braced_glob) = if import_source_snippet. is_empty ( ) {
3494+ // This is a `_::{_, *}` import
3495+ // In this case `use_path.span` is empty and ends directly in front of the `*`,
3496+ // so we need to extend it by one byte.
3497+ ( use_path. span . with_hi ( use_path. span . hi ( ) + BytePos ( 1 ) ) , true )
3498+ } else {
3499+ // In this case, the `use_path.span` ends right before the `::*`, so we need to
3500+ // extend it up to the `*`. Since it is hard to find the `*` in weird
3501+ // formatting like `use _ :: *;`, we extend it up to, but not including the
3502+ // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
3503+ // can just use the end of the item span
3504+ let mut span = use_path. span . with_hi ( item. span . hi ( ) ) ;
3505+ if snippet ( cx, span, "" ) . ends_with ( ';' ) {
3506+ span = use_path. span . with_hi ( item. span . hi ( ) - BytePos ( 1 ) ) ;
3507+ }
3508+ ( span, false )
3509+ } ;
3510+
3511+ let mut imports: Vec < _ > = used_imports. iter ( ) . map ( ToString :: to_string) . collect ( ) ;
3512+ let imports_string = if imports. len ( ) == 1 {
3513+ imports. pop ( ) . unwrap ( )
3514+ } else if braced_glob {
3515+ imports. join ( ", " )
3516+ } else {
3517+ format ! ( "{{{}}}" , imports. join( ", " ) )
3518+ } ;
3519+
3520+ let sugg = if braced_glob {
3521+ imports_string
3522+ } else {
3523+ format ! ( "{import_source_snippet}::{imports_string}" )
3524+ } ;
3525+
3526+ ( span, sugg, applicability)
3527+ }
0 commit comments