1515#![ warn( unreachable_pub) ]
1616// tidy-alphabetical-end
1717
18- use std:: path:: Path ;
18+ use std:: path:: { Path , PathBuf } ;
19+ use std:: str:: Utf8Error ;
1920
2021use rustc_ast as ast;
2122use rustc_ast:: tokenstream:: TokenStream ;
2223use rustc_ast:: { AttrItem , Attribute , MetaItemInner , token} ;
2324use rustc_ast_pretty:: pprust;
2425use rustc_data_structures:: sync:: Lrc ;
25- use rustc_errors:: { Diag , FatalError , PResult } ;
26+ use rustc_errors:: { Diag , EmissionGuarantee , FatalError , PResult } ;
2627use rustc_session:: parse:: ParseSess ;
28+ use rustc_span:: source_map:: SourceMap ;
2729use rustc_span:: { FileName , SourceFile , Span } ;
2830pub use unicode_normalization:: UNICODE_VERSION as UNICODE_NORMALIZATION_VERSION ;
2931
@@ -74,36 +76,21 @@ pub fn new_parser_from_file<'a>(
7476 path : & Path ,
7577 sp : Option < Span > ,
7678) -> Result < Parser < ' a > , Vec < Diag < ' a > > > {
77- let source_file = psess. source_map ( ) . load_file ( path) . unwrap_or_else ( |e| {
79+ let sm = psess. source_map ( ) ;
80+ let source_file = sm. load_file ( path) . unwrap_or_else ( |e| {
7881 let msg = format ! ( "couldn't read `{}`: {}" , path. display( ) , e) ;
7982 let mut err = psess. dcx ( ) . struct_fatal ( msg) ;
8083 if let Ok ( contents) = std:: fs:: read ( path)
81- && let Err ( utf8err) = String :: from_utf8 ( contents)
84+ && let Err ( utf8err) = String :: from_utf8 ( contents. clone ( ) )
8285 {
83- // The file exists, but it wasn't valid UTF-8.
84- let start = utf8err. utf8_error ( ) . valid_up_to ( ) ;
85- let note = format ! ( "invalid utf-8 at byte `{start}`" ) ;
86- let msg = if let Some ( len) = utf8err. utf8_error ( ) . error_len ( ) {
87- format ! ( "`{:?}` is not valid utf-8" , & utf8err. as_bytes( ) [ start..start + len] )
88- } else {
89- note. clone ( )
90- } ;
91- let contents = utf8err. into_utf8_lossy ( ) ;
92- let source = psess. source_map ( ) . new_source_file ( path. to_owned ( ) . into ( ) , contents) ;
93- let span = Span :: with_root_ctxt (
94- source. normalized_byte_pos ( start as u32 ) ,
95- source. normalized_byte_pos ( start as u32 ) ,
86+ utf8_error (
87+ sm,
88+ & path. display ( ) . to_string ( ) ,
89+ sp,
90+ & mut err,
91+ utf8err. utf8_error ( ) ,
92+ & contents,
9693 ) ;
97- if span. is_dummy ( ) {
98- err. note ( note) ;
99- } else {
100- if sp. is_some ( ) {
101- err. span_note ( span, msg) ;
102- } else {
103- err. span ( span) ;
104- err. span_label ( span, msg) ;
105- }
106- }
10794 }
10895 if let Some ( sp) = sp {
10996 err. span ( sp) ;
@@ -113,6 +100,40 @@ pub fn new_parser_from_file<'a>(
113100 new_parser_from_source_file ( psess, source_file)
114101}
115102
103+ pub fn utf8_error < E : EmissionGuarantee > (
104+ sm : & SourceMap ,
105+ path : & str ,
106+ sp : Option < Span > ,
107+ err : & mut Diag < ' _ , E > ,
108+ utf8err : Utf8Error ,
109+ contents : & [ u8 ] ,
110+ ) {
111+ // The file exists, but it wasn't valid UTF-8.
112+ let start = utf8err. valid_up_to ( ) ;
113+ let note = format ! ( "invalid utf-8 at byte `{start}`" ) ;
114+ let msg = if let Some ( len) = utf8err. error_len ( ) {
115+ format ! ( "`{:?}` is not valid utf-8" , & contents[ start..start + len] )
116+ } else {
117+ note. clone ( )
118+ } ;
119+ let contents = String :: from_utf8_lossy ( contents) . to_string ( ) ;
120+ let source = sm. new_source_file ( PathBuf :: from ( path) . into ( ) , contents) ;
121+ let span = Span :: with_root_ctxt (
122+ source. normalized_byte_pos ( start as u32 ) ,
123+ source. normalized_byte_pos ( start as u32 ) ,
124+ ) ;
125+ if span. is_dummy ( ) {
126+ err. note ( note) ;
127+ } else {
128+ if sp. is_some ( ) {
129+ err. span_note ( span, msg) ;
130+ } else {
131+ err. span ( span) ;
132+ err. span_label ( span, msg) ;
133+ }
134+ }
135+ }
136+
116137/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing
117138/// the initial token stream.
118139fn new_parser_from_source_file (
0 commit comments