diff options
| author | bors <bors@rust-lang.org> | 2019-10-01 07:56:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-10-01 07:56:52 +0000 |
| commit | 702b45e409495a41afcccbe87a251a692b0cefab (patch) | |
| tree | 6dbfa88da0422f72926f0352a968d79bf84e8464 /src/librustc_errors | |
| parent | 42ec6831b019114a4b6f6b58bfb5bc2927d70388 (diff) | |
| parent | 46bf6ad416cf922c410fed11e9f73c03c0015bcd (diff) | |
| download | rust-702b45e409495a41afcccbe87a251a692b0cefab.tar.gz rust-702b45e409495a41afcccbe87a251a692b0cefab.zip | |
Auto merge of #64946 - Centril:rollup-66mj5o0, r=Centril
Rollup of 10 pull requests Successful merges: - #63674 (syntax: Support modern attribute syntax in the `meta` matcher) - #63931 (Stabilize macros in some more positions) - #64887 (syntax: recover trailing `|` in or-patterns) - #64895 (async/await: improve not-send errors) - #64896 (Remove legacy grammar) - #64907 (A small amount of tidying-up factored out from PR #64648) - #64928 (Add tests for some issues) - #64930 (Silence unreachable code lint from await desugaring) - #64935 (Improve code clarity) - #64937 (Deduplicate closure type errors) Failed merges: r? @ghost
Diffstat (limited to 'src/librustc_errors')
| -rw-r--r-- | src/librustc_errors/emitter.rs | 512 |
1 files changed, 239 insertions, 273 deletions
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2a89c94652a..0c7aa3582ac 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -99,8 +99,8 @@ impl Margin { // ``` let mut m = Margin { - whitespace_left: if whitespace_left >= 6 { whitespace_left - 6 } else { 0 }, - span_left: if span_left >= 6 { span_left - 6 } else { 0 }, + whitespace_left: whitespace_left.saturating_sub(6), + span_left: span_left.saturating_sub(6), span_right: span_right + 6, computed_left: 0, computed_right: 0, @@ -125,7 +125,7 @@ impl Margin { } else { self.computed_right }; - right < line_len && line_len > self.computed_left + self.column_width + right < line_len && self.computed_left + self.column_width < line_len } fn compute(&mut self, max_line_len: usize) { @@ -167,12 +167,10 @@ impl Margin { } fn right(&self, line_len: usize) -> usize { - if max(line_len, self.computed_left) - self.computed_left <= self.column_width { - line_len - } else if self.computed_right > line_len { + if line_len.saturating_sub(self.computed_left) <= self.column_width { line_len } else { - self.computed_right + min(line_len, self.computed_right) } } } @@ -297,81 +295,82 @@ pub trait Emitter { source_map: &Option<Lrc<SourceMapperDyn>>, span: &mut MultiSpan, always_backtrace: bool) -> bool { - let mut spans_updated = false; + let sm = match source_map { + Some(ref sm) => sm, + None => return false, + }; - if let Some(ref sm) = source_map { - let mut before_after: Vec<(Span, Span)> = vec![]; - let mut new_labels: Vec<(Span, String)> = vec![]; + let mut before_after: Vec<(Span, Span)> = vec![]; + let mut new_labels: Vec<(Span, String)> = vec![]; - // First, find all the spans in <*macros> and point instead at their use site - for sp in span.primary_spans() { - if sp.is_dummy() { + // First, find all the spans in <*macros> and point instead at their use site + for sp in span.primary_spans() { + if sp.is_dummy() { + continue; + } + let call_sp = sm.call_span_if_macro(*sp); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); + } + let backtrace_len = sp.macro_backtrace().len(); + for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { + // Only show macro locations that are local + // and display them like a span_note + if trace.def_site_span.is_dummy() { continue; } - let call_sp = sm.call_span_if_macro(*sp); - if call_sp != *sp && !always_backtrace { - before_after.push((*sp, call_sp)); + if always_backtrace { + new_labels.push((trace.def_site_span, + format!("in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + String::new() + }))); } - let backtrace_len = sp.macro_backtrace().len(); - for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { - // Only show macro locations that are local - // and display them like a span_note - if trace.def_site_span.is_dummy() { - continue; - } - if always_backtrace { - new_labels.push((trace.def_site_span, - format!("in this expansion of `{}`{}", - trace.macro_decl_name, - if backtrace_len > 2 { - // if backtrace_len == 1 it'll be pointed - // at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }))); - } - // Check to make sure we're not in any <*macros> - if !sm.span_to_filename(trace.def_site_span).is_macros() && - !trace.macro_decl_name.starts_with("desugaring of ") && - !trace.macro_decl_name.starts_with("#[") || - always_backtrace { - new_labels.push((trace.call_site, - format!("in this macro invocation{}", - if backtrace_len > 2 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }))); - if !always_backtrace { - break; - } + // Check to make sure we're not in any <*macros> + if !sm.span_to_filename(trace.def_site_span).is_macros() && + !trace.macro_decl_name.starts_with("desugaring of ") && + !trace.macro_decl_name.starts_with("#[") || + always_backtrace { + new_labels.push((trace.call_site, + format!("in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + String::new() + }))); + if !always_backtrace { + break; } } } - for (label_span, label_text) in new_labels { - span.push_span_label(label_span, label_text); + } + for (label_span, label_text) in new_labels { + span.push_span_label(label_span, label_text); + } + for sp_label in span.span_labels() { + if sp_label.span.is_dummy() { + continue; } - for sp_label in span.span_labels() { - if sp_label.span.is_dummy() { - continue; - } - if sm.span_to_filename(sp_label.span.clone()).is_macros() && - !always_backtrace - { - let v = sp_label.span.macro_backtrace(); - if let Some(use_site) = v.last() { - before_after.push((sp_label.span.clone(), use_site.call_site.clone())); - } + if sm.span_to_filename(sp_label.span.clone()).is_macros() && + !always_backtrace + { + let v = sp_label.span.macro_backtrace(); + if let Some(use_site) = v.last() { + before_after.push((sp_label.span.clone(), use_site.call_site.clone())); } } - // After we have them, make sure we replace these 'bad' def sites with their use sites - for (before, after) in before_after { - span.replace(before, after); - spans_updated = true; - } + } + // After we have them, make sure we replace these 'bad' def sites with their use sites + let spans_updated = !before_after.is_empty(); + for (before, after) in before_after { + span.replace(before, after); } spans_updated @@ -593,9 +592,9 @@ impl EmitterWriter { let left = margin.left(source_string.len()); // Left trim // Account for unicode characters of width !=0 that were removed. - let left = source_string.chars().take(left).fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) - }); + let left = source_string.chars().take(left) + .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum(); self.draw_line( buffer, @@ -623,18 +622,16 @@ impl EmitterWriter { // 3 | | // 4 | | } // | |_^ test - if line.annotations.len() == 1 { - if let Some(ref ann) = line.annotations.get(0) { - if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { - let style = if ann.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; - buffer.putc(line_offset, width_offset + depth - 1, '/', style); - return vec![(depth, style)]; - } + if let [ann] = &line.annotations[..] { + if let AnnotationType::MultilineStart(depth) = ann.annotation_type { + if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { + let style = if ann.is_primary { + Style::UnderlinePrimary + } else { + Style::UnderlineSecondary + }; + buffer.putc(line_offset, width_offset + depth - 1, '/', style); + return vec![(depth, style)]; } } } @@ -763,11 +760,7 @@ impl EmitterWriter { annotations_position.push((p, annotation)); for (j, next) in annotations.iter().enumerate() { if j > i { - let l = if let Some(ref label) = next.label { - label.len() + 2 - } else { - 0 - }; + let l = next.label.as_ref().map_or(0, |label| label.len() + 2); if (overlaps(next, annotation, l) // Do not allow two labels to be in the same // line if they overlap including padding, to // avoid situations like: @@ -797,9 +790,7 @@ impl EmitterWriter { } } } - if line_len < p { - line_len = p; - } + line_len = max(line_len, p); } if line_len != 0 { @@ -941,17 +932,9 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, if annotation.end_col + 1 > left { - annotation.end_col + 1 - left - } else { - 0 - }) + (pos + 1, (annotation.end_col + 1).saturating_sub(left)) } else { - (pos + 2, if annotation.start_col > left { - annotation.start_col - left - } else { - 0 - }) + (pos + 2, annotation.start_col.saturating_sub(left)) }; if let Some(ref label) = annotation.label { buffer.puts(line_offset + pos, code_offset + col, &label, style); @@ -966,9 +949,9 @@ impl EmitterWriter { // | | | // | | something about `foo` // | something about `fn foo()` - annotations_position.sort_by(|a, b| { - // Decreasing order. When `a` and `b` are the same length, prefer `Primary`. - (a.1.len(), !a.1.is_primary).cmp(&(b.1.len(), !b.1.is_primary)).reverse() + annotations_position.sort_by_key(|(_, ann)| { + // Decreasing order. When annotations share the same length, prefer `Primary`. + (Reverse(ann.len()), ann.is_primary) }); // Write the underlines. @@ -991,11 +974,7 @@ impl EmitterWriter { for p in annotation.start_col..annotation.end_col { buffer.putc( line_offset + 1, - if code_offset + p > left { - code_offset + p - left - } else { - 0 - }, + (code_offset + p).saturating_sub(left), underline, style, ); @@ -1018,40 +997,36 @@ impl EmitterWriter { } fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize { + let sm = match self.sm { + Some(ref sm) => sm, + None => return 0, + }; + let mut max = 0; - if let Some(ref sm) = self.sm { - for primary_span in msp.primary_spans() { - if !primary_span.is_dummy() { - let hi = sm.lookup_char_pos(primary_span.hi()); - if hi.line > max { - max = hi.line; - } - } + for primary_span in msp.primary_spans() { + if !primary_span.is_dummy() { + let hi = sm.lookup_char_pos(primary_span.hi()); + max = (hi.line).max(max); } - if !self.short_message { - for span_label in msp.span_labels() { - if !span_label.span.is_dummy() { - let hi = sm.lookup_char_pos(span_label.span.hi()); - if hi.line > max { - max = hi.line; - } - } + } + if !self.short_message { + for span_label in msp.span_labels() { + if !span_label.span.is_dummy() { + let hi = sm.lookup_char_pos(span_label.span.hi()); + max = (hi.line).max(max); } } } + max } fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> usize { - let primary = self.get_multispan_max_line_num(span); - let mut max = primary; - - for sub in children { - let sub_result = self.get_multispan_max_line_num(&sub.span); - max = std::cmp::max(sub_result, max); - } - max + children.iter() + .map(|sub| self.get_multispan_max_line_num(&sub.span)) + .max() + .unwrap_or(primary) } /// Adds a left margin to every line but the first, given a padding length and the label being @@ -1081,14 +1056,12 @@ impl EmitterWriter { // `max_line_num_len` let padding = " ".repeat(padding + label.len() + 5); - /// Returns `true` if `style`, or the override if present and the style is `NoStyle`. - fn style_or_override(style: Style, override_style: Option<Style>) -> Style { - if let Some(o) = override_style { - if style == Style::NoStyle { - return o; - } + /// Returns `override` if it is present and `style` is `NoStyle` or `style` otherwise + fn style_or_override(style: Style, override_: Option<Style>) -> Style { + match (style, override_) { + (Style::NoStyle, Some(override_)) => override_, + _ => style, } - style } let mut line_number = 0; @@ -1324,13 +1297,12 @@ impl EmitterWriter { for line in &annotated_file.lines { max_line_len = max(max_line_len, annotated_file.file .get_line(line.line_index - 1) - .map(|s| s.len()) - .unwrap_or(0)); + .map_or(0, |s| s.len())); for ann in &line.annotations { span_right_margin = max(span_right_margin, ann.start_col); span_right_margin = max(span_right_margin, ann.end_col); // FIXME: account for labels not in the same line - let label_right = ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0); + let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1); label_right_margin = max(label_right_margin, ann.end_col + label_right); } } @@ -1459,122 +1431,125 @@ impl EmitterWriter { level: &Level, max_line_num_len: usize, ) -> io::Result<()> { - if let Some(ref sm) = self.sm { - let mut buffer = StyledBuffer::new(); + let sm = match self.sm { + Some(ref sm) => sm, + None => return Ok(()) + }; - // Render the suggestion message - let level_str = level.to_string(); - if !level_str.is_empty() { - buffer.append(0, &level_str, Style::Level(level.clone())); - buffer.append(0, ": ", Style::HeaderMsg); + let mut buffer = StyledBuffer::new(); + + // Render the suggestion message + let level_str = level.to_string(); + if !level_str.is_empty() { + buffer.append(0, &level_str, Style::Level(level.clone())); + buffer.append(0, ": ", Style::HeaderMsg); + } + self.msg_to_buffer( + &mut buffer, + &[(suggestion.msg.to_owned(), Style::NoStyle)], + max_line_num_len, + "suggestion", + Some(Style::HeaderMsg), + ); + + // Render the replacements for each suggestion + let suggestions = suggestion.splice_lines(&**sm); + + let mut row_num = 2; + for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) { + // Only show underline if the suggestion spans a single line and doesn't cover the + // entirety of the code output. If you have multiple replacements in the same line + // of code, show the underline. + let show_underline = !(parts.len() == 1 + && parts[0].snippet.trim() == complete.trim()) + && complete.lines().count() == 1; + + let lines = sm.span_to_lines(parts[0].span).unwrap(); + + assert!(!lines.lines.is_empty()); + + let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; + draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); + let mut line_pos = 0; + let mut lines = complete.lines(); + for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { + // Print the span column to avoid confusion + buffer.puts(row_num, + 0, + &self.maybe_anonymized(line_start + line_pos), + Style::LineNumber); + // print the suggestion + draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + buffer.append(row_num, line, Style::NoStyle); + line_pos += 1; + row_num += 1; } - self.msg_to_buffer( - &mut buffer, - &[(suggestion.msg.to_owned(), Style::NoStyle)], - max_line_num_len, - "suggestion", - Some(Style::HeaderMsg), - ); - - // Render the replacements for each suggestion - let suggestions = suggestion.splice_lines(&**sm); - - let mut row_num = 2; - for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) { - // Only show underline if the suggestion spans a single line and doesn't cover the - // entirety of the code output. If you have multiple replacements in the same line - // of code, show the underline. - let show_underline = !(parts.len() == 1 - && parts[0].snippet.trim() == complete.trim()) - && complete.lines().count() == 1; - - let lines = sm.span_to_lines(parts[0].span).unwrap(); - - assert!(!lines.lines.is_empty()); - - let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; - draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); - let mut line_pos = 0; - let mut lines = complete.lines(); - for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { - // Print the span column to avoid confusion - buffer.puts(row_num, - 0, - &self.maybe_anonymized(line_start + line_pos), - Style::LineNumber); - // print the suggestion - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); - buffer.append(row_num, line, Style::NoStyle); - line_pos += 1; - row_num += 1; - } - // This offset and the ones below need to be signed to account for replacement code - // that is shorter than the original code. - let mut offset: isize = 0; - // Only show an underline in the suggestions if the suggestion is not the - // entirety of the code being shown and the displayed code is not multiline. - if show_underline { - draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); - for part in parts { - let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; - let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display; - - // Do not underline the leading... - let start = part.snippet.len() - .saturating_sub(part.snippet.trim_start().len()); - // ...or trailing spaces. Account for substitutions containing unicode - // characters. - let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) - }); - - let underline_start = (span_start_pos + start) as isize + offset; - let underline_end = (span_start_pos + start + sub_len) as isize + offset; - for p in underline_start..underline_end { + // This offset and the ones below need to be signed to account for replacement code + // that is shorter than the original code. + let mut offset: isize = 0; + // Only show an underline in the suggestions if the suggestion is not the + // entirety of the code being shown and the displayed code is not multiline. + if show_underline { + draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); + for part in parts { + let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; + let span_end_pos = sm.lookup_char_pos(part.span.hi()).col_display; + + // Do not underline the leading... + let start = part.snippet.len() + .saturating_sub(part.snippet.trim_start().len()); + // ...or trailing spaces. Account for substitutions containing unicode + // characters. + let sub_len: usize = part.snippet.trim().chars() + .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum(); + + let underline_start = (span_start_pos + start) as isize + offset; + let underline_end = (span_start_pos + start + sub_len) as isize + offset; + for p in underline_start..underline_end { + buffer.putc(row_num, + max_line_num_len + 3 + p as usize, + '^', + Style::UnderlinePrimary); + } + // underline removals too + if underline_start == underline_end { + for p in underline_start-1..underline_start+1 { buffer.putc(row_num, max_line_num_len + 3 + p as usize, - '^', - Style::UnderlinePrimary); + '-', + Style::UnderlineSecondary); } - // underline removals too - if underline_start == underline_end { - for p in underline_start-1..underline_start+1 { - buffer.putc(row_num, - max_line_num_len + 3 + p as usize, - '-', - Style::UnderlineSecondary); - } - } - - // length of the code after substitution - let full_sub_len = part.snippet.chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) as isize - }); - - // length of the code to be substituted - let snippet_len = span_end_pos as isize - span_start_pos as isize; - // For multiple substitutions, use the position *after* the previous - // substitutions have happened. - offset += full_sub_len - snippet_len; } - row_num += 1; - } - // if we elided some lines, add an ellipsis - if lines.next().is_some() { - buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); - } else if !show_underline { - draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); - row_num += 1; + // length of the code after substitution + let full_sub_len = part.snippet.chars() + .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum::<usize>() as isize; + + // length of the code to be substituted + let snippet_len = span_end_pos as isize - span_start_pos as isize; + // For multiple substitutions, use the position *after* the previous + // substitutions have happened. + offset += full_sub_len - snippet_len; } + row_num += 1; } - if suggestions.len() > MAX_SUGGESTIONS { - let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS); - buffer.puts(row_num, 0, &msg, Style::NoStyle); + + // if we elided some lines, add an ellipsis + if lines.next().is_some() { + buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); + } else if !show_underline { + draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); + row_num += 1; } - emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; } + if suggestions.len() > MAX_SUGGESTIONS { + let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS); + buffer.puts(row_num, 0, &msg, Style::NoStyle); + } + emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; Ok(()) } @@ -1732,7 +1707,7 @@ impl FileWithAnnotatedLines { hi.col_display += 1; } - let ann_type = if lo.line != hi.line { + if lo.line != hi.line { let ml = MultilineAnnotation { depth: 1, line_start: lo.line, @@ -1740,34 +1715,27 @@ impl FileWithAnnotatedLines { start_col: lo.col_display, end_col: hi.col_display, is_primary: span_label.is_primary, - label: span_label.label.clone(), + label: span_label.label, overlaps_exactly: false, }; - multiline_annotations.push((lo.file.clone(), ml.clone())); - AnnotationType::Multiline(ml) + multiline_annotations.push((lo.file, ml)); } else { - AnnotationType::Singleline - }; - let ann = Annotation { - start_col: lo.col_display, - end_col: hi.col_display, - is_primary: span_label.is_primary, - label: span_label.label.clone(), - annotation_type: ann_type, - }; - - if !ann.is_multiline() { + let ann = Annotation { + start_col: lo.col_display, + end_col: hi.col_display, + is_primary: span_label.is_primary, + label: span_label.label, + annotation_type: AnnotationType::Singleline, + }; add_annotation_to_file(&mut output, lo.file, lo.line, ann); - } + }; } } // Find overlapping multiline annotations, put them at different depths multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end)); - for item in multiline_annotations.clone() { - let ann = item.1; - for item in multiline_annotations.iter_mut() { - let ref mut a = item.1; + for (_, ann) in multiline_annotations.clone() { + for (_, a) in multiline_annotations.iter_mut() { // Move all other multiline annotations overlapping with this one // one level to the right. if !(ann.same_span(a)) && @@ -1784,9 +1752,7 @@ impl FileWithAnnotatedLines { let mut max_depth = 0; // max overlapping multiline spans for (file, ann) in multiline_annotations { - if ann.depth > max_depth { - max_depth = ann.depth; - } + max_depth = max(max_depth, ann.depth); let mut end_ann = ann.as_end(); if !ann.overlaps_exactly { // avoid output like |
