diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4e2495ab14c9a..e5b61d7000a32 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -31,7 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_data_structures::thin_vec::ThinVec; use rustc_macros::HashStable_Generic; -use rustc_serialize::{self, Decoder, Encoder}; +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}; @@ -2488,11 +2488,11 @@ rustc_index::newtype_index! { } } -impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId { +impl<S: Encoder> Encodable<S> for AttrId { fn encode(&self, _s: &mut S) {} } -impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId { +impl<D: Decoder> Decodable<D> for AttrId { fn decode(_: &mut D) -> AttrId { crate::attr::mk_attr_id() } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 8d187a4be8aee..37a4bf5fdcad7 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,44 +1,299 @@ -use rustc_ast::{ptr::P, Expr, Path}; +use crate::assert::expr_if_not; +use rustc_ast::{ + attr, + ptr::P, + token, + tokenstream::{DelimSpan, TokenStream, TokenTree}, + BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path, + PathSegment, Stmt, UseTree, UseTreeKind, DUMMY_NODE_ID, +}; +use rustc_ast_pretty::pprust; +use rustc_data_structures::fx::FxHashSet; use rustc_expand::base::ExtCtxt; -use rustc_span::Span; +use rustc_span::{ + symbol::{sym, Ident, Symbol}, + Span, +}; pub(super) struct Context<'cx, 'a> { + // Top-level `let captureN = Capture::new()` statements + capture_decls: Vec<Capture>, cx: &'cx ExtCtxt<'a>, + // Formatting string used for debugging + fmt_string: String, + // Top-level `let __local_bindN = &expr` statements + local_bind_decls: Vec<Stmt>, + // Used to avoid capturing duplicated paths + // + // ```rust + // let a = 1i32; + // assert!(add(a, a) == 3); + // ``` + paths: FxHashSet<Ident>, span: Span, } impl<'cx, 'a> Context<'cx, 'a> { pub(super) fn new(cx: &'cx ExtCtxt<'a>, span: Span) -> Self { - Self { cx, span } + Self { + capture_decls: <_>::default(), + cx, + fmt_string: <_>::default(), + local_bind_decls: <_>::default(), + paths: <_>::default(), + span, + } } - /// Builds the whole `assert!` expression. + /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to: /// + /// ```rust + /// let elem = 1; /// { - /// use ::core::asserting::{ ... }; + /// #[allow(unused_imports)] + /// use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + /// let mut __capture0 = ::core::asserting::Capture::new(); + /// let __local_bind0 = &elem; + /// if !( + /// *{ + /// (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + /// __local_bind0 + /// } == 1 + /// ) { + /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {}", __capture0) + /// } + /// } + /// ``` + pub(super) fn build(mut self, mut cond_expr: P<Expr>, panic_path: Path) -> P<Expr> { + let expr_str = pprust::expr_to_string(&cond_expr); + self.manage_cond_expr(&mut cond_expr); + let initial_imports = self.build_initial_imports(); + let panic = self.build_panic(&expr_str, panic_path); + + let Self { capture_decls, cx, local_bind_decls, span, .. } = self; + + let mut stmts = Vec::with_capacity(4); + stmts.push(initial_imports); + stmts.extend(capture_decls.into_iter().map(|c| c.decl)); + stmts.extend(local_bind_decls); + stmts.push(cx.stmt_expr(expr_if_not(cx, span, cond_expr, panic, None))); + cx.expr_block(cx.block(span, stmts)) + } + + /// Initial **trait** imports + /// + /// use ::core::asserting::{ ... }; + fn build_initial_imports(&self) -> Stmt { + let nested_tree = |this: &Self, sym| { + ( + UseTree { + prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]), + kind: UseTreeKind::Simple(None, DUMMY_NODE_ID, DUMMY_NODE_ID), + span: this.span, + }, + DUMMY_NODE_ID, + ) + }; + self.cx.stmt_item( + self.span, + self.cx.item( + self.span, + Ident::empty(), + vec![self.cx.attribute(attr::mk_list_item( + Ident::new(sym::allow, self.span), + vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))], + ))], + ItemKind::Use(UseTree { + prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), + kind: UseTreeKind::Nested(vec![ + nested_tree(self, sym::TryCaptureGeneric), + nested_tree(self, sym::TryCapturePrintable), + ]), + span: self.span, + }), + ), + ) + } + + /// The necessary custom `panic!(...)` expression. + /// + /// panic!( + /// "Assertion failed: ... \n With expansion: ...", + /// __capture0, + /// ... + /// ); + fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> { + let escaped_expr_str = escape_to_fmt(expr_str); + let initial = [ + TokenTree::token( + token::Literal(token::Lit { + kind: token::LitKind::Str, + symbol: Symbol::intern(&if self.fmt_string.is_empty() { + format!("Assertion failed: {escaped_expr_str}") + } else { + format!( + "Assertion failed: {escaped_expr_str}\nWith captures:\n{}", + &self.fmt_string + ) + }), + suffix: None, + }), + self.span, + ), + TokenTree::token(token::Comma, self.span), + ]; + let captures = self.capture_decls.iter().flat_map(|cap| { + [ + TokenTree::token(token::Ident(cap.ident.name, false), cap.ident.span), + TokenTree::token(token::Comma, self.span), + ] + }); + self.cx.expr( + self.span, + ExprKind::MacCall(MacCall { + path: panic_path, + args: P(MacArgs::Delimited( + DelimSpan::from_single(self.span), + MacDelimiter::Parenthesis, + initial.into_iter().chain(captures).collect::<TokenStream>(), + )), + prior_type_ascription: None, + }), + ) + } + + /// Recursive function called until `cond_expr` and `fmt_str` are fully modified. + /// + /// See [Self::manage_initial_capture] and [Self::manage_try_capture] + fn manage_cond_expr(&mut self, expr: &mut P<Expr>) { + match (*expr).kind { + ExprKind::Binary(_, ref mut lhs, ref mut rhs) => { + self.manage_cond_expr(lhs); + self.manage_cond_expr(rhs); + } + ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => { + let path_ident = path_segment.ident; + self.manage_initial_capture(expr, path_ident); + } + _ => {} + } + } + + /// Pushes the top-level declarations and modifies `expr` to try capturing variables. /// - /// let mut __capture0 = Capture::new(); - /// ... - /// ... - /// ... + /// `fmt_str`, the formatting string used for debugging, is constructed to show possible + /// captured variables. + fn manage_initial_capture(&mut self, expr: &mut P<Expr>, path_ident: Ident) { + if self.paths.contains(&path_ident) { + return; + } else { + self.fmt_string.push_str(" "); + self.fmt_string.push_str(path_ident.as_str()); + self.fmt_string.push_str(" = {:?}\n"); + let _ = self.paths.insert(path_ident); + } + let curr_capture_idx = self.capture_decls.len(); + let capture_string = format!("__capture{curr_capture_idx}"); + let ident = Ident::new(Symbol::intern(&capture_string), self.span); + let init_std_path = self.cx.std_path(&[sym::asserting, sym::Capture, sym::new]); + let init = self.cx.expr_call( + self.span, + self.cx.expr_path(self.cx.path(self.span, init_std_path)), + vec![], + ); + let capture = Capture { decl: self.cx.stmt_let(self.span, true, ident, init), ident }; + self.capture_decls.push(capture); + self.manage_try_capture(ident, curr_capture_idx, expr); + } + + /// Tries to copy `__local_bindN` into `__captureN`. /// - /// if !{ - /// ... - /// ... - /// ... - /// } { - /// panic!( - /// "Assertion failed: ... \n With expansion: ...", - /// __capture0, - /// ... - /// ... - /// ... - /// ); - /// } + /// *{ + /// (&Wrapper(__local_bindN)).try_capture(&mut __captureN); + /// __local_bindN /// } - pub(super) fn build(self, _cond_expr: P<Expr>, _panic_path: Path) -> P<Expr> { - let Self { cx, span, .. } = self; - let stmts = Vec::new(); - cx.expr_block(cx.block(span, stmts)) + fn manage_try_capture(&mut self, capture: Ident, curr_capture_idx: usize, expr: &mut P<Expr>) { + let local_bind_string = format!("__local_bind{curr_capture_idx}"); + let local_bind = Ident::new(Symbol::intern(&local_bind_string), self.span); + self.local_bind_decls.push(self.cx.stmt_let( + self.span, + false, + local_bind, + self.cx.expr_addr_of(self.span, expr.clone()), + )); + let wrapper = self.cx.expr_call( + self.span, + self.cx.expr_path( + self.cx.path(self.span, self.cx.std_path(&[sym::asserting, sym::Wrapper])), + ), + vec![self.cx.expr_path(Path::from_ident(local_bind))], + ); + let try_capture_call = self + .cx + .stmt_expr(expr_method_call( + self.cx, + PathSegment { + args: None, + id: DUMMY_NODE_ID, + ident: Ident::new(sym::try_capture, self.span), + }, + vec![ + expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)), + expr_addr_of_mut( + self.cx, + self.span, + self.cx.expr_path(Path::from_ident(capture)), + ), + ], + self.span, + )) + .add_trailing_semicolon(); + let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind)); + let ret = self.cx.stmt_expr(local_bind_path); + let block = self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret])); + *expr = self.cx.expr_deref(self.span, block); + } +} + +/// Information about a captured element. +#[derive(Debug)] +struct Capture { + // Generated indexed `Capture` statement. + // + // `let __capture{} = Capture::new();` + decl: Stmt, + // The name of the generated indexed `Capture` variable. + // + // `__capture{}` + ident: Ident, +} + +/// Escapes to use as a formatting string. +fn escape_to_fmt(s: &str) -> String { + let mut rslt = String::with_capacity(s.len()); + for c in s.chars() { + rslt.extend(c.escape_debug()); + match c { + '{' | '}' => rslt.push(c), + _ => {} + } } + rslt +} + +fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> { + cx.expr(sp, ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e)) +} + +fn expr_method_call( + cx: &ExtCtxt<'_>, + path: PathSegment, + args: Vec<P<Expr>>, + span: Span, +) -> P<Expr> { + cx.expr(span, ExprKind::MethodCall(path, args, span)) +} + +fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> { + cx.expr(sp, ExprKind::Paren(e)) } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 124d0d18cdbe2..11565ba72d755 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -6,6 +6,7 @@ #![feature(array_windows)] #![feature(box_patterns)] #![feature(decl_macro)] +#![feature(if_let_guard)] #![feature(is_sorted)] #![feature(let_chains)] #![feature(let_else)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 771157dcad954..750432b0b2653 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -29,7 +29,8 @@ use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::ty::query::{ExternProviders, Providers}; -use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; +use rustc_serialize::opaque::{MemDecoder, MemEncoder}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; @@ -203,7 +204,7 @@ const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); impl CodegenResults { pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> { - let mut encoder = opaque::Encoder::new(); + let mut encoder = MemEncoder::new(); encoder.emit_raw_bytes(RLINK_MAGIC); // `emit_raw_bytes` is used to make sure that the version representation does not depend on // Encoder's inner representation of `u32`. @@ -230,7 +231,7 @@ impl CodegenResults { return Err(".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}".to_string()); } - let mut decoder = opaque::Decoder::new(&data[4..], 0); + let mut decoder = MemDecoder::new(&data[4..], 0); let rustc_version = decoder.read_str(); let current_version = RUSTC_VERSION.unwrap(); if rustc_version != current_version { diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index a032b039f34ef..5ff2d18dd2be3 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -1,5 +1,5 @@ use crate::stable_hasher; -use rustc_serialize::{Decodable, Encodable}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::convert::TryInto; use std::hash::{Hash, Hasher}; @@ -142,14 +142,14 @@ impl stable_hasher::StableHasherResult for Fingerprint { impl_stable_hash_via_hash!(Fingerprint); -impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint { +impl<E: Encoder> Encodable<E> for Fingerprint { #[inline] fn encode(&self, s: &mut E) { s.emit_raw_bytes(&self.to_le_bytes()); } } -impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint { +impl<D: Decoder> Decodable<D> for Fingerprint { #[inline] fn decode(d: &mut D) -> Self { Fingerprint::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) @@ -184,7 +184,7 @@ impl std::fmt::Display for PackedFingerprint { } } -impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint { +impl<E: Encoder> Encodable<E> for PackedFingerprint { #[inline] fn encode(&self, s: &mut E) { // Copy to avoid taking reference to packed field. @@ -193,7 +193,7 @@ impl<E: rustc_serialize::Encoder> Encodable<E> for PackedFingerprint { } } -impl<D: rustc_serialize::Decoder> Decodable<D> for PackedFingerprint { +impl<D: Decoder> Decodable<D> for PackedFingerprint { #[inline] fn decode(d: &mut D) -> Self { Self(Fingerprint::decode(d)) diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 9de14950aa8d3..9c325faae8058 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::memmap::Mmap; use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::ty::OnDiskCache; -use rustc_serialize::opaque::Decoder; +use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; use rustc_session::Session; @@ -156,7 +156,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result { // Decode the list of work_products - let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos); + let mut work_product_decoder = MemDecoder::new(&work_products_data[..], start_pos); let work_products: Vec<SerializedWorkProduct> = Decodable::decode(&mut work_product_decoder); @@ -193,7 +193,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::Error { message } => LoadResult::Error { message }, LoadResult::Ok { data: (bytes, start_pos) } => { - let mut decoder = Decoder::new(&bytes, start_pos); + let mut decoder = MemDecoder::new(&bytes, start_pos); let prev_commandline_args_hash = u64::decode(&mut decoder); if prev_commandline_args_hash != expected_hash { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 186031d4586aa..c1ded99a25af5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -26,7 +26,8 @@ use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::GeneratorDiagnosticData; use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; -use rustc_serialize::{opaque, Decodable, Decoder}; +use rustc_serialize::opaque::MemDecoder; +use rustc_serialize::{Decodable, Decoder}; use rustc_session::cstore::{ CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib, }; @@ -154,7 +155,7 @@ struct ImportedSourceFile { } pub(super) struct DecodeContext<'a, 'tcx> { - opaque: opaque::Decoder<'a>, + opaque: MemDecoder<'a>, cdata: Option<CrateMetadataRef<'a>>, blob: &'a MetadataBlob, sess: Option<&'tcx Session>, @@ -186,7 +187,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { let tcx = self.tcx(); DecodeContext { - opaque: opaque::Decoder::new(self.blob(), pos), + opaque: MemDecoder::new(self.blob(), pos), cdata: self.cdata(), blob: self.blob(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), @@ -418,7 +419,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { where F: FnOnce(&mut Self) -> R, { - let new_opaque = opaque::Decoder::new(self.opaque.data, pos); + let new_opaque = MemDecoder::new(self.opaque.data, pos); let old_opaque = mem::replace(&mut self.opaque, new_opaque); let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); let r = f(self); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 50c09aaf8d445..26fb21020008a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -27,7 +27,8 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; -use rustc_serialize::{opaque, Encodable, Encoder}; +use rustc_serialize::opaque::MemEncoder; +use rustc_serialize::{Encodable, Encoder}; use rustc_session::config::CrateType; use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind}; @@ -43,7 +44,7 @@ use std::num::NonZeroUsize; use tracing::{debug, trace}; pub(super) struct EncodeContext<'a, 'tcx> { - opaque: opaque::Encoder, + opaque: MemEncoder, tcx: TyCtxt<'tcx>, feat: &'tcx rustc_feature::Features, @@ -93,8 +94,8 @@ macro_rules! encoder_methods { } impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { - type Ok = <opaque::Encoder as Encoder>::Ok; - type Err = <opaque::Encoder as Encoder>::Err; + type Ok = <MemEncoder as Encoder>::Ok; + type Err = <MemEncoder as Encoder>::Err; encoder_methods! { emit_usize(usize); @@ -2180,7 +2181,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { } fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { - let mut encoder = opaque::Encoder::new(); + let mut encoder = MemEncoder::new(); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index fb2ffe1d73d96..04f0847f5cccc 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt}; -use rustc_serialize::opaque::Encoder; +use rustc_serialize::opaque::MemEncoder; use rustc_session::config::SymbolManglingVersion; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; @@ -323,7 +323,7 @@ macro_rules! define_tables { } impl TableBuilders { - fn encode(&self, buf: &mut Encoder) -> LazyTables { + fn encode(&self, buf: &mut MemEncoder) -> LazyTables { LazyTables { $($name: self.$name.encode(buf)),+ } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 8baa67a8f9fcf..5ab4269ae99ad 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -4,8 +4,8 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def::{CtorKind, CtorOf}; use rustc_index::vec::Idx; use rustc_middle::ty::ParameterizedOverTcx; -use rustc_serialize::opaque::Encoder; -use rustc_serialize::Encoder as _; +use rustc_serialize::opaque::MemEncoder; +use rustc_serialize::Encoder; use rustc_span::hygiene::MacroKind; use std::convert::TryInto; use std::marker::PhantomData; @@ -281,7 +281,7 @@ where Some(value).write_to_bytes(&mut self.blocks[i]); } - pub(crate) fn encode<const N: usize>(&self, buf: &mut Encoder) -> LazyTable<I, T> + pub(crate) fn encode<const N: usize>(&self, buf: &mut MemEncoder) -> LazyTable<I, T> where Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>, { diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs index 096bf8cbc158a..1279f5aee3691 100644 --- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs +++ b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs @@ -3,7 +3,7 @@ use rustc_data_structures::graph::{ }; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::OnceCell; -use rustc_serialize as serialize; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; /// Helper type to cache the result of `graph::is_cyclic`. #[derive(Clone, Debug)] @@ -36,17 +36,17 @@ impl GraphIsCyclicCache { } } -impl<S: serialize::Encoder> serialize::Encodable<S> for GraphIsCyclicCache { +impl<S: Encoder> Encodable<S> for GraphIsCyclicCache { #[inline] fn encode(&self, s: &mut S) { - serialize::Encodable::encode(&(), s); + Encodable::encode(&(), s); } } -impl<D: serialize::Decoder> serialize::Decodable<D> for GraphIsCyclicCache { +impl<D: Decoder> Decodable<D> for GraphIsCyclicCache { #[inline] fn decode(d: &mut D) -> Self { - let () = serialize::Decodable::decode(d); + let () = Decodable::decode(d); Self::new() } } diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs index 9bc0cb1138ff1..620cf7e336ba4 100644 --- a/compiler/rustc_middle/src/mir/predecessors.rs +++ b/compiler/rustc_middle/src/mir/predecessors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::OnceCell; use rustc_index::vec::IndexVec; -use rustc_serialize as serialize; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; use crate::mir::{BasicBlock, BasicBlockData}; @@ -54,12 +54,12 @@ impl PredecessorCache { } } -impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache { +impl<S: Encoder> Encodable<S> for PredecessorCache { #[inline] fn encode(&self, _s: &mut S) {} } -impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache { +impl<D: Decoder> Decodable<D> for PredecessorCache { #[inline] fn decode(_: &mut D) -> Self { Self::new() diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs index 4872a7835e3fa..99d13fcfef43e 100644 --- a/compiler/rustc_middle/src/mir/switch_sources.rs +++ b/compiler/rustc_middle/src/mir/switch_sources.rs @@ -5,7 +5,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::sync::OnceCell; use rustc_index::vec::IndexVec; -use rustc_serialize as serialize; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind}; @@ -54,12 +54,12 @@ impl SwitchSourceCache { } } -impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache { +impl<S: Encoder> Encodable<S> for SwitchSourceCache { #[inline] fn encode(&self, _s: &mut S) {} } -impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache { +impl<D: Decoder> Decodable<D> for SwitchSourceCache { #[inline] fn decode(_: &mut D) -> Self { Self::new() diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index f745e55307ae2..7228e3f33b126 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -1,7 +1,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::OnceCell; use rustc_index::bit_set::BitSet; -use rustc_serialize as serialize; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use super::*; @@ -365,12 +365,12 @@ impl PostorderCache { } } -impl<S: serialize::Encoder> serialize::Encodable<S> for PostorderCache { +impl<S: Encoder> Encodable<S> for PostorderCache { #[inline] fn encode(&self, _s: &mut S) {} } -impl<D: serialize::Decoder> serialize::Decodable<D> for PostorderCache { +impl<D: Decoder> Decodable<D> for PostorderCache { #[inline] fn decode(_: &mut D) -> Self { Self::new() diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b224fa9596eb8..81bab0e3513c9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2248,36 +2248,59 @@ impl<'a> Parser<'a> { &mut self, attrs: AttrVec, lo: Span, - cond: P<Expr>, + mut cond: P<Expr>, ) -> PResult<'a, P<Expr>> { - let missing_then_block_binop_span = || { - match cond.kind { - ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right) - if let ExprKind::Block(..) = right.kind => Some(binop_span), - _ => None + let cond_span = cond.span; + // Tries to interpret `cond` as either a missing expression if it's a block, + // or as an unfinished expression if it's a binop and the RHS is a block. + // We could probably add more recoveries here too... + let mut recover_block_from_condition = |this: &mut Self| { + let block = match &mut cond.kind { + ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) + if let ExprKind::Block(_, None) = right.kind => { + this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit(); + std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi())) + }, + ExprKind::Block(_, None) => { + this.error_missing_if_cond(lo, cond_span).emit(); + std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi())) + } + _ => { + return None; + } + }; + if let ExprKind::Block(block, _) = &block.kind { + Some(block.clone()) + } else { + unreachable!() } }; - // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then - // verify that the last statement is either an implicit return (no `;`) or an explicit - // return. This won't catch blocks with an explicit `return`, but that would be caught by - // the dead code lint. - let thn = if self.token.is_keyword(kw::Else) || !cond.returns() { - if let Some(binop_span) = missing_then_block_binop_span() { - self.error_missing_if_then_block(lo, None, Some(binop_span)).emit(); - self.mk_block_err(cond.span) + // Parse then block + let thn = if self.token.is_keyword(kw::Else) { + if let Some(block) = recover_block_from_condition(self) { + block } else { - self.error_missing_if_cond(lo, cond.span) + self.error_missing_if_then_block(lo, cond_span, false).emit(); + self.mk_block_err(cond_span.shrink_to_hi()) } } else { let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery. - let not_block = self.token != token::OpenDelim(Delimiter::Brace); - let block = self.parse_block().map_err(|err| { - if not_block { - self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span()) + let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { + self.parse_block()? + } else { + if let Some(block) = recover_block_from_condition(self) { + block } else { - err + // Parse block, which will always fail, but we can add a nice note to the error + self.parse_block().map_err(|mut err| { + err.span_note( + cond_span, + "the `if` expression is missing a block after this condition", + ); + err + })? } - })?; + }; self.error_on_if_block_attrs(lo, false, block.span, &attrs); block }; @@ -2288,31 +2311,34 @@ impl<'a> Parser<'a> { fn error_missing_if_then_block( &self, if_span: Span, - err: Option<DiagnosticBuilder<'a, ErrorGuaranteed>>, - binop_span: Option<Span>, + cond_span: Span, + is_unfinished: bool, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let msg = "this `if` expression has a condition, but no block"; - - let mut err = if let Some(mut err) = err { - err.span_label(if_span, msg); - err + let mut err = self.struct_span_err( + if_span, + "this `if` expression is missing a block after the condition", + ); + if is_unfinished { + err.span_help(cond_span, "this binary operation is possibly unfinished"); } else { - self.struct_span_err(if_span, msg) - }; - - if let Some(binop_span) = binop_span { - err.span_help(binop_span, "maybe you forgot the right operand of the condition?"); + err.span_help(cond_span.shrink_to_hi(), "add a block here"); } - err } - fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> { - let sp = self.sess.source_map().next_point(lo); - self.struct_span_err(sp, "missing condition for `if` expression") - .span_label(sp, "expected if condition here") - .emit(); - self.mk_block_err(span) + fn error_missing_if_cond( + &self, + lo: Span, + span: Span, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let next_span = self.sess.source_map().next_point(lo); + let mut err = self.struct_span_err(next_span, "missing condition for `if` expression"); + err.span_label(next_span, "expected condition here"); + err.span_label( + self.sess.source_map().start_point(span), + "if this block is the condition of the `if` expression, then it must be followed by another block" + ); + err } /// Parses the condition of a `if` or `while` expression. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 42355dd93a7a5..51bd9d2d386ad 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -432,10 +432,23 @@ impl<'a> Parser<'a> { // // which is valid in other languages, but not Rust. match self.parse_stmt_without_recovery(false, ForceCollect::No) { - // If the next token is an open brace (e.g., `if a b {`), the place- - // inside-a-block suggestion would be more likely wrong than right. + // If the next token is an open brace, e.g., we have: + // + // if expr other_expr { + // ^ ^ ^- lookahead(1) is a brace + // | |- current token is not "else" + // |- (statement we just parsed) + // + // the place-inside-a-block suggestion would be more likely wrong than right. + // + // FIXME(compiler-errors): this should probably parse an arbitrary expr and not + // just lookahead one token, so we can see if there's a brace after _that_, + // since we want to protect against: + // `if 1 1 + 1 {` being suggested as `if { 1 } 1 + 1 {` + // + + Ok(Some(_)) - if self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace)) + if (!self.token.is_keyword(kw::Else) + && self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Brace))) || do_not_suggest_help => {} // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836). Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {} diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index c2c876f7f1a12..d7327ca4bc602 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::dep_graph::DepContext; use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects}; use rustc_serialize::{ - opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, + opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}, Decodable, Decoder, Encodable, Encoder, }; use rustc_session::Session; @@ -158,7 +158,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { // Wrap in a scope so we can borrow `data`. let footer: Footer = { - let mut decoder = opaque::Decoder::new(&data, start_pos); + let mut decoder = MemDecoder::new(&data, start_pos); // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. @@ -437,7 +437,7 @@ impl<'sess> OnDiskCache<'sess> { let serialized_data = self.serialized_data.read(); let mut decoder = CacheDecoder { tcx, - opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()), + opaque: MemDecoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()), source_map: self.source_map, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, @@ -458,7 +458,7 @@ impl<'sess> OnDiskCache<'sess> { /// will also handle things that contain `Ty` instances. pub struct CacheDecoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - opaque: opaque::Decoder<'a>, + opaque: MemDecoder<'a>, source_map: &'a SourceMap, file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>, file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>, @@ -510,7 +510,7 @@ trait DecoderWithPosition: Decoder { fn position(&self) -> usize; } -impl<'a> DecoderWithPosition for opaque::Decoder<'a> { +impl<'a> DecoderWithPosition for MemDecoder<'a> { fn position(&self) -> usize { self.position() } @@ -586,7 +586,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { { debug_assert!(pos < self.opaque.data.len()); - let new_opaque = opaque::Decoder::new(self.opaque.data, pos); + let new_opaque = MemDecoder::new(self.opaque.data, pos); let old_opaque = mem::replace(&mut self.opaque, new_opaque); let r = f(self); self.opaque = old_opaque; diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 7fde9c0119b85..d583b45698ac4 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; use rustc_index::vec::{Idx, IndexVec}; -use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}; +use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use smallvec::SmallVec; use std::convert::TryInto; @@ -96,11 +96,11 @@ impl<K: DepKind> SerializedDepGraph<K> { } } -impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>> +impl<'a, K: DepKind + Decodable<MemDecoder<'a>>> Decodable<MemDecoder<'a>> for SerializedDepGraph<K> { #[instrument(level = "debug", skip(d))] - fn decode(d: &mut opaque::Decoder<'a>) -> SerializedDepGraph<K> { + fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph<K> { let start_position = d.position(); // The last 16 bytes are the node count and edge count. diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d2306254e3142..460d505ba98b5 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -396,7 +396,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; - let candidates = self + let mut candidates = self .r .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) .into_iter() @@ -408,6 +408,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { }) .collect::<Vec<_>>(); let crate_def_id = CRATE_DEF_ID.to_def_id(); + // Try to filter out intrinsics candidates, as long as we have + // some other candidates to suggest. + let intrinsic_candidates: Vec<_> = candidates + .drain_filter(|sugg| { + let path = path_names_to_string(&sugg.path); + path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::") + }) + .collect(); + if candidates.is_empty() { + // Put them back if we have no more candidates to suggest... + candidates.extend(intrinsic_candidates); + } if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) { let mut enum_candidates: Vec<_> = self .r diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index b2dbf937eb75a..f828c0b71063d 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -1,5 +1,5 @@ use crate::leb128::{self, max_leb128_len}; -use crate::serialize::{self, Decoder as _, Encoder as _}; +use crate::serialize::{Decodable, Decoder, Encodable, Encoder}; use std::convert::TryInto; use std::fs::File; use std::io::{self, Write}; @@ -11,13 +11,13 @@ use std::ptr; // Encoder // ----------------------------------------------------------------------------- -pub struct Encoder { +pub struct MemEncoder { pub data: Vec<u8>, } -impl Encoder { - pub fn new() -> Encoder { - Encoder { data: vec![] } +impl MemEncoder { + pub fn new() -> MemEncoder { + MemEncoder { data: vec![] } } #[inline] @@ -53,7 +53,7 @@ macro_rules! write_leb128 { /// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout const STR_SENTINEL: u8 = 0xC1; -impl serialize::Encoder for Encoder { +impl Encoder for MemEncoder { type Ok = Vec<u8>; type Err = !; @@ -161,7 +161,7 @@ pub type FileEncodeResult = Result<usize, io::Error>; // `FileEncoder` encodes data to file via fixed-size buffer. // // When encoding large amounts of data to a file, using `FileEncoder` may be -// preferred over using `Encoder` to encode to a `Vec`, and then writing the +// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the // `Vec` to file, as the latter uses as much memory as there is encoded data, // while the former uses the fixed amount of memory allocated to the buffer. // `FileEncoder` also has the advantage of not needing to reallocate as data @@ -425,7 +425,7 @@ macro_rules! file_encoder_write_leb128 { }}; } -impl serialize::Encoder for FileEncoder { +impl Encoder for FileEncoder { type Ok = usize; type Err = io::Error; @@ -535,15 +535,15 @@ impl serialize::Encoder for FileEncoder { // Decoder // ----------------------------------------------------------------------------- -pub struct Decoder<'a> { +pub struct MemDecoder<'a> { pub data: &'a [u8], position: usize, } -impl<'a> Decoder<'a> { +impl<'a> MemDecoder<'a> { #[inline] - pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { - Decoder { data, position } + pub fn new(data: &'a [u8], position: usize) -> MemDecoder<'a> { + MemDecoder { data, position } } #[inline] @@ -566,7 +566,7 @@ macro_rules! read_leb128 { ($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }}; } -impl<'a> serialize::Decoder for Decoder<'a> { +impl<'a> Decoder for MemDecoder<'a> { #[inline] fn read_u128(&mut self) -> u128 { read_leb128!(self, read_u128_leb128) @@ -688,25 +688,25 @@ impl<'a> serialize::Decoder for Decoder<'a> { // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc., // since the default implementations call `encode` on their slices internally. -impl serialize::Encodable<Encoder> for [u8] { - fn encode(&self, e: &mut Encoder) { - serialize::Encoder::emit_usize(e, self.len()); +impl Encodable<MemEncoder> for [u8] { + fn encode(&self, e: &mut MemEncoder) { + Encoder::emit_usize(e, self.len()); e.emit_raw_bytes(self); } } -impl serialize::Encodable<FileEncoder> for [u8] { +impl Encodable<FileEncoder> for [u8] { fn encode(&self, e: &mut FileEncoder) { - serialize::Encoder::emit_usize(e, self.len()); + Encoder::emit_usize(e, self.len()); e.emit_raw_bytes(self); } } // Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc., // since the default implementations call `decode` to produce a `Vec<u8>` internally. -impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> { - fn decode(d: &mut Decoder<'a>) -> Self { - let len = serialize::Decoder::read_usize(d); +impl<'a> Decodable<MemDecoder<'a>> for Vec<u8> { + fn decode(d: &mut MemDecoder<'a>) -> Self { + let len = Decoder::read_usize(d); d.read_raw_bytes(len).to_owned() } } @@ -718,9 +718,9 @@ impl IntEncodedWithFixedSize { pub const ENCODED_SIZE: usize = 8; } -impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize { +impl Encodable<MemEncoder> for IntEncodedWithFixedSize { #[inline] - fn encode(&self, e: &mut Encoder) { + fn encode(&self, e: &mut MemEncoder) { let _start_pos = e.position(); e.emit_raw_bytes(&self.0.to_le_bytes()); let _end_pos = e.position(); @@ -728,7 +728,7 @@ impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize { } } -impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize { +impl Encodable<FileEncoder> for IntEncodedWithFixedSize { #[inline] fn encode(&self, e: &mut FileEncoder) { let _start_pos = e.position(); @@ -738,9 +738,9 @@ impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize { } } -impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize { +impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize { #[inline] - fn decode(decoder: &mut Decoder<'a>) -> IntEncodedWithFixedSize { + fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize { let _start_pos = decoder.position(); let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE); let value = u64::from_le_bytes(bytes.try_into().unwrap()); diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs index 703b7f5e7a5f4..4eafb6fabde8e 100644 --- a/compiler/rustc_serialize/tests/opaque.rs +++ b/compiler/rustc_serialize/tests/opaque.rs @@ -1,7 +1,7 @@ #![allow(rustc::internal)] use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::opaque::{Decoder, Encoder}; +use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder as EncoderTrait}; use std::fmt::Debug; @@ -28,16 +28,18 @@ struct Struct { q: Option<u32>, } -fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + PartialEq + Debug>( +fn check_round_trip< + T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug, +>( values: Vec<T>, ) { - let mut encoder = Encoder::new(); + let mut encoder = MemEncoder::new(); for value in &values { Encodable::encode(value, &mut encoder); } let data = encoder.finish().unwrap(); - let mut decoder = Decoder::new(&data[..], 0); + let mut decoder = MemDecoder::new(&data[..], 0); for value in values { let decoded = Decodable::decode(&mut decoder); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index d7e2f621065f0..5d3d56b1e6699 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1911,13 +1911,13 @@ impl_pos! { pub struct CharPos(pub usize); } -impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos { +impl<S: Encoder> Encodable<S> for BytePos { fn encode(&self, s: &mut S) { s.emit_u32(self.0); } } -impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos { +impl<D: Decoder> Decodable<D> for BytePos { fn decode(d: &mut D) -> BytePos { BytePos(d.read_u32()) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6547ec493c862..c35a11ff7619e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -157,6 +157,7 @@ symbols! { C, CStr, CString, + Capture, Center, Clone, Continue, @@ -267,6 +268,8 @@ symbols! { ToOwned, ToString, Try, + TryCaptureGeneric, + TryCapturePrintable, TryFrom, TryInto, Ty, @@ -276,6 +279,7 @@ symbols! { UnsafeArg, Vec, VecDeque, + Wrapper, Yield, _DECLS, _Self, @@ -358,6 +362,7 @@ symbols! { assert_receiver_is_total_eq, assert_uninit_valid, assert_zero_valid, + asserting, associated_const_equality, associated_consts, associated_type_bounds, @@ -1437,6 +1442,7 @@ symbols! { truncf32, truncf64, try_blocks, + try_capture, try_from, try_into, try_trait_v2, @@ -1499,6 +1505,7 @@ symbols! { unsized_tuple_coercion, unstable, untagged_unions, + unused_imports, unused_qualifications, unwind, unwind_attributes, diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index a6a0d02c8ba99..9407218439993 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -14,7 +14,7 @@ use crate::UintTy; use self::TyKind::*; use rustc_data_structures::stable_hasher::HashStable; -use rustc_serialize::{Decodable, Encodable}; +use rustc_serialize::{Decodable, Decoder, Encodable}; /// Defines the kinds of types used by the type system. /// @@ -833,56 +833,34 @@ where I::AllocId: Decodable<D>, { fn decode(d: &mut D) -> Self { - match rustc_serialize::Decoder::read_usize(d) { + match Decoder::read_usize(d) { 0 => Bool, 1 => Char, - 2 => Int(rustc_serialize::Decodable::decode(d)), - 3 => Uint(rustc_serialize::Decodable::decode(d)), - 4 => Float(rustc_serialize::Decodable::decode(d)), - 5 => Adt(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)), - 6 => Foreign(rustc_serialize::Decodable::decode(d)), + 2 => Int(Decodable::decode(d)), + 3 => Uint(Decodable::decode(d)), + 4 => Float(Decodable::decode(d)), + 5 => Adt(Decodable::decode(d), Decodable::decode(d)), + 6 => Foreign(Decodable::decode(d)), 7 => Str, - 8 => { - Array(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) - } - 9 => Slice(rustc_serialize::Decodable::decode(d)), - 10 => RawPtr(rustc_serialize::Decodable::decode(d)), - 11 => Ref( - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - ), - 12 => { - FnDef(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) - } - 13 => FnPtr(rustc_serialize::Decodable::decode(d)), - 14 => Dynamic( - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - ), - 15 => Closure( - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - ), - 16 => Generator( - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - rustc_serialize::Decodable::decode(d), - ), - 17 => GeneratorWitness(rustc_serialize::Decodable::decode(d)), + 8 => Array(Decodable::decode(d), Decodable::decode(d)), + 9 => Slice(Decodable::decode(d)), + 10 => RawPtr(Decodable::decode(d)), + 11 => Ref(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), + 12 => FnDef(Decodable::decode(d), Decodable::decode(d)), + 13 => FnPtr(Decodable::decode(d)), + 14 => Dynamic(Decodable::decode(d), Decodable::decode(d)), + 15 => Closure(Decodable::decode(d), Decodable::decode(d)), + 16 => Generator(Decodable::decode(d), Decodable::decode(d), Decodable::decode(d)), + 17 => GeneratorWitness(Decodable::decode(d)), 18 => Never, - 19 => Tuple(rustc_serialize::Decodable::decode(d)), - 20 => Projection(rustc_serialize::Decodable::decode(d)), - 21 => { - Opaque(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) - } - 22 => Param(rustc_serialize::Decodable::decode(d)), - 23 => { - Bound(rustc_serialize::Decodable::decode(d), rustc_serialize::Decodable::decode(d)) - } - 24 => Placeholder(rustc_serialize::Decodable::decode(d)), - 25 => Infer(rustc_serialize::Decodable::decode(d)), - 26 => Error(rustc_serialize::Decodable::decode(d)), + 19 => Tuple(Decodable::decode(d)), + 20 => Projection(Decodable::decode(d)), + 21 => Opaque(Decodable::decode(d), Decodable::decode(d)), + 22 => Param(Decodable::decode(d)), + 23 => Bound(Decodable::decode(d), Decodable::decode(d)), + 24 => Placeholder(Decodable::decode(d)), + 25 => Infer(Decodable::decode(d)), + 26 => Error(Decodable::decode(d)), _ => panic!( "{}", format!( diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 242f926967c93..da09ae9dd0662 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -17,7 +17,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_serialize::{ - opaque::{Decoder, FileEncoder}, + opaque::{FileEncoder, MemDecoder}, Decodable, Encodable, Encoder, }; use rustc_session::getopts; @@ -336,7 +336,7 @@ pub(crate) fn load_call_locations( let mut all_calls: AllCallLocations = FxHashMap::default(); for path in with_examples { let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?; - let mut decoder = Decoder::new(&bytes, 0); + let mut decoder = MemDecoder::new(&bytes, 0); let calls = AllCallLocations::decode(&mut decoder); for (function, fn_calls) in calls.into_iter() { diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs index a09deeec4f182..4ad4ef60a5294 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs @@ -7,7 +7,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::opaque; +use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; #[derive(Encodable, Decodable)] @@ -18,11 +18,11 @@ struct A { fn main() { let obj = A { foo: Box::new([true, false]) }; - let mut encoder = opaque::Encoder::new(); + let mut encoder = MemEncoder::new(); obj.encode(&mut encoder); let data = encoder.finish().unwrap(); - let mut decoder = opaque::Decoder::new(&data, 0); + let mut decoder = MemDecoder::new(&data, 0); let obj2 = A::decode(&mut decoder); assert_eq!(obj.foo, obj2.foo); diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs index 9b6fb0e580621..3ac3abae692af 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs @@ -9,7 +9,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::opaque; +use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; use std::cell::{Cell, RefCell}; @@ -27,11 +27,11 @@ struct B { fn main() { let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) }; - let mut encoder = opaque::Encoder::new(); + let mut encoder = MemEncoder::new(); obj.encode(&mut encoder); let data = encoder.finish().unwrap(); - let mut decoder = opaque::Decoder::new(&data, 0); + let mut decoder = MemDecoder::new(&data, 0); let obj2 = B::decode(&mut decoder); assert_eq!(obj.foo.get(), obj2.foo.get()); diff --git a/src/test/ui-fulldeps/issue-14021.rs b/src/test/ui-fulldeps/issue-14021.rs index 4241456367e46..b7b6e1b860d35 100644 --- a/src/test/ui-fulldeps/issue-14021.rs +++ b/src/test/ui-fulldeps/issue-14021.rs @@ -8,7 +8,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::opaque; +use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; #[derive(Encodable, Decodable, PartialEq, Debug)] @@ -17,11 +17,11 @@ struct UnitLikeStruct; pub fn main() { let obj = UnitLikeStruct; - let mut encoder = opaque::Encoder::new(); + let mut encoder = MemEncoder::new(); obj.encode(&mut encoder); let data = encoder.finish().unwrap(); - let mut decoder = opaque::Decoder::new(&data, 0); + let mut decoder = MemDecoder::new(&data, 0); let obj2 = UnitLikeStruct::decode(&mut decoder); assert_eq!(obj, obj2); diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index 609a5efd46fee..3ccc14bba5422 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -25,10 +25,16 @@ LL | println!("Then when?"); error: expected `{`, found `;` --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31 | -LL | if not // lack of braces is [sic] - | -- this `if` expression has a condition, but no block LL | println!("Then when?"); | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:19:8 + | +LL | if not // lack of braces is [sic] + | ________^ +LL | | println!("Then when?"); + | |______________________________^ error: unexpected `2` after identifier --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 diff --git a/src/test/ui/expr/if/if-without-block.rs b/src/test/ui/expr/if/if-without-block.rs index 8a4c59f32613d..5add9dfda4b9d 100644 --- a/src/test/ui/expr/if/if-without-block.rs +++ b/src/test/ui/expr/if/if-without-block.rs @@ -1,9 +1,7 @@ fn main() { let n = 1; if 5 == { - //~^ NOTE this `if` expression has a condition, but no block + //~^ ERROR this `if` expression is missing a block after the condition println!("five"); } } -//~^ ERROR expected `{`, found `}` -//~| NOTE expected `{` diff --git a/src/test/ui/expr/if/if-without-block.stderr b/src/test/ui/expr/if/if-without-block.stderr index d3f6ca07617f4..2d1ee04ce09a8 100644 --- a/src/test/ui/expr/if/if-without-block.stderr +++ b/src/test/ui/expr/if/if-without-block.stderr @@ -1,17 +1,14 @@ -error: expected `{`, found `}` - --> $DIR/if-without-block.rs:7:1 +error: this `if` expression is missing a block after the condition + --> $DIR/if-without-block.rs:3:5 | LL | if 5 == { - | -- this `if` expression has a condition, but no block -... -LL | } - | ^ expected `{` + | ^^ | -help: maybe you forgot the right operand of the condition? - --> $DIR/if-without-block.rs:3:10 +help: this binary operation is possibly unfinished + --> $DIR/if-without-block.rs:3:8 | LL | if 5 == { - | ^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr index feabe3814dcf9..387ef0776ff4a 100644 --- a/src/test/ui/issues/issue-39848.stderr +++ b/src/test/ui/issues/issue-39848.stderr @@ -2,13 +2,19 @@ error: expected `{`, found `foo` --> $DIR/issue-39848.rs:3:21 | LL | if $tgt.has_$field() {} - | -- ^^^^^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^^^^^ expected `{` ... LL | get_opt!(bar, foo); | ------------------ in this macro invocation | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-39848.rs:3:12 + | +LL | if $tgt.has_$field() {} + | ^^^^^^^^^ +... +LL | get_opt!(bar, foo); + | ------------------ in this macro invocation = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) help: try placing this code inside a block | diff --git a/src/test/ui/macros/assert-trailing-junk.rs b/src/test/ui/macros/assert-trailing-junk.rs index cd7faf9bf8bfb..da725e19e2ada 100644 --- a/src/test/ui/macros/assert-trailing-junk.rs +++ b/src/test/ui/macros/assert-trailing-junk.rs @@ -1,3 +1,6 @@ +// revisions: with-generic-asset without-generic-asset +// [with-generic-asset] compile-flags: --cfg feature="generic_assert" + // Ensure assert macro does not ignore trailing garbage. // // See https://github.com/rust-lang/rust/issues/60024 for details. diff --git a/src/test/ui/macros/assert-trailing-junk.stderr b/src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr similarity index 86% rename from src/test/ui/macros/assert-trailing-junk.stderr rename to src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr index eb001429c5522..09dd16a0b0d89 100644 --- a/src/test/ui/macros/assert-trailing-junk.stderr +++ b/src/test/ui/macros/assert-trailing-junk.with-generic-asset.stderr @@ -1,17 +1,17 @@ error: expected one of `,`, `.`, `?`, or an operator, found `some` - --> $DIR/assert-trailing-junk.rs:6:18 + --> $DIR/assert-trailing-junk.rs:9:18 | LL | assert!(true some extra junk, "whatever"); | ^^^^ expected one of `,`, `.`, `?`, or an operator error: expected one of `,`, `.`, `?`, or an operator, found `some` - --> $DIR/assert-trailing-junk.rs:9:18 + --> $DIR/assert-trailing-junk.rs:12:18 | LL | assert!(true some extra junk); | ^^^^ expected one of `,`, `.`, `?`, or an operator error: no rules expected the token `blah` - --> $DIR/assert-trailing-junk.rs:12:30 + --> $DIR/assert-trailing-junk.rs:15:30 | LL | assert!(true, "whatever" blah); | -^^^^ no rules expected this token in macro call @@ -19,7 +19,7 @@ LL | assert!(true, "whatever" blah); | help: missing comma here error: unexpected string literal - --> $DIR/assert-trailing-junk.rs:15:18 + --> $DIR/assert-trailing-junk.rs:18:18 | LL | assert!(true "whatever" blah); | -^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | assert!(true "whatever" blah); | help: try adding a comma error: no rules expected the token `blah` - --> $DIR/assert-trailing-junk.rs:15:29 + --> $DIR/assert-trailing-junk.rs:18:29 | LL | assert!(true "whatever" blah); | -^^^^ no rules expected this token in macro call @@ -35,7 +35,7 @@ LL | assert!(true "whatever" blah); | help: missing comma here error: macro requires an expression as an argument - --> $DIR/assert-trailing-junk.rs:19:5 + --> $DIR/assert-trailing-junk.rs:22:5 | LL | assert!(true;); | ^^^^^^^^^^^^-^ @@ -43,7 +43,7 @@ LL | assert!(true;); | help: try removing semicolon error: unexpected string literal - --> $DIR/assert-trailing-junk.rs:22:27 + --> $DIR/assert-trailing-junk.rs:25:27 | LL | assert!(false || true "error message"); | -^^^^^^^^^^^^^^^ diff --git a/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr b/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr new file mode 100644 index 0000000000000..09dd16a0b0d89 --- /dev/null +++ b/src/test/ui/macros/assert-trailing-junk.without-generic-asset.stderr @@ -0,0 +1,54 @@ +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:9:18 + | +LL | assert!(true some extra junk, "whatever"); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: expected one of `,`, `.`, `?`, or an operator, found `some` + --> $DIR/assert-trailing-junk.rs:12:18 + | +LL | assert!(true some extra junk); + | ^^^^ expected one of `,`, `.`, `?`, or an operator + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:15:30 + | +LL | assert!(true, "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:18:18 + | +LL | assert!(true "whatever" blah); + | -^^^^^^^^^^ + | | + | help: try adding a comma + +error: no rules expected the token `blah` + --> $DIR/assert-trailing-junk.rs:18:29 + | +LL | assert!(true "whatever" blah); + | -^^^^ no rules expected this token in macro call + | | + | help: missing comma here + +error: macro requires an expression as an argument + --> $DIR/assert-trailing-junk.rs:22:5 + | +LL | assert!(true;); + | ^^^^^^^^^^^^-^ + | | + | help: try removing semicolon + +error: unexpected string literal + --> $DIR/assert-trailing-junk.rs:25:27 + | +LL | assert!(false || true "error message"); + | -^^^^^^^^^^^^^^^ + | | + | help: try adding a comma + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/macros/assert.rs b/src/test/ui/macros/assert.rs index 71b0dbb19e262..a314db907b8a2 100644 --- a/src/test/ui/macros/assert.rs +++ b/src/test/ui/macros/assert.rs @@ -1,3 +1,6 @@ +// revisions: with-generic-asset without-generic-asset +// [with-generic-asset] compile-flags: --cfg feature="generic_assert" + fn main() { assert!(); //~ ERROR requires a boolean expression assert!(struct); //~ ERROR expected expression diff --git a/src/test/ui/macros/assert.stderr b/src/test/ui/macros/assert.with-generic-asset.stderr similarity index 87% rename from src/test/ui/macros/assert.stderr rename to src/test/ui/macros/assert.with-generic-asset.stderr index 57e5c77a56692..51d8f28a35c39 100644 --- a/src/test/ui/macros/assert.stderr +++ b/src/test/ui/macros/assert.with-generic-asset.stderr @@ -1,17 +1,17 @@ error: macro requires a boolean expression as an argument - --> $DIR/assert.rs:2:5 + --> $DIR/assert.rs:5:5 | LL | assert!(); | ^^^^^^^^^ boolean expression required error: expected expression, found keyword `struct` - --> $DIR/assert.rs:3:13 + --> $DIR/assert.rs:6:13 | LL | assert!(struct); | ^^^^^^ expected expression error: macro requires a boolean expression as an argument - --> $DIR/assert.rs:4:5 + --> $DIR/assert.rs:7:5 | LL | debug_assert!(); | ^^^^^^^^^^^^^^^ boolean expression required @@ -19,7 +19,7 @@ LL | debug_assert!(); = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found keyword `struct` - --> $DIR/assert.rs:5:19 + --> $DIR/assert.rs:8:19 | LL | debug_assert!(struct); | ^^^^^^ expected expression diff --git a/src/test/ui/macros/assert.without-generic-asset.stderr b/src/test/ui/macros/assert.without-generic-asset.stderr new file mode 100644 index 0000000000000..51d8f28a35c39 --- /dev/null +++ b/src/test/ui/macros/assert.without-generic-asset.stderr @@ -0,0 +1,28 @@ +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:5:5 + | +LL | assert!(); + | ^^^^^^^^^ boolean expression required + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:6:13 + | +LL | assert!(struct); + | ^^^^^^ expected expression + +error: macro requires a boolean expression as an argument + --> $DIR/assert.rs:7:5 + | +LL | debug_assert!(); + | ^^^^^^^^^^^^^^^ boolean expression required + | + = note: this error originates in the macro `debug_assert` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found keyword `struct` + --> $DIR/assert.rs:8:19 + | +LL | debug_assert!(struct); + | ^^^^^^ expected expression + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr index 148e214e58ec1..16954223a4521 100644 --- a/src/test/ui/missing/missing-block-hint.stderr +++ b/src/test/ui/missing/missing-block-hint.stderr @@ -2,18 +2,25 @@ error: expected `{`, found `=>` --> $DIR/missing-block-hint.rs:3:18 | LL | if (foo) => {} - | -- ^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:3:12 + | +LL | if (foo) => {} + | ^^^^^ error: expected `{`, found `bar` --> $DIR/missing-block-hint.rs:7:13 | -LL | if (foo) - | -- this `if` expression has a condition, but no block LL | bar; | ^^^ expected `{` | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:6:12 + | +LL | if (foo) + | ^^^^^ help: try placing this code inside a block | LL | { bar; } diff --git a/src/test/ui/parser/bad-if-statements.rs b/src/test/ui/parser/bad-if-statements.rs new file mode 100644 index 0000000000000..2c501e3a5b399 --- /dev/null +++ b/src/test/ui/parser/bad-if-statements.rs @@ -0,0 +1,38 @@ +fn a() { + if {} + //~^ ERROR missing condition for `if` expression +} + +fn b() { + if true && {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c() { + let x = {}; + if true x + //~^ ERROR expected `{`, found `x` +} + +fn a2() { + if {} else {} + //~^ ERROR missing condition for `if` expression +} + +fn b2() { + if true && {} else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c2() { + let x = {}; + if true x else {} + //~^ ERROR expected `{`, found `x` +} + +fn d() { + if true else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn main() {} diff --git a/src/test/ui/parser/bad-if-statements.stderr b/src/test/ui/parser/bad-if-statements.stderr new file mode 100644 index 0000000000000..ee839db645509 --- /dev/null +++ b/src/test/ui/parser/bad-if-statements.stderr @@ -0,0 +1,86 @@ +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:2:7 + | +LL | if {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:7:5 + | +LL | if true && {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:7:8 + | +LL | if true && {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:13:13 + | +LL | if true x + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:13:8 + | +LL | if true x + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } + | + + + +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:18:7 + | +LL | if {} else {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:23:5 + | +LL | if true && {} else {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:23:8 + | +LL | if true && {} else {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:29:13 + | +LL | if true x else {} + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:29:8 + | +LL | if true x else {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } else {} + | + + + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:34:5 + | +LL | if true else {} + | ^^ + | +help: add a block here + --> $DIR/bad-if-statements.rs:34:12 + | +LL | if true else {} + | ^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/parser/if-block-unreachable-expr.rs b/src/test/ui/parser/if-block-unreachable-expr.rs new file mode 100644 index 0000000000000..4063a33708402 --- /dev/null +++ b/src/test/ui/parser/if-block-unreachable-expr.rs @@ -0,0 +1,8 @@ +// check-pass + +// This regressed from 1.20 -> 1.21 -- the condition is unreachable, +// but it's still an expression, and should parse fine. + +fn main() { + if { if true { return; } else { return; }; } {} +} diff --git a/src/test/ui/parser/issue-61858.stderr b/src/test/ui/parser/issue-61858.stderr index 8b95d9c6ae48b..03f51c6e3a8f4 100644 --- a/src/test/ui/parser/issue-61858.stderr +++ b/src/test/ui/parser/issue-61858.stderr @@ -2,9 +2,13 @@ error: expected `{`, found `)` --> $DIR/issue-61858.rs:2:15 | LL | (if foobar) - | -- ^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-61858.rs:2:9 + | +LL | (if foobar) + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs index 00f90cc73b344..57d36feb37b13 100644 --- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs +++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs @@ -1,7 +1,8 @@ macro_rules! x { ($($c:tt)*) => { - $($c)ö* {} //~ ERROR missing condition for `if` expression - }; //~| ERROR mismatched types + $($c)ö* {} + //~^ ERROR missing condition for `if` expression + }; } fn main() { diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr index cdd4c670500f0..6674b924e9c4b 100644 --- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr +++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr @@ -2,19 +2,9 @@ error: missing condition for `if` expression --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14 | LL | $($c)ö* {} - | ^ expected if condition here + | ^ - if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here -error[E0308]: mismatched types - --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17 - | -LL | $($c)ö* {} - | ^^ expected `bool`, found `()` -... -LL | x!(if); - | ------ in this macro invocation - | - = note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issue-91421.rs b/src/test/ui/parser/issue-91421.rs index 9959df5663837..8bba27f372439 100644 --- a/src/test/ui/parser/issue-91421.rs +++ b/src/test/ui/parser/issue-91421.rs @@ -2,9 +2,8 @@ fn main() { let value = if true && { - //~^ ERROR: this `if` expression has a condition, but no block - //~| HELP: maybe you forgot the right operand of the condition? + //~^ ERROR: this `if` expression is missing a block after the condition + //~| HELP: this binary operation is possibly unfinished 3 - //~^ ERROR: mismatched types [E0308] } else { 4 }; } diff --git a/src/test/ui/parser/issue-91421.stderr b/src/test/ui/parser/issue-91421.stderr index 04284d5e3b2f7..2d9652051dd56 100644 --- a/src/test/ui/parser/issue-91421.stderr +++ b/src/test/ui/parser/issue-91421.stderr @@ -1,21 +1,14 @@ -error: this `if` expression has a condition, but no block +error: this `if` expression is missing a block after the condition --> $DIR/issue-91421.rs:4:17 | LL | let value = if true && { | ^^ | -help: maybe you forgot the right operand of the condition? - --> $DIR/issue-91421.rs:4:25 +help: this binary operation is possibly unfinished + --> $DIR/issue-91421.rs:4:20 | LL | let value = if true && { - | ^^ + | ^^^^^^^ -error[E0308]: mismatched types - --> $DIR/issue-91421.rs:7:9 - | -LL | 3 - | ^ expected `bool`, found integer - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issues/issue-13483.rs b/src/test/ui/parser/issues/issue-13483.rs index a2fd9264b1530..4e32fcab3f098 100644 --- a/src/test/ui/parser/issues/issue-13483.rs +++ b/src/test/ui/parser/issues/issue-13483.rs @@ -1,15 +1,15 @@ fn main() { if true { - } else if { //~ ERROR missing condition - //~^ ERROR mismatched types + } else if { + //~^ ERROR missing condition for `if` expression } else { } } fn foo() { if true { - } else if { //~ ERROR missing condition - //~^ ERROR mismatched types + } else if { + //~^ ERROR missing condition for `if` expression } bar(); } diff --git a/src/test/ui/parser/issues/issue-13483.stderr b/src/test/ui/parser/issues/issue-13483.stderr index 5fd05b18ce06e..f5534090f18a4 100644 --- a/src/test/ui/parser/issues/issue-13483.stderr +++ b/src/test/ui/parser/issues/issue-13483.stderr @@ -2,32 +2,17 @@ error: missing condition for `if` expression --> $DIR/issue-13483.rs:3:14 | LL | } else if { - | ^ expected if condition here + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here error: missing condition for `if` expression --> $DIR/issue-13483.rs:11:14 | LL | } else if { - | ^ expected if condition here + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here -error[E0308]: mismatched types - --> $DIR/issue-13483.rs:3:15 - | -LL | } else if { - | _______________^ -LL | | -LL | | } else { - | |_____^ expected `bool`, found `()` - -error[E0308]: mismatched types - --> $DIR/issue-13483.rs:11:15 - | -LL | } else if { - | _______________^ -LL | | -LL | | } - | |_____^ expected `bool`, found `()` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issues/issue-51602.stderr b/src/test/ui/parser/issues/issue-51602.stderr index d800890bca38d..4a5653fdb513e 100644 --- a/src/test/ui/parser/issues/issue-51602.stderr +++ b/src/test/ui/parser/issues/issue-51602.stderr @@ -2,9 +2,13 @@ error: expected `{`, found keyword `in` --> $DIR/issue-51602.rs:2:10 | LL | if i in 1..10 { - | -- ^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-51602.rs:2:8 + | +LL | if i in 1..10 { + | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-62554.stderr b/src/test/ui/parser/issues/issue-62554.stderr index 3589016e1dc83..9e62572e388fd 100644 --- a/src/test/ui/parser/issues/issue-62554.stderr +++ b/src/test/ui/parser/issues/issue-62554.stderr @@ -57,10 +57,13 @@ error: expected `{`, found `macro_rules` --> $DIR/issue-62554.rs:6:23 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { - | -- ^^^^^^^^^^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^^^^^^^^^^ expected `{` | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-62554.rs:6:20 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | ^^ help: try placing this code inside a block | LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { } diff --git a/src/test/ui/resolve/filter-intrinsics.rs b/src/test/ui/resolve/filter-intrinsics.rs new file mode 100644 index 0000000000000..c0956ef85aff6 --- /dev/null +++ b/src/test/ui/resolve/filter-intrinsics.rs @@ -0,0 +1,10 @@ +fn main() { + // Should suggest only `std::mem::size_of` + let _ = size_of::<usize>(); + //~^ ERROR cannot find + + // Should suggest `std::intrinsics::fabsf64`, + // since there is no non-intrinsic to suggest. + let _ = fabsf64(1.0); + //~^ ERROR cannot find +} diff --git a/src/test/ui/resolve/filter-intrinsics.stderr b/src/test/ui/resolve/filter-intrinsics.stderr new file mode 100644 index 0000000000000..955070891fbbe --- /dev/null +++ b/src/test/ui/resolve/filter-intrinsics.stderr @@ -0,0 +1,25 @@ +error[E0425]: cannot find function `size_of` in this scope + --> $DIR/filter-intrinsics.rs:3:13 + | +LL | let _ = size_of::<usize>(); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::mem::size_of; + | + +error[E0425]: cannot find function `fabsf64` in this scope + --> $DIR/filter-intrinsics.rs:8:13 + | +LL | let _ = fabsf64(1.0); + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL | use std::intrinsics::fabsf64; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/src/test/ui/rfc-2011-nicer-assert-messages/all-expr-kinds.rs new file mode 100644 index 0000000000000..c0e9f29fdbce0 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/all-expr-kinds.rs @@ -0,0 +1,143 @@ +// edition:2021 +// ignore-tidy-linelength +// only-x86_64 +// run-pass + +#![allow(path_statements, unused_allocation)] +#![feature(box_syntax, core_intrinsics, generic_assert, generic_assert_internals)] + +macro_rules! test { + ( + let mut $elem_ident:ident = $elem_expr:expr; + [ $($assert:tt)* ] => $msg:literal + ) => { + { + #[allow(unused_assignments, unused_mut, unused_variables)] + let rslt = std::panic::catch_unwind(|| { + let mut $elem_ident = $elem_expr; + assert!($($assert)*); + }); + let err = rslt.unwrap_err(); + if let Some(elem) = err.downcast_ref::<String>() { + assert_eq!(elem, &$msg); + } + else if let Some(elem) = err.downcast_ref::<&str>() { + assert_eq!(elem, &$msg); + } + else { + panic!("assert!( ... ) should return a string"); + } + } + } +} + +macro_rules! tests { + ( + let mut $elem_ident:ident = $elem_expr:expr; + + $( + [ $($elem_assert:tt)* ] => $elem_msg:literal + )+ + ) => { + $( + test!( + let mut $elem_ident = $elem_expr; + [ $($elem_assert)* ] => $elem_msg + ); + )+ + } +} + +const FOO: Foo = Foo { bar: 1 }; + +#[derive(Clone, Copy, Debug, PartialEq)] +struct Foo { + bar: i32 +} + +fn main() { + // ***** Allowed ***** + + tests!( + let mut elem = 1i32; + + // binary + [ elem + 1 == 3 ] => "Assertion failed: elem + 1 == 3\nWith captures:\n elem = 1\n" + ); + + // ***** Disallowed ***** + + tests!( + let mut elem = 1i32; + + // assign + [ { let local = elem; local } == 3 ] => "Assertion failed: { let local = elem; local } == 3" + + // assign op + [ { elem += 1; elem } == 3 ] => "Assertion failed: { elem += 1; elem } == 3" + + // async + [ { let _ = async { elem }; elem } == 3 ] => "Assertion failed: { let _ = async { elem }; elem } == 3" + + // await + + // block + [ { elem } == 3 ] => "Assertion failed: { elem } == 3" + + // box + [ box elem == box 3 ] => "Assertion failed: box elem == box 3" + + // break + [ loop { break elem; } == 3 ] => "Assertion failed: loop { break elem; } == 3" + + // closure + [(|| elem)() == 3 ] => "Assertion failed: (|| elem)() == 3" + + // const block + + // continue + + // err + + // field + [ FOO.bar == 3 ] => "Assertion failed: FOO.bar == 3" + + // for loop + [ { for _ in 0..elem { elem; } elem } == 3 ] => "Assertion failed: { for _ in 0..elem { elem; } elem } == 3" + + // if + [ if true { elem } else { elem } == 3 ] => "Assertion failed: if true { elem } else { elem } == 3" + + // inline asm + + // let + [ if let true = true { elem } else { elem } == 3 ] => "Assertion failed: if let true = true { elem } else { elem } == 3" + + // lit + + // loop + [ loop { elem; break elem; } == 3 ] => "Assertion failed: loop { elem; break elem; } == 3" + + // mac call + + // match + [ match elem { _ => elem } == 3 ] => "Assertion failed: match elem { _ => elem, } == 3" + + // ret + [ (|| { return elem; })() == 3 ] => "Assertion failed: (|| { return elem; })() == 3" + + // try + [ (|| { Some(Some(elem)?) })() == Some(3) ] => "Assertion failed: (|| { Some(Some(elem)?) })() == Some(3)" + + // try block + + // underscore + + // while + [ { while false { elem; break; } elem } == 3 ] => "Assertion failed: { while false { elem; break; } elem } == 3" + + // yeet + + // yield + ); +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/src/test/ui/rfc-2011-nicer-assert-messages/all-not-available-cases.rs new file mode 100644 index 0000000000000..86697c58fbcf1 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/all-not-available-cases.rs @@ -0,0 +1,43 @@ +// aux-build:common.rs +// ignore-tidy-linelength +// only-x86_64 +// run-pass + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +extern crate common; + +#[derive(Clone, Copy, PartialEq)] +struct CopyNoDebug(i32); + +#[derive(Debug, PartialEq)] +struct NoCopyDebug(i32); + +#[derive(PartialEq)] +struct NoCopyNoDebug(i32); + +fn main() { + // Has Copy but does not have Debug + common::test!( + let mut copy_no_debug = CopyNoDebug(1); + [ copy_no_debug == CopyNoDebug(3) ] => "Assertion failed: copy_no_debug == CopyNoDebug(3)\nWith captures:\n copy_no_debug = N/A\n" + ); + + // Does not have Copy but has Debug + common::test!( + let mut no_copy_debug = NoCopyDebug(1); + [ no_copy_debug == NoCopyDebug(3) ] => "Assertion failed: no_copy_debug == NoCopyDebug(3)\nWith captures:\n no_copy_debug = N/A\n" + ); + + // Does not have Copy and does not have Debug + common::test!( + let mut no_copy_no_debug = NoCopyNoDebug(1); + [ no_copy_no_debug == NoCopyNoDebug(3) ] => "Assertion failed: no_copy_no_debug == NoCopyNoDebug(3)\nWith captures:\n no_copy_no_debug = N/A\n" + ); + + // Unevaluated (Expression short-circuited) + common::test!( + let mut elem = true; + [ false && elem ] => "Assertion failed: false && elem\nWith captures:\n elem = N/A\n" + ); +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/src/test/ui/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs new file mode 100644 index 0000000000000..6a1435f792bf4 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs @@ -0,0 +1,13 @@ +// compile-flags: --test +// run-pass + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +#[should_panic(expected = "Custom user message")] +#[test] +fn test() { + assert!(1 == 3, "Custom user message"); +} + +fn main() { +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/src/test/ui/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs new file mode 100644 index 0000000000000..06c4993ec30d6 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs @@ -0,0 +1,14 @@ +// aux-build:common.rs +// only-x86_64 +// run-pass + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +extern crate common; + +fn main() { + common::test!( + let mut _nothing = (); + [ 1 == 3 ] => "Assertion failed: 1 == 3" + ); +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/auxiliary/common.rs b/src/test/ui/rfc-2011-nicer-assert-messages/auxiliary/common.rs new file mode 100644 index 0000000000000..903ed507c2e51 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/auxiliary/common.rs @@ -0,0 +1,25 @@ +#[macro_export] +macro_rules! test { + ( + let mut $elem_ident:ident = $elem_expr:expr; + [ $($assert:tt)* ] => $msg:literal + ) => { + { + #[allow(unused_assignments, unused_mut, unused_variables)] + let rslt = std::panic::catch_unwind(|| { + let mut $elem_ident = $elem_expr; + assert!($($assert)*); + }); + let err = rslt.unwrap_err(); + if let Some(elem) = err.downcast_ref::<String>() { + assert_eq!(elem, &$msg); + } + else if let Some(elem) = err.downcast_ref::<&str>() { + assert_eq!(elem, &$msg); + } + else { + panic!("assert!( ... ) should return a string"); + } + } + } +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/codegen.rs b/src/test/ui/rfc-2011-nicer-assert-messages/codegen.rs new file mode 100644 index 0000000000000..1db9d33c72aee --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/codegen.rs @@ -0,0 +1,9 @@ +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] + +fn main() { + let elem = 1i32; + assert!(elem == 1); +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/codegen.stdout b/src/test/ui/rfc-2011-nicer-assert-messages/codegen.stdout new file mode 100644 index 0000000000000..a590eb3223254 --- /dev/null +++ b/src/test/ui/rfc-2011-nicer-assert-messages/codegen.stdout @@ -0,0 +1,29 @@ +#![feature(prelude_import)] +#![no_std] +// check-pass +// compile-flags: -Z unpretty=expanded + +#![feature(core_intrinsics, generic_assert, generic_assert_internals)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn main() { + let elem = 1i32; + { + #[allow(unused_imports)] + use ::core::asserting::{TryCaptureGeneric, TryCapturePrintable}; + let mut __capture0 = ::core::asserting::Capture::new(); + let __local_bind0 = &elem; + if !(*{ + (&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0); + __local_bind0 + } == 1) { + { + ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ", + "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)])) + } + } + }; +} diff --git a/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs index f70ca87e304a9..01860adaac250 100644 --- a/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs +++ b/src/test/ui/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs @@ -1,8 +1,7 @@ // compile-flags: --test +// ignore-tidy-linelength // run-pass -// `generic_assert` is completely unimplemented and doesn't generate any logic, thus the -// reason why this test currently passes #![feature(core_intrinsics, generic_assert, generic_assert_internals)] use std::fmt::{Debug, Formatter}; @@ -16,10 +15,11 @@ impl Debug for CopyDebug { } } +#[should_panic(expected = "Assertion failed: copy_debug == CopyDebug(3)\nWith captures:\n copy_debug = With great power comes great electricity bills\n")] #[test] fn test() { - let _copy_debug = CopyDebug(1); - assert!(_copy_debug == CopyDebug(3)); + let copy_debug = CopyDebug(1); + assert!(copy_debug == CopyDebug(3)); } fn main() { diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs index e24649ea044f5..e66caa19ec96b 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs @@ -21,15 +21,15 @@ fn main() { }; if let Some(n) = opt else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; if let Some(n) = opt && n == 1 else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; if let Some(n) = opt && let another = n else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr index aebfc1a72b7aa..eea8ed0c9633e 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -20,23 +20,41 @@ help: wrap the expression in parentheses LL | let Some(n) = (opt && let another = n) else { | + + -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5 | LL | if let Some(n) = opt else { - | ^ expected if condition here + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25 + | +LL | if let Some(n) = opt else { + | ^ -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5 | LL | if let Some(n) = opt && n == 1 else { - | ^ expected if condition here + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35 + | +LL | if let Some(n) = opt && n == 1 else { + | ^ -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5 + | +LL | if let Some(n) = opt && let another = n else { + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44 | LL | if let Some(n) = opt && let another = n else { - | ^ expected if condition here + | ^ error: expected `{`, found keyword `else` --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33