From e8869cb7a7e760f39088190a724991726cd05c50 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 4 May 2021 21:41:45 +0200 Subject: [PATCH] Wrap the span_map tuple index into a type called "LightSpan" --- src/librustdoc/html/highlight.rs | 37 ++++---------- src/librustdoc/html/render/context.rs | 6 +-- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/span_map.rs | 67 +++++++++++++++++++++----- 4 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index edbb5dba1f3..808e1ca236f 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -17,7 +17,7 @@ use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; use super::format::{self, Buffer}; -use super::render::LinkFromSrc; +use super::render::{LightSpan, LinkFromSrc}; /// Highlights `src`, returning the HTML output. crate fn render_with_highlighting( @@ -74,7 +74,7 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option Option<(u32, u32)> { + fn get_span(self) -> Option { match self { Self::Ident(sp) | Self::Self_(sp) => Some(sp), _ => None, @@ -201,23 +201,6 @@ fn get_real_ident_class(text: &str, edition: Edition, allow_path_keywords: bool) }) } -/// Before explaining what this function does, some global explanations on rust's `Span`: -/// -/// Each source code file is stored in the source map in the compiler and has a -/// `lo` and a `hi` (lowest and highest bytes in this source map which can be seen as one huge -/// string to simplify things). So in this case, this represents the starting byte of the current -/// file. It'll be used later on to retrieve the "definition span" from the -/// `span_correspondance_map` (which is inside `context`). -/// -/// This when we transform the "span" we have from reading the input into a "span" which can be -/// used as index to the `span_correspondance_map` to get the definition of this item. -/// -/// So in here, `file_span_lo` is representing the "lo" byte in the global source map, and to make -/// our "span" works in there, we simply add `file_span_lo` to our values. -fn local_span_to_global_span(file_span_lo: u32, start: u32, end: u32) -> (u32, u32) { - (start + file_span_lo, end + file_span_lo) -} - /// Processes program tokens, classifying strings of text by highlighting /// category (`Class`). struct Classifier<'a> { @@ -234,7 +217,7 @@ struct Classifier<'a> { impl<'a> Classifier<'a> { /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code /// file "lo" byte which we be used later on by the `span_correspondance_map`. More explanations - /// are provided in the [`local_span_to_global_span`] function documentation about how it works. + /// are provided in the [`LightSpan::new_in_file`] function documentation about how it works. fn new(src: &str, edition: Edition, file_span_lo: u32) -> Classifier<'_> { let tokens = TokenIter { src }.peekable(); Classifier { @@ -496,12 +479,12 @@ impl<'a> Classifier<'a> { self.in_macro_nonterminal = false; Class::MacroNonTerminal } - "self" | "Self" => Class::Self_(local_span_to_global_span( + "self" | "Self" => Class::Self_(LightSpan::new_in_file( self.file_span_lo, before, before + text.len() as u32, )), - _ => Class::Ident(local_span_to_global_span( + _ => Class::Ident(LightSpan::new_in_file( self.file_span_lo, before, before + text.len() as u32, @@ -509,7 +492,7 @@ impl<'a> Classifier<'a> { }, Some(c) => c, }, - TokenKind::RawIdent | TokenKind::UnknownPrefix => Class::Ident(local_span_to_global_span( + TokenKind::RawIdent | TokenKind::UnknownPrefix => Class::Ident(LightSpan::new_in_file( self.file_span_lo, before, before + text.len() as u32, @@ -572,7 +555,7 @@ fn string( "self" | "Self" => write!( &mut path, "{}", - Class::Self_((0, 0)).as_html(), + Class::Self_(LightSpan::empty()).as_html(), t ), "crate" | "super" => write!( diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index c0668fcce99..36ec2cf3f7a 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -18,8 +18,8 @@ use super::cache::{build_index, ExternalLocation}; use super::print_item::{full_path, item_path, print_item}; use super::write_shared::write_shared; use super::{ - collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath, - BASIC_KEYWORDS, + collect_spans_and_sources, print_sidebar, settings, AllTypes, LightSpan, LinkFromSrc, NameDoc, + StylePath, BASIC_KEYWORDS, }; use crate::clean; @@ -131,7 +131,7 @@ crate struct SharedContext<'tcx> { /// Correspondance map used to link types used in the source code pages to allow to click on /// links to jump to the type's definition. - crate span_correspondance_map: FxHashMap<(u32, u32), LinkFromSrc>, + crate span_correspondance_map: FxHashMap, } impl SharedContext<'_> { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fd2e18a8be7..584afdeb280 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -34,7 +34,7 @@ mod span_map; mod write_shared; crate use context::*; -crate use span_map::{collect_spans_and_sources, LinkFromSrc}; +crate use span_map::{collect_spans_and_sources, LightSpan, LinkFromSrc}; use std::collections::VecDeque; use std::default::Default; diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 9990d6f0ce6..c7cc2250c24 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -24,6 +24,43 @@ crate enum LinkFromSrc { External(DefId), } +/// This struct is used only as index in the `span_map`, not as [`Span`]! `Span`s contain +/// some extra information (the syntax context) we don't need. **Do not convert this type back to +/// `Span`!!!** +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +crate struct LightSpan { + crate lo: u32, + crate hi: u32, +} + +impl LightSpan { + /// Before explaining what this method does, some global explanations on rust's `Span`: + /// + /// Each source code file is stored in the source map in the compiler and has a + /// `lo` and a `hi` (lowest and highest bytes in this source map which can be seen as one huge + /// string to simplify things). So in this case, this represents the starting byte of the + /// current file. It'll be used later on to retrieve the "definition span" from the + /// `span_correspondance_map` (which is inside `context`). + /// + /// This when we transform the "span" we have from reading the input into a "span" which can be + /// used as index to the `span_correspondance_map` to get the definition of this item. + /// + /// So in here, `file_span_lo` is representing the "lo" byte in the global source map, and to + /// make our "span" works in there, we simply add `file_span_lo` to our values. + crate fn new_in_file(file_span_lo: u32, lo: u32, hi: u32) -> Self { + Self { lo: lo + file_span_lo, hi: hi + file_span_lo } + } + + crate fn empty() -> Self { + Self { lo: 0, hi: 0 } + } + + /// Extra the `lo` and `hi` from the [`Span`] and discard the unused syntax context. + fn new_from_span(sp: Span) -> Self { + Self { lo: sp.lo().0, hi: sp.hi().0 } + } +} + /// This function will do at most two things: /// /// 1. Generate a `span` correspondance map which links an item `span` to its definition `span`. @@ -40,7 +77,7 @@ crate fn collect_spans_and_sources( src_root: &Path, include_sources: bool, generate_link_to_definition: bool, -) -> (clean::Crate, FxHashMap, FxHashMap<(u32, u32), LinkFromSrc>) { +) -> (clean::Crate, FxHashMap, FxHashMap) { let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() }; if include_sources { @@ -54,13 +91,9 @@ crate fn collect_spans_and_sources( } } -fn span_to_tuple(span: Span) -> (u32, u32) { - (span.lo().0, span.hi().0) -} - struct SpanMapVisitor<'tcx> { crate tcx: TyCtxt<'tcx>, - crate matches: FxHashMap<(u32, u32), LinkFromSrc>, + crate matches: FxHashMap, } impl<'tcx> SpanMapVisitor<'tcx> { @@ -77,12 +110,16 @@ impl<'tcx> SpanMapVisitor<'tcx> { }; if let Some(span) = self.tcx.hir().res_span(path.res) { self.matches.insert( - path_span.map(span_to_tuple).unwrap_or_else(|| span_to_tuple(path.span)), + path_span + .map(LightSpan::new_from_span) + .unwrap_or_else(|| LightSpan::new_from_span(path.span)), LinkFromSrc::Local(span), ); } else if let Some(def_id) = info { self.matches.insert( - path_span.map(span_to_tuple).unwrap_or_else(|| span_to_tuple(path.span)), + path_span + .map(LightSpan::new_from_span) + .unwrap_or_else(|| LightSpan::new_from_span(path.span)), LinkFromSrc::External(def_id), ); } @@ -122,8 +159,10 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> { if let Some(node) = self.tcx.hir().find(id) { match node { Node::Item(item) => { - self.matches - .insert(span_to_tuple(item.ident.span), LinkFromSrc::Local(m.inner)); + self.matches.insert( + LightSpan::new_from_span(item.ident.span), + LinkFromSrc::Local(m.inner), + ); } _ => {} } @@ -146,12 +185,14 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> { if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { match hir.span_if_local(def_id) { Some(span) => { - self.matches - .insert(span_to_tuple(method_span), LinkFromSrc::Local(span)); + self.matches.insert( + LightSpan::new_from_span(method_span), + LinkFromSrc::Local(span), + ); } None => { self.matches.insert( - span_to_tuple(method_span), + LightSpan::new_from_span(method_span), LinkFromSrc::External(def_id), ); }