@@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher};
44use std:: marker:: PhantomData ;
55use std:: ops:: { Deref , DerefMut } ;
66use std:: panic;
7+ use std:: path:: PathBuf ;
78use std:: thread:: panicking;
89
910use rustc_data_structures:: fx:: FxIndexMap ;
@@ -301,6 +302,7 @@ pub struct DiagInner {
301302
302303 pub is_lint : Option < IsLint > ,
303304
305+ pub long_ty_path : Option < PathBuf > ,
304306 /// With `-Ztrack_diagnostics` enabled,
305307 /// we print where in rustc this error was emitted.
306308 pub ( crate ) emitted_at : DiagLocation ,
@@ -324,6 +326,7 @@ impl DiagInner {
324326 args : Default :: default ( ) ,
325327 sort_span : DUMMY_SP ,
326328 is_lint : None ,
329+ long_ty_path : None ,
327330 emitted_at : DiagLocation :: caller ( ) ,
328331 }
329332 }
@@ -1293,9 +1296,37 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
12931296 /// `cancel`, etc. Afterwards, `drop` is the only code that will be run on
12941297 /// `self`.
12951298 fn take_diag ( & mut self ) -> DiagInner {
1299+ if let Some ( path) = & self . long_ty_path {
1300+ self . note ( format ! (
1301+ "the full name for the type has been written to '{}'" ,
1302+ path. display( )
1303+ ) ) ;
1304+ self . note ( "consider using `--verbose` to print the full type name to the console" ) ;
1305+ }
12961306 Box :: into_inner ( self . diag . take ( ) . unwrap ( ) )
12971307 }
12981308
1309+ /// This method allows us to access the path of the file where "long types" are written to.
1310+ ///
1311+ /// When calling `Diag::emit`, as part of that we will check if a `long_ty_path` has been set,
1312+ /// and if it has been then we add a note mentioning the file where the "long types" were
1313+ /// written to.
1314+ ///
1315+ /// When calling `tcx.short_string()` after a `Diag` is constructed, the preferred way of doing
1316+ /// so is `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that
1317+ /// keeps the existence of a "long type" anywhere in the diagnostic, so the note telling the
1318+ /// user where we wrote the file to is only printed once at most, *and* it makes it much harder
1319+ /// to forget to set it.
1320+ ///
1321+ /// If the diagnostic hasn't been created before a "short ty string" is created, then you should
1322+ /// ensure that this method is called to set it `*diag.long_ty_path() = path`.
1323+ ///
1324+ /// As a rule of thumb, if you see or add at least one `tcx.short_string()` call anywhere, in a
1325+ /// scope, `diag.long_ty_path()` should be called once somewhere close by.
1326+ pub fn long_ty_path ( & mut self ) -> & mut Option < PathBuf > {
1327+ & mut self . long_ty_path
1328+ }
1329+
12991330 /// Most `emit_producing_guarantee` functions use this as a starting point.
13001331 fn emit_producing_nothing ( mut self ) {
13011332 let diag = self . take_diag ( ) ;
0 commit comments