Skip to content

Commit

Permalink
Auto merge of rust-lang#84564 - Dylan-DPC:rollup-wxa2yr0, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - rust-lang#84235 (refactor StyledBuffer)
 - rust-lang#84450 (Give a better error when `std` or `core` are missing)
 - rust-lang#84486 (Handle pretty printing of `else if let` clauses without ICEing)
 - rust-lang#84499 (Tweak trait not `use`d suggestion)
 - rust-lang#84516 (Add suggestion to "use break" when attempting to implicit-break a loop)
 - rust-lang#84520 (Improve diagnostics for function passed when a type was expected.)
 - rust-lang#84541 (Inline most raw socket, fd and handle conversions)
 - rust-lang#84547 (Get rid of is_min_const_fn)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 25, 2021
2 parents 3709ae3 + 000a630 commit f8f5968
Show file tree
Hide file tree
Showing 50 changed files with 623 additions and 197 deletions.
90 changes: 55 additions & 35 deletions compiler/rustc_errors/src/styled_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,52 @@
// Code for creating styled buffers

use crate::snippet::{Style, StyledString};
use std::iter;

#[derive(Debug)]
pub struct StyledBuffer {
text: Vec<Vec<char>>,
styles: Vec<Vec<Style>>,
lines: Vec<Vec<StyledChar>>,
}

#[derive(Debug, Clone)]
struct StyledChar {
chr: char,
style: Style,
}

impl StyledChar {
const SPACE: Self = StyledChar::new(' ', Style::NoStyle);

const fn new(chr: char, style: Style) -> Self {
StyledChar { chr, style }
}
}

impl StyledBuffer {
pub fn new() -> StyledBuffer {
StyledBuffer { text: vec![], styles: vec![] }
StyledBuffer { lines: vec![] }
}

/// Returns content of `StyledBuffer` splitted by lines and line styles
pub fn render(&self) -> Vec<Vec<StyledString>> {
// Tabs are assumed to have been replaced by spaces in calling code.
debug_assert!(self.text.iter().all(|r| !r.contains(&'\t')));
debug_assert!(self.lines.iter().all(|r| !r.iter().any(|sc| sc.chr == '\t')));

let mut output: Vec<Vec<StyledString>> = vec![];
let mut styled_vec: Vec<StyledString> = vec![];

for (row, row_style) in iter::zip(&self.text, &self.styles) {
for styled_line in &self.lines {
let mut current_style = Style::NoStyle;
let mut current_text = String::new();

for (&c, &s) in iter::zip(row, row_style) {
if s != current_style {
for sc in styled_line {
if sc.style != current_style {
if !current_text.is_empty() {
styled_vec.push(StyledString { text: current_text, style: current_style });
}
current_style = s;
current_style = sc.style;
current_text = String::new();
}
current_text.push(c);
current_text.push(sc.chr);
}
if !current_text.is_empty() {
styled_vec.push(StyledString { text: current_text, style: current_style });
Expand All @@ -49,29 +62,25 @@ impl StyledBuffer {
}

fn ensure_lines(&mut self, line: usize) {
while line >= self.text.len() {
self.text.push(vec![]);
self.styles.push(vec![]);
if line >= self.lines.len() {
self.lines.resize(line + 1, Vec::new());
}
}

/// Sets `chr` with `style` for given `line`, `col`.
/// If `line` does not exist in our buffer, adds empty lines up to the given
/// and fills the last line with unstyled whitespace.
pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
self.ensure_lines(line);
if col < self.text[line].len() {
self.text[line][col] = chr;
self.styles[line][col] = style;
} else {
let mut i = self.text[line].len();
while i < col {
self.text[line].push(' ');
self.styles[line].push(Style::NoStyle);
i += 1;
}
self.text[line].push(chr);
self.styles[line].push(style);
if col >= self.lines[line].len() {
self.lines[line].resize(col + 1, StyledChar::SPACE);
}
self.lines[line][col] = StyledChar::new(chr, style);
}

/// Sets `string` with `style` for given `line`, starting from `col`.
/// If `line` does not exist in our buffer, adds empty lines up to the given
/// and fills the last line with unstyled whitespace.
pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
let mut n = col;
for c in string.chars() {
Expand All @@ -80,32 +89,40 @@ impl StyledBuffer {
}
}

/// For given `line` inserts `string` with `style` before old content of that line,
/// adding lines if needed
pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
self.ensure_lines(line);
let string_len = string.chars().count();

// Push the old content over to make room for new content
for _ in 0..string_len {
self.styles[line].insert(0, Style::NoStyle);
self.text[line].insert(0, ' ');
if !self.lines[line].is_empty() {
// Push the old content over to make room for new content
for _ in 0..string_len {
self.lines[line].insert(0, StyledChar::SPACE);
}
}

self.puts(line, 0, string, style);
}

/// For given `line` inserts `string` with `style` after old content of that line,
/// adding lines if needed
pub fn append(&mut self, line: usize, string: &str, style: Style) {
if line >= self.text.len() {
if line >= self.lines.len() {
self.puts(line, 0, string, style);
} else {
let col = self.text[line].len();
let col = self.lines[line].len();
self.puts(line, col, string, style);
}
}

pub fn num_lines(&self) -> usize {
self.text.len()
self.lines.len()
}

/// Set `style` for `line`, `col_start..col_end` range if:
/// 1. That line and column range exist in `StyledBuffer`
/// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation`
pub fn set_style_range(
&mut self,
line: usize,
Expand All @@ -119,10 +136,13 @@ impl StyledBuffer {
}
}

/// Set `style` for `line`, `col` if:
/// 1. That line and column exist in `StyledBuffer`
/// 2. `overwrite` is `true` or existing style is `Style::NoStyle` or `Style::Quotation`
pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
if let Some(ref mut line) = self.styles.get_mut(line) {
if let Some(s) = line.get_mut(col) {
if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
if let Some(ref mut line) = self.lines.get_mut(line) {
if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
if overwrite || *s == Style::NoStyle || *s == Style::Quotation {
*s = style;
}
}
Expand Down
24 changes: 22 additions & 2 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,8 +1095,8 @@ impl<'a> State<'a> {

fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
match els {
Some(_else) => {
match _else.kind {
Some(else_) => {
match else_.kind {
// "another else-if"
hir::ExprKind::If(ref i, ref then, ref e) => {
self.cbox(INDENT_UNIT - 1);
Expand All @@ -1114,6 +1114,26 @@ impl<'a> State<'a> {
self.s.word(" else ");
self.print_block(&b)
}
hir::ExprKind::Match(ref expr, arms, _) => {
// else if let desugared to match
assert!(arms.len() == 2, "if let desugars to match with two arms");

self.s.word(" else ");
self.s.word("{");

self.cbox(INDENT_UNIT);
self.ibox(INDENT_UNIT);
self.word_nbsp("match");
self.print_expr_as_cond(&expr);
self.s.space();
self.bopen();
for arm in arms {
self.print_arm(arm);
}
self.bclose(expr.span);

self.s.word("}");
}
// BLEAH, constraints would be great here
_ => {
panic!("print_if saw if with weird alternative");
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,8 +511,11 @@ impl<'a> CrateLoader<'a> {
if dep.is_none() {
self.used_extern_options.insert(name);
}
self.maybe_resolve_crate(name, dep_kind, dep)
.unwrap_or_else(|err| err.report(self.sess, span))
self.maybe_resolve_crate(name, dep_kind, dep).unwrap_or_else(|err| {
let missing_core =
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
err.report(&self.sess, span, missing_core)
})
}

fn maybe_resolve_crate<'b>(
Expand Down
37 changes: 34 additions & 3 deletions compiler/rustc_metadata/src/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,8 @@ pub fn find_plugin_registrar(
) -> (PathBuf, CrateDisambiguator) {
match find_plugin_registrar_impl(sess, metadata_loader, name) {
Ok(res) => res,
Err(err) => err.report(sess, span),
// `core` is always available if we got as far as loading plugins.
Err(err) => err.report(sess, span, false),
}
}

Expand Down Expand Up @@ -883,7 +884,7 @@ crate enum CrateError {
}

impl CrateError {
crate fn report(self, sess: &Session, span: Span) -> ! {
crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
let mut err = match self {
CrateError::NonAsciiName(crate_name) => sess.struct_span_err(
span,
Expand Down Expand Up @@ -1068,7 +1069,37 @@ impl CrateError {
if (crate_name == sym::std || crate_name == sym::core)
&& locator.triple != TargetTriple::from_triple(config::host_triple())
{
err.note(&format!("the `{}` target may not be installed", locator.triple));
if missing_core {
err.note(&format!(
"the `{}` target may not be installed",
locator.triple
));
} else {
err.note(&format!(
"the `{}` target may not support the standard library",
locator.triple
));
}
if missing_core && std::env::var("RUSTUP_HOME").is_ok() {
err.help(&format!(
"consider downloading the target with `rustup target add {}`",
locator.triple
));
}
// Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
// NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
// If it's not a dummy, that means someone added `extern crate std` explicitly and `#![no_std]` won't help.
if !missing_core && span.is_dummy() {
let current_crate =
sess.opts.crate_name.as_deref().unwrap_or("<unknown>");
err.note(&format!(
"`std` is required by `{}` because it does not declare `#![no_std]`",
current_crate
));
}
if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
}
} else if crate_name == sym::profiler_builtins {
err.note(&"the compiler may have been built without the profiler runtime");
}
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ use super::{Field, SourceInfo};

#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationKind {
/// Only permitted in regular `fn`s, prohibited in `const fn`s.
/// Unsafe operation outside `unsafe`.
General,
/// Permitted both in `const fn`s and regular `fn`s.
GeneralAndConstFn,
/// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
/// Has to be handled as a lint for backwards compatibility.
UnsafeFn,
Expand Down
49 changes: 0 additions & 49 deletions compiler/rustc_mir/src/const_eval/fn_queries.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use rustc_attr as attr;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::hir::map::blocks::FnLikeNode;
Expand Down Expand Up @@ -34,54 +33,6 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
}
}

/// Returns `true` if this function must conform to `min_const_fn`
pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// Bail out if the signature doesn't contain `const`
if !tcx.is_const_fn_raw(def_id) {
return false;
}

if tcx.features().staged_api {
// In order for a libstd function to be considered min_const_fn
// it needs to be stable and have no `rustc_const_unstable` attribute.
match tcx.lookup_const_stability(def_id) {
// `rustc_const_unstable` functions don't need to conform.
Some(&attr::ConstStability { ref level, .. }) if level.is_unstable() => false,
None => {
if let Some(stab) = tcx.lookup_stability(def_id) {
if stab.level.is_stable() {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
"stable const functions must have either `rustc_const_stable` or \
`rustc_const_unstable` attribute",
);
// While we errored above, because we don't know if we need to conform, we
// err on the "safe" side and require min_const_fn.
true
} else {
// Unstable functions need not conform to min_const_fn.
false
}
} else {
// Internal functions are forced to conform to min_const_fn.
// Annotate the internal function with a const stability attribute if
// you need to use unstable features.
// Note: this is an arbitrary choice that does not affect stability or const
// safety or anything, it just changes whether we need to annotate some
// internal functions with `rustc_const_stable` or with `rustc_const_unstable`
true
}
}
// Everything else needs to conform, because it would be callable from
// other `min_const_fn` functions.
_ => true,
}
} else {
// users enabling the `const_fn` feature gate can do what they want
!tcx.features().const_fn
}
}

pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
let parent_id = tcx.hir().get_parent_did(hir_id);
if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false }
Expand Down
Loading

0 comments on commit f8f5968

Please sign in to comment.