diff --git a/Cargo.lock b/Cargo.lock index f0c6e371c38be..716f4d7501467 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,7 +221,6 @@ dependencies = [ "getopts", "ignore", "libc", - "num_cpus", "once_cell", "opener", "pretty_assertions", @@ -249,7 +248,6 @@ dependencies = [ "anyhow", "flate2", "hex 0.4.2", - "num_cpus", "rayon", "serde", "serde_json", @@ -4241,7 +4239,6 @@ name = "rustc_session" version = "0.0.0" dependencies = [ "getopts", - "num_cpus", "rustc_ast", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4502d15f36fa1..684a3ced5a070 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -5,16 +5,21 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; +use rustc_middle::ty::{ + self, suggest_constraining_type_param, suggest_constraining_type_params, PredicateKind, Ty, +}; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::symbol::sym; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::TraitEngineExt as _; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; @@ -423,7 +428,63 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); } + } else { + // Try to find predicates on *generic params* that would allow copying `ty` + + let tcx = self.infcx.tcx; + let generics = tcx.generics_of(self.mir_def_id()); + if let Some(hir_generics) = tcx + .typeck_root_def_id(self.mir_def_id().to_def_id()) + .as_local() + .and_then(|def_id| tcx.hir().get_generics(def_id)) + { + let predicates: Result, _> = tcx.infer_ctxt().enter(|infcx| { + let mut fulfill_cx = + >::new(infcx.tcx); + + let copy_did = infcx.tcx.lang_items().copy_trait().unwrap(); + let cause = ObligationCause::new( + span, + self.mir_hir_id(), + rustc_infer::traits::ObligationCauseCode::MiscObligation, + ); + fulfill_cx.register_bound(&infcx, self.param_env, ty, copy_did, cause); + let errors = fulfill_cx.select_where_possible(&infcx); + + // Only emit suggestion if all required predicates are on generic + errors + .into_iter() + .map(|err| match err.obligation.predicate.kind().skip_binder() { + PredicateKind::Trait(predicate) => { + match predicate.self_ty().kind() { + ty::Param(param_ty) => Ok(( + generics.type_param(param_ty, tcx), + predicate + .trait_ref + .print_only_trait_path() + .to_string(), + )), + _ => Err(()), + } + } + _ => Err(()), + }) + .collect() + }); + + if let Ok(predicates) = predicates { + suggest_constraining_type_params( + tcx, + hir_generics, + &mut err, + predicates.iter().map(|(param, constraint)| { + (param.name.as_str(), &**constraint, None) + }), + ); + } + } } + let span = if let Some(local) = place.as_local() { let decl = &self.body.local_decls[local]; Some(decl.source_info.span) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4a8894983b98d..6e9e0332faf60 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -576,12 +576,12 @@ pub enum PassKind { Module, } -/// LLVMRustThinLTOData +// LLVMRustThinLTOData extern "C" { pub type ThinLTOData; } -/// LLVMRustThinLTOBuffer +// LLVMRustThinLTOBuffer extern "C" { pub type ThinLTOBuffer; } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d6f856a6f0a70..bf7e811c76f8e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -500,15 +500,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. // First, check x % y != 0 (or if that computation overflows). let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?; - if overflow || res.assert_bits(a.layout.size) != 0 { - // Then, check if `b` is -1, which is the "MIN / -1" case. - let minus1 = Scalar::from_int(-1, dest.layout.size); - let b_scalar = b.to_scalar().unwrap(); - if b_scalar == minus1 { - throw_ub_format!("exact_div: result of dividing MIN by -1 cannot be represented") - } else { - throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b,) - } + assert!(!overflow); // All overflow is UB, so this should never return on overflow. + if res.assert_bits(a.layout.size) != 0 { + throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b) } // `Rem` says this is all right, so we can let `Div` do its job. self.binop_ignore_overflow(BinOp::Div, &a, &b, dest) diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 48c90e1881a9a..079ce9f07b8e1 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -196,16 +196,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => None, }; if let Some(op) = op { + let l = self.sign_extend(l, left_layout) as i128; let r = self.sign_extend(r, right_layout) as i128; - // We need a special check for overflowing remainder: - // "int_min % -1" overflows and returns 0, but after casting things to a larger int - // type it does *not* overflow nor give an unrepresentable result! - if bin_op == Rem { - if r == -1 && l == (1 << (size.bits() - 1)) { - return Ok((Scalar::from_int(0, size), true, left_layout.ty)); + + // We need a special check for overflowing Rem and Div since they are *UB* + // on overflow, which can happen with "int_min $OP -1". + if matches!(bin_op, Rem | Div) { + if l == size.signed_int_min() && r == -1 { + if bin_op == Rem { + throw_ub!(RemainderOverflow) + } else { + throw_ub!(DivisionOverflow) + } } } - let l = self.sign_extend(l, left_layout) as i128; let (result, oflo) = op(l, r); // This may be out-of-bounds for the result type, so we have to truncate ourselves. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 46b90baa5858a..72b8d8bb297a6 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1086,6 +1086,16 @@ impl EarlyLintPass for UnusedDocComment { fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) { warn_if_doc(cx, param.ident.span, "generic parameters", ¶m.attrs); } + + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) { + warn_if_doc(cx, block.span, "block", &block.attrs()); + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + if let ast::ItemKind::ForeignMod(_) = item.kind { + warn_if_doc(cx, item.span, "extern block", &item.attrs); + } + } } declare_lint! { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 7ca564f29e659..f977b0fffebb6 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -56,6 +56,7 @@ #![feature(nonzero_ops)] #![feature(unwrap_infallible)] #![feature(decl_macro)] +#![feature(drain_filter)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 98cb90296a521..e524625f96646 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -233,6 +233,10 @@ pub enum UndefinedBehaviorInfo<'tcx> { DivisionByZero, /// Something was "remainded" by 0 (x % 0). RemainderByZero, + /// Signed division overflowed (INT_MIN / -1). + DivisionOverflow, + /// Signed remainder overflowed (INT_MIN % -1). + RemainderOverflow, /// Overflowing inbounds pointer arithmetic. PointerArithOverflow, /// Invalid metadata in a wide pointer (using `str` to avoid allocations). @@ -310,6 +314,8 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { } DivisionByZero => write!(f, "dividing by zero"), RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), + DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"), + RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), InvalidVtableDropFn(sig) => write!( diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 58cf9fa7a8943..99a3d4c7fe4f7 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -7,6 +7,7 @@ use crate::ty::{ ProjectionTy, Term, Ty, TyCtxt, TypeAndMut, }; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -157,9 +158,17 @@ pub fn suggest_arbitrary_trait_bound( true } +#[derive(Debug)] +enum SuggestChangingConstraintsMessage<'a> { + RestrictBoundFurther, + RestrictType { ty: &'a str }, + RestrictTypeFurther { ty: &'a str }, + RemovingQSized, +} + fn suggest_removing_unsized_bound( generics: &hir::Generics<'_>, - err: &mut Diagnostic, + suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>, param_name: &str, param: &hir::GenericParam<'_>, def_id: Option, @@ -221,13 +230,12 @@ fn suggest_removing_unsized_bound( // ^^^^^^^^^ (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()), }; - err.span_suggestion_verbose( + + suggestions.push(( sp, - "consider removing the `?Sized` bound to make the \ - type parameter `Sized`", String::new(), - Applicability::MaybeIncorrect, - ); + SuggestChangingConstraintsMessage::RemovingQSized, + )); } } _ => {} @@ -249,13 +257,12 @@ fn suggest_removing_unsized_bound( // ^^^^^^^^^ (_, pos) => param.bounds[pos - 1].span().shrink_to_hi().to(bound.span()), }; - err.span_suggestion_verbose( + + suggestions.push(( sp, - "consider removing the `?Sized` bound to make the type parameter \ - `Sized`", String::new(), - Applicability::MaybeIncorrect, - ); + SuggestChangingConstraintsMessage::RemovingQSized, + )); } _ => {} } @@ -271,184 +278,249 @@ pub fn suggest_constraining_type_param( constraint: &str, def_id: Option, ) -> bool { - let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); + suggest_constraining_type_params( + tcx, + generics, + err, + [(param_name, constraint, def_id)].into_iter(), + ) +} - let Some(param) = param else { - return false; - }; +/// Suggest restricting a type param with a new bound. +pub fn suggest_constraining_type_params<'a>( + tcx: TyCtxt<'_>, + generics: &hir::Generics<'_>, + err: &mut Diagnostic, + param_names_and_constraints: impl Iterator)>, +) -> bool { + let mut grouped = FxHashMap::default(); + param_names_and_constraints.for_each(|(param_name, constraint, def_id)| { + grouped.entry(param_name).or_insert(Vec::new()).push((constraint, def_id)) + }); - const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound"; - let msg_restrict_type = format!("consider restricting type parameter `{}`", param_name); - let msg_restrict_type_further = - format!("consider further restricting type parameter `{}`", param_name); + let mut applicability = Applicability::MachineApplicable; + let mut suggestions = Vec::new(); - if def_id == tcx.lang_items().sized_trait() { - // Type parameters are already `Sized` by default. - err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint)); - suggest_removing_unsized_bound(generics, err, param_name, param, def_id); - return true; - } - let mut suggest_restrict = |span| { - err.span_suggestion_verbose( - span, - MSG_RESTRICT_BOUND_FURTHER, - format!(" + {}", constraint), - Applicability::MachineApplicable, - ); - }; + for (param_name, mut constraints) in grouped { + let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name); + let Some(param) = param else { return false }; - if param_name.starts_with("impl ") { - // If there's an `impl Trait` used in argument position, suggest - // restricting it: - // - // fn foo(t: impl Foo) { ... } - // -------- - // | - // help: consider further restricting this bound with `+ Bar` - // - // Suggestion for tools in this case is: - // - // fn foo(t: impl Foo) { ... } - // -------- - // | - // replace with: `impl Foo + Bar` - - suggest_restrict(param.span.shrink_to_hi()); - return true; - } + { + let mut sized_constraints = + constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait()); + if let Some((constraint, def_id)) = sized_constraints.next() { + applicability = Applicability::MaybeIncorrect; - if generics.where_clause.predicates.is_empty() - // Given `trait Base: Super` where `T: Copy`, suggest restricting in the - // `where` clause instead of `trait Base: Super`. - && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) - { - if let Some(span) = param.bounds_span_for_suggestions() { - // If user has provided some bounds, suggest restricting them: + err.span_label( + param.span, + &format!("this type parameter needs to be `{}`", constraint), + ); + suggest_removing_unsized_bound( + generics, + &mut suggestions, + param_name, + param, + def_id, + ); + } + } + + if constraints.is_empty() { + continue; + } + + let constraint = constraints.iter().map(|&(c, _)| c).collect::>().join(" + "); + let mut suggest_restrict = |span| { + suggestions.push(( + span, + format!(" + {}", constraint), + SuggestChangingConstraintsMessage::RestrictBoundFurther, + )) + }; + + if param_name.starts_with("impl ") { + // If there's an `impl Trait` used in argument position, suggest + // restricting it: // - // fn foo(t: T) { ... } - // --- + // fn foo(t: impl Foo) { ... } + // -------- // | // help: consider further restricting this bound with `+ Bar` // // Suggestion for tools in this case is: // - // fn foo(t: T) { ... } - // -- - // | - // replace with: `T: Bar +` - suggest_restrict(span); - } else { - // If user hasn't provided any bounds, suggest adding a new one: - // - // fn foo(t: T) { ... } - // - help: consider restricting this type parameter with `T: Foo` - err.span_suggestion_verbose( - param.span.shrink_to_hi(), - &msg_restrict_type, - format!(": {}", constraint), - Applicability::MachineApplicable, - ); + // fn foo(t: impl Foo) { ... } + // -------- + // | + // replace with: `impl Foo + Bar` + + suggest_restrict(param.span.shrink_to_hi()); + continue; } - true - } else { - // This part is a bit tricky, because using the `where` clause user can - // provide zero, one or many bounds for the same type parameter, so we - // have following cases to consider: - // - // 1) When the type parameter has been provided zero bounds - // - // Message: - // fn foo(x: X, y: Y) where Y: Foo { ... } - // - help: consider restricting this type parameter with `where X: Bar` - // - // Suggestion: - // fn foo(x: X, y: Y) where Y: Foo { ... } - // - insert: `, X: Bar` - // - // - // 2) When the type parameter has been provided one bound - // - // Message: - // fn foo(t: T) where T: Foo { ... } - // ^^^^^^ - // | - // help: consider further restricting this bound with `+ Bar` - // - // Suggestion: - // fn foo(t: T) where T: Foo { ... } - // ^^ - // | - // replace with: `T: Bar +` - // - // - // 3) When the type parameter has been provided many bounds - // - // Message: - // fn foo(t: T) where T: Foo, T: Bar {... } - // - help: consider further restricting this type parameter with `where T: Zar` - // - // Suggestion: - // fn foo(t: T) where T: Foo, T: Bar {... } - // - insert: `, T: Zar` - // - // Additionally, there may be no `where` clause whatsoever in the case that this was - // reached because the generic parameter has a default: - // - // Message: - // trait Foo {... } - // - help: consider further restricting this type parameter with `where T: Zar` - // - // Suggestion: - // trait Foo where T: Zar {... } - // - insert: `where T: Zar` - - if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) - && generics.where_clause.predicates.len() == 0 + if generics.where_clause.predicates.is_empty() + // Given `trait Base: Super` where `T: Copy`, suggest restricting in the + // `where` clause instead of `trait Base: Super`. + && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) { - // Suggest a bound, but there is no existing `where` clause *and* the type param has a - // default (``), so we suggest adding `where T: Bar`. - err.span_suggestion_verbose( - generics.where_clause.tail_span_for_suggestion(), - &msg_restrict_type_further, - format!(" where {}: {}", param_name, constraint), - Applicability::MachineApplicable, - ); + if let Some(span) = param.bounds_span_for_suggestions() { + // If user has provided some bounds, suggest restricting them: + // + // fn foo(t: T) { ... } + // --- + // | + // help: consider further restricting this bound with `+ Bar` + // + // Suggestion for tools in this case is: + // + // fn foo(t: T) { ... } + // -- + // | + // replace with: `T: Bar +` + suggest_restrict(span); + } else { + // If user hasn't provided any bounds, suggest adding a new one: + // + // fn foo(t: T) { ... } + // - help: consider restricting this type parameter with `T: Foo` + suggestions.push(( + param.span.shrink_to_hi(), + format!(": {}", constraint), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } else { - let mut param_spans = Vec::new(); + // This part is a bit tricky, because using the `where` clause user can + // provide zero, one or many bounds for the same type parameter, so we + // have following cases to consider: + // + // 1) When the type parameter has been provided zero bounds + // + // Message: + // fn foo(x: X, y: Y) where Y: Foo { ... } + // - help: consider restricting this type parameter with `where X: Bar` + // + // Suggestion: + // fn foo(x: X, y: Y) where Y: Foo { ... } + // - insert: `, X: Bar` + // + // + // 2) When the type parameter has been provided one bound + // + // Message: + // fn foo(t: T) where T: Foo { ... } + // ^^^^^^ + // | + // help: consider further restricting this bound with `+ Bar` + // + // Suggestion: + // fn foo(t: T) where T: Foo { ... } + // ^^ + // | + // replace with: `T: Bar +` + // + // + // 3) When the type parameter has been provided many bounds + // + // Message: + // fn foo(t: T) where T: Foo, T: Bar {... } + // - help: consider further restricting this type parameter with `where T: Zar` + // + // Suggestion: + // fn foo(t: T) where T: Foo, T: Bar {... } + // - insert: `, T: Zar` + // + // Additionally, there may be no `where` clause whatsoever in the case that this was + // reached because the generic parameter has a default: + // + // Message: + // trait Foo {... } + // - help: consider further restricting this type parameter with `where T: Zar` + // + // Suggestion: + // trait Foo where T: Zar {... } + // - insert: `where T: Zar` - for predicate in generics.where_clause.predicates { - if let WherePredicate::BoundPredicate(WhereBoundPredicate { - span, - bounded_ty, - .. - }) = predicate - { - if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind { - if let Some(segment) = path.segments.first() { - if segment.ident.to_string() == param_name { - param_spans.push(span); + if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) + && generics.where_clause.predicates.len() == 0 + { + // Suggest a bound, but there is no existing `where` clause *and* the type param has a + // default (``), so we suggest adding `where T: Bar`. + suggestions.push(( + generics.where_clause.tail_span_for_suggestion(), + format!(" where {}: {}", param_name, constraint), + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name }, + )); + } else { + let mut param_spans = Vec::new(); + + for predicate in generics.where_clause.predicates { + if let WherePredicate::BoundPredicate(WhereBoundPredicate { + span, + bounded_ty, + .. + }) = predicate + { + if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind { + if let Some(segment) = path.segments.first() { + if segment.ident.to_string() == param_name { + param_spans.push(span); + } } } } } - } - match param_spans[..] { - [¶m_span] => suggest_restrict(param_span.shrink_to_hi()), - _ => { - err.span_suggestion_verbose( - generics.where_clause.tail_span_for_suggestion(), - &msg_restrict_type_further, - format!(", {}: {}", param_name, constraint), - Applicability::MachineApplicable, - ); + match param_spans[..] { + [¶m_span] => suggest_restrict(param_span.shrink_to_hi()), + _ => { + suggestions.push(( + generics.where_clause.tail_span_for_suggestion(), + constraints + .iter() + .map(|&(constraint, _)| format!(", {}: {}", param_name, constraint)) + .collect::(), + SuggestChangingConstraintsMessage::RestrictTypeFurther { + ty: param_name, + }, + )); + } } } } + } - true + if suggestions.len() == 1 { + let (span, suggestion, msg) = suggestions.pop().unwrap(); + + let s; + let msg = match msg { + SuggestChangingConstraintsMessage::RestrictBoundFurther => { + "consider further restricting this bound" + } + SuggestChangingConstraintsMessage::RestrictType { ty } => { + s = format!("consider restricting type parameter `{}`", ty); + &s + } + SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => { + s = format!("consider further restricting type parameter `{}`", ty); + &s + } + SuggestChangingConstraintsMessage::RemovingQSized => { + "consider removing the `?Sized` bound to make the type parameter `Sized`" + } + }; + + err.span_suggestion_verbose(span, msg, suggestion, applicability); + } else { + err.multipart_suggestion_verbose( + "consider restricting type parameters", + suggestions.into_iter().map(|(span, suggestion, _)| (span, suggestion)).collect(), + applicability, + ); } + + true } /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index c5ef1e101460f..d849bc408fab4 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -1196,12 +1196,21 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { AssertKind::RemainderByZero(op) => { Some(AssertKind::RemainderByZero(eval_to_int(op))) } + AssertKind::Overflow(bin_op @ (BinOp::Div | BinOp::Rem), op1, op2) => { + // Division overflow is *UB* in the MIR, and different than the + // other overflow checks. + Some(AssertKind::Overflow( + *bin_op, + eval_to_int(op1), + eval_to_int(op2), + )) + } AssertKind::BoundsCheck { ref len, ref index } => { let len = eval_to_int(len); let index = eval_to_int(index); Some(AssertKind::BoundsCheck { len, index }) } - // Overflow is are already covered by checks on the binary operators. + // Remaining overflow errors are already covered by checks on the binary operators. AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) => None, // Need proper const propagator for these. _ => None, diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 37cfc4a0dc3c2..6b1eaa4d399d9 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -15,6 +15,5 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } rustc_fs_util = { path = "../rustc_fs_util" } -num_cpus = "1.0" rustc_ast = { path = "../rustc_ast" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c2b13346cd6c9..43123d30ad5c6 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -551,7 +551,7 @@ mod parse { crate fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(0) => { - *slot = ::num_cpus::get(); + *slot = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get); true } Some(i) => { diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 040a087b2352e..f01843ebabacf 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -276,11 +276,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we suggest adding a separate return expression instead. // (To avoid things like suggesting `Ok(while .. { .. })`.) if expr_ty.is_unit() { + let mut id = expr.hir_id; + let mut parent; + + // Unroll desugaring, to make sure this works for `for` loops etc. + loop { + parent = self.tcx.hir().get_parent_node(id); + if let Some(parent_span) = self.tcx.hir().opt_span(parent) { + if parent_span.find_ancestor_inside(expr.span).is_some() { + // The parent node is part of the same span, so is the result of the + // same expansion/desugaring and not the 'real' parent node. + id = parent; + continue; + } + } + break; + } + if let Some(hir::Node::Block(&hir::Block { span: block_span, expr: Some(e), .. - })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) + })) = self.tcx.hir().find(parent) { - if e.hir_id == expr.hir_id { + if e.hir_id == id { if let Some(span) = expr.span.find_ancestor_inside(block_span) { let return_suggestions = if self.tcx.is_diagnostic_item(sym::Result, expected_adt.did) { diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index e5255686ff984..2b611e5aae276 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -117,7 +117,7 @@ mod c_char_definition { all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), all(target_os = "l4re", target_arch = "x86_64"), all( - target_os = "freebsd", + any(target_os = "freebsd", target_os = "openbsd"), any( target_arch = "aarch64", target_arch = "arm", @@ -130,7 +130,6 @@ mod c_char_definition { target_os = "netbsd", any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc") ), - all(target_os = "openbsd", target_arch = "aarch64"), all( target_os = "vxworks", any( diff --git a/library/core/tests/num/wrapping.rs b/library/core/tests/num/wrapping.rs index c4fb321ef26cf..8ded139a1809f 100644 --- a/library/core/tests/num/wrapping.rs +++ b/library/core/tests/num/wrapping.rs @@ -308,3 +308,13 @@ fn wrapping_int_api() { } } } + +#[test] +fn wrapping_const() { + // Specifically the wrapping behavior of division and remainder is subtle, + // see https://github.com/rust-lang/rust/pull/94512. + const _: () = { + assert!(i32::MIN.wrapping_div(-1) == i32::MIN); + assert!(i32::MIN.wrapping_rem(-1) == 0); + }; +} diff --git a/library/portable-simd/crates/core_simd/src/intrinsics.rs b/library/portable-simd/crates/core_simd/src/intrinsics.rs index 4c68d11e8932a..cf2c0a02351ed 100644 --- a/library/portable-simd/crates/core_simd/src/intrinsics.rs +++ b/library/portable-simd/crates/core_simd/src/intrinsics.rs @@ -18,9 +18,10 @@ //! //! Unless stated otherwise, all intrinsics for binary operations require SIMD vectors of equal types and lengths. -/// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are -/// mostly lowered to the matching LLVM instructions by the compiler in a fairly straightforward manner. -/// The associated LLVM instruction or intrinsic is documented alongside each Rust intrinsic function. + +// These intrinsics aren't linked directly from LLVM and are mostly undocumented, however they are +// mostly lowered to the matching LLVM instructions by the compiler in a fairly straightforward manner. +// The associated LLVM instruction or intrinsic is documented alongside each Rust intrinsic function. extern "platform-intrinsic" { /// add/fadd pub(crate) fn simd_add(x: T, y: T) -> T; diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index df11dc21aa7a6..13bb079194fbe 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -11,3 +11,6 @@ pub mod owned; // Implementations for `AsRawFd` etc. for network types. mod net; + +#[cfg(test)] +mod tests; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index d72f9a2ff9c8f..807b057234ac1 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -21,6 +21,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// descriptor, so it can be used in FFI in places where a file descriptor is /// passed as an argument, it is not captured or consumed, and it never has the /// value `-1`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedFd` +/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file +/// descriptor, which is then borrowed under the same lifetime. #[derive(Copy, Clone)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] @@ -62,7 +66,7 @@ impl BorrowedFd<'_> { /// the returned `BorrowedFd`, and it must not have the value `-1`. #[inline] #[unstable(feature = "io_safety", issue = "87074")] - pub unsafe fn borrow_raw_fd(fd: RawFd) -> Self { + pub unsafe fn borrow_raw(fd: RawFd) -> Self { assert_ne!(fd, u32::MAX as RawFd); // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) unsafe { Self { fd, _phantom: PhantomData } } @@ -231,7 +235,7 @@ impl AsFd for OwnedFd { // Safety: `OwnedFd` and `BorrowedFd` have the same validity // invariants, and the `BorrowdFd` is bounded by the lifetime // of `&self`. - unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) } + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } } } diff --git a/library/std/src/os/fd/tests.rs b/library/std/src/os/fd/tests.rs new file mode 100644 index 0000000000000..26ef93e3d7110 --- /dev/null +++ b/library/std/src/os/fd/tests.rs @@ -0,0 +1,34 @@ +#[cfg(any(unix, target_os = "wasi"))] +#[test] +fn test_raw_fd() { + #[cfg(unix)] + use crate::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; + #[cfg(target_os = "wasi")] + use crate::os::wasi::io::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; + + let raw_fd: RawFd = crate::io::stdin().as_raw_fd(); + + let stdin_as_file = unsafe { crate::fs::File::from_raw_fd(raw_fd) }; + assert_eq!(stdin_as_file.as_raw_fd(), raw_fd); + assert_eq!(unsafe { BorrowedFd::borrow_raw(raw_fd).as_raw_fd() }, raw_fd); + assert_eq!(stdin_as_file.into_raw_fd(), 0); +} + +#[cfg(any(unix, target_os = "wasi"))] +#[test] +fn test_fd() { + #[cfg(unix)] + use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; + #[cfg(target_os = "wasi")] + use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; + + let stdin = crate::io::stdin(); + let fd: BorrowedFd<'_> = stdin.as_fd(); + let raw_fd: RawFd = fd.as_raw_fd(); + let owned_fd: OwnedFd = unsafe { OwnedFd::from_raw_fd(raw_fd) }; + + let stdin_as_file = crate::fs::File::from(owned_fd); + + assert_eq!(stdin_as_file.as_fd().as_raw_fd(), raw_fd); + assert_eq!(Into::::into(stdin_as_file).into_raw_fd(), raw_fd); +} diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 8df6c54a4144e..842a15ae1bfc0 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -28,6 +28,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// And, it *may* have the value `NULL` (0), which can occur when consoles are /// detached from processes, or when `windows_subsystem` is used. /// +/// This type's `.to_owned()` implementation returns another `BorrowedHandle` +/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw +/// handle, which is then borrowed under the same lifetime. +/// /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[derive(Copy, Clone)] #[repr(transparent)] @@ -131,7 +135,7 @@ impl BorrowedHandle<'_> { /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443 #[inline] #[unstable(feature = "io_safety", issue = "87074")] - pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self { + pub unsafe fn borrow_raw(handle: RawHandle) -> Self { Self { handle, _phantom: PhantomData } } } @@ -345,7 +349,7 @@ impl AsHandle for OwnedHandle { // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity // invariants, and the `BorrowdHandle` is bounded by the lifetime // of `&self`. - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } @@ -373,49 +377,49 @@ impl From for fs::File { impl AsHandle for crate::io::Stdin { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl<'a> AsHandle for crate::io::StdinLock<'a> { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl AsHandle for crate::io::Stdout { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl<'a> AsHandle for crate::io::StdoutLock<'a> { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl AsHandle for crate::io::Stderr { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl<'a> AsHandle for crate::io::StderrLock<'a> { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } impl AsHandle for crate::process::ChildStdin { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } @@ -429,7 +433,7 @@ impl From for OwnedHandle { impl AsHandle for crate::process::ChildStdout { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } @@ -443,7 +447,7 @@ impl From for OwnedHandle { impl AsHandle for crate::process::ChildStderr { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } @@ -457,7 +461,7 @@ impl From for OwnedHandle { impl AsHandle for crate::thread::JoinHandle { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { - unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) } + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 2f13eb77a1b94..a695a4106e810 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -21,6 +21,10 @@ use crate::sys::cvt; /// so it can be used in FFI in places where a socket is passed as an argument, /// it is not captured or consumed, and it never has the value /// `INVALID_SOCKET`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedSocket` +/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw +/// socket, which is then borrowed under the same lifetime. #[derive(Copy, Clone)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] @@ -67,7 +71,7 @@ impl BorrowedSocket<'_> { /// `INVALID_SOCKET`. #[inline] #[unstable(feature = "io_safety", issue = "87074")] - pub unsafe fn borrow_raw_socket(socket: RawSocket) -> Self { + pub unsafe fn borrow_raw(socket: RawSocket) -> Self { debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket); Self { socket, _phantom: PhantomData } } @@ -239,14 +243,14 @@ impl AsSocket for OwnedSocket { // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity // invariants, and the `BorrowdSocket` is bounded by the lifetime // of `&self`. - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } } impl AsSocket for crate::net::TcpStream { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } } @@ -267,7 +271,7 @@ impl From for crate::net::TcpStream { impl AsSocket for crate::net::TcpListener { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } } @@ -288,7 +292,7 @@ impl From for crate::net::TcpListener { impl AsSocket for crate::net::UdpSocket { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { - unsafe { BorrowedSocket::borrow_raw_socket(self.as_raw_socket()) } + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } } diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs index b359987595d30..e4d83ba0ffd13 100644 --- a/library/std/src/sys/unix/stdio.rs +++ b/library/std/src/sys/unix/stdio.rs @@ -96,7 +96,7 @@ pub fn panic_output() -> Option { impl AsFd for io::Stdin { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) } } } @@ -104,7 +104,7 @@ impl AsFd for io::Stdin { impl<'a> AsFd for io::StdinLock<'a> { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDIN_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) } } } @@ -112,7 +112,7 @@ impl<'a> AsFd for io::StdinLock<'a> { impl AsFd for io::Stdout { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) } } } @@ -120,7 +120,7 @@ impl AsFd for io::Stdout { impl<'a> AsFd for io::StdoutLock<'a> { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDOUT_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) } } } @@ -128,7 +128,7 @@ impl<'a> AsFd for io::StdoutLock<'a> { impl AsFd for io::Stderr { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) } } } @@ -136,6 +136,6 @@ impl AsFd for io::Stderr { impl<'a> AsFd for io::StderrLock<'a> { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw_fd(libc::STDERR_FILENO) } + unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) } } } diff --git a/library/stdarch b/library/stdarch index b4a0e07552cf9..bcbe010614f39 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit b4a0e07552cf90ef8f1a5b775bf70e4db94b3d63 +Subproject commit bcbe010614f398ec86f3a9274d22e33e5f2ee60b diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 592a137e379de..02efc08cc791f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -37,7 +37,6 @@ test = false build_helper = { path = "../build_helper" } cmake = "0.1.38" filetime = "0.2" -num_cpus = "1.0" getopts = "0.2.19" cc = "1.0.69" libc = "0.2" diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d6f77fe6cd6d0..ce76ccd57551d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1187,7 +1187,7 @@ fn set(field: &mut T, val: Option) { fn threads_from_config(v: u32) -> u32 { match v { - 0 => num_cpus::get() as u32, + 0 => std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32, n => n, } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 9180c5f03af68..74528f2752f5f 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -208,7 +208,7 @@ To learn more about a subcommand, run `./x.py -h`", let j_msg = format!( "number of jobs to run in parallel; \ defaults to {} (this host's logical CPU count)", - num_cpus::get() + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) ); opts.optopt("j", "jobs", &j_msg, "JOBS"); opts.optflag("h", "help", "print this help message"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 86339c8d7f88d..6a58de40181c2 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -917,7 +917,9 @@ impl Build { /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { - self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32) + self.config.jobs.unwrap_or_else(|| { + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32 + }) } fn debuginfo_map_to(&self, which: GitRepo) -> Option { diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d7e0b9d50f084..4c05818440b09 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -139,7 +139,7 @@ target | std | notes `armv7r-none-eabi` | * | Bare ARMv7-R `armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat `asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten -`i586-pc-windows-msvc` | ✓ | 32-bit Windows w/o SSE +`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23) `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL `i686-linux-android` | ✓ | 32-bit x86 Android @@ -236,7 +236,7 @@ target | std | host | notes `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) -`i686-pc-windows-msvc` | ✓ | | 32-bit Windows XP support +`i686-pc-windows-msvc` | * | | 32-bit Windows XP support `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD @@ -283,7 +283,7 @@ target | std | host | notes [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS -`x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support +`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku diff --git a/src/test/ui/async-await/proper-span-for-type-error.fixed b/src/test/ui/async-await/proper-span-for-type-error.fixed index 1f1e1184dcc02..7d43b575d2f66 100644 --- a/src/test/ui/async-await/proper-span-for-type-error.fixed +++ b/src/test/ui/async-await/proper-span-for-type-error.fixed @@ -5,7 +5,8 @@ async fn a() {} async fn foo() -> Result<(), i32> { - Ok(a().await) //~ ERROR mismatched types + a().await; + Ok(()) //~ ERROR mismatched types } fn main() {} diff --git a/src/test/ui/async-await/proper-span-for-type-error.stderr b/src/test/ui/async-await/proper-span-for-type-error.stderr index 611dc0407bf96..25f05156ce2bc 100644 --- a/src/test/ui/async-await/proper-span-for-type-error.stderr +++ b/src/test/ui/async-await/proper-span-for-type-error.stderr @@ -6,10 +6,11 @@ LL | a().await | = note: expected enum `Result<(), i32>` found unit type `()` -help: try wrapping the expression in `Ok` +help: try adding an expression at the end of the block + | +LL ~ a().await; +LL ~ Ok(()) | -LL | Ok(a().await) - | +++ + error: aborting due to previous error diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index 22e8c8dabc970..ad880d56d904d 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -266,7 +266,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:134:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_div` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow in signed division (dividing MIN by -1) error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:137:25 @@ -278,7 +278,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:139:25 | LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_rem` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow in signed remainder (dividing MIN by -1) error[E0080]: evaluation of constant value failed --> $DIR/const-int-unchecked.rs:144:25 diff --git a/src/test/ui/did_you_mean/compatible-variants.rs b/src/test/ui/did_you_mean/compatible-variants.rs index a70dda8386f08..b078064b26745 100644 --- a/src/test/ui/did_you_mean/compatible-variants.rs +++ b/src/test/ui/did_you_mean/compatible-variants.rs @@ -23,6 +23,21 @@ fn b() -> Result<(), ()> { //~| HELP try adding an expression } +fn c() -> Option<()> { + for _ in [1, 2] { + //~^ ERROR mismatched types + f(); + } + //~^ HELP try adding an expression +} + +fn d() -> Option<()> { + c()? + //~^ ERROR incompatible types + //~| HELP try removing this `?` + //~| HELP try adding an expression +} + fn main() { let _: Option<()> = while false {}; //~^ ERROR mismatched types diff --git a/src/test/ui/did_you_mean/compatible-variants.stderr b/src/test/ui/did_you_mean/compatible-variants.stderr index 0dfd8f5c128f6..51c1bf97c4e2c 100644 --- a/src/test/ui/did_you_mean/compatible-variants.stderr +++ b/src/test/ui/did_you_mean/compatible-variants.stderr @@ -37,7 +37,52 @@ LL + Ok(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:27:25 + --> $DIR/compatible-variants.rs:27:5 + | +LL | fn c() -> Option<()> { + | ---------- expected `Option<()>` because of return type +LL | / for _ in [1, 2] { +LL | | +LL | | f(); +LL | | } + | |_____^ expected enum `Option`, found `()` + | + = note: expected enum `Option<()>` + found unit type `()` +help: try adding an expression at the end of the block + | +LL ~ } +LL + None + | +LL ~ } +LL + Some(()) + | + +error[E0308]: `?` operator has incompatible types + --> $DIR/compatible-variants.rs:35:5 + | +LL | c()? + | ^^^^ expected enum `Option`, found `()` + | + = note: `?` operator cannot convert from `()` to `Option<()>` + = note: expected enum `Option<()>` + found unit type `()` +help: try removing this `?` + | +LL - c()? +LL + c() + | +help: try adding an expression at the end of the block + | +LL ~ c()?; +LL + None + | +LL ~ c()?; +LL + Some(()) + | + +error[E0308]: mismatched types + --> $DIR/compatible-variants.rs:42:25 | LL | let _: Option<()> = while false {}; | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -52,7 +97,7 @@ LL | let _: Option<()> = Some(while false {}); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:31:9 + --> $DIR/compatible-variants.rs:46:9 | LL | while false {} | ^^^^^^^^^^^^^^ expected enum `Option`, found `()` @@ -69,7 +114,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:35:31 + --> $DIR/compatible-variants.rs:50:31 | LL | let _: Result = 1; | ---------------- ^ expected enum `Result`, found integer @@ -86,7 +131,7 @@ LL | let _: Result = Err(1); | ++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:38:26 + --> $DIR/compatible-variants.rs:53:26 | LL | let _: Option = 1; | ----------- ^ expected enum `Option`, found integer @@ -101,7 +146,7 @@ LL | let _: Option = Some(1); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:41:28 + --> $DIR/compatible-variants.rs:56:28 | LL | let _: Hey = 1; | ------------- ^ expected enum `Hey`, found integer @@ -118,7 +163,7 @@ LL | let _: Hey = Hey::B(1); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:44:29 + --> $DIR/compatible-variants.rs:59:29 | LL | let _: Hey = false; | -------------- ^^^^^ expected enum `Hey`, found `bool` @@ -133,7 +178,7 @@ LL | let _: Hey = Hey::B(false); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:48:19 + --> $DIR/compatible-variants.rs:63:19 | LL | let _ = Foo { bar }; | ^^^ expected enum `Option`, found `i32` @@ -145,6 +190,6 @@ help: try wrapping the expression in `Some` LL | let _ = Foo { bar: Some(bar) }; | ++++++++++ + -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs index 258f9e4831f9a..54d86c31fb4fb 100644 --- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs +++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.rs @@ -29,4 +29,18 @@ fn doc_comment_on_expr(num: u8) -> bool { fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} //~^ ERROR: unused doc comment +fn doc_comment_on_block() { + /// unused doc comment + //~^ ERROR: unused doc comment + { + let x = 12; + } +} + +/// unused doc comment +//~^ ERROR: unused doc comment +extern "C" { + fn foo(); +} + fn main() {} diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr index 3ce1df71a2ed5..30a96af583af7 100644 --- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr +++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr @@ -49,6 +49,32 @@ LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {} | = help: use `//` for a plain comment +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:33:5 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / { +LL | | let x = 12; +LL | | } + | |_____- rustdoc does not generate documentation for expressions + | + = help: use `//` for a plain comment + +error: unused doc comment + --> $DIR/unused-doc-comments-edge-cases.rs:40:1 + | +LL | /// unused doc comment + | ^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | / extern "C" { +LL | | fn foo(); +LL | | } + | |_- rustdoc does not generate documentation for extern block + | + = help: use `//` for a plain comment + error[E0308]: mismatched types --> $DIR/unused-doc-comments-edge-cases.rs:14:9 | @@ -63,7 +89,7 @@ help: you might have meant to return this value LL | return true; | ++++++ + -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs b/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs new file mode 100644 index 0000000000000..d5c8d4e6bdf2b --- /dev/null +++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.rs @@ -0,0 +1,6 @@ +// `Rc` is not ever `Copy`, we should not suggest adding `T: Copy` constraint +fn duplicate_rc(t: std::rc::Rc) -> (std::rc::Rc, std::rc::Rc) { + (t, t) //~ use of moved value: `t` +} + +fn main() {} diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr new file mode 100644 index 0000000000000..c25981e6f8063 --- /dev/null +++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_clone_suggestions.rs:3:9 + | +LL | fn duplicate_rc(t: std::rc::Rc) -> (std::rc::Rc, std::rc::Rc) { + | - move occurs because `t` has type `Rc`, which does not implement the `Copy` trait +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed new file mode 100644 index 0000000000000..d31046c77006e --- /dev/null +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -0,0 +1,72 @@ +// run-rustfix +#![allow(dead_code)] + +fn duplicate_t(t: T) -> (T, T) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_opt(t: Option) -> (Option, Option) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + //~^ HELP consider restricting type parameters + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom(t: S) -> (S, S) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +struct S(T); +trait Trait {} +impl Clone for S { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl Copy for S {} + +trait A {} +trait B {} + +// Test where bounds are added with different bound placements +fn duplicate_custom_1(t: S) -> (S, S) where { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_2(t: S) -> (S, S) +where + T: A + Trait + Copy, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_3(t: S) -> (S, S) +where + T: A, + T: B, T: Trait, T: Copy + //~^ HELP consider further restricting type parameter `T` +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_4(t: S) -> (S, S) +where + T: B + Trait + Copy, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn main() {} diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs b/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs new file mode 100644 index 0000000000000..7cc5189fac017 --- /dev/null +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -0,0 +1,72 @@ +// run-rustfix +#![allow(dead_code)] + +fn duplicate_t(t: T) -> (T, T) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_opt(t: Option) -> (Option, Option) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + //~^ HELP consider restricting type parameters + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom(t: S) -> (S, S) { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +struct S(T); +trait Trait {} +impl Clone for S { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl Copy for S {} + +trait A {} +trait B {} + +// Test where bounds are added with different bound placements +fn duplicate_custom_1(t: S) -> (S, S) where { + //~^ HELP consider restricting type parameter `T` + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_2(t: S) -> (S, S) +where + T: A, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_3(t: S) -> (S, S) +where + T: A, + T: B, + //~^ HELP consider further restricting type parameter `T` +{ + (t, t) //~ use of moved value: `t` +} + +fn duplicate_custom_4(t: S) -> (S, S) +where + T: B, + //~^ HELP consider further restricting this bound +{ + (t, t) //~ use of moved value: `t` +} + +fn main() {} diff --git a/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr new file mode 100644 index 0000000000000..8e72697ca30bb --- /dev/null +++ b/src/test/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -0,0 +1,147 @@ +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:6:9 + | +LL | fn duplicate_t(t: T) -> (T, T) { + | - move occurs because `t` has type `T`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_t(t: T) -> (T, T) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:11:9 + | +LL | fn duplicate_opt(t: Option) -> (Option, Option) { + | - move occurs because `t` has type `Option`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_opt(t: Option) -> (Option, Option) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:16:9 + | +LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + | - move occurs because `t` has type `(T,)`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { + | ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:21:9 + | +LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + | - move occurs because `t` has type `(A, B)`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameters + | +LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { + | ++++++ ++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:26:9 + | +LL | fn duplicate_custom(t: S) -> (S, S) { + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_custom(t: S) -> (S, S) { + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:44:9 + | +LL | fn duplicate_custom_1(t: S) -> (S, S) where { + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +LL | +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider restricting type parameter `T` + | +LL | fn duplicate_custom_1(t: S) -> (S, S) where { + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:52:9 + | +LL | fn duplicate_custom_2(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting this bound + | +LL | T: A + Trait + Copy, + | ++++++++++++++ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:61:9 + | +LL | fn duplicate_custom_3(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting type parameter `T` + | +LL | T: B, T: Trait, T: Copy + | ~~~~~~~~~~~~~~~~~~~ + +error[E0382]: use of moved value: `t` + --> $DIR/use_of_moved_value_copy_suggestions.rs:69:9 + | +LL | fn duplicate_custom_4(t: S) -> (S, S) + | - move occurs because `t` has type `S`, which does not implement the `Copy` trait +... +LL | (t, t) + | - ^ value used here after move + | | + | value moved here + | +help: consider further restricting this bound + | +LL | T: B + Trait + Copy, + | ++++++++++++++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr index d94c7742de301..e2eee1ccdc98c 100644 --- a/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr @@ -1,36 +1,36 @@ -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow | - = note: `#[deny(arithmetic_overflow)]` on by default + = note: `#[deny(unconditional_panic)]` on by default -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:23:36 | LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); @@ -41,8 +41,6 @@ error: this operation will panic at runtime | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide `1_isize` by zero - | - = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:27:36 @@ -74,37 +72,37 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); | ^^^^^^^^^ attempt to divide `1_i128` by zero -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:41:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:47:36 | LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr index d94c7742de301..e2eee1ccdc98c 100644 --- a/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr @@ -1,36 +1,36 @@ -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow | - = note: `#[deny(arithmetic_overflow)]` on by default + = note: `#[deny(unconditional_panic)]` on by default -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:23:36 | LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); @@ -41,8 +41,6 @@ error: this operation will panic at runtime | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide `1_isize` by zero - | - = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:27:36 @@ -74,37 +72,37 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); | ^^^^^^^^^ attempt to divide `1_i128` by zero -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:41:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:47:36 | LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr index d94c7742de301..e2eee1ccdc98c 100644 --- a/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr @@ -1,36 +1,36 @@ -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:13:36 | LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow | - = note: `#[deny(arithmetic_overflow)]` on by default + = note: `#[deny(unconditional_panic)]` on by default -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:15:36 | LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:17:36 | LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:19:36 | LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:21:36 | LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:23:36 | LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); @@ -41,8 +41,6 @@ error: this operation will panic at runtime | LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide `1_isize` by zero - | - = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:27:36 @@ -74,37 +72,37 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); | ^^^^^^^^^ attempt to divide `1_i128` by zero -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:37:36 | LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:39:36 | LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:41:36 | LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:43:36 | LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:45:36 | LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow -error: this arithmetic operation will overflow +error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:47:36 | LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.rs b/src/test/ui/numbers-arithmetic/issue-8460-const.rs index dc754666c8e1f..8cad6deb3db5e 100644 --- a/src/test/ui/numbers-arithmetic/issue-8460-const.rs +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.rs @@ -11,17 +11,17 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); @@ -35,17 +35,17 @@ fn main() { assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); //~^ ERROR operation will panic assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - //~^ ERROR arithmetic operation will overflow + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index c022d3aa0acd7..c437bde5ae69a 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -13,4 +13,3 @@ tar = "0.4.29" sha2 = "0.10.1" rayon = "1.5.1" hex = "0.4.2" -num_cpus = "1.13.0" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8a62146abfc4e..378efeb644375 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -208,7 +208,7 @@ fn main() { let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") { num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS") } else { - num_cpus::get() + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) }; rayon::ThreadPoolBuilder::new() .num_threads(num_threads)