diff --git a/Cargo.lock b/Cargo.lock index 5d05a09f03893..dbff82cf53608 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4070,6 +4070,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_macros", "rustc_middle", "rustc_serialize", "rustc_session", diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index e14c9ea9a5d1a..4ca59144b2990 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(feature = "nightly", feature(step_trait, rustc_attrs, min_specialization))] -use std::convert::{TryFrom, TryInto}; use std::fmt; #[cfg(feature = "nightly")] use std::iter::Step; diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs index 3db8adb2a2444..2286712f02565 100644 --- a/compiler/rustc_apfloat/src/ieee.rs +++ b/compiler/rustc_apfloat/src/ieee.rs @@ -2,7 +2,6 @@ use crate::{Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO}; use crate::{Float, FloatConvert, ParseError, Round, Status, StatusAnd}; use core::cmp::{self, Ordering}; -use core::convert::TryFrom; use core::fmt::{self, Write}; use core::marker::PhantomData; use core::mem; diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 46dbbd83d1905..4fae5ef845f7d 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -28,7 +28,7 @@ use smallvec::SmallVec; use std::alloc::Layout; use std::cell::{Cell, RefCell}; use std::cmp; -use std::marker::{PhantomData, Send}; +use std::marker::PhantomData; use std::mem::{self, MaybeUninit}; use std::ptr::{self, NonNull}; use std::slice; diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4d80f904ac461..2e86970bcfdc7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -33,7 +33,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use std::convert::TryFrom; use std::fmt; use std::mem; use thin_vec::{thin_vec, ThinVec}; @@ -1735,8 +1734,10 @@ pub enum StrStyle { /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { - /// The original literal token as written in source code. - pub token_lit: token::Lit, + /// The original literal as written in the source code. + pub symbol: Symbol, + /// The original suffix as written in the source code. + pub suffix: Option, /// The "semantic" representation of the literal lowered from the original tokens. /// Strings are unescaped, hexadecimal forms are eliminated, etc. pub kind: LitKind, @@ -1746,13 +1747,14 @@ pub struct MetaItemLit { /// Similar to `MetaItemLit`, but restricted to string literals. #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct StrLit { - /// The original literal token as written in source code. - pub style: StrStyle, + /// The original literal as written in source code. pub symbol: Symbol, + /// The original suffix as written in source code. pub suffix: Option, - pub span: Span, - /// The unescaped "semantic" representation of the literal lowered from the original token. + /// The semantic (unescaped) representation of the literal. pub symbol_unescaped: Symbol, + pub style: StrStyle, + pub span: Span, } impl StrLit { @@ -1798,8 +1800,9 @@ pub enum LitKind { /// A string literal (`"foo"`). The symbol is unescaped, and so may differ /// from the original token's symbol. Str(Symbol, StrStyle), - /// A byte string (`b"foo"`). - ByteStr(Lrc<[u8]>), + /// A byte string (`b"foo"`). Not stored as a symbol because it might be + /// non-utf8, and symbols only allow utf8 strings. + ByteStr(Lrc<[u8]>, StrStyle), /// A byte char (`b'f'`). Byte(u8), /// A character literal (`'a'`). @@ -1824,7 +1827,7 @@ impl LitKind { /// Returns `true` if this literal is byte literal string. pub fn is_bytestr(&self) -> bool { - matches!(self, LitKind::ByteStr(_)) + matches!(self, LitKind::ByteStr(..)) } /// Returns `true` if this is a numeric literal. @@ -3101,7 +3104,7 @@ mod size_asserts { static_assert_size!(ItemKind, 112); static_assert_size!(LitKind, 24); static_assert_size!(Local, 72); - static_assert_size!(MetaItemLit, 48); + static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); static_assert_size!(Pat, 88); static_assert_size!(Path, 24); diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 057cc26b5799e..d99f6ed2c1cd3 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -1,15 +1,15 @@ //! Functions dealing with attributes and meta items. -use crate::ast; use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute}; use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit}; use crate::ast::{MacDelimiter, MetaItem, MetaItemKind, NestedMetaItem, NormalAttr}; -use crate::ast::{Path, PathSegment, StrStyle, DUMMY_NODE_ID}; +use crate::ast::{Path, PathSegment, DUMMY_NODE_ID}; use crate::ptr::P; use crate::token::{self, CommentKind, Delimiter, Token}; use crate::tokenstream::{DelimSpan, Spacing, TokenTree}; use crate::tokenstream::{LazyAttrTokenStream, TokenStream}; use crate::util::comments; +use crate::util::literal::escape_string_symbol; use rustc_data_structures::sync::WorkerLocal; use rustc_index::bit_set::GrowableBitSet; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -321,18 +321,6 @@ impl Attribute { } } -/* Constructors */ - -pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem { - mk_name_value_item(ident, LitKind::Str(str, ast::StrStyle::Cooked), str_span) -} - -pub fn mk_name_value_item(ident: Ident, kind: LitKind, lit_span: Span) -> MetaItem { - let lit = MetaItemLit { token_lit: kind.to_token_lit(), kind, span: lit_span }; - let span = ident.span.to(lit_span); - MetaItem { path: Path::from_ident(ident), kind: MetaItemKind::NameValue(lit), span } -} - pub struct AttrIdGenerator(WorkerLocal>); #[cfg(debug_assertions)] @@ -408,7 +396,7 @@ pub fn mk_attr_name_value_str( val: Symbol, span: Span, ) -> Attribute { - let lit = LitKind::Str(val, StrStyle::Cooked).to_token_lit(); + let lit = token::Lit::new(token::Str, escape_string_symbol(val), None); let expr = P(Expr { id: DUMMY_NODE_ID, kind: ExprKind::Lit(lit), diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 30481eddf9160..4b2850336a03d 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -22,7 +22,6 @@ //! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. use std::fmt::{self, Debug, Display}; -use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; use std::{slice, vec}; diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 482c302950f01..29a5eb4b7c509 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -362,7 +362,7 @@ impl TokenStream { } } -impl iter::FromIterator for TokenStream { +impl FromIterator for TokenStream { fn from_iter>(iter: I) -> Self { TokenStream::new(iter.into_iter().collect::>()) } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index f6f186b51073b..0daeecb53a8b9 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -1,11 +1,31 @@ //! Code related to parsing literals. -use crate::ast::{self, LitKind, MetaItemLit}; +use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; use crate::token::{self, Token}; use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; -use std::ascii; +use std::{ascii, fmt, str}; + +// Escapes a string, represented as a symbol. Reuses the original symbol, +// avoiding interning, if no changes are required. +pub fn escape_string_symbol(symbol: Symbol) -> Symbol { + let s = symbol.as_str(); + let escaped = s.escape_default().to_string(); + if s == escaped { symbol } else { Symbol::intern(&escaped) } +} + +// Escapes a char. +pub fn escape_char_symbol(ch: char) -> Symbol { + let s: String = ch.escape_default().map(Into::::into).collect(); + Symbol::intern(&s) +} + +// Escapes a byte string. +pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol { + let s = bytes.escape_ascii().to_string(); + Symbol::intern(&s) +} #[derive(Debug)] pub enum LitError { @@ -115,9 +135,9 @@ impl LitKind { } }); error?; - LitKind::ByteStr(buf.into()) + LitKind::ByteStr(buf.into(), StrStyle::Cooked) } - token::ByteStrRaw(_) => { + token::ByteStrRaw(n) => { let s = symbol.as_str(); let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); @@ -136,69 +156,95 @@ impl LitKind { symbol.to_string().into_bytes() }; - LitKind::ByteStr(bytes.into()) + LitKind::ByteStr(bytes.into(), StrStyle::Raw(n)) } token::Err => LitKind::Err, }) } +} - /// Attempts to recover a token from semantic literal. - /// This function is used when the original token doesn't exist (e.g. the literal is created - /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn to_token_lit(&self) -> token::Lit { - let (kind, symbol, suffix) = match *self { - LitKind::Str(symbol, ast::StrStyle::Cooked) => { - // Don't re-intern unless the escaped string is different. - let s = symbol.as_str(); - let escaped = s.escape_default().to_string(); - let symbol = if s == escaped { symbol } else { Symbol::intern(&escaped) }; - (token::Str, symbol, None) - } - LitKind::Str(symbol, ast::StrStyle::Raw(n)) => (token::StrRaw(n), symbol, None), - LitKind::ByteStr(ref bytes) => { - let string = bytes.escape_ascii().to_string(); - (token::ByteStr, Symbol::intern(&string), None) +impl fmt::Display for LitKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + LitKind::Byte(b) => { + let b: String = ascii::escape_default(b).map(Into::::into).collect(); + write!(f, "b'{}'", b)?; } - LitKind::Byte(byte) => { - let string: String = ascii::escape_default(byte).map(Into::::into).collect(); - (token::Byte, Symbol::intern(&string), None) + LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?, + LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?, + LitKind::Str(sym, StrStyle::Raw(n)) => write!( + f, + "r{delim}\"{string}\"{delim}", + delim = "#".repeat(n as usize), + string = sym + )?, + LitKind::ByteStr(ref bytes, StrStyle::Cooked) => { + write!(f, "b\"{}\"", escape_byte_str_symbol(bytes))? } - LitKind::Char(ch) => { - let string: String = ch.escape_default().map(Into::::into).collect(); - (token::Char, Symbol::intern(&string), None) + LitKind::ByteStr(ref bytes, StrStyle::Raw(n)) => { + // Unwrap because raw byte string literals can only contain ASCII. + let symbol = str::from_utf8(bytes).unwrap(); + write!( + f, + "br{delim}\"{string}\"{delim}", + delim = "#".repeat(n as usize), + string = symbol + )?; } LitKind::Int(n, ty) => { - let suffix = match ty { - ast::LitIntType::Unsigned(ty) => Some(ty.name()), - ast::LitIntType::Signed(ty) => Some(ty.name()), - ast::LitIntType::Unsuffixed => None, - }; - (token::Integer, sym::integer(n), suffix) + write!(f, "{}", n)?; + match ty { + ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?, + ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?, + ast::LitIntType::Unsuffixed => {} + } } LitKind::Float(symbol, ty) => { - let suffix = match ty { - ast::LitFloatType::Suffixed(ty) => Some(ty.name()), - ast::LitFloatType::Unsuffixed => None, - }; - (token::Float, symbol, suffix) + write!(f, "{}", symbol)?; + match ty { + ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?, + ast::LitFloatType::Unsuffixed => {} + } } - LitKind::Bool(value) => { - let symbol = if value { kw::True } else { kw::False }; - (token::Bool, symbol, None) + LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?, + LitKind::Err => { + // This only shows up in places like `-Zunpretty=hir` output, so we + // don't bother to produce something useful. + write!(f, "")?; } - // This only shows up in places like `-Zunpretty=hir` output, so we - // don't bother to produce something useful. - LitKind::Err => (token::Err, Symbol::intern(""), None), - }; + } - token::Lit::new(kind, symbol, suffix) + Ok(()) } } impl MetaItemLit { - /// Converts token literal into a meta item literal. + /// Converts a token literal into a meta item literal. pub fn from_token_lit(token_lit: token::Lit, span: Span) -> Result { - Ok(MetaItemLit { token_lit, kind: LitKind::from_token_lit(token_lit)?, span }) + Ok(MetaItemLit { + symbol: token_lit.symbol, + suffix: token_lit.suffix, + kind: LitKind::from_token_lit(token_lit)?, + span, + }) + } + + /// Cheaply converts a meta item literal into a token literal. + pub fn as_token_lit(&self) -> token::Lit { + let kind = match self.kind { + LitKind::Bool(_) => token::Bool, + LitKind::Str(_, ast::StrStyle::Cooked) => token::Str, + LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n), + LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr, + LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n), + LitKind::Byte(_) => token::Byte, + LitKind::Char(_) => token::Char, + LitKind::Int(..) => token::Integer, + LitKind::Float(..) => token::Float, + LitKind::Err => token::Err, + }; + + token::Lit::new(kind, self.symbol, self.suffix) } /// Converts an arbitrary token into meta item literal. diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 24e2985cf567a..3946aab646a1a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -97,7 +97,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan( self.lower_span(e.span), - LitKind::ByteStr(bytes.clone()), + LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), )), ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4fa18907fcd46..d67ede6e1302e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -456,8 +456,8 @@ pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> { } // Drop AST to free memory - std::mem::drop(ast_index); - sess.time("drop_ast", || std::mem::drop(krate)); + drop(ast_index); + sess.time("drop_ast", || drop(krate)); // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.unstable_opts.keep_hygiene_data { @@ -958,7 +958,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lit } else { MetaItemLit { - token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None), + symbol: kw::Empty, + suffix: None, kind: LitKind::Err, span: DUMMY_SP, } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d3d8431c163c7..d0e4761a10db8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -376,7 +376,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) { - self.print_token_literal(lit.token_lit, lit.span) + self.print_token_literal(lit.as_token_lit(), lit.span) } fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 4ed16e337d297..3b17f6dd627eb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -2,6 +2,8 @@ use crate::pp::Breaks::Inconsistent; use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT}; use rustc_ast::ptr::P; +use rustc_ast::token; +use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::{self as ast, BlockCheckMode}; @@ -323,7 +325,7 @@ impl<'a> State<'a> { self.print_token_literal(*token_lit, expr.span); } ast::ExprKind::IncludedBytes(bytes) => { - let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit(); + let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None); self.print_token_literal(lit, expr.span) } ast::ExprKind::Cast(expr, ty) => { diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 9ae65c641fd62..7da9bdc38a2a8 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -4,8 +4,6 @@ use rustc_expand::base::{self, DummyResult}; use rustc_session::errors::report_lit_error; use rustc_span::symbol::Symbol; -use std::string::String; - pub fn expand_concat( cx: &mut base::ExtCtxt<'_>, sp: rustc_span::Span, diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 70ce5a6c41929..4c424ea430bdf 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -69,7 +69,7 @@ fn invalid_type_err( Ok(ast::LitKind::Int(_, _)) => { cx.span_err(span, "numeric literal is not a `u8`"); } - Ok(ast::LitKind::ByteStr(_) | ast::LitKind::Byte(_)) => unreachable!(), + Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(), Err(err) => { report_lit_error(&cx.sess.parse_sess, err, token_lit, span); } @@ -97,7 +97,7 @@ fn handle_array_element( )) if val <= u8::MAX.into() => Some(val as u8), Ok(ast::LitKind::Byte(val)) => Some(val), - Ok(ast::LitKind::ByteStr(_)) => { + Ok(ast::LitKind::ByteStr(..)) => { if !*has_errors { cx.struct_span_err(expr.span, "cannot concatenate doubly nested array") .note("byte strings are treated as arrays of bytes") @@ -174,7 +174,7 @@ pub fn expand_concat_bytes( Ok(ast::LitKind::Byte(val)) => { accumulator.push(val); } - Ok(ast::LitKind::ByteStr(ref bytes)) => { + Ok(ast::LitKind::ByteStr(ref bytes, _)) => { accumulator.extend_from_slice(&bytes); } _ => { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index fa5a45730ac7a..2a8dc02849ea7 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,7 +1,7 @@ use crate::cfg_eval::cfg_eval; use rustc_ast as ast; -use rustc_ast::{token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_feature::AttributeTemplate; @@ -130,9 +130,11 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { } fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) { - let help_msg = match lit.token_lit.kind { - token::Str if rustc_lexer::is_ident(lit.token_lit.symbol.as_str()) => { - format!("try using `#[derive({})]`", lit.token_lit.symbol) + let help_msg = match lit.kind { + ast::LitKind::Str(_, ast::StrStyle::Cooked) + if rustc_lexer::is_ident(lit.symbol.as_str()) => + { + format!("try using `#[derive({})]`", lit.symbol) } _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4f396e970ad70..664697e0edaa4 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -41,7 +41,6 @@ use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_target::abi::{Align, Size, VariantIdx}; use std::collections::BTreeSet; -use std::convert::TryFrom; use std::time::{Duration, Instant}; use itertools::Itertools; diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index c27790d8887a3..319f2b2c25ebf 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::convert::TryInto; use either::{Left, Right}; diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 269ae15d49745..b1fdeb01b100a 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -1,5 +1,4 @@ use std::assert_matches::assert_matches; -use std::convert::TryFrom; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::{Float, FloatConvert}; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 7940efcd2b11f..b9be7fa48000b 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -2,8 +2,6 @@ //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE //! and miri. -use std::convert::TryFrom; - use rustc_hir::def_id::DefId; use rustc_middle::mir::{ self, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index 7d94a22c43d71..77c7b4bacb8c8 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -1,5 +1,3 @@ -use std::convert::TryFrom; - use rustc_ast::Mutability; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::TerminatorKind; diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 1f1d0665139d0..949f95c5fa81c 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,5 +1,3 @@ -use std::convert::TryFrom; - use rustc_apfloat::Float; use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 2bc521d5bbe0b..e4f716c31945c 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,6 +1,5 @@ use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use std::convert::TryInto; use std::ops::ControlFlow; /// Checks whether a type contains generic parameters which require substitution. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0e85c7d11bce5..fc65306e440a9 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -4,7 +4,6 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. -use std::convert::TryFrom; use std::fmt::{Display, Write}; use std::num::NonZeroUsize; diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs index c43de3368c62f..10783c5ed1d1c 100644 --- a/compiler/rustc_const_eval/src/util/aggregate.rs +++ b/compiler/rustc_const_eval/src/util/aggregate.rs @@ -3,7 +3,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::VariantIdx; -use std::convert::TryFrom; use std::iter::TrustedLen; /// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields. diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index d98f4e43fe884..b6e866f15efe3 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -1,6 +1,5 @@ use crate::stable_hasher; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::convert::TryInto; use std::hash::{Hash, Hasher}; #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 7099ca7eb88c2..b31092eca9837 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -9,7 +9,6 @@ use crate::fx::FxHashSet; use crate::graph::vec_graph::VecGraph; use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; -use std::cmp::Ord; use std::ops::Range; #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs index e8efbd09a2c38..94232bb7626ec 100644 --- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs @@ -1,5 +1,3 @@ -use std::cmp::Ord; - use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs index 980a540ccba7a..d1d92b905b82e 100644 --- a/compiler/rustc_data_structures/src/owning_ref/mod.rs +++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs @@ -867,11 +867,9 @@ where ///////////////////////////////////////////////////////////////////////////// use std::borrow::Borrow; -use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; -use std::convert::From; +use std::cmp::Ordering; use std::fmt::{self, Debug}; use std::hash::{Hash, Hasher}; -use std::marker::{Send, Sync}; impl Deref for OwningRef { type Target = T; @@ -1096,7 +1094,6 @@ where // std types integration and convenience type defs ///////////////////////////////////////////////////////////////////////////// -use std::boxed::Box; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; use std::sync::Arc; diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs index 320c03d5139f4..a9b187c4ce0a7 100644 --- a/compiler/rustc_data_structures/src/owning_ref/tests.rs +++ b/compiler/rustc_data_structures/src/owning_ref/tests.rs @@ -3,7 +3,7 @@ mod owning_ref { use super::super::OwningRef; use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; - use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; + use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::collections::HashMap; use std::hash::{Hash, Hasher}; @@ -368,7 +368,7 @@ mod owning_handle { mod owning_ref_mut { use super::super::BoxRef; use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; - use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; + use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::collections::HashMap; use std::hash::{Hash, Hasher}; diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index aa7a01eed15c9..1d4014f05acdc 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -86,7 +86,6 @@ use crate::fx::FxHashMap; use std::borrow::Borrow; use std::collections::hash_map::Entry; -use std::convert::Into; use std::error::Error; use std::fs; use std::path::Path; diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index d13313dfd0ebf..03ff5e5b3751f 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,7 +1,6 @@ use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; use std::borrow::Borrow; use std::cmp::Ordering; -use std::iter::FromIterator; use std::mem; use std::ops::{Bound, Index, IndexMut, RangeBounds}; diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index c2f0ae328962b..7af5c14942adf 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -1,7 +1,6 @@ //! A variant of `SortedMap` that preserves insertion order. use std::hash::{Hash, Hasher}; -use std::iter::FromIterator; use crate::stable_hasher::{HashStable, StableHasher}; use rustc_index::vec::{Idx, IndexVec}; diff --git a/compiler/rustc_data_structures/src/sso/either_iter.rs b/compiler/rustc_data_structures/src/sso/either_iter.rs index 131eeef4582de..bca6c0955b905 100644 --- a/compiler/rustc_data_structures/src/sso/either_iter.rs +++ b/compiler/rustc_data_structures/src/sso/either_iter.rs @@ -1,7 +1,5 @@ use std::fmt; -use std::iter::ExactSizeIterator; use std::iter::FusedIterator; -use std::iter::Iterator; /// Iterator which may contain instance of /// one of two specific implementations. diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index ec6a62016a87c..7cdac58197714 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -3,7 +3,6 @@ use crate::fx::FxHashMap; use arrayvec::ArrayVec; use std::fmt; use std::hash::Hash; -use std::iter::FromIterator; use std::ops::Index; // For pointer-sized arguments arrays diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs index 406f0270dcc1b..a4b40138933de 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -1,6 +1,5 @@ use std::fmt; use std::hash::Hash; -use std::iter::FromIterator; use super::map::SsoHashMap; diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index e4f47b22ac358..ed5341c40ef08 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -138,7 +138,7 @@ cfg_if! { } } - pub use std::iter::Iterator as ParallelIterator; + pub use Iterator as ParallelIterator; pub fn par_iter(t: T) -> T::IntoIter { t.into_iter() diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs index d44ccd368b3cb..b0315c93d934d 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs @@ -76,7 +76,7 @@ where fn drop(&mut self) { // No need to drop the tag, as it's Copy unsafe { - std::mem::drop(P::from_usize(self.raw.pointer_raw())); + drop(P::from_usize(self.raw.pointer_raw())); } } } diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 86be0bd8775d7..2417df66bb9d8 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -1,6 +1,5 @@ use std::borrow::Borrow; use std::fmt::Debug; -use std::iter::FromIterator; use std::slice::Iter; use std::vec::IntoIter; diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index f06ca5a0733a5..711eed2b27231 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -45,7 +45,6 @@ use rustc_target::json::ToJson; use std::borrow::Cow; use std::cmp::max; -use std::default::Default; use std::env; use std::ffi::OsString; use std::fs; diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md index 79e7c069a91c4..7c0719dc217d0 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0492.md +++ b/compiler/rustc_error_codes/src/error_codes/E0492.md @@ -55,7 +55,6 @@ wrapper: ``` use std::cell::Cell; -use std::marker::Sync; struct NotThreadSafe { value: Cell, diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl new file mode 100644 index 0000000000000..60d3d3e69abbe --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/mir_build.ftl @@ -0,0 +1,301 @@ +mir_build_unconditional_recursion = function cannot return without recursing + .label = cannot return without recursing + .help = a `loop` may express intention better if this is on purpose + +mir_build_unconditional_recursion_call_site_label = recursive call site + +mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = + call to unsafe function `{$function}` is unsafe and requires unsafe block (error E0133) + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless = + call to unsafe function is unsafe and requires unsafe block (error E0133) + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = + use of inline assembly is unsafe and requires unsafe block (error E0133) + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe + block (error E0133) + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe = + use of mutable static is unsafe and requires unsafe block (error E0133) + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe = + use of extern static is unsafe and requires unsafe block (error E0133) + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe = + dereference of raw pointer is unsafe and requires unsafe block (error E0133) + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe = + access to union field is unsafe and requires unsafe block (error E0133) + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe = + mutation of layout constrained field is unsafe and requires unsafe block (error E0133) + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe block (error E0133) + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block (error E0133) + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` + +mir_build_call_to_unsafe_fn_requires_unsafe = + call to unsafe function `{$function}` is unsafe and requires unsafe block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_nameless = + call to unsafe function is unsafe and requires unsafe block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + call to unsafe function `{$function}` is unsafe and requires unsafe function or block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed = + call to unsafe function is unsafe and requires unsafe function or block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + +mir_build_inline_assembly_requires_unsafe = + use of inline assembly is unsafe and requires unsafe block + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of inline assembly is unsafe and requires unsafe function or block + .note = inline assembly is entirely unchecked and can cause undefined behavior + .label = use of inline assembly + +mir_build_initializing_type_with_requires_unsafe = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block + .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior + .label = initializing type with `rustc_layout_scalar_valid_range` attr + +mir_build_mutable_static_requires_unsafe = + use of mutable static is unsafe and requires unsafe block + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of mutable static is unsafe and requires unsafe function or block + .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + .label = use of mutable static + +mir_build_extern_static_requires_unsafe = + use of extern static is unsafe and requires unsafe block + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + use of extern static is unsafe and requires unsafe function or block + .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + .label = use of extern static + +mir_build_deref_raw_pointer_requires_unsafe = + dereference of raw pointer is unsafe and requires unsafe block + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + dereference of raw pointer is unsafe and requires unsafe function or block + .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + .label = dereference of raw pointer + +mir_build_union_field_requires_unsafe = + access to union field is unsafe and requires unsafe block + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + access to union field is unsafe and requires unsafe function or block + .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior + .label = access to union field + +mir_build_mutation_of_layout_constrained_field_requires_unsafe = + mutation of layout constrained field is unsafe and requires unsafe block + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + mutation of layout constrained field is unsafe and requires unsafe function or block + .note = mutating layout constrained fields cannot statically be checked for valid values + .label = mutation of layout constrained field + +mir_build_borrow_of_layout_constrained_field_requires_unsafe = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe block + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + .label = borrow of layout constrained field with interior mutability + +mir_build_call_to_fn_with_requires_unsafe = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` + +mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = + call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block + .note = can only be called if the required target features are available + .label = call to function with `#[target_feature]` + +mir_build_unused_unsafe = unnecessary `unsafe` block + .label = unnecessary `unsafe` block + +mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block +mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn + +mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty + .def_note = `{$peeled_ty}` defined here + .type_note = the matched value is of type `{$ty}` + .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive + .reference_note = references are always considered inhabited + .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +mir_build_static_in_pattern = statics cannot be referenced in patterns + +mir_build_assoc_const_in_pattern = associated consts cannot be referenced in patterns + +mir_build_const_param_in_pattern = const parameters cannot be referenced in patterns + +mir_build_non_const_path = runtime values cannot be referenced in patterns + +mir_build_unreachable_pattern = unreachable pattern + .label = unreachable pattern + .catchall_label = matches any value + +mir_build_const_pattern_depends_on_generic_parameter = + constant pattern depends on a generic parameter + +mir_build_could_not_eval_const_pattern = could not evaluate constant pattern + +mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = + lower range bound must be less than or equal to upper + .label = lower bound larger than upper bound + .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. + +mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper + +mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count -> + [one] pattern + *[other] patterns + } in let chain + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match + .help = consider moving {$count -> + [one] it + *[other] them + } outside of the construct + +mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> + [one] pattern + *[other] patterns + } in let chain + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match + .help = consider moving {$count -> + [one] it + *[other] them + } into the body + +mir_build_bindings_with_variant_name = + pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}` + .suggestion = to match on the variant, qualify the path + +mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `let` is useless + .help = consider removing `let` + +mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `if let` is useless + .help = consider replacing the `if let` with a `let` + +mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the guard is useless + .help = consider removing the guard and adding a `let` inside the match arm + +mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the `else` clause is useless + .help = consider removing the `else` clause + +mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count -> + [one] pattern + *[other] patterns + } + .note = {$count -> + [one] this pattern + *[other] these patterns + } will always match, so the loop will never exit + .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it + +mir_build_borrow_of_moved_value = borrow of moved value + .label = value moved into `{$name}` here + .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait + .value_borrowed_label = value borrowed here after move + .suggestion = borrow this binding in the pattern to avoid moving the value + +mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time + .label = first mutable borrow, by `{$name}`, occurs here + .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here + .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here + .moved = also moved into `{$name_moved}` here diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 418ba3c74d776..25d0e736e599f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -57,6 +57,7 @@ fluent_messages! { lint => "../locales/en-US/lint.ftl", metadata => "../locales/en-US/metadata.ftl", middle => "../locales/en-US/middle.ftl", + mir_build => "../locales/en-US/mir_build.ftl", mir_dataflow => "../locales/en-US/mir_dataflow.ftl", monomorphize => "../locales/en-US/monomorphize.ftl", parse => "../locales/en-US/parse.ftl", diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index cb39e997436e0..628cb90903fee 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -59,7 +59,7 @@ into_diagnostic_arg_using_display!( i128, u128, std::io::Error, - std::boxed::Box, + Box, std::num::NonZeroU32, hir::Target, Edition, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 6f159663e80cf..00453f78287ef 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -34,7 +34,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; -use std::default::Default; use std::iter; use std::path::PathBuf; use std::rc::Rc; @@ -1232,7 +1231,7 @@ pub fn expr_to_spanned_string<'a>( Err(match expr.kind { ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)), - Ok(ast::LitKind::ByteStr(_)) => { + Ok(ast::LitKind::ByteStr(..)) => { let mut err = cx.struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); err.span_suggestion( diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 4812bdd9dd8b9..ef50efb81253f 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -1,8 +1,7 @@ use crate::base::ExtCtxt; -use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; -use rustc_data_structures::sync::Lrc; +use rustc_ast::{attr, token, util::literal}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -332,36 +331,36 @@ impl<'a> ExtCtxt<'a> { self.expr_struct(span, self.path_ident(span, id), fields) } - fn expr_lit(&self, span: Span, lit_kind: ast::LitKind) -> P { - let token_lit = lit_kind.to_token_lit(); - self.expr(span, ast::ExprKind::Lit(token_lit)) + pub fn expr_usize(&self, span: Span, n: usize) -> P { + let suffix = Some(ast::UintTy::Usize.name()); + let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_usize(&self, span: Span, i: usize) -> P { - self.expr_lit( - span, - ast::LitKind::Int(i as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), - ) - } - - pub fn expr_u32(&self, sp: Span, u: u32) -> P { - self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U32))) + pub fn expr_u32(&self, span: Span, n: u32) -> P { + let suffix = Some(ast::UintTy::U32.name()); + let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_bool(&self, sp: Span, value: bool) -> P { - self.expr_lit(sp, ast::LitKind::Bool(value)) + pub fn expr_bool(&self, span: Span, value: bool) -> P { + let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_str(&self, sp: Span, s: Symbol) -> P { - self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) + pub fn expr_str(&self, span: Span, s: Symbol) -> P { + let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_char(&self, sp: Span, ch: char) -> P { - self.expr_lit(sp, ast::LitKind::Char(ch)) + pub fn expr_char(&self, span: Span, ch: char) -> P { + let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None); + self.expr(span, ast::ExprKind::Lit(lit)) } - pub fn expr_byte_str(&self, sp: Span, bytes: Vec) -> P { - self.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(bytes))) + pub fn expr_byte_str(&self, span: Span, bytes: Vec) -> P { + let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None); + self.expr(span, ast::ExprKind::Lit(lit)) } /// `[expr1, expr2, ...]` diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 7616579611711..768bdab8a5419 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -6,6 +6,7 @@ use pm::{Delimiter, Level, LineColumn}; use rustc_ast as ast; use rustc_ast::token; use rustc_ast::tokenstream::{self, Spacing::*, TokenStream}; +use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -526,7 +527,7 @@ impl server::TokenStream for Rustc<'_, '_> { Ok(tokenstream::TokenStream::token_alone(token::Literal(*token_lit), expr.span)) } ast::ExprKind::IncludedBytes(bytes) => { - let lit = ast::LitKind::ByteStr(bytes.clone()).to_token_lit(); + let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None); Ok(tokenstream::TokenStream::token_alone(token::TokenKind::Literal(lit), expr.span)) } ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index 6e2fbf96cbfb3..e870aa543d0b5 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -6,7 +6,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::Ident; use rustc_span::Span; -use std::iter::{Enumerate, ExactSizeIterator}; +use std::iter::Enumerate; pub struct EnumerateAndAdjust { enumerate: Enumerate, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b065ace6bf5e1..69eb96fe8e925 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -31,7 +31,6 @@ use rustc_trait_selection::traits::{ }; use std::cell::LazyCell; -use std::convert::TryInto; use std::iter; use std::ops::{ControlFlow, Deref}; diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 94bab9f339d8c..ef98c4ba54cbd 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1245,7 +1245,7 @@ impl<'a> State<'a> { fn print_literal(&mut self, lit: &hir::Lit) { self.maybe_print_comment(lit.span.lo()); - self.word(lit.node.to_token_lit().to_string()) + self.word(lit.node.to_string()) } fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 60fec05d36d6d..93618c6141730 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match lit.node { ast::LitKind::Str(..) => tcx.mk_static_str(), - ast::LitKind::ByteStr(ref v) => { + ast::LitKind::ByteStr(ref v, _) => { tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.u8, v.len() as u64)) } ast::LitKind::Byte(_) => tcx.types.u8, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index decd317d9fc9b..6810353f9e778 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. let mut pat_ty = ty; - if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind { + if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind { let expected = self.structurally_resolved_type(span, expected); if let ty::Ref(_, inner_ty, _) = expected.kind() && matches!(inner_ty.kind(), ty::Slice(_)) diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index a8acaf6597aab..d1d328128bc15 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -30,8 +30,6 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use std::iter::FromIterator; -use std::vec::Vec; const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; const EXCEPT: Symbol = sym::except; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 97ebed0585579..1fd2b9b0d7b7b 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -113,7 +113,6 @@ use rustc_span::Symbol; use std::fs as std_fs; use std::io::{self, ErrorKind}; -use std::mem; use std::path::{Path, PathBuf}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -305,7 +304,7 @@ pub fn prepare_session_directory( } delete_session_dir_lock_file(sess, &lock_file_path); - mem::drop(directory_lock); + drop(directory_lock); } } } @@ -864,7 +863,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { // Let's make it explicit that the file lock is released at this point, // or rather, that we held on to it until here - mem::drop(lock); + drop(lock); } Err(_) => { debug!( @@ -898,7 +897,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { // Let's make it explicit that the file lock is released at this point, // or rather, that we held on to it until here - mem::drop(lock); + drop(lock); } Ok(()) diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 39aa27a23c1d2..c18a911b2fbcd 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -4,7 +4,6 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; use std::fmt::Debug; use std::hash::Hash; -use std::iter::FromIterator; use std::marker::PhantomData; use std::ops::{Index, IndexMut, RangeBounds}; use std::slice; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2b8f6557c829b..e903cb86dd204 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -25,7 +25,6 @@ use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrate use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; -use std::iter::FromIterator; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 3fbabbc6344a7..50d6d5b9bab91 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -34,7 +34,6 @@ pub use crate::cursor::Cursor; use self::LiteralKind::*; use self::TokenKind::*; use crate::cursor::EOF_CHAR; -use std::convert::TryFrom; /// Parsed token. /// It doesn't contain information about data that has been parsed, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 297b509d4023d..8446da6098ee9 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -16,7 +16,6 @@ use rustc_target::abi::{Abi, Size, WrappingRange}; use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::spec::abi::Abi as SpecAbi; -use std::cmp; use std::iter; use std::ops::ControlFlow; @@ -531,7 +530,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits { _ => {} }; - fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { + fn is_valid(binop: hir::BinOp, v: T, min: T, max: T) -> bool { match binop.node { hir::BinOpKind::Lt => v > min && v <= max, hir::BinOpKind::Le => v >= min && v < max, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 29fe6110797e3..716655c7f144d 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -7,7 +7,6 @@ use rustc_middle::ty::ParameterizedOverTcx; use rustc_serialize::opaque::FileEncoder; use rustc_serialize::Encoder as _; use rustc_span::hygiene::MacroKind; -use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index efa9464529e71..0b55757eb0382 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -3,7 +3,6 @@ use rustc_macros::HashStable; use rustc_span::Symbol; -use std::cmp::Ord; use std::fmt::{self, Debug, Formatter}; rustc_index::newtype_index! { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index d79cd8b7a8a4b..8fe349d9640da 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -95,7 +95,6 @@ mod pointer; mod queries; mod value; -use std::convert::TryFrom; use std::fmt; use std::io; use std::io::{Read, Write}; diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 9c270ba1ec179..b083099107620 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -3,7 +3,6 @@ use super::{AllocId, InterpResult}; use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; -use std::convert::{TryFrom, TryInto}; use std::fmt; //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index e6636e50e6e7a..88fb14eb35942 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -1,4 +1,3 @@ -use std::convert::{TryFrom, TryInto}; use std::fmt; use either::{Either, Left, Right}; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a513444e1e08b..db4fe6f886b25 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -36,7 +36,6 @@ use rustc_span::{Span, DUMMY_SP}; use either::Either; use std::borrow::Cow; -use std::convert::TryInto; use std::fmt::{self, Debug, Display, Formatter, Write}; use std::ops::{ControlFlow, Index, IndexMut}; use std::{iter, mem}; diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index fb152b63f6344..d40d7de5f315f 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -12,7 +12,6 @@ use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_span::source_map::Span; -use std::iter::FromIterator; pub mod type_op { use crate::ty::fold::TypeFoldable; diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index f3186e1c30c3d..2a8a4d598882d 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -2,7 +2,6 @@ use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_target::abi::Size; -use std::convert::{TryFrom, TryInto}; use std::fmt; use std::num::NonZeroU8; diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index becc2b805dd1e..d9721863a58c8 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,5 +1,3 @@ -use std::convert::TryInto; - use super::Const; use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 5303341ba443c..01e96fa5c7ade 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -23,7 +23,6 @@ use smallvec::SmallVec; use std::cell::Cell; use std::char; use std::collections::BTreeMap; -use std::convert::TryFrom; use std::fmt::{self, Write as _}; use std::iter; use std::ops::{ControlFlow, Deref, DerefMut}; diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 6eae94511e4d6..802925dfb043e 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -1,4 +1,3 @@ -use std::convert::TryFrom; use std::fmt; use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 2baa3bfcb6401..4ad3343d3031b 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -17,6 +17,7 @@ rustc_index = { path = "../rustc_index" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } +rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 717c62315745b..3b7ed818dc9b7 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -135,14 +135,14 @@ pub(crate) fn lit_to_mir_constant<'tcx>( let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: s.len() } } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: data.len() } } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let id = tcx.allocate_bytes(data); ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx)) } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index e90db2c7d05e7..7edcd46a34f29 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -30,7 +30,6 @@ mod test; mod util; use std::borrow::Borrow; -use std::convert::TryFrom; use std::mem; impl<'a, 'tcx> Builder<'a, 'tcx> { diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index bd435f9ab0095..cbd494862a01f 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -7,7 +7,6 @@ use rustc_middle::thir::*; use rustc_middle::ty; use rustc_middle::ty::TypeVisitable; use smallvec::SmallVec; -use std::convert::TryInto; impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn field_match_pairs<'pat>( diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index fb1ea9ed300ad..3f0f05711edd3 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,7 +1,7 @@ use crate::build::ExprCategory; +use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; @@ -12,7 +12,6 @@ use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::Symbol; use rustc_span::Span; -use std::borrow::Cow; use std::ops::Bound; struct UnsafetyVisitor<'a, 'tcx> { @@ -46,7 +45,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { self.warn_unused_unsafe( hir_id, block_span, - Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")), + Some(UnusedUnsafeEnclosing::Block { + span: self.tcx.sess.source_map().guess_head_span(enclosing_span), + }), ); f(self); } else { @@ -60,7 +61,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { hir_id, span, if self.unsafe_op_in_unsafe_fn_allowed() { - self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn")) + self.body_unsafety + .unsafe_fn_sig_span() + .map(|span| UnusedUnsafeEnclosing::Function { span }) } else { None }, @@ -83,30 +86,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { - let (description, note) = kind.description_and_note(self.tcx); // unsafe_op_in_unsafe_fn is disallowed - self.tcx.struct_span_lint_hir( - UNSAFE_OP_IN_UNSAFE_FN, - self.hir_context, - span, - format!("{} is unsafe and requires unsafe block (error E0133)", description,), - |lint| lint.span_label(span, kind.simple_description()).note(note), - ) + kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); } SafetyContext::Safe => { - let (description, note) = kind.description_and_note(self.tcx); - let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" }; - struct_span_err!( - self.tcx.sess, - span, - E0133, - "{} is unsafe and requires unsafe{} block", - description, - fn_sugg, - ) - .span_label(span, kind.simple_description()) - .note(note) - .emit(); + kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed); } } } @@ -115,17 +99,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { &self, hir_id: hir::HirId, block_span: Span, - enclosing_unsafe: Option<(Span, &'static str)>, + enclosing_unsafe: Option, ) { let block_span = self.tcx.sess.source_map().guess_head_span(block_span); - let msg = "unnecessary `unsafe` block"; - self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| { - lint.span_label(block_span, msg); - if let Some((span, kind)) = enclosing_unsafe { - lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind)); - } - lint - }); + self.tcx.emit_spanned_lint( + UNUSED_UNSAFE, + hir_id, + block_span, + UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe }, + ); } /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node. @@ -529,81 +511,189 @@ enum UnsafeOpKind { use UnsafeOpKind::*; impl UnsafeOpKind { - pub fn simple_description(&self) -> &'static str { - match self { - CallToUnsafeFunction(..) => "call to unsafe function", - UseOfInlineAssembly => "use of inline assembly", - InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr", - UseOfMutableStatic => "use of mutable static", - UseOfExternStatic => "use of extern static", - DerefOfRawPointer => "dereference of raw pointer", - AccessToUnionField => "access to union field", - MutationOfLayoutConstrainedField => "mutation of layout constrained field", - BorrowOfLayoutConstrainedField => { - "borrow of layout constrained field with interior mutability" - } - CallToFunctionWith(..) => "call to function with `#[target_feature]`", - } - } - - pub fn description_and_note(&self, tcx: TyCtxt<'_>) -> (Cow<'static, str>, &'static str) { + pub fn emit_unsafe_op_in_unsafe_fn_lint( + &self, + tcx: TyCtxt<'_>, + hir_id: hir::HirId, + span: Span, + ) { match self { - CallToUnsafeFunction(did) => ( - if let Some(did) = did { - Cow::from(format!("call to unsafe function `{}`", tcx.def_path_str(*did))) - } else { - Cow::Borrowed(self.simple_description()) + CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { + span, + function: &tcx.def_path_str(did.unwrap()), }, - "consult the function's documentation for information on how to avoid undefined \ - behavior", ), - UseOfInlineAssembly => ( - Cow::Borrowed(self.simple_description()), - "inline assembly is entirely unchecked and can cause undefined behavior", + CallToUnsafeFunction(..) => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span }, + ), + UseOfInlineAssembly => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span }, ), - InitializingTypeWith => ( - Cow::Borrowed(self.simple_description()), - "initializing a layout restricted type's field with a value outside the valid \ - range is undefined behavior", + InitializingTypeWith => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span }, ), - UseOfMutableStatic => ( - Cow::Borrowed(self.simple_description()), - "mutable statics can be mutated by multiple threads: aliasing violations or data \ - races will cause undefined behavior", + UseOfMutableStatic => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span }, ), - UseOfExternStatic => ( - Cow::Borrowed(self.simple_description()), - "extern statics are not controlled by the Rust type system: invalid data, \ - aliasing violations or data races will cause undefined behavior", + UseOfExternStatic => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span }, ), - DerefOfRawPointer => ( - Cow::Borrowed(self.simple_description()), - "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \ - and cause data races: all of these are undefined behavior", + DerefOfRawPointer => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span }, ), - AccessToUnionField => ( - Cow::Borrowed(self.simple_description()), - "the field may not be properly initialized: using uninitialized data will cause \ - undefined behavior", + AccessToUnionField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span }, ), - MutationOfLayoutConstrainedField => ( - Cow::Borrowed(self.simple_description()), - "mutating layout constrained fields cannot statically be checked for valid values", + MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, ), - BorrowOfLayoutConstrainedField => ( - Cow::Borrowed(self.simple_description()), - "references to fields of layout constrained fields lose the constraints. Coupled \ - with interior mutability, the field can be changed to invalid values", + BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, ), - CallToFunctionWith(did) => ( - Cow::from(format!( - "call to function `{}` with `#[target_feature]`", - tcx.def_path_str(*did) - )), - "can only be called if the required target features are available", + CallToFunctionWith(did) => tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + hir_id, + span, + UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { + span, + function: &tcx.def_path_str(*did), + }, ), } } + + pub fn emit_requires_unsafe_err( + &self, + tcx: TyCtxt<'_>, + span: Span, + unsafe_op_in_unsafe_fn_allowed: bool, + ) { + match self { + CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + function: &tcx.def_path_str(did.unwrap()), + }); + } + CallToUnsafeFunction(did) if did.is_some() => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe { + span, + function: &tcx.def_path_str(did.unwrap()), + }); + } + CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span }, + ); + } + CallToUnsafeFunction(..) => { + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span }); + } + UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfInlineAssembly => { + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span }); + } + InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + InitializingTypeWith => { + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span }); + } + UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfMutableStatic => { + tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span }); + } + UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + UseOfExternStatic => { + tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span }); + } + DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + DerefOfRawPointer => { + tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span }); + } + AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess + .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + } + AccessToUnionField => { + tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span }); + } + MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + }, + ); + } + MutationOfLayoutConstrainedField => { + tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span }); + } + BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err( + BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }, + ); + } + BorrowOfLayoutConstrainedField => { + tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span }); + } + CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { + tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + function: &tcx.def_path_str(*did), + }); + } + CallToFunctionWith(did) => { + tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { + span, + function: &tcx.def_path_str(*did), + }); + } + } + } } pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs new file mode 100644 index 0000000000000..f3bfafb37b77f --- /dev/null +++ b/compiler/rustc_mir_build/src/errors.rs @@ -0,0 +1,616 @@ +use crate::thir::pattern::MatchCheckCtxt; +use rustc_errors::Handler; +use rustc_errors::{ + error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, +}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_middle::ty::{self, Ty}; +use rustc_span::{symbol::Ident, Span}; + +#[derive(LintDiagnostic)] +#[diag(mir_build_unconditional_recursion)] +#[help] +pub struct UnconditionalRecursion { + #[label] + pub span: Span, + #[label(mir_build_unconditional_recursion_call_site_label)] + pub call_sites: Vec, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)] +pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)] +#[note] +pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeNameless { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(Diagnostic)] +#[diag( + mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfInlineAssemblyRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")] +#[note] +pub struct InitializingTypeWithRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag( + mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfMutableStaticRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")] +#[note] +pub struct UseOfExternStaticRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")] +#[note] +pub struct DerefOfRawPointerRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_union_field_requires_unsafe, code = "E0133")] +#[note] +pub struct AccessToUnionFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[note] +pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag( + mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")] +#[note] +pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag( + mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + code = "E0133" +)] +#[note] +pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")] +#[note] +pub struct CallToFunctionWithRequiresUnsafe<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(Diagnostic)] +#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")] +#[note] +pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { + #[primary_span] + #[label] + pub span: Span, + pub function: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unused_unsafe)] +pub struct UnusedUnsafe { + #[label] + pub span: Span, + #[subdiagnostic] + pub enclosing: Option, +} + +#[derive(Subdiagnostic)] +pub enum UnusedUnsafeEnclosing { + #[label(mir_build_unused_unsafe_enclosing_block_label)] + Block { + #[primary_span] + span: Span, + }, + #[label(mir_build_unused_unsafe_enclosing_fn_label)] + Function { + #[primary_span] + span: Span, + }, +} + +pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { + pub cx: &'m MatchCheckCtxt<'p, 'tcx>, + pub expr_span: Span, + pub span: Span, + pub ty: Ty<'tcx>, +} + +impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { + fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = handler.struct_span_err_with_code( + self.span, + rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty, + error_code!(E0004), + ); + + let peeled_ty = self.ty.peel_refs(); + diag.set_arg("ty", self.ty); + diag.set_arg("peeled_ty", peeled_ty); + + if let ty::Adt(def, _) = peeled_ty.kind() { + let def_span = self + .cx + .tcx + .hir() + .get_if_local(def.did()) + .and_then(|node| node.ident()) + .map(|ident| ident.span) + .unwrap_or_else(|| self.cx.tcx.def_span(def.did())); + + // workaround to make test pass + let mut span: MultiSpan = def_span.into(); + span.push_span_label(def_span, ""); + + diag.span_note(span, rustc_errors::fluent::def_note); + } + + let is_variant_list_non_exhaustive = match self.ty.kind() { + ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => { + true + } + _ => false, + }; + + if is_variant_list_non_exhaustive { + diag.note(rustc_errors::fluent::non_exhaustive_type_note); + } else { + diag.note(rustc_errors::fluent::type_note); + } + + if let ty::Ref(_, sub_ty, _) = self.ty.kind() { + if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) { + diag.note(rustc_errors::fluent::reference_note); + } + } + + let mut suggestion = None; + let sm = self.cx.tcx.sess.source_map(); + if self.span.eq_ctxt(self.expr_span) { + // Get the span for the empty match body `{}`. + let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) { + (format!("\n{}", snippet), " ") + } else { + (" ".to_string(), "") + }; + suggestion = Some(( + self.span.shrink_to_hi().with_hi(self.expr_span.hi()), + format!( + " {{{indentation}{more}_ => todo!(),{indentation}}}", + indentation = indentation, + more = more, + ), + )); + } + + if let Some((span, sugg)) = suggestion { + diag.span_suggestion_verbose( + span, + rustc_errors::fluent::suggestion, + sugg, + Applicability::HasPlaceholders, + ); + } else { + diag.help(rustc_errors::fluent::help); + } + + diag + } +} + +#[derive(Diagnostic)] +#[diag(mir_build_static_in_pattern, code = "E0158")] +pub struct StaticInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_assoc_const_in_pattern, code = "E0158")] +pub struct AssocConstInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_const_param_in_pattern, code = "E0158")] +pub struct ConstParamInPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_non_const_path, code = "E0080")] +pub struct NonConstPath { + #[primary_span] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_unreachable_pattern)] +pub struct UnreachablePattern { + #[label] + pub span: Option, + #[label(catchall_label)] + pub catchall: Option, +} + +#[derive(Diagnostic)] +#[diag(mir_build_const_pattern_depends_on_generic_parameter)] +pub struct ConstPatternDependsOnGenericParameter { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_could_not_eval_const_pattern)] +pub struct CouldNotEvalConstPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")] +pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper { + #[primary_span] + #[label] + pub span: Span, + #[note(teach_note)] + pub teach: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")] +pub struct LowerRangeBoundMustBeLessThanUpper { + #[primary_span] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_leading_irrefutable_let_patterns)] +#[note] +#[help] +pub struct LeadingIrrefutableLetPatterns { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_trailing_irrefutable_let_patterns)] +#[note] +#[help] +pub struct TrailingIrrefutableLetPatterns { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_bindings_with_variant_name, code = "E0170")] +pub struct BindingsWithVariantName { + #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")] + pub suggestion: Option, + pub ty_path: String, + pub ident: Ident, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_irrefutable_let_patterns_generic_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsGenericLet { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_irrefutable_let_patterns_if_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsIfLet { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_irrefutable_let_patterns_if_let_guard)] +#[note] +#[help] +pub struct IrrefutableLetPatternsIfLetGuard { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_irrefutable_let_patterns_let_else)] +#[note] +#[help] +pub struct IrrefutableLetPatternsLetElse { + pub count: usize, +} + +#[derive(LintDiagnostic)] +#[diag(mir_build_irrefutable_let_patterns_while_let)] +#[note] +#[help] +pub struct IrrefutableLetPatternsWhileLet { + pub count: usize, +} + +#[derive(Diagnostic)] +#[diag(mir_build_borrow_of_moved_value)] +pub struct BorrowOfMovedValue<'tcx> { + #[primary_span] + pub span: Span, + #[label] + #[label(occurs_because_label)] + pub binding_span: Span, + #[label(value_borrowed_label)] + pub conflicts_ref: Vec, + pub name: Ident, + pub ty: Ty<'tcx>, + #[suggestion(code = "ref ", applicability = "machine-applicable")] + pub suggest_borrowing: Option, +} + +#[derive(Diagnostic)] +#[diag(mir_build_multiple_mut_borrows)] +pub struct MultipleMutBorrows { + #[primary_span] + pub span: Span, + #[label] + pub binding_span: Span, + #[subdiagnostic(eager)] + pub occurences: Vec, + pub name: Ident, +} + +#[derive(Subdiagnostic)] +pub enum MultipleMutBorrowOccurence { + #[label(mutable_borrow)] + Mutable { + #[primary_span] + span: Span, + name_mut: Ident, + }, + #[label(immutable_borrow)] + Immutable { + #[primary_span] + span: Span, + name_immut: Ident, + }, + #[label(moved)] + Moved { + #[primary_span] + span: Span, + name_moved: Ident, + }, +} diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 8797529459534..2b05e92fdcf20 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -19,6 +19,7 @@ extern crate rustc_middle; mod build; mod check_unsafety; +mod errors; mod lints; pub mod thir; diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index b21f30efce807..8529c64cd5cca 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -1,3 +1,4 @@ +use crate::errors::UnconditionalRecursion; use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; @@ -36,19 +37,11 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let sp = tcx.def_span(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - tcx.struct_span_lint_hir( + tcx.emit_spanned_lint( UNCONDITIONAL_RECURSION, hir_id, sp, - "function cannot return without recursing", - |lint| { - lint.span_label(sp, "cannot return without recursing"); - // offer some help to the programmer. - for call_span in vis.reachable_recursive_calls { - lint.span_label(call_span, "recursive call site"); - } - lint.help("a `loop` may express intention better if this is on purpose") - }, + UnconditionalRecursion { span: sp, call_sites: vis.reachable_recursive_calls }, ); } } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index a9ed945d4a15a..57ae6a3652df5 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -33,13 +33,13 @@ pub(crate) fn lit_to_const<'tcx>( let str_bytes = s.as_str().as_bytes(); ty::ValTree::from_raw_bytes(tcx, str_bytes) } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } - (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { + (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { let bytes = data as &[u8]; ty::ValTree::from_raw_bytes(tcx, bytes) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e369dba55242c..ddd52114ecfe6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -4,11 +4,13 @@ use super::usefulness::{ }; use super::{PatCtxt, PatternError}; +use crate::errors::*; + use rustc_arena::TypedArena; use rustc_ast::Mutability; use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::*; @@ -107,28 +109,20 @@ impl PatCtxt<'_, '_> { for error in &self.errors { match *error { PatternError::StaticInPattern(span) => { - self.span_e0158(span, "statics cannot be referenced in patterns") + self.tcx.sess.emit_err(StaticInPattern { span }); } PatternError::AssocConstInPattern(span) => { - self.span_e0158(span, "associated consts cannot be referenced in patterns") + self.tcx.sess.emit_err(AssocConstInPattern { span }); } PatternError::ConstParamInPattern(span) => { - self.span_e0158(span, "const parameters cannot be referenced in patterns") + self.tcx.sess.emit_err(ConstParamInPattern { span }); } PatternError::NonConstPath(span) => { - rustc_middle::mir::interpret::struct_error( - self.tcx.at(span), - "runtime values cannot be referenced in patterns", - ) - .emit(); + self.tcx.sess.emit_err(NonConstPath { span }); } } } } - - fn span_e0158(&self, span: Span, text: &str) { - struct_span_err!(self.tcx.sess, span, E0158, "{}", text).emit(); - } } impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { @@ -345,29 +339,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { ); return true; } - let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| { - let span_start = affix[0].unwrap().0; - let span_end = affix.last().unwrap().unwrap().0; - let span = span_start.to(span_end); - let cnt = affix.len(); - let s = pluralize!(cnt); - cx.tcx.struct_span_lint_hir( - IRREFUTABLE_LET_PATTERNS, - top, - span, - format!("{kind} irrefutable pattern{s} in let chain"), - |lint| { - lint.note(format!( - "{these} pattern{s} will always match", - these = pluralize!("this", cnt), - )) - .help(format!( - "consider moving {} {suggestion}", - if cnt > 1 { "them" } else { "it" } - )) - }, - ); - }; if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 { // The chain has a non-zero prefix of irrefutable `let` statements. @@ -381,13 +352,21 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; - lint_affix(prefix, "leading", "outside of the construct"); + let span_start = prefix[0].unwrap().0; + let span_end = prefix.last().unwrap().unwrap().0; + let span = span_start.to(span_end); + let count = prefix.len(); + cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count }); } } if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) { // The chain has a non-empty suffix of irrefutable `let` statements let suffix = &chain_refutabilities[from + 1..]; - lint_affix(suffix, "trailing", "into the body"); + let span_start = suffix[0].unwrap().0; + let span_end = suffix.last().unwrap().unwrap().0; + let span = span_start.to(span_end); + let count = suffix.len(); + cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count }); } true } @@ -568,32 +547,20 @@ fn check_for_bindings_named_same_as_variants( }) { let variant_count = edef.variants().len(); - cx.tcx.struct_span_lint_hir( + let ty_path = cx.tcx.def_path_str(edef.did()); + cx.tcx.emit_spanned_lint( BINDINGS_WITH_VARIANT_NAME, p.hir_id, p.span, - DelayDm(|| format!( - "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", - ident, cx.tcx.def_path_str(edef.did()) - )), - |lint| { - let ty_path = cx.tcx.def_path_str(edef.did()); - lint.code(error_code!(E0170)); - + BindingsWithVariantName { // If this is an irrefutable pattern, and there's > 1 variant, // then we can't actually match on this. Applying the below // suggestion would produce code that breaks on `check_irrefutable`. - if rf == Refutable || variant_count == 1 { - lint.span_suggestion( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable, - ); - } - - lint + suggestion: if rf == Refutable || variant_count == 1 { + Some(p.span) + } else { None }, + ty_path, + ident, }, ) } @@ -611,14 +578,12 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { } fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option) { - tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| { - if let Some(catchall) = catchall { - // We had a catchall pattern, hint at that. - lint.span_label(span, "unreachable pattern"); - lint.span_label(catchall, "matches any value"); - } - lint - }); + tcx.emit_spanned_lint( + UNREACHABLE_PATTERNS, + id, + span, + UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall }, + ); } fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) { @@ -634,67 +599,18 @@ fn irrefutable_let_patterns( span: Span, ) { macro_rules! emit_diag { - ( - $lint:expr, - $source_name:expr, - $note_sufix:expr, - $help_sufix:expr - ) => {{ - let s = pluralize!(count); - let these = pluralize!("this", count); - tcx.struct_span_lint_hir( - IRREFUTABLE_LET_PATTERNS, - id, - span, - format!("irrefutable {} pattern{s}", $source_name), - |lint| { - lint.note(&format!( - "{these} pattern{s} will always match, so the {}", - $note_sufix - )) - .help(concat!("consider ", $help_sufix)) - }, - ) + ($lint:tt) => {{ + tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count }); }}; } match source { - LetSource::GenericLet => { - emit_diag!(lint, "`let`", "`let` is useless", "removing `let`"); - } - LetSource::IfLet => { - emit_diag!( - lint, - "`if let`", - "`if let` is useless", - "replacing the `if let` with a `let`" - ); - } - LetSource::IfLetGuard => { - emit_diag!( - lint, - "`if let` guard", - "guard is useless", - "removing the guard and adding a `let` inside the match arm" - ); - } - LetSource::LetElse => { - emit_diag!( - lint, - "`let...else`", - "`else` clause is useless", - "removing the `else` clause" - ); - } - LetSource::WhileLet => { - emit_diag!( - lint, - "`while let`", - "loop will never exit", - "instead using a `loop { ... }` with a `let` inside it" - ); - } - }; + LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet), + LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet), + LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard), + LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse), + LetSource::WhileLet => emit_diag!(IrrefutableLetPatternsWhileLet), + } } fn is_let_irrefutable<'p, 'tcx>( @@ -760,15 +676,17 @@ fn non_exhaustive_match<'p, 'tcx>( // informative. let mut err; let pattern; - let mut patterns_len = 0; + let patterns_len; if is_empty_match && !non_empty_enum { - err = create_e0004( - cx.tcx.sess, - sp, - format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), - ); - pattern = "_".to_string(); + cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty { + cx, + expr_span, + span: sp, + ty: scrut_ty, + }); + return; } else { + // FIXME: migration of this diagnostic will require list support let joined_patterns = joined_uncovered_patterns(cx, &witnesses); err = create_e0004( cx.tcx.sess, @@ -1039,24 +957,17 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa } }); if !conflicts_ref.is_empty() { - let occurs_because = format!( - "move occurs because `{}` has type `{}` which does not implement the `Copy` trait", + sess.emit_err(BorrowOfMovedValue { + span: pat.span, + binding_span, + conflicts_ref, name, - typeck_results.node_type(pat.hir_id), - ); - let mut err = sess.struct_span_err(pat.span, "borrow of moved value"); - err.span_label(binding_span, format!("value moved into `{}` here", name)) - .span_label(binding_span, occurs_because) - .span_labels(conflicts_ref, "value borrowed here after move"); - if pat.span.contains(binding_span) { - err.span_suggestion_verbose( - binding_span.shrink_to_lo(), - "borrow this binding in the pattern to avoid moving the value", - "ref ".to_string(), - Applicability::MachineApplicable, - ); - } - err.emit(); + ty: typeck_results.node_type(pat.hir_id), + suggest_borrowing: pat + .span + .contains(binding_span) + .then(|| binding_span.shrink_to_lo()), + }); } return; } @@ -1086,19 +997,18 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa // Report errors if any. if !conflicts_mut_mut.is_empty() { // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - let mut err = sess - .struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time"); - err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name)); - for (span, name) in conflicts_mut_mut { - err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name)); + let mut occurences = vec![]; + + for (span, name_mut) in conflicts_mut_mut { + occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut }); } - for (span, name) in conflicts_mut_ref { - err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name)); + for (span, name_immut) in conflicts_mut_ref { + occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut }); } - for (span, name) in conflicts_move { - err.span_label(span, format!("also moved into `{}` here", name)); + for (span, name_moved) in conflicts_move { + occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved }); } - err.emit(); + sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name }); } else if !conflicts_mut_ref.is_empty() { // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. let (primary, also) = match mut_outer { diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index d60e8722cb61d..18e9c69c4870e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -45,7 +45,7 @@ use std::cell::Cell; use std::cmp::{self, max, min, Ordering}; use std::fmt; -use std::iter::{once, IntoIterator}; +use std::iter::once; use std::ops::RangeInclusive; use smallvec::{smallvec, SmallVec}; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 48a231a6cd6b7..2c775b397182b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -6,10 +6,12 @@ mod deconstruct_pat; mod usefulness; pub(crate) use self::check_match::check_match; +pub(crate) use self::usefulness::MatchCheckCtxt; +use crate::errors::*; use crate::thir::util::UserAnnotatedTyHelpers; -use rustc_errors::struct_span_err; +use rustc_errors::error_code; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; @@ -139,13 +141,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } // `x..y` where `x >= y`. The range is empty => error. (RangeEnd::Excluded, _) => { - struct_span_err!( - self.tcx.sess, - span, - E0579, - "lower range bound must be less than upper" - ) - .emit(); + self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanUpper { span }); PatKind::Wild } // `x..=y` where `x == y`. @@ -156,23 +152,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } // `x..=y` where `x > y` hence the range is empty => error. (RangeEnd::Included, _) => { - let mut err = struct_span_err!( - self.tcx.sess, + self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper { span, - E0030, - "lower range bound must be less than or equal to upper" - ); - err.span_label(span, "lower bound larger than upper bound"); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "When matching against a range, the compiler \ - verifies that the range is non-empty. Range \ - patterns include both end-points, so this is \ - equivalent to requiring the start of the range \ - to be less than or equal to the end of the range.", - ); - } - err.emit(); + teach: if self.tcx.sess.teach(&error_code!(E0030)) { Some(()) } else { None }, + }); PatKind::Wild } } @@ -501,7 +484,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } Err(_) => { - self.tcx.sess.span_err(span, "could not evaluate constant pattern"); + self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); return pat_from_kind(PatKind::Wild); } }; @@ -548,11 +531,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Err(ErrorHandled::TooGeneric) => { // While `Reported | Linted` cases will have diagnostics emitted already // it is not true for TooGeneric case, so we need to give user more information. - self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); pat_from_kind(PatKind::Wild) } Err(_) => { - self.tcx.sess.span_err(span, "could not evaluate constant pattern"); + self.tcx.sess.emit_err(CouldNotEvalConstPattern { span }); pat_from_kind(PatKind::Wild) } } @@ -584,7 +567,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind, mir::ConstantKind::Unevaluated(..) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. - self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); return PatKind::Wild; } } diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index f0e75c53ea15c..8fdac7b2cf501 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -26,7 +26,7 @@ //! ## `PartialOrd` //! //! Given that they represent partially ordered sets, you may be surprised that [`JoinSemiLattice`] -//! and [`MeetSemiLattice`] do not have [`PartialOrd`][std::cmp::PartialOrd] as a supertrait. This +//! and [`MeetSemiLattice`] do not have [`PartialOrd`] as a supertrait. This //! is because most standard library types use lexicographic ordering instead of set inclusion for //! their `PartialOrd` impl. Since we do not actually need to compare lattice elements to run a //! dataflow analysis, there's no need for a newtype wrapper with a custom `PartialOrd` impl. The diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 475e2ec9a1dea..8212a7b523bbc 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -35,7 +35,6 @@ use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Vis use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use smallvec::SmallVec; -use std::convert::TryInto; pub struct SimplifyCfg { label: String, diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 650076c2213a3..703ed09a254a9 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -20,7 +20,6 @@ use rustc_middle::ty::{ Const, Ty, TyCtxt, }; use rustc_span::symbol::sym; -use std::convert::TryInto; use std::ops::ControlFlow; use crate::errors::UnusedGenericParams; diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c7d239b647f35..686454a8f1811 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -6,7 +6,6 @@ use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; -use std::convert::TryInto; // Public for rustfmt usage #[derive(Debug)] diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index a084a70108859..b97f22417cb7b 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -8,7 +8,6 @@ use rustc_errors::PResult; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, DUMMY_SP}; -use std::convert::TryInto; use std::ops::Range; /// A wrapper type to ensure that the parser handles outer attributes correctly. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f6a6ed379a2b5..8a3545eb3be3a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1534,15 +1534,16 @@ impl<'a> Parser<'a> { && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma) || self.token.is_op()) { - let lit = self.recover_unclosed_char(label_.ident, |self_| { - self_.sess.create_err(UnexpectedTokenAfterLabel { - span: self_.token.span, - remove_label: None, - enclose_in_block: None, - }) - }); + let (lit, _) = + self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| { + self_.sess.create_err(UnexpectedTokenAfterLabel { + span: self_.token.span, + remove_label: None, + enclose_in_block: None, + }) + }); consume_colon = false; - Ok(self.mk_expr(lo, ExprKind::Lit(lit.token_lit))) + Ok(self.mk_expr(lo, ExprKind::Lit(lit))) } else if !ate_colon && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) { @@ -1617,12 +1618,13 @@ impl<'a> Parser<'a> { Ok(expr) } - /// Emit an error when a char is parsed as a lifetime because of a missing quote - pub(super) fn recover_unclosed_char( + /// Emit an error when a char is parsed as a lifetime because of a missing quote. + pub(super) fn recover_unclosed_char( &self, lifetime: Ident, + mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, - ) -> ast::MetaItemLit { + ) -> L { if let Some(mut diag) = self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { @@ -1644,11 +1646,7 @@ impl<'a> Parser<'a> { .emit(); } let name = lifetime.without_first_quote().name; - ast::MetaItemLit { - token_lit: token::Lit::new(token::LitKind::Char, name, None), - kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')), - span: lifetime.span, - } + mk_lit_char(name, lifetime.span) } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. @@ -1764,8 +1762,8 @@ impl<'a> Parser<'a> { Some(lit) => match lit.kind { ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { style, - symbol: lit.token_lit.symbol, - suffix: lit.token_lit.suffix, + symbol: lit.symbol, + suffix: lit.suffix, span: lit.span, symbol_unescaped, }), @@ -1775,7 +1773,23 @@ impl<'a> Parser<'a> { } } - fn handle_missing_lit(&mut self) -> PResult<'a, MetaItemLit> { + pub(crate) fn mk_token_lit_char(name: Symbol, span: Span) -> (token::Lit, Span) { + (token::Lit { symbol: name, suffix: None, kind: token::Char }, span) + } + + fn mk_meta_item_lit_char(name: Symbol, span: Span) -> MetaItemLit { + ast::MetaItemLit { + symbol: name, + suffix: None, + kind: ast::LitKind::Char(name.as_str().chars().next().unwrap_or('_')), + span, + } + } + + fn handle_missing_lit( + &mut self, + mk_lit_char: impl FnOnce(Symbol, Span) -> L, + ) -> PResult<'a, L> { if let token::Interpolated(inner) = &self.token.kind { let expr = match inner.as_ref() { token::NtExpr(expr) => Some(expr), @@ -1799,7 +1813,7 @@ impl<'a> Parser<'a> { // On an error path, eagerly consider a lifetime to be an unclosed character lit if self.token.is_lifetime() { let lt = self.expect_lifetime(); - Ok(self.recover_unclosed_char(lt.ident, err)) + Ok(self.recover_unclosed_char(lt.ident, mk_lit_char, err)) } else { Err(err(self)) } @@ -1808,11 +1822,13 @@ impl<'a> Parser<'a> { pub(super) fn parse_token_lit(&mut self) -> PResult<'a, (token::Lit, Span)> { self.parse_opt_token_lit() .ok_or(()) - .or_else(|()| self.handle_missing_lit().map(|lit| (lit.token_lit, lit.span))) + .or_else(|()| self.handle_missing_lit(Parser::mk_token_lit_char)) } pub(super) fn parse_meta_item_lit(&mut self) -> PResult<'a, MetaItemLit> { - self.parse_opt_meta_item_lit().ok_or(()).or_else(|()| self.handle_missing_lit()) + self.parse_opt_meta_item_lit() + .ok_or(()) + .or_else(|()| self.handle_missing_lit(Parser::mk_meta_item_lit_char)) } fn recover_after_dot(&mut self) -> Option { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 03f25392a7c1f..7ebcda249e23a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -21,7 +21,6 @@ use rustc_span::lev_distance::lev_distance; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::DUMMY_SP; -use std::convert::TryFrom; use std::mem; use thin_vec::ThinVec; use tracing::debug; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index cbeec951e2dfe..a1981e1147775 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -411,16 +411,20 @@ impl<'a> Parser<'a> { { // Recover a `'a` as a `'a'` literal let lt = self.expect_lifetime(); - let lit = self.recover_unclosed_char(lt.ident, |self_| { - let expected = expected.unwrap_or("pattern"); - let msg = - format!("expected {}, found {}", expected, super::token_descr(&self_.token)); + let (lit, _) = + self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| { + let expected = expected.unwrap_or("pattern"); + let msg = format!( + "expected {}, found {}", + expected, + super::token_descr(&self_.token) + ); - let mut err = self_.struct_span_err(self_.token.span, &msg); - err.span_label(self_.token.span, format!("expected {}", expected)); - err - }); - PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit.token_lit))) + let mut err = self_.struct_span_err(self_.token.span, &msg); + err.span_label(self_.token.span, format!("expected {}", expected)); + err + }); + PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit))) } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 38c7c6cce6765..0e7d628c1eb63 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -46,7 +46,7 @@ impl DepNodeIndex { pub const FOREVER_RED_NODE: DepNodeIndex = DepNodeIndex::from_u32(1); } -impl std::convert::From for QueryInvocationId { +impl From for QueryInvocationId { #[inline] fn from(dep_node_index: DepNodeIndex) -> Self { QueryInvocationId(dep_node_index.as_u32()) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 3b20ec70d73cb..d292f4beef2eb 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -22,7 +22,6 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable}; use smallvec::SmallVec; -use std::convert::TryInto; // The maximum value of `SerializedDepNodeIndex` leaves the upper two bits // unused so that we can store multiple index types in `CompressedHybridIndex`, diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 4c4680b5d8ea8..f65846fc77f6e 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -9,7 +9,6 @@ use rustc_data_structures::sharded::Sharded; use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::WorkerLocal; use rustc_index::vec::{Idx, IndexVec}; -use std::default::Default; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 49bbcf5780459..701bbde6ad23f 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -22,8 +22,8 @@ use { rustc_data_structures::{jobserver, OnDrop}, rustc_rayon_core as rayon_core, rustc_span::DUMMY_SP, - std::iter::{self, FromIterator}, - std::{mem, process}, + std::iter, + std::process, }; /// Represents a span and a query key. @@ -247,7 +247,7 @@ impl QueryLatch { jobserver::release_thread(); waiter.condvar.wait(&mut info); // Release the lock before we potentially block in `acquire_thread` - mem::drop(info); + drop(info); jobserver::acquire_thread(); } } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 7735c571310dd..6c310abf10ac5 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -36,7 +36,6 @@ use rustc_span::symbol::Ident; use rustc_span::*; use std::cell::Cell; -use std::default::Default; use std::env; use std::fs::File; use std::io::BufWriter; diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 0afeb86fceb24..0e0ebc79eb2e3 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -1,6 +1,5 @@ use crate::leb128::{self, largest_max_leb128_len}; use crate::serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::convert::TryInto; use std::fs::File; use std::io::{self, Write}; use std::mem::MaybeUninit; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7a20100fd3133..6de564a3a0692 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -32,7 +32,7 @@ use std::collections::btree_map::{ use std::collections::{BTreeMap, BTreeSet}; use std::fmt; use std::hash::Hash; -use std::iter::{self, FromIterator}; +use std::iter; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 1b66773be6f08..1855a49c1ecdf 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -3,7 +3,6 @@ use smallvec::{smallvec, SmallVec}; use std::env; use std::fs; -use std::iter::FromIterator; use std::path::{Path, PathBuf}; use crate::search_paths::{PathKind, SearchPath}; diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 2ae57d9e56d7c..43a3172270733 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -15,11 +15,10 @@ pub use crate::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{AtomicU32, Lrc, MappedReadGuard, ReadGuard, RwLock}; +use std::cmp; use std::hash::Hash; use std::path::{Path, PathBuf}; use std::sync::atomic::Ordering; -use std::{clone::Clone, cmp}; -use std::{convert::TryFrom, unreachable}; use std::fs; use std::io; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1fcf8c7a8bf13..d0fe598ce086e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -9,7 +9,6 @@ use rustc_data_structures::sync::Lock; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::cmp::{Ord, PartialEq, PartialOrd}; use std::fmt; use std::hash::{Hash, Hasher}; use std::str; @@ -1974,7 +1973,6 @@ pub mod kw { /// For example `sym::rustfmt` or `sym::u8`. pub mod sym { use super::Symbol; - use std::convert::TryInto; #[doc(inline)] pub use super::sym_generated::*; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index b69a0a645a415..dc2cc23ffb1e4 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -18,7 +18,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use std::iter::FromIterator; use std::path::{Path, PathBuf}; #[macro_use] diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1db1d7e85adcc..be994eda14c00 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -45,9 +45,7 @@ use rustc_span::symbol::{sym, Symbol}; use serde_json::Value; use std::borrow::Cow; use std::collections::BTreeMap; -use std::convert::TryFrom; use std::hash::{Hash, Hasher}; -use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 3ed616d709b1e..9aa2be124e294 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -1,6 +1,6 @@ #![allow(rustc::usage_of_ty_tykind)] -use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use std::cmp::Ordering; use std::{fmt, hash}; use crate::DebruijnIndex; diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index ef6eee75f1ce6..d4d26654ed114 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -434,6 +434,9 @@ replacement is purely textual, with no consideration of the current system's pathname syntax. For example `--remap-path-prefix foo=bar` will match `foo/lib.rs` but not `./foo/lib.rs`. +When multiple remappings are given and several of them match, the **last** +matching one is applied. + ## `--json`: configure json messages printed by the compiler diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 7f72d5d39a752..81f6767243683 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -1,9 +1,8 @@ use super::*; -use rustc_ast::attr; -use rustc_ast::Path; +use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle}; use rustc_span::create_default_session_globals_then; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::DUMMY_SP; fn word_cfg(s: &str) -> Cfg { @@ -22,6 +21,15 @@ fn dummy_meta_item_word(name: &str) -> MetaItem { } } +fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem { + let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }; + MetaItem { + path: Path::from_ident(Ident::from_str(name)), + kind: MetaItemKind::NameValue(lit), + span: DUMMY_SP, + } +} + macro_rules! dummy_meta_item_list { ($name:ident, [$($list:ident),* $(,)?]) => { MetaItem { @@ -242,8 +250,8 @@ fn test_parse_ok() { let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); - let mi = - attr::mk_name_value_item_str(Ident::from_str("all"), Symbol::intern("done"), DUMMY_SP); + let done = Symbol::intern("done"); + let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked)); assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); let mi = dummy_meta_item_list!(all, [a, b]); @@ -272,7 +280,7 @@ fn test_parse_ok() { #[test] fn test_parse_err() { create_default_session_globals_then(|| { - let mi = attr::mk_name_value_item(Ident::from_str("foo"), LitKind::Bool(false), DUMMY_SP); + let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false)); assert!(Cfg::parse(&mi).is_err()); let mi = dummy_meta_item_list!(not, [a, b]); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2590bb0df3f0e..98329e7fc9193 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -10,7 +10,6 @@ use std::{cmp, fmt, iter}; use arrayvec::ArrayVec; use thin_vec::ThinVec; -use rustc_ast::attr; use rustc_ast::util::comments::beautify_doc_string; use rustc_ast::{self as ast, AttrStyle}; use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel}; @@ -27,7 +26,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility}; use rustc_session::Session; use rustc_span::hygiene::MacroKind; -use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, FileName, Loc}; use rustc_target::abi::VariantIdx; @@ -982,12 +980,12 @@ impl AttributesExt for [ast::Attribute] { // #[doc(cfg(target_feature = "feat"))] attributes as well for attr in self.lists(sym::target_feature) { if attr.has_name(sym::enable) { - if let Some(feat) = attr.value_str() { - let meta = attr::mk_name_value_item_str( - Ident::with_dummy_span(sym::target_feature), - feat, - DUMMY_SP, - ); + if attr.value_str().is_some() { + // Clone `enable = "feat"`, change to `target_feature = "feat"`. + // Unwrap is safe because `value_str` succeeded above. + let mut meta = attr.meta_item().unwrap().clone(); + meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); + if let Ok(feat_cfg) = Cfg::parse(&meta) { cfg &= feat_cfg; } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5ce62224d35e5..1e1c657b0bf22 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -246,8 +246,6 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { _ => {} } } - let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); - let text = lines.intersperse("\n".into()).collect::(); let parse_result = match kind { CodeBlockKind::Fenced(ref lang) => { @@ -260,7 +258,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> {
{}
\ ", lang, - Escape(&text), + Escape(&origtext), ) .into(), )); @@ -270,6 +268,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { CodeBlockKind::Indented => Default::default(), }; + let lines = origtext.lines().filter_map(|l| map_line(l).for_html()); + let text = lines.intersperse("\n".into()).collect::(); + compile_fail = parse_result.compile_fail; should_panic = parse_result.should_panic; ignore = parse_result.ignore; diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index e4f72a057892f..68b31a6ee083d 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -309,3 +309,40 @@ fn test_find_testable_code_line() { t("```rust\n```\n```rust\n```", &[1, 3]); t("```rust\n```\n ```rust\n```", &[1, 3]); } + +#[test] +fn test_ascii_with_prepending_hashtag() { + fn t(input: &str, expect: &str) { + let mut map = IdMap::new(); + let output = Markdown { + content: input, + links: &[], + ids: &mut map, + error_codes: ErrorCodes::Yes, + edition: DEFAULT_EDITION, + playground: &None, + heading_offset: HeadingOffset::H2, + } + .into_string(); + assert_eq!(output, expect, "original: {}", input); + } + + t( + r#"```ascii +#..#.####.#....#.....##.. +#..#.#....#....#....#..#. +####.###..#....#....#..#. +#..#.#....#....#....#..#. +#..#.#....#....#....#..#. +#..#.####.####.####..##.. +```"#, + "
\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+
", + ); +} diff --git a/src/test/ui/traits/object/issue-44454-1.rs b/src/test/ui/traits/object/issue-44454-1.rs new file mode 100644 index 0000000000000..bbaf3188a8963 --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-1.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issue-256435333 + +trait Animal: 'static {} + +fn foo() +where + Y: Animal + ?Sized, +{ + // `Y` implements `Animal` so `Y` is 'static. + baz::() +} + +fn bar<'a>(_arg: &'a i32) { + foo::, &'a i32>() //~ ERROR: lifetime may not live long enough +} + +fn baz() {} + +fn main() { + let a = 5; + bar(&a); +} diff --git a/src/test/ui/traits/object/issue-44454-1.stderr b/src/test/ui/traits/object/issue-44454-1.stderr new file mode 100644 index 0000000000000..859487f50ac1e --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-1.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-1.rs:14:5 + | +LL | fn bar<'a>(_arg: &'a i32) { + | -- lifetime `'a` defined here +LL | foo::, &'a i32>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/traits/object/issue-44454-2.rs b/src/test/ui/traits/object/issue-44454-2.rs new file mode 100644 index 0000000000000..f5178bcdbe224 --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-2.rs @@ -0,0 +1,22 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1175925928 + +trait Trait: 'static { + type Assoc: AsRef; +} + +fn hr(x: T::Assoc) -> Box + 'static> +where + T: Trait +{ + Box::new(x) +} + +fn extend_lt<'a>(x: &'a str) -> Box + 'static> { + type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; + hr::(x) //~ ERROR: borrowed data escapes outside of function +} + +fn main() { + let extended = extend_lt(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); +} diff --git a/src/test/ui/traits/object/issue-44454-2.stderr b/src/test/ui/traits/object/issue-44454-2.stderr new file mode 100644 index 0000000000000..7f574769b7f60 --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-2.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-44454-2.rs:16:5 + | +LL | fn extend_lt<'a>(x: &'a str) -> Box + 'static> { + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; +LL | hr::(x) + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/traits/object/issue-44454-3.rs b/src/test/ui/traits/object/issue-44454-3.rs new file mode 100644 index 0000000000000..bff7270353464 --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-3.rs @@ -0,0 +1,33 @@ +// Taken from https://github.com/rust-lang/rust/issues/44454#issuecomment-1332781290 + +use std::any::Any; + +trait Animal: 'static {} + +trait Projector { + type Foo; +} + +impl Projector for dyn Animal { + type Foo = X; +} + +fn make_static<'a, T>(t: &'a T) -> &'static T { + let x: as Projector>::Foo = t; + let any = generic::, &'a T>(x); + //~^ ERROR: lifetime may not live long enough + any.downcast_ref::<&'static T>().unwrap() +} + +fn generic + ?Sized, U>(x: ::Foo) -> Box { + make_static_any(x) +} + +fn make_static_any(u: U) -> Box { + Box::new(u) +} + +fn main() { + let a = make_static(&"salut".to_string()); + println!("{}", *a); +} diff --git a/src/test/ui/traits/object/issue-44454-3.stderr b/src/test/ui/traits/object/issue-44454-3.stderr new file mode 100644 index 0000000000000..294684d26bdfc --- /dev/null +++ b/src/test/ui/traits/object/issue-44454-3.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/issue-44454-3.rs:17:15 + | +LL | fn make_static<'a, T>(t: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let x: as Projector>::Foo = t; +LL | let any = generic::, &'a T>(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs index e0a607f9a95b6..6a4861747d267 100644 --- a/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs +++ b/src/tools/clippy/clippy_lints/src/invalid_utf8_in_unchecked.rs @@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidUtf8InUnchecked { if let Some([arg]) = match_function_call(cx, expr, &paths::STR_FROM_UTF8_UNCHECKED) { match &arg.kind { ExprKind::Lit(Spanned { node: lit, .. }) => { - if let LitKind::ByteStr(bytes) = &lit + if let LitKind::ByteStr(bytes, _) = &lit && std::str::from_utf8(bytes).is_err() { lint(cx, expr.span); diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs index 84dd61a1e4b0d..424c0d9e79828 100644 --- a/src/tools/clippy/clippy_lints/src/large_include_file.rs +++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs @@ -60,7 +60,7 @@ impl LateLintPass<'_> for LargeIncludeFile { then { let len = match &lit.node { // include_bytes - LitKind::ByteStr(bstr) => bstr.len(), + LitKind::ByteStr(bstr, _) => bstr.len(), // include_str LitKind::Str(sym, _) => sym.as_str().len(), _ => return, diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 168c1e4d2e60d..158e6caa4de54 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -282,7 +282,7 @@ impl<'a> NormalizedPat<'a> { // TODO: Handle negative integers. They're currently treated as a wild match. ExprKind::Lit(lit) => match lit.node { LitKind::Str(sym, _) => Self::LitStr(sym), - LitKind::ByteStr(ref bytes) => Self::LitBytes(bytes), + LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Int(val, _) => Self::LitInt(val), diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 0c052d86eda40..bd7daf0773caf 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { }; kind!("Float(_, {float_ty})"); }, - LitKind::ByteStr(ref vec) => { + LitKind::ByteStr(ref vec, _) => { bind!(self, vec); kind!("ByteStr(ref {vec})"); chain!(self, "let [{:?}] = **{vec}", vec.value); diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index c6bf98b7b8bbd..43f0df145f0ec 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -69,7 +69,9 @@ fn lit_search_pat(lit: &LitKind) -> (Pat, Pat) { LitKind::Str(_, StrStyle::Cooked) => (Pat::Str("\""), Pat::Str("\"")), LitKind::Str(_, StrStyle::Raw(0)) => (Pat::Str("r"), Pat::Str("\"")), LitKind::Str(_, StrStyle::Raw(_)) => (Pat::Str("r#"), Pat::Str("#")), - LitKind::ByteStr(_) => (Pat::Str("b\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Cooked) => (Pat::Str("b\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Raw(0)) => (Pat::Str("br\""), Pat::Str("\"")), + LitKind::ByteStr(_, StrStyle::Raw(_)) => (Pat::Str("br#\""), Pat::Str("#")), LitKind::Byte(_) => (Pat::Str("b'"), Pat::Str("'")), LitKind::Char(_) => (Pat::Str("'"), Pat::Str("'")), LitKind::Int(_, LitIntType::Signed(IntTy::Isize)) => (Pat::Num, Pat::Str("isize")), diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 315aea9aa091b..7a637d32babec 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -210,7 +210,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), - LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)), + LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 2ac703b957b86..c503eeeb9b3b9 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -260,7 +260,9 @@ impl Rewrite for ast::NestedMetaItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self { ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), - ast::NestedMetaItem::Lit(ref l) => rewrite_literal(context, l.token_lit, l.span, shape), + ast::NestedMetaItem::Lit(ref l) => { + rewrite_literal(context, l.as_token_lit(), l.span, shape) + } } } } @@ -308,18 +310,18 @@ impl Rewrite for ast::MetaItem { }), )? } - ast::MetaItemKind::NameValue(ref literal) => { + ast::MetaItemKind::NameValue(ref lit) => { let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?; // 3 = ` = ` let lit_shape = shape.shrink_left(path.len() + 3)?; - // `rewrite_literal` returns `None` when `literal` exceeds max + // `rewrite_literal` returns `None` when `lit` exceeds max // width. Since a literal is basically unformattable unless it // is a string literal (and only if `format_strings` is set), // we might be better off ignoring the fact that the attribute // is longer than the max width and continue on formatting. // See #2479 for example. - let value = rewrite_literal(context, literal.token_lit, literal.span, lit_shape) - .unwrap_or_else(|| context.snippet(literal.span).to_owned()); + let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape) + .unwrap_or_else(|| context.snippet(lit.span).to_owned()); format!("{} = {}", path, value) } })