diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 5830ce26fea3f..9d56bc193fb29 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1960,6 +1960,7 @@ declare_lint! { "detects proc macro derives using inaccessible names from parent modules", @future_incompatible = FutureIncompatibleInfo { reference: "issue #83583 ", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow, }; } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index abdac78ae242d..9b1ea3b4c4cf5 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -740,7 +740,9 @@ fn get_metadata_section( // Header is okay -> inflate the actual metadata let compressed_bytes = &buf[header_len..]; debug!("inflating {} bytes of compressed metadata", compressed_bytes.len()); - let mut inflated = Vec::new(); + // Assume the decompressed data will be at least the size of the compressed data, so we + // don't have to grow the buffer as much. + let mut inflated = Vec::with_capacity(compressed_bytes.len()); match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()), Err(_) => { diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 0039d3188d57a..3e2548845e20f 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -11,6 +11,37 @@ use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; /// exist. See [this `mir-dataflow` test][flow-test] for an example. You almost never want to use /// this analysis without also looking at the results of [`MaybeBorrowedLocals`]. /// +/// ## Field-(in)sensitivity +/// +/// As the name suggests, this analysis is field insensitive. If a projection of a variable `x` is +/// assigned to (e.g. `x.0 = 42`), it does not "define" `x` as far as liveness is concerned. In fact, +/// such an assignment is currently marked as a "use" of `x` in an attempt to be maximally +/// conservative. +/// +/// ## Enums and `SetDiscriminant` +/// +/// Assigning a literal value to an `enum` (e.g. `Option`), does not result in a simple +/// assignment of the form `_1 = /*...*/` in the MIR. For example, the following assignment to `x`: +/// +/// ``` +/// x = Some(4); +/// ``` +/// +/// compiles to this MIR +/// +/// ``` +/// ((_1 as Some).0: i32) = const 4_i32; +/// discriminant(_1) = 1; +/// ``` +/// +/// However, `MaybeLiveLocals` **does** mark `x` (`_1`) as "killed" after a statement like this. +/// That's because it treats the `SetDiscriminant` operation as a definition of `x`, even though +/// the writes that actually initialized the locals happened earlier. +/// +/// This makes `MaybeLiveLocals` unsuitable for certain classes of optimization normally associated +/// with a live variables analysis, notably dead-store elimination. It's a dirty hack, but it works +/// okay for the generator state transform (currently the main consumuer of this analysis). +/// /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3e59fc4f55159..e7b2a018680ad 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; -use rustc_data_structures::stable_set::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; @@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> { target: Target, item: Option>, ) { + let mut doc_aliases = FxHashMap::default(); let mut is_valid = true; let mut specified_inline = None; let mut seen = FxHashSet::default(); @@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> { sym::track_caller => { self.check_track_caller(hir_id, &attr.span, attrs, span, target) } - sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline), + sym::doc => self.check_doc_attrs( + attr, + hir_id, + target, + &mut specified_inline, + &mut doc_aliases, + ), sym::no_link => self.check_no_link(hir_id, &attr, span, target), sym::export_name => self.check_export_name(hir_id, &attr, span, target), sym::rustc_layout_scalar_valid_range_start @@ -512,6 +519,7 @@ impl CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, is_list: bool, + aliases: &mut FxHashMap, ) -> bool { let tcx = self.tcx; let err_fn = move |span: Span, msg: &str| { @@ -582,17 +590,38 @@ impl CheckAttrVisitor<'tcx> { if &*item_name.as_str() == doc_alias { return err_fn(meta.span(), "is the same as the item's name"); } + let span = meta.span(); + if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| { + lint.build("doc alias is duplicated") + .span_label(*entry.entry.get(), "first defined here") + .emit(); + }); + } true } - fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool { + fn check_doc_alias( + &self, + meta: &NestedMetaItem, + hir_id: HirId, + target: Target, + aliases: &mut FxHashMap, + ) -> bool { if let Some(values) = meta.meta_item_list() { let mut errors = 0; for v in values { match v.literal() { Some(l) => match l.kind { LitKind::Str(s, _) => { - if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) { + if !self.check_doc_alias_value( + v, + &s.as_str(), + hir_id, + target, + true, + aliases, + ) { errors += 1; } } @@ -621,7 +650,7 @@ impl CheckAttrVisitor<'tcx> { } errors == 0 } else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) { - self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false) + self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases) } else { self.tcx .sess @@ -858,6 +887,7 @@ impl CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, specified_inline: &mut Option<(bool, Span)>, + aliases: &mut FxHashMap, ) -> bool { let mut is_valid = true; @@ -867,7 +897,7 @@ impl CheckAttrVisitor<'tcx> { match i_meta.name_or_empty() { sym::alias if !self.check_attr_not_crate_level(&meta, hir_id, "alias") - || !self.check_doc_alias(&meta, hir_id, target) => + || !self.check_doc_alias(&meta, hir_id, target, aliases) => { is_valid = false } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index f583a5d58d540..4adec3c4f608d 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -9,8 +9,9 @@ #![feature(in_band_lifetimes)] #![feature(format_args_capture)] #![feature(iter_zip)] -#![feature(nll)] +#![feature(map_try_insert)] #![feature(min_specialization)] +#![feature(nll)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 0d7abeba1a703..3d7a215754aca 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -265,12 +265,13 @@ impl IrMaps<'tcx> { self.capture_info_map.insert(hir_id, Rc::new(cs)); } - fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) { + fn collect_shorthand_field_ids(&self, pat: &hir::Pat<'tcx>) -> HirIdSet { // For struct patterns, take note of which fields used shorthand // (`x` rather than `x: x`). let mut shorthand_field_ids = HirIdSet::default(); let mut pats = VecDeque::new(); pats.push_back(pat); + while let Some(pat) = pats.pop_front() { use rustc_hir::PatKind::*; match &pat.kind { @@ -278,8 +279,10 @@ impl IrMaps<'tcx> { pats.extend(inner_pat.iter()); } Struct(_, fields, _) => { - let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id); - shorthand_field_ids.extend(ids); + let (short, not_short): (Vec<&_>, Vec<&_>) = + fields.iter().partition(|f| f.is_shorthand); + shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id)); + pats.extend(not_short.iter().map(|f| f.pat)); } Ref(inner_pat, _) | Box(inner_pat) => { pats.push_back(inner_pat); @@ -296,6 +299,12 @@ impl IrMaps<'tcx> { } } + return shorthand_field_ids; + } + + fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) { + let shorthand_field_ids = self.collect_shorthand_field_ids(pat); + pat.each_binding(|_, hir_id, _, ident| { self.add_live_node_for_node(hir_id, VarDefNode(ident.span, hir_id)); self.add_variable(Local(LocalInfo { @@ -373,15 +382,13 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { + let shorthand_field_ids = self.collect_shorthand_field_ids(param.pat); param.pat.each_binding(|_bm, hir_id, _x, ident| { let var = match param.pat.kind { - rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo { + rustc_hir::PatKind::Struct(..) => Local(LocalInfo { id: hir_id, name: ident.name, - is_shorthand: fields - .iter() - .find(|f| f.ident == ident) - .map_or(false, |f| f.is_shorthand), + is_shorthand: shorthand_field_ids.contains(&hir_id), }), _ => Param(hir_id, ident.name), }; diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 24fa5007f1ecd..25ec9682d8407 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -236,16 +236,27 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { self.body.exprs[self.body_id].span } - fn error(&mut self, span: Option, msg: &str) -> Result { + fn error(&mut self, span: Span, msg: &str) -> Result { self.tcx .sess .struct_span_err(self.root_span(), "overly complex generic constant") - .span_label(span.unwrap_or(self.root_span()), msg) + .span_label(span, msg) .help("consider moving this anonymous constant into a `const` function") .emit(); Err(ErrorReported) } + fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result { + self.tcx + .sess + .struct_span_err(self.root_span(), "overly complex generic constant") + .span_label(span, msg) + .help("consider moving this anonymous constant into a `const` function") + .note("this operation may be supported in the future") + .emit(); + + Err(ErrorReported) + } fn new( tcx: TyCtxt<'tcx>, @@ -337,14 +348,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { Ok(match &node.kind { // I dont know if handling of these 3 is correct &ExprKind::Scope { value, .. } => self.recurse_build(value)?, - &ExprKind::PlaceTypeAscription { source, .. } | - &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, + &ExprKind::PlaceTypeAscription { source, .. } + | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?, // subtle: associated consts are literals this arm handles // `::ASSOC` as well as `12` &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)), - ExprKind::Call { fun, args, .. } => { + ExprKind::Call { fun, args, .. } => { let fun = self.recurse_build(*fun)?; let mut new_args = Vec::::with_capacity(args.len()); @@ -353,7 +364,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { } let new_args = self.tcx.arena.alloc_slice(&new_args); self.nodes.push(Node::FunctionCall(fun, new_args)) - }, + } &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => { let lhs = self.recurse_build(lhs)?; let rhs = self.recurse_build(rhs)?; @@ -362,7 +373,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { &ExprKind::Unary { op, arg } if Self::check_unop(op) => { let arg = self.recurse_build(arg)?; self.nodes.push(Node::UnaryOp(op, arg)) - }, + } // This is necessary so that the following compiles: // // ``` @@ -370,60 +381,100 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // bar::<{ N + 1 }>(); // } // ``` - ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?, + ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => { + self.recurse_build(*e)? + } // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested) &ExprKind::Use { source } => { let arg = self.recurse_build(source)?; self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty)) - }, + } &ExprKind::Cast { source } => { let arg = self.recurse_build(source)?; self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty)) - }, + } // FIXME(generic_const_exprs): We may want to support these. ExprKind::AddressOf { .. } | ExprKind::Borrow { .. } - | ExprKind::Deref { .. } - | ExprKind::Repeat { .. } - | ExprKind::Array { .. } - | ExprKind::Block { .. } - | ExprKind::NeverToAny { .. } - | ExprKind::Tuple { .. } - | ExprKind::Index { .. } - | ExprKind::Field { .. } - | ExprKind::ConstBlock { .. } - | ExprKind::Adt(_) => self.error( - Some(node.span), - "unsupported operation in generic constant, this may be supported in the future", + | ExprKind::Deref { .. } => self.maybe_supported_error( + node.span, + "dereferencing is not supported in generic constants", + )?, + ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error( + node.span, + "array construction is not supported in generic constants", + )?, + ExprKind::Block { .. } => self.maybe_supported_error( + node.span, + "blocks are not supported in generic constant", + )?, + ExprKind::NeverToAny { .. } => self.maybe_supported_error( + node.span, + "converting nevers to any is not supported in generic constant", + )?, + ExprKind::Tuple { .. } => self.maybe_supported_error( + node.span, + "tuple construction is not supported in generic constants", + )?, + ExprKind::Index { .. } => self.maybe_supported_error( + node.span, + "indexing is not supported in generic constant", + )?, + ExprKind::Field { .. } => self.maybe_supported_error( + node.span, + "field access is not supported in generic constant", + )?, + ExprKind::ConstBlock { .. } => self.maybe_supported_error( + node.span, + "const blocks are not supported in generic constant", + )?, + ExprKind::Adt(_) => self.maybe_supported_error( + node.span, + "struct/enum construction is not supported in generic constants", + )?, + // dont know if this is correct + ExprKind::Pointer { .. } => + self.error(node.span, "pointer casts are not allowed in generic constants")?, + ExprKind::Yield { .. } => + self.error(node.span, "generator control flow is not allowed in generic constants")?, + ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self + .error( + node.span, + "loops and loop control flow are not supported in generic constants", )?, + ExprKind::Box { .. } => + self.error(node.span, "allocations are not allowed in generic constants")?, + + ExprKind::Unary { .. } => unreachable!(), + // we handle valid unary/binary ops above + ExprKind::Binary { .. } => + self.error(node.span, "unsupported binary operation in generic constants")?, + ExprKind::LogicalOp { .. } => + self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?, + ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { + self.error(node.span, "assignment is not supported in generic constants")? + } + ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error( + node.span, + "closures and function keywords are not supported in generic constants", + )?, + // let expressions imply control flow + ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } => + self.error(node.span, "control flow is not supported in generic constants")?, + ExprKind::LlvmInlineAsm { .. } | ExprKind::InlineAsm { .. } => { + self.error(node.span, "assembly is not supported in generic constants")? + } - ExprKind::Match { .. } // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen - | ExprKind::VarRef { .. } + ExprKind::VarRef { .. } | ExprKind::UpvarRef { .. } - | ExprKind::Closure { .. } - | ExprKind::Let { .. } // let expressions imply control flow - | ExprKind::Loop { .. } - | ExprKind::Assign { .. } | ExprKind::StaticRef { .. } - | ExprKind::LogicalOp { .. } - // we handle valid unary/binary ops above - | ExprKind::Unary { .. } - | ExprKind::Binary { .. } - | ExprKind::Break { .. } - | ExprKind::Continue { .. } - | ExprKind::If { .. } - | ExprKind::Pointer { .. } // dont know if this is correct - | ExprKind::ThreadLocalRef(_) - | ExprKind::LlvmInlineAsm { .. } - | ExprKind::Return { .. } - | ExprKind::Box { .. } // allocations not allowed in constants - | ExprKind::AssignOp { .. } - | ExprKind::InlineAsm { .. } - | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?, + | ExprKind::ThreadLocalRef(_) => { + self.error(node.span, "unsupported operation in generic constant")? + } }) } } diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 8ff074e2fe534..65eedd2daafa8 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -107,6 +107,7 @@ use rustc_middle::util; use rustc_session::config::EntryFnType; use rustc_span::{symbol::sym, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::{ self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, @@ -328,7 +329,26 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ObligationCauseCode::MainFunctionType, ); let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause); + // normalize any potential projections in the return type, then add + // any possible obligations to the fulfillment context. + // HACK(ThePuzzlemaker) this feels symptomatic of a problem within + // checking trait fulfillment, not this here. I'm not sure why it + // works in the example in `fn test()` given in #88609? This also + // probably isn't the best way to do this. + let InferOk { value: norm_return_ty, obligations } = infcx + .partially_normalize_associated_types_in( + cause.clone(), + ty::ParamEnv::empty(), + return_ty, + ); + fulfillment_cx.register_predicate_obligations(&infcx, obligations); + fulfillment_cx.register_bound( + &infcx, + ty::ParamEnv::empty(), + norm_return_ty, + term_id, + cause, + ); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err, None, false); error = true; diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index db45640df48d6..05ca50a97a644 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -305,7 +305,6 @@ macro_rules! impl_Exp { n /= 10; exponent += 1; } - let trailing_zeros = exponent; let (added_precision, subtracted_precision) = match f.precision() { Some(fmt_prec) => { @@ -333,7 +332,7 @@ macro_rules! impl_Exp { n += 1; } } - (n, exponent, trailing_zeros, added_precision) + (n, exponent, exponent, added_precision) }; // 39 digits (worst case u128) + . = 40 diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index f1dcdf2c1aa04..9d46948ce02af 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1533,9 +1533,8 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) { - // Using `&` helps LLVM see that it is the same check made in division. - if unlikely!((self == Self::MIN) & (rhs == -1)) { - (0, true) + if unlikely!(rhs == -1) { + (0, self == Self::MIN) } else { (self % rhs, false) } @@ -1565,9 +1564,8 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { - // Using `&` helps LLVM see that it is the same check made in division. - if unlikely!((self == Self::MIN) & (rhs == -1)) { - (0, true) + if unlikely!(rhs == -1) { + (0, self == Self::MIN) } else { (self.rem_euclid(rhs), false) } diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs index 275a1d062cafb..b958422d14f84 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/core/tests/fmt/num.rs @@ -146,6 +146,7 @@ fn test_format_int_exp_precision() { assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000))); //test zero precision assert_eq!(format!("{:.0e}", 1), format!("1e0",)); + assert_eq!(format!("{:.0e}", 35), format!("4e1",)); //test padding with precision (and sign) assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 8c33051cfa436..99013efb495d0 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -333,9 +333,19 @@ impl Command { let mut set = MaybeUninit::::uninit(); cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?; - let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); - if ret == libc::SIG_ERR { - return Err(io::Error::last_os_error()); + + #[cfg(target_os = "android")] // see issue #88585 + { + let mut action: libc::sigaction = mem::zeroed(); + action.sa_sigaction = libc::SIG_DFL; + cvt(libc::sigaction(libc::SIGPIPE, &action, ptr::null_mut()))?; + } + #[cfg(not(target_os = "android"))] + { + let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); + if ret == libc::SIG_ERR { + return Err(io::Error::last_os_error()); + } } } diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr index 9b3c32a939779..041232e869079 100644 --- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr @@ -10,9 +10,10 @@ error: overly complex generic constant --> $DIR/array-size-in-generic-struct-param.rs:19:15 | LL | arr: [u8; CFG.arr_size], - | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^ field access is not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr index 95dae4ecc0431..0dfd804be41b4 100644 --- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr @@ -4,9 +4,10 @@ error: overly complex generic constant LL | fn test() -> [u8; N + (|| 42)()] {} | ^^^^-------^^ | | - | unsupported operation in generic constant, this may be supported in the future + | dereferencing is not supported in generic constants | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr index c9f847995223a..5ebb4c3999c36 100644 --- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr @@ -2,17 +2,19 @@ error: overly complex generic constant --> $DIR/let-bindings.rs:6:68 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/let-bindings.rs:6:35 | LL | fn test() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default { - | ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr index 3da91b19a5ed9..df73acf53de65 100644 --- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr @@ -2,25 +2,28 @@ error: overly complex generic constant --> $DIR/unused_expr.rs:4:34 | LL | fn add() -> [u8; { N + 1; 5 }] { - | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/unused_expr.rs:9:34 | LL | fn div() -> [u8; { N / 1; 5 }] { - | ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: overly complex generic constant --> $DIR/unused_expr.rs:16:38 | LL | fn fn_call() -> [u8; { foo(N); 5 }] { - | ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future + | ^^^^^^^^^^^^^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr index 8c9672fd7fc1c..0f0e339655bca 100644 --- a/src/test/ui/const-generics/issues/issue-67375.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr @@ -4,7 +4,7 @@ error: overly complex generic constant LL | inner: [(); { [|_: &T| {}; 0].len() }], | ^^---------------------^^ | | - | unsupported operation in generic constant + | pointer casts are not allowed in generic constants | = help: consider moving this anonymous constant into a `const` function diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr index fe0351a829220..cce85772aa4da 100644 --- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr +++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr @@ -8,9 +8,10 @@ LL | | let x: Option> = None; LL | | LL | | 0 LL | | }], - | |_____^ unsupported operation in generic constant, this may be supported in the future + | |_____^ blocks are not supported in generic constant | = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future error: aborting due to previous error diff --git a/src/test/ui/duplicate_doc_alias.rs b/src/test/ui/duplicate_doc_alias.rs new file mode 100644 index 0000000000000..a564ab64532b7 --- /dev/null +++ b/src/test/ui/duplicate_doc_alias.rs @@ -0,0 +1,9 @@ +#![deny(unused_attributes)] + +#[doc(alias = "A")] +#[doc(alias = "A")] //~ ERROR +#[doc(alias = "B")] +#[doc(alias("B"))] //~ ERROR +pub struct Foo; + +fn main() {} diff --git a/src/test/ui/duplicate_doc_alias.stderr b/src/test/ui/duplicate_doc_alias.stderr new file mode 100644 index 0000000000000..4b2dd1f8eb68e --- /dev/null +++ b/src/test/ui/duplicate_doc_alias.stderr @@ -0,0 +1,24 @@ +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:4:7 + | +LL | #[doc(alias = "A")] + | ----------- first defined here +LL | #[doc(alias = "A")] + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/duplicate_doc_alias.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: doc alias is duplicated + --> $DIR/duplicate_doc_alias.rs:6:13 + | +LL | #[doc(alias = "B")] + | ----------- first defined here +LL | #[doc(alias("B"))] + | ^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mir-dataflow/liveness-enum.rs b/src/test/ui/mir-dataflow/liveness-enum.rs new file mode 100644 index 0000000000000..5eb04ae8c8d37 --- /dev/null +++ b/src/test/ui/mir-dataflow/liveness-enum.rs @@ -0,0 +1,22 @@ +#![feature(core_intrinsics, rustc_attrs)] + +use std::intrinsics::rustc_peek; + +#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)] +fn foo() -> Option { + let mut x = None; + + // `x` is live here since it is used in the next statement... + rustc_peek(x); + + dbg!(x); + + // But not here, since it is overwritten below + rustc_peek(x); //~ ERROR rustc_peek: bit not set + + x = Some(4); + + x +} + +fn main() {} diff --git a/src/test/ui/mir-dataflow/liveness-enum.stderr b/src/test/ui/mir-dataflow/liveness-enum.stderr new file mode 100644 index 0000000000000..483944d731aed --- /dev/null +++ b/src/test/ui/mir-dataflow/liveness-enum.stderr @@ -0,0 +1,10 @@ +error: rustc_peek: bit not set + --> $DIR/liveness-enum.rs:15:5 + | +LL | rustc_peek(x); + | ^^^^^^^^^^^^^ + +error: stop_after_dataflow ended compilation + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index 285876aadb293..d6fd4baeb5ece 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -82,3 +82,75 @@ LL | #[derive(generate_mod::CheckDerive)] error: aborting due to 4 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0412`. +Future incompatibility report: Future breakage diagnostic: +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:16:10 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDerive` in this scope + --> $DIR/generate-mod.rs:23:14 + | +LL | #[derive(generate_mod::CheckDerive)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `FromOutside` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | +note: the lint level is defined here + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + +Future breakage diagnostic: +warning: cannot find type `OuterDeriveLint` in this scope + --> $DIR/generate-mod.rs:30:10 + | +LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #83583 + = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.fixed b/src/test/ui/suggestions/ignore-nested-field-binding.fixed new file mode 100644 index 0000000000000..1dc44838e8bb0 --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.fixed @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i: _ } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i: _ } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.rs b/src/test/ui/suggestions/ignore-nested-field-binding.rs new file mode 100644 index 0000000000000..6dc0263ec9f2b --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.rs @@ -0,0 +1,20 @@ +// Regression test for #88403, where prefixing with an underscore was +// erroneously suggested for a nested shorthand struct field binding. + +// run-rustfix +#![allow(unused)] +#![forbid(unused_variables)] + +struct Inner { i: i32 } +struct Outer { o: Inner } + +fn foo(Outer { o: Inner { i } }: Outer) {} +//~^ ERROR: unused variable: `i` +//~| HELP: try ignoring the field + +fn main() { + let s = Outer { o: Inner { i: 42 } }; + let Outer { o: Inner { i } } = s; + //~^ ERROR: unused variable: `i` + //~| HELP: try ignoring the field +} diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.stderr b/src/test/ui/suggestions/ignore-nested-field-binding.stderr new file mode 100644 index 0000000000000..b2936a22a22f1 --- /dev/null +++ b/src/test/ui/suggestions/ignore-nested-field-binding.stderr @@ -0,0 +1,20 @@ +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:11:27 + | +LL | fn foo(Outer { o: Inner { i } }: Outer) {} + | ^ help: try ignoring the field: `i: _` + | +note: the lint level is defined here + --> $DIR/ignore-nested-field-binding.rs:6:11 + | +LL | #![forbid(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: unused variable: `i` + --> $DIR/ignore-nested-field-binding.rs:17:28 + | +LL | let Outer { o: Inner { i } } = s; + | ^ help: try ignoring the field: `i: _` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/typeck/issue-88609.rs b/src/test/ui/typeck/issue-88609.rs new file mode 100644 index 0000000000000..dc459c885fa70 --- /dev/null +++ b/src/test/ui/typeck/issue-88609.rs @@ -0,0 +1,19 @@ +// Regression test for #88609: +// The return type for `main` is not normalized while checking if it implements +// the trait `std::process::Termination`. + +// build-pass + +trait Same { + type Output; +} + +impl Same for T { + type Output = T; +} + +type Unit = <() as Same>::Output; + +fn main() -> Result { + unimplemented!() +}