diff options
721 files changed, 10189 insertions, 5225 deletions
diff --git a/Cargo.lock b/Cargo.lock index 97148641670..f99e58e59b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2675,9 +2675,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "packed_simd_2" @@ -3295,9 +3295,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c4b4625eeb148cccf82d5e9b90ad7fab3b11a0204cf75cc7fa04981a0fdffd" +checksum = "d65b1271cdac365b71b59570ea35d945dea2dd2cc47eba3d33b4bd1e0190ac6d" dependencies = [ "anyhow", "rustc_version", @@ -5203,9 +5203,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -5309,6 +5309,7 @@ dependencies = [ "lazy_static", "miropt-test-tools", "regex", + "termcolor", "walkdir", ] diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 31596a1e9bf..c1b26ca0925 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -572,7 +572,7 @@ impl Pat { PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()), // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, mutbl) => { - pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? + pat.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))? } // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, // when `P` can be reparsed as a type `T`. @@ -1193,7 +1193,7 @@ impl Expr { ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => { - expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? + expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))? } ExprKind::Repeat(expr, expr_len) => { @@ -2031,7 +2031,7 @@ impl Clone for Ty { impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { final_ty = ty; } final_ty @@ -2058,7 +2058,7 @@ pub enum TyKind { /// A raw pointer (`*const T` or `*mut T`). Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`). - Rptr(Option<Lifetime>, MutTy), + Ref(Option<Lifetime>, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P<BareFnTy>), /// The never type (`!`). @@ -2286,7 +2286,7 @@ impl Param { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { + TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } _ => Some(respan( @@ -2319,7 +2319,7 @@ impl Param { Mutability::Not, P(Ty { id: DUMMY_NODE_ID, - kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }), + kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }), span, tokens: None, }), @@ -2743,8 +2743,19 @@ impl Item { /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub enum Extern { + /// No explicit extern keyword was used + /// + /// E.g. `fn foo() {}` None, + /// An explicit extern keyword was used, but with implicit ABI + /// + /// E.g. `extern fn foo() {}` + /// + /// This is just `extern "C"` (see `rustc_target::spec::abi::Abi::FALLBACK`) Implicit(Span), + /// An explicit extern keyword was used with an explicit ABI + /// + /// E.g. `extern "C" fn foo() {}` Explicit(StrLit, Span), } @@ -2763,9 +2774,13 @@ impl Extern { /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct FnHeader { + /// The `unsafe` keyword, if any pub unsafety: Unsafe, + /// The `async` keyword, if any pub asyncness: Async, + /// The `const` keyword, if any pub constness: Const, + /// The `extern` keyword and corresponding ABI string, if any pub ext: Extern, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a45ee6067bb..c572171e8f4 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -459,7 +459,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {} TyKind::Slice(ty) => vis.visit_ty(ty), TyKind::Ptr(mt) => vis.visit_mt(mt), - TyKind::Rptr(lt, mt) => { + TyKind::Ref(lt, mt) => { visit_opt(lt, |lt| noop_visit_lifetime(lt, vis)); vis.visit_mt(mt); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 991eb489f6b..df7145a722a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -92,7 +92,7 @@ impl<'a> FnKind<'a> { #[derive(Copy, Clone, Debug)] pub enum LifetimeCtxt { /// Appears in a reference type. - Rptr, + Ref, /// Appears as a bound on a type or another lifetime. Bound, /// Appears as a generic argument. @@ -396,8 +396,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { match &typ.kind { TyKind::Slice(ty) | TyKind::Paren(ty) => visitor.visit_ty(ty), TyKind::Ptr(mutable_type) => visitor.visit_ty(&mutable_type.ty), - TyKind::Rptr(opt_lifetime, mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Rptr); + TyKind::Ref(opt_lifetime, mutable_type) => { + walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); visitor.visit_ty(&mutable_type.ty) } TyKind::Tup(tuple_element_types) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 4abb1d90f44..b6b242bfc27 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> { param.id, ¶m.kind, ¶m.bounds, + param.colon_span, + generics.span, itctx, PredicateOrigin::GenericParam, ) @@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], + colon_span: Option<Span>, + parent_span: Span, itctx: &ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { @@ -1377,21 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.lower_ident(ident); let param_span = ident.span; - let span = bounds - .iter() - .fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| { - let bound_span = bound.span(); - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. - if !bound_span.can_be_used_for_suggestions() { - None - } else if let Some(span) = span { - Some(span.to(bound_span)) - } else { - Some(bound_span) - } - }) - .unwrap_or(param_span.shrink_to_hi()); + + // Reconstruct the span of the entire predicate from the individual generic bounds. + let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi()); + let span = bounds.iter().fold(span_start, |span_accum, bound| { + match bound.span().find_ancestor_inside(parent_span) { + Some(bound_span) => span_accum.to(bound_span), + None => span_accum, + } + }); + let span = self.lower_span(span); + match kind { GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a089510493e..83174afdb12 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -776,7 +776,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Intercept all spans entering HIR. /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { - if self.tcx.sess.opts.unstable_opts.incremental_relative_spans { + if self.tcx.sess.opts.incremental_relative_spans() { span.with_parent(Some(self.current_hir_id_owner.def_id)) } else { // Do not make spans relative when not using incremental compilation. @@ -1238,7 +1238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Err => hir::TyKind::Err, TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), - TyKind::Rptr(region, mt) => { + TyKind::Ref(region, mt) => { let region = region.unwrap_or_else(|| { let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) = self.resolver.get_lifetime_res(t.id) @@ -1252,7 +1252,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); - hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) + hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); @@ -1771,7 +1771,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Given we are only considering `ImplicitSelf` types, we needn't consider // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. - TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { + TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { hir::Mutability::Not => hir::ImplicitSelfKind::ImmRef, hir::Mutability::Mut => hir::ImplicitSelfKind::MutRef, }, @@ -2245,6 +2245,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) { // Add a definition for the in-band `Param`. let def_id = self.local_def_id(node_id); + let span = self.lower_span(span); // Set the name to `impl Bound1 + Bound2`. let param = hir::GenericParam { @@ -2252,7 +2253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, name: ParamName::Plain(self.lower_ident(ident)), pure_wrt_drop: false, - span: self.lower_span(span), + span, kind: hir::GenericParamKind::Type { default: None, synthetic: true }, colon_span: None, }; @@ -2262,6 +2263,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, + /* colon_span */ None, + span, &ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); @@ -2271,7 +2274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { - span: self.lower_span(span), + span, res, segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 914fc5f58da..3989fc48619 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -83,7 +83,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { visit::walk_ty(self, t); self.current_binders.pop(); } - TyKind::Rptr(None, _) => { + TyKind::Ref(None, _) => { self.record_elided_anchor(t.id, t.span); visit::walk_ty(self, t); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d0e4761a10d..104cdd3a8e1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1025,7 +1025,7 @@ impl<'a> State<'a> { self.word("*"); self.print_mt(mt, true); } - ast::TyKind::Rptr(lifetime, mt) => { + ast::TyKind::Ref(lifetime, mt) => { self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 01be379120d..e4942f9b666 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -12,7 +12,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { place: &str, borrow_place: &str, value_place: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow { place, span, @@ -28,7 +28,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, borrow_span: Span, borrow_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_loan_span: Span, old_opt_via: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( @@ -98,7 +98,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, old_loan_span: Span, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, new_loan_span, @@ -269,7 +269,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0594, "cannot assign to {}", desc) } @@ -348,7 +348,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, path: &str, reason: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) } @@ -359,7 +359,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_place: &str, immutable_section: &str, action: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, mutate_span, @@ -378,7 +378,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, yield_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -392,7 +392,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn cannot_borrow_across_destructor( &self, borrow_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!( self, borrow_span, @@ -405,7 +405,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, path: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0597, "{} does not live long enough", path,) } @@ -415,7 +415,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { return_kind: &str, reference_desc: &str, path_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -440,7 +440,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { closure_kind: &str, borrowed_path: &str, capture_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, closure_span, @@ -458,14 +458,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn thread_local_value_does_not_live_long_enough( &self, span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) } pub(crate) fn temporary_value_borrowed_for_too_long( &self, span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 26212dd384c..3c3cb8c6b9c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2681,7 +2681,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Need to use the `rustc_middle::ty` types to compare against the // `return_region`. Then use the `rustc_hir` type to get only // the lifetime span. - if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind { + if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind { // With access to the lifetime, we can get // the span of it. arguments.push((*argument, lifetime.ident.span)); @@ -2702,7 +2702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output { - if let hir::TyKind::Rptr(lifetime, _) = ty.kind { + if let hir::TyKind::Ref(lifetime, _) = ty.kind { return_span = lifetime.ident.span; } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3319a80681f..6f6d1b01bd4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -180,6 +180,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // the verbs used in some diagnostic messages. let act; let acted_on; + let mut suggest = true; + let mut mut_error = None; + let mut count = 1; let span = match error_access { AccessKind::Mutate => { @@ -194,15 +197,50 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let borrow_spans = self.borrow_spans(span, location); let borrow_span = borrow_spans.args_or_use(); - err = self.cannot_borrow_path_as_mutable_because(borrow_span, &item_msg, &reason); - borrow_spans.var_span_label( - &mut err, - format!( - "mutable borrow occurs due to use of {} in closure", - self.describe_any_place(access_place.as_ref()), - ), - "mutable", - ); + match the_place_err { + PlaceRef { local, projection: [] } + if self.body.local_decls[local].can_be_made_mutable() => + { + let span = self.body.local_decls[local].source_info.span; + mut_error = Some(span); + if let Some((buffer, c)) = self.get_buffered_mut_error(span) { + // We've encountered a second (or more) attempt to mutably borrow an + // immutable binding, so the likely problem is with the binding + // declaration, not the use. We collect these in a single diagnostic + // and make the binding the primary span of the error. + err = buffer; + count = c + 1; + if count == 2 { + err.replace_span_with(span, false); + err.span_label(span, "not mutable"); + } + suggest = false; + } else { + err = self.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + ); + } + } + _ => { + err = self.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + ); + } + } + if suggest { + borrow_spans.var_span_label( + &mut err, + format!( + "mutable borrow occurs due to use of {} in closure", + self.describe_any_place(access_place.as_ref()), + ), + "mutable", + ); + } borrow_span } }; @@ -276,7 +314,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { pat_span: _, }, )))) => { - err.span_note(sp, "the binding is already a mutable borrow"); + if suggest { + err.span_note(sp, "the binding is already a mutable borrow"); + } } _ => { err.span_note( @@ -333,16 +373,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let local_decl = &self.body.local_decls[local]; assert_eq!(local_decl.mutability, Mutability::Not); - err.span_label(span, format!("cannot {ACT}", ACT = act)); - err.span_suggestion( - local_decl.source_info.span, - "consider changing this to be mutable", - format!("mut {}", self.local_names[local].unwrap()), - Applicability::MachineApplicable, - ); - let tcx = self.infcx.tcx; - if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() { - self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); + if count < 10 { + err.span_label(span, format!("cannot {act}")); + } + if suggest { + err.span_suggestion_verbose( + local_decl.source_info.span.shrink_to_lo(), + "consider changing this to be mutable", + "mut ".to_string(), + Applicability::MachineApplicable, + ); + let tcx = self.infcx.tcx; + if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() { + self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); + } } } @@ -357,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let captured_place = &self.upvars[upvar_index.index()].place; - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); let upvar_hir_id = captured_place.get_root_variable(); @@ -397,7 +441,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .span_to_snippet(span) .map_or(false, |snippet| snippet.starts_with("&mut ")) => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); err.span_suggestion( span, "try removing `&mut` here", @@ -409,7 +453,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local, projection: [ProjectionElem::Deref] } if self.body.local_decls[local].is_ref_for_guard() => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); err.note( "variables bound in patterns are immutable until the end of the pattern guard", ); @@ -537,7 +581,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some((true, err_help_span, suggested_code)) => { let (is_trait_sig, local_trait) = self.is_error_in_trait(local); if !is_trait_sig { - err.span_suggestion( + err.span_suggestion_verbose( err_help_span, &format!( "consider changing this to be a mutable {pointer_desc}" @@ -546,7 +590,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if let Some(x) = local_trait { - err.span_suggestion( + err.span_suggestion_verbose( x, &format!( "consider changing that to be a mutable {pointer_desc}" @@ -569,24 +613,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_label( span, format!( - "`{NAME}` is a `{SIGIL}` {DESC}, \ - so the data it refers to cannot be {ACTED_ON}", - NAME = name, - SIGIL = pointer_sigil, - DESC = pointer_desc, - ACTED_ON = acted_on + "`{name}` is a `{pointer_sigil}` {pointer_desc}, \ + so the data it refers to cannot be {acted_on}", ), ); } _ => { err.span_label( span, - format!( - "cannot {ACT} through `{SIGIL}` {DESC}", - ACT = act, - SIGIL = pointer_sigil, - DESC = pointer_desc - ), + format!("cannot {act} through `{pointer_sigil}` {pointer_desc}"), ); } } @@ -605,13 +640,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(BorrowedContentSource::OverloadedDeref(ty)) => { err.help(&format!( "trait `DerefMut` is required to modify through a dereference, \ - but it is not implemented for `{ty}`", + but it is not implemented for `{ty}`", )); } Some(BorrowedContentSource::OverloadedIndex(ty)) => { err.help(&format!( "trait `IndexMut` is required to modify indexed content, \ - but it is not implemented for `{ty}`", + but it is not implemented for `{ty}`", )); self.suggest_map_index_mut_alternatives(ty, &mut err, span); } @@ -620,11 +655,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } _ => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); } } - self.buffer_error(err); + if let Some(span) = mut_error { + self.buffer_mut_error(span, err, count); + } else { + self.buffer_error(err); + } } fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { @@ -1209,7 +1248,7 @@ fn get_mut_span_in_struct_field<'tcx>( // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. && let hir::Node::Field(field) = node - && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind + && let hir::TyKind::Ref(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind { return Some(lt.ident.span.between(ty.span)); } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 171e62d91e1..dbd4cac7b14 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -493,10 +493,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // // & // - let's call the lifetime of this reference `'1` - ( - ty::Ref(region, referent_ty, _), - hir::TyKind::Rptr(_lifetime, referent_hir_ty), - ) => { + (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => { if region.to_region_vid() == needle_fr { // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 168b798788b..ae1bea008b6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2270,6 +2270,7 @@ mod error { /// same primary span come out in a consistent order. buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>, + buffered_mut_errors: FxHashMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>, /// Diagnostics to be reported buffer. buffered: Vec<Diagnostic>, /// Set to Some if we emit an error during borrowck @@ -2281,6 +2282,7 @@ mod error { BorrowckErrors { tcx, buffered_move_errors: BTreeMap::new(), + buffered_mut_errors: Default::default(), buffered: Default::default(), tainted_by_errors: None, } @@ -2331,12 +2333,34 @@ mod error { } } + pub fn get_buffered_mut_error( + &mut self, + span: Span, + ) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> { + self.errors.buffered_mut_errors.remove(&span) + } + + pub fn buffer_mut_error( + &mut self, + span: Span, + t: DiagnosticBuilder<'tcx, ErrorGuaranteed>, + count: usize, + ) { + self.errors.buffered_mut_errors.insert(span, (t, count)); + } + pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. diag.buffer(&mut self.errors.buffered); } + for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { + if count > 10 { + diag.note(&format!("...and {} other attempted mutable borrows", count - 10)); + } + diag.buffer(&mut self.errors.buffered); + } if !self.errors.buffered.is_empty() { self.errors.buffered.sort_by_key(|diag| diag.sort_span); diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 544d971b27a..5b1b7e6804c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -117,8 +117,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // `let names: &'static _ = &["field1", "field2"];` let names_let = if is_struct { let lt_static = Some(cx.lifetime_static(span)); - let ty_static_ref = - cx.ty_rptr(span, cx.ty_infer(span), lt_static, ast::Mutability::Not); + let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not); Some(cx.stmt_let_ty( span, false, @@ -138,13 +137,13 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> ); let ty_slice = cx.ty( span, - ast::TyKind::Slice(cx.ty_rptr(span, ty_dyn_debug, None, ast::Mutability::Not)), + ast::TyKind::Slice(cx.ty_ref(span, ty_dyn_debug, None, ast::Mutability::Not)), ); let values_let = cx.stmt_let_ty( span, false, Ident::new(sym::values, span), - Some(cx.ty_rptr(span, ty_slice, None, ast::Mutability::Not)), + Some(cx.ty_ref(span, ty_slice, None, ast::Mutability::Not)), cx.expr_array_ref(span, value_exprs), ); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index eaa4881906a..c6f5f5d0807 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -97,7 +97,7 @@ impl Ty { match self { Ref(ty, mutbl) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); - cx.ty_rptr(span, raw_ty, None, *mutbl) + cx.ty_ref(span, raw_ty, None, *mutbl) } Path(p) => p.to_ty(cx, span, self_ty, self_generics), Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index a7283ea601b..84d06b69a9d 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -30,7 +30,7 @@ pub fn expand_option_env<'cx>( sp, true, cx.std_path(&[sym::option, sym::Option, sym::None]), - vec![GenericArg::Type(cx.ty_rptr( + vec![GenericArg::Type(cx.ty_ref( sp, cx.ty_ident(sp, Ident::new(sym::str, sp)), Some(lt), diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index b88de224675..21c8caa658f 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -349,7 +349,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> { .item_static( span, Ident::new(sym::_DECLS, span), - cx.ty_rptr( + cx.ty_ref( span, cx.ty( span, diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 05f059c89d5..c63caa06818 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,6 +1,7 @@ use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; use std::borrow::Borrow; use std::cmp::Ordering; +use std::fmt::Debug; use std::mem; use std::ops::{Bound, Index, IndexMut, RangeBounds}; @@ -16,7 +17,7 @@ pub use index_map::SortedIndexMultiMap; /// stores data in a more compact way. It also supports accessing contiguous /// ranges of elements as a slice, and slices of already sorted elements can be /// inserted efficiently. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] pub struct SortedMap<K, V> { data: Vec<(K, V)>, } @@ -314,5 +315,11 @@ impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> fo } } +impl<K: Debug, V: Debug> Debug for SortedMap<K, V> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_map().entries(self.data.iter().map(|(a, b)| (a, b))).finish() + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 31e08c44d29..30179e97872 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1199,8 +1199,8 @@ static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + }; // Invoke the default handler, which prints the actual panic message and optionally a backtrace - // Don't do this for `ExplicitBug`, which has an unhelpful message and backtrace. - if !info.payload().is::<rustc_errors::ExplicitBug>() { + // Don't do this for `GoodPathBug`, which already emits its own more useful backtrace. + if !info.payload().is::<rustc_errors::GoodPathBug>() { (*DEFAULT_HOOK)(info); // Separate the output with an empty line @@ -1237,7 +1237,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // a .span_bug or .bug call has already printed what // it wants to print. - if !info.payload().is::<rustc_errors::ExplicitBug>() { + if !info.payload().is::<rustc_errors::ExplicitBug>() + && !info.payload().is::<rustc_errors::GoodPathBug>() + { let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); handler.emit_diagnostic(&mut d); } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index d05559e9244..3fba2cf5749 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -244,6 +244,7 @@ E0457: include_str!("./error_codes/E0457.md"), E0458: include_str!("./error_codes/E0458.md"), E0459: include_str!("./error_codes/E0459.md"), E0460: include_str!("./error_codes/E0460.md"), +E0461: include_str!("./error_codes/E0461.md"), E0462: include_str!("./error_codes/E0462.md"), E0463: include_str!("./error_codes/E0463.md"), E0464: include_str!("./error_codes/E0464.md"), @@ -275,10 +276,12 @@ E0509: include_str!("./error_codes/E0509.md"), E0510: include_str!("./error_codes/E0510.md"), E0511: include_str!("./error_codes/E0511.md"), E0512: include_str!("./error_codes/E0512.md"), +E0514: include_str!("./error_codes/E0514.md"), E0515: include_str!("./error_codes/E0515.md"), E0516: include_str!("./error_codes/E0516.md"), E0517: include_str!("./error_codes/E0517.md"), E0518: include_str!("./error_codes/E0518.md"), +E0519: include_str!("./error_codes/E0519.md"), E0520: include_str!("./error_codes/E0520.md"), E0521: include_str!("./error_codes/E0521.md"), E0522: include_str!("./error_codes/E0522.md"), @@ -595,8 +598,7 @@ E0791: include_str!("./error_codes/E0791.md"), // E0421, // merged into 531 // E0427, // merged into 530 // E0456, // plugin `..` is not available for triple `..` - E0461, // couldn't find crate `..` with expected target triple .. - E0465, // multiple .. candidates for `..` found +// E0465, // removed: merged with E0464 // E0467, // removed // E0470, // removed // E0471, // constant evaluation error (in pattern) @@ -615,8 +617,6 @@ E0791: include_str!("./error_codes/E0791.md"), // E0488, // lifetime of variable does not enclose its declaration // E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0514, // metadata version mismatch - E0519, // local crate and dependency have same (crate-name, disambiguator) E0523, // two dependencies have same (crate-name, disambiguator) but different SVH // E0526, // shuffle indices are not constant // E0540, // multiple rustc_deprecated attributes diff --git a/compiler/rustc_error_codes/src/error_codes/E0461.md b/compiler/rustc_error_codes/src/error_codes/E0461.md new file mode 100644 index 00000000000..33105c43ccf --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0461.md @@ -0,0 +1,30 @@ +Couldn't find crate `..` with expected target triple `..`. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +#![crate_type = "lib"] + +fn foo() {} +``` + +`main.rs` +```ignore (cannot-link-with-other-tests) +extern crate a; + +fn main() { + a::foo(); +} +``` + +`a.rs` is then compiled with `--target powerpc-unknown-linux-gnu` and `b.rs` +with `--target x86_64-unknown-linux-gnu`. `a.rs` is compiled into a binary +format incompatible with `b.rs`; PowerPC and x86 are totally different +architectures. This issue also extends to any difference in target triples, as +`std` is operating-system specific. + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager, automatically + fixing this issue. + * Recompiling either crate so that they target a consistent target triple. diff --git a/compiler/rustc_error_codes/src/error_codes/E0514.md b/compiler/rustc_error_codes/src/error_codes/E0514.md new file mode 100644 index 00000000000..ce2bbc5c505 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0514.md @@ -0,0 +1,33 @@ +Dependency compiled with different version of `rustc`. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +// compiled with stable `rustc` + +#[crate_type = "lib"] +``` + +`b.rs` +```ignore (cannot-link-with-other-tests) +// compiled with nightly `rustc` + +#[crate_type = "lib"] + +extern crate a; // error: found crate `a` compiled by an incompatible version + // of rustc +``` + +This error is caused when the version of `rustc` used to compile a crate, as +stored in the binary's metadata, differs from the version of one of its +dependencies. Many parts of Rust binaries are considered unstable. For +instance, the Rust ABI is not stable between compiler versions. This means that +the compiler cannot be sure about *how* to call a function between compiler +versions, and therefore this error occurs. + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager and + [Rustup](https://rust-lang.github.io/rustup/), the Rust toolchain installer, + automatically fixing this issue. + * Recompiling the crates with a uniform `rustc` version. diff --git a/compiler/rustc_error_codes/src/error_codes/E0519.md b/compiler/rustc_error_codes/src/error_codes/E0519.md new file mode 100644 index 00000000000..12876e2ad75 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0519.md @@ -0,0 +1,40 @@ +The current crate is indistinguishable from one of its dependencies, in terms +of metadata. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +#![crate_name = "a"] +#![crate_type = "lib"] + +pub fn foo() {} +``` + +`b.rs` +```ignore (cannot-link-with-other-tests) +#![crate_name = "a"] +#![crate_type = "lib"] + +// error: the current crate is indistinguishable from one of its dependencies: +// it has the same crate-name `a` and was compiled with the same +// `-C metadata` arguments. This will result in symbol conflicts between +// the two. +extern crate a; + +pub fn foo() {} + +fn bar() { + a::foo(); // is this calling the local crate or the dependency? +} +``` + +The above example compiles two crates with exactly the same name and +`crate_type` (plus any other metadata). This causes an error because it becomes +impossible for the compiler to distinguish between symbols (`pub` item names). + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager, automatically + fixing this issue. + * Recompiling the crate with different metadata (different name/ + `crate_type`). diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index b3ca540417d..b42b228bde9 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -196,11 +196,7 @@ metadata_extern_location_not_file = extern location for {$crate_name} is not a file: {$location} metadata_multiple_candidates = - multiple {$flavor} candidates for `{$crate_name}` found - -metadata_multiple_matching_crates = - multiple matching crates for `{$crate_name}` - .note = candidates:{$candidates} + multiple candidates for `{$flavor}` dependency `{$crate_name}` found metadata_symbol_conflicts_current = the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index b53550e5fd5..3401978caf5 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -365,3 +365,6 @@ parse_invalid_identifier_with_leading_number = expected identifier, found number parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` .suggestion = replace `fn` with `impl` here + +parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn` + .suggestion = use `Fn` to refer to the trait diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 585a54308c6..e19a6fe0ee9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -365,12 +365,12 @@ impl Diagnostic { self } - pub fn replace_span_with(&mut self, after: Span) -> &mut Self { + pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); self.set_span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { - if span_label.is_primary { + if span_label.is_primary && keep_label { self.span.push_span_label(after, label); } else { self.span.push_span_label(span_label.span, label); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index e2a0e436fd5..0ca200abe19 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -845,7 +845,10 @@ impl EmitterWriter { // 3 | | // 4 | | } // | |_^ test - if let [ann] = &line.annotations[..] { + let mut buffer_ops = vec![]; + let mut annotations = vec![]; + let mut short_start = true; + for ann in &line.annotations { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { let style = if ann.is_primary { @@ -853,10 +856,23 @@ impl EmitterWriter { } else { Style::UnderlineSecondary }; - buffer.putc(line_offset, width_offset + depth - 1, '/', style); - return vec![(depth, style)]; + annotations.push((depth, style)); + buffer_ops.push((line_offset, width_offset + depth - 1, '/', style)); + } else { + short_start = false; + break; } + } else if let AnnotationType::MultilineLine(_) = ann.annotation_type { + } else { + short_start = false; + break; + } + } + if short_start { + for (y, x, c, s) in buffer_ops { + buffer.putc(y, x, c, s); } + return annotations; } // We want to display like this: diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b03352d5fec..136c360201e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -40,12 +40,13 @@ use rustc_span::source_map::SourceMap; use rustc_span::HashStableContext; use rustc_span::{Loc, Span}; +use std::any::Any; use std::borrow::Cow; +use std::fmt; use std::hash::Hash; use std::num::NonZeroUsize; use std::panic; use std::path::Path; -use std::{error, fmt}; use termcolor::{Color, ColorSpec}; @@ -361,16 +362,11 @@ pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. -#[derive(Copy, Clone, Debug)] pub struct ExplicitBug; -impl fmt::Display for ExplicitBug { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "parser internal bug") - } -} - -impl error::Error for ExplicitBug {} +/// Signifies that the compiler died with an explicit call to `.delay_good_path_bug` +/// rather than a failed assertion, etc. +pub struct GoodPathBug; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, @@ -473,10 +469,12 @@ pub enum StashKey { CallAssocMethod, } -fn default_track_diagnostic(_: &Diagnostic) {} +fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { + (*f)(d) +} -pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&Diagnostic)> = - AtomicRef::new(&(default_track_diagnostic as fn(&_))); +pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> = + AtomicRef::new(&(default_track_diagnostic as _)); #[derive(Copy, Clone, Default)] pub struct HandlerFlags { @@ -507,7 +505,11 @@ impl Drop for HandlerInner { if !self.has_errors() { let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new()); - self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + self.flush_delayed( + bugs, + "no errors encountered even though `delay_span_bug` issued", + ExplicitBug, + ); } // FIXME(eddyb) this explains what `delayed_good_path_bugs` are! @@ -520,6 +522,7 @@ impl Drop for HandlerInner { self.flush_delayed( bugs.into_iter().map(DelayedDiagnostic::decorate), "no warnings or errors encountered even though `delayed_good_path_bugs` issued", + GoodPathBug, ); } @@ -653,17 +656,19 @@ impl Handler { /// Retrieve a stashed diagnostic with `steal_diagnostic`. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { let mut inner = self.inner.borrow_mut(); - inner.stash((span, key), diag); + inner.stash((span.with_parent(None), key), diag); } /// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key. pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> { let mut inner = self.inner.borrow_mut(); - inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) + inner + .steal((span.with_parent(None), key)) + .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { - self.inner.borrow().stashed_diagnostics.get(&(span, key)).is_some() + self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some() } /// Emit all stashed diagnostics. @@ -1203,7 +1208,11 @@ impl Handler { pub fn flush_delayed(&self) { let mut inner = self.inner.lock(); let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new()); - inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + inner.flush_delayed( + bugs, + "no errors encountered even though `delay_span_bug` issued", + ExplicitBug, + ); } } @@ -1288,67 +1297,69 @@ impl HandlerInner { && !diagnostic.is_force_warn() { if diagnostic.has_future_breakage() { - (*TRACK_DIAGNOSTICS)(diagnostic); + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); } return None; } - (*TRACK_DIAGNOSTICS)(diagnostic); - if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) { + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); return None; } - if let Some(ref code) = diagnostic.code { - self.emitted_diagnostic_codes.insert(code.clone()); - } - - let already_emitted = |this: &mut Self| { - let mut hasher = StableHasher::new(); - diagnostic.hash(&mut hasher); - let diagnostic_hash = hasher.finish(); - !this.emitted_diagnostics.insert(diagnostic_hash) - }; + let mut guaranteed = None; + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| { + if let Some(ref code) = diagnostic.code { + self.emitted_diagnostic_codes.insert(code.clone()); + } - // Only emit the diagnostic if we've been asked to deduplicate or - // haven't already emitted an equivalent diagnostic. - if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { - debug!(?diagnostic); - debug!(?self.emitted_diagnostics); - let already_emitted_sub = |sub: &mut SubDiagnostic| { - debug!(?sub); - if sub.level != Level::OnceNote { - return false; - } + let already_emitted = |this: &mut Self| { let mut hasher = StableHasher::new(); - sub.hash(&mut hasher); + diagnostic.hash(&mut hasher); let diagnostic_hash = hasher.finish(); - debug!(?diagnostic_hash); - !self.emitted_diagnostics.insert(diagnostic_hash) + !this.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); - - self.emitter.emit_diagnostic(diagnostic); - if diagnostic.is_error() { - self.deduplicated_err_count += 1; - } else if let Warning(_) = diagnostic.level { - self.deduplicated_warn_count += 1; + // Only emit the diagnostic if we've been asked to deduplicate or + // haven't already emitted an equivalent diagnostic. + if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { + debug!(?diagnostic); + debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { + debug!(?sub); + if sub.level != Level::OnceNote { + return false; + } + let mut hasher = StableHasher::new(); + sub.hash(&mut hasher); + let diagnostic_hash = hasher.finish(); + debug!(?diagnostic_hash); + !self.emitted_diagnostics.insert(diagnostic_hash) + }; + + diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); + + self.emitter.emit_diagnostic(diagnostic); + if diagnostic.is_error() { + self.deduplicated_err_count += 1; + } else if let Warning(_) = diagnostic.level { + self.deduplicated_warn_count += 1; + } } - } - if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { - self.bump_lint_err_count(); + if diagnostic.is_error() { + if matches!(diagnostic.level, Level::Error { lint: true }) { + self.bump_lint_err_count(); + } else { + self.bump_err_count(); + } + + guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } else { - self.bump_err_count(); + self.bump_warn_count(); } + }); - Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - self.bump_warn_count(); - - None - } + guaranteed } fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { @@ -1580,6 +1591,7 @@ impl HandlerInner { &mut self, bugs: impl IntoIterator<Item = Diagnostic>, explanation: impl Into<DiagnosticMessage> + Copy, + panic_with: impl Any + Send + 'static, ) { let mut no_bugs = true; for mut bug in bugs { @@ -1607,7 +1619,7 @@ impl HandlerInner { // Panic with `ExplicitBug` to avoid "unexpected panic" messages. if !no_bugs { - panic::panic_any(ExplicitBug); + panic::panic_any(panic_with); } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ef50efb8125..93b3af4ab97 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -87,14 +87,14 @@ impl<'a> ExtCtxt<'a> { self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident))) } - pub fn ty_rptr( + pub fn ty_ref( &self, span: Span, ty: P<ast::Ty>, lifetime: Option<ast::Lifetime>, mutbl: ast::Mutability, ) -> P<ast::Ty> { - self.ty(span, ast::TyKind::Rptr(lifetime, self.ty_mt(ty, mutbl))) + self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl))) } pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> { @@ -626,7 +626,7 @@ impl<'a> ExtCtxt<'a> { // Builds `#[name = val]`. // - // Note: `span` is used for both the identifer and the value. + // Note: `span` is used for both the identifier and the value. pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { let g = &self.sess.parse_sess.attr_id_generator; attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e26c16dcd7e..5d47c1ed363 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -587,7 +587,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { .resolver .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment); - if self.cx.sess.opts.unstable_opts.incremental_relative_spans { + if self.cx.sess.opts.incremental_relative_spans() { for (invoc, _) in invocations.iter_mut() { let expn_id = invoc.expansion_data.id; let parent_def = self.cx.resolver.invocation_parent(expn_id); diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 197f056917f..3a38d7a9669 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -43,7 +43,7 @@ pub(super) fn failed_to_match_macro<'cx>( return result; } - let Some((token, label, remaining_matcher)) = tracker.best_failure else { + let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else { return DummyResult::any(sp); }; @@ -95,11 +95,24 @@ struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> { cx: &'a mut ExtCtxt<'cx>, remaining_matcher: Option<&'matcher MatcherLoc>, /// Which arm's failure should we report? (the one furthest along) - best_failure: Option<(Token, &'static str, MatcherLoc)>, + best_failure: Option<BestFailure>, root_span: Span, result: Option<Box<dyn MacResult + 'cx>>, } +struct BestFailure { + token: Token, + position_in_tokenstream: usize, + msg: &'static str, + remaining_matcher: MatcherLoc, +} + +impl BestFailure { + fn is_better_position(&self, position: usize) -> bool { + position > self.position_in_tokenstream + } +} + impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) { if self.remaining_matcher.is_none() @@ -119,18 +132,25 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, "should not collect detailed info for successful macro match", ); } - Failure(token, msg) => match self.best_failure { - Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {} - _ => { - self.best_failure = Some(( - token.clone(), + Failure(token, approx_position, msg) => { + debug!(?token, ?msg, "a new failure of an arm"); + + if self + .best_failure + .as_ref() + .map_or(true, |failure| failure.is_better_position(*approx_position)) + { + self.best_failure = Some(BestFailure { + token: token.clone(), + position_in_tokenstream: *approx_position, msg, - self.remaining_matcher + remaining_matcher: self + .remaining_matcher .expect("must have collected matcher already") .clone(), - )) + }) } - }, + } Error(err_sp, msg) => { let span = err_sp.substitute_dummy(self.root_span); self.cx.struct_span_err(span, msg).emit(); @@ -178,12 +198,12 @@ pub(super) fn emit_frag_parse_err( ); if !e.span.is_dummy() { // early end of macro arm (#52866) - e.replace_span_with(parser.token.span.shrink_to_hi()); + e.replace_span_with(parser.token.span.shrink_to_hi(), true); } } if e.span.is_dummy() { // Get around lack of span in error (#30128) - e.replace_span_with(site_span); + e.replace_span_with(site_span, true); if !parser.sess.source_map().is_imported(arm_span) { e.span_label(arm_span, "in this macro arm"); } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index d161868edce..df1c1834c1d 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -310,7 +310,8 @@ pub(crate) enum ParseResult<T> { Success(T), /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. - Failure(Token, &'static str), + /// The usize is the approximate position of the token in the input token stream. + Failure(Token, usize, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), ErrorReported(ErrorGuaranteed), @@ -455,6 +456,7 @@ impl TtParser { &mut self, matcher: &'matcher [MatcherLoc], token: &Token, + approx_position: usize, track: &mut T, ) -> Option<NamedParseResult> { // Matcher positions that would be valid if the macro invocation was over now. Only @@ -598,6 +600,7 @@ impl TtParser { token::Eof, if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() }, ), + approx_position, "missing tokens in macro arguments", ), }) @@ -627,7 +630,12 @@ impl TtParser { // Process `cur_mps` until either we have finished the input or we need to get some // parsing from the black-box parser done. - let res = self.parse_tt_inner(matcher, &parser.token, track); + let res = self.parse_tt_inner( + matcher, + &parser.token, + parser.approx_token_stream_pos(), + track, + ); if let Some(res) = res { return res; } @@ -642,6 +650,7 @@ impl TtParser { // parser: syntax error. return Failure( parser.token.clone(), + parser.approx_token_stream_pos(), "no rules expected this token in macro call", ); } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 3e6bc81f672..fbb806fe81b 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -326,8 +326,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( return Ok((i, named_matches)); } - Failure(_, _) => { - trace!("Failed to match arm, trying the next one"); + Failure(_, reached_position, _) => { + trace!(%reached_position, "Failed to match arm, trying the next one"); // Try the next arm. } Error(_, _) => { @@ -432,7 +432,7 @@ pub fn compile_declarative_macro( let argument_map = match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { Success(m) => m, - Failure(token, msg) => { + Failure(token, _, msg) => { let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e5348039edd..e2f30fb89b9 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -194,7 +194,7 @@ declare_features! ( /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), /// Allows `#[instruction_set(_)]` attribute. - (accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None), + (accepted, isa_attribute, "1.67.0", Some(74727), None), /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), @@ -240,7 +240,7 @@ declare_features! ( /// Allows specifying the bundle link modifier (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490), None), /// Allows specifying the verbatim link modifier - (accepted, native_link_modifiers_verbatim, "CURRENT_RUSTC_VERSION", Some(81490), None), + (accepted, native_link_modifiers_verbatim, "1.67.0", Some(81490), None), /// Allows specifying the whole-archive link modifier (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None), /// Allows using non lexical lifetimes (RFC 2094). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a616dd70f8e..beade4d44da 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -383,7 +383,7 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), /// Allows `dyn* Trait` objects. - (incomplete, dyn_star, "1.65.0", Some(91611), None), + (incomplete, dyn_star, "1.65.0", Some(102425), None), /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), /// Allows exhaustive pattern matching on types that contain uninhabited types. @@ -418,7 +418,7 @@ declare_features! ( /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), /// Allows referencing `Self` and projections in impl-trait. - (active, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None), + (active, impl_trait_projections, "1.67.0", Some(103532), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. @@ -505,7 +505,7 @@ declare_features! ( /// Allows lints part of the strict provenance effort. (active, strict_provenance, "1.61.0", Some(95228), None), /// Allows string patterns to dereference values to match them. - (active, string_deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121), None), + (active, string_deref_patterns, "1.67.0", Some(87121), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 91825c29258..034f06bb889 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -854,7 +854,11 @@ impl fmt::Debug for OwnerNodes<'_> { &self .nodes .iter_enumerated() - .map(|(id, parented_node)| (id, parented_node.as_ref().map(|node| node.parent))) + .map(|(id, parented_node)| { + let parented_node = parented_node.as_ref().map(|node| node.parent); + + debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})")) + }) .collect::<Vec<_>>(), ) .field("bodies", &self.bodies) @@ -2431,7 +2435,7 @@ impl<'hir> Ty<'hir> { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { final_ty = ty; } final_ty @@ -2588,7 +2592,7 @@ pub enum TyKind<'hir> { /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). - Rptr(&'hir Lifetime, MutTy<'hir>), + Ref(&'hir Lifetime, MutTy<'hir>), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(&'hir BareFnTy<'hir>), /// The never type (`!`). @@ -3609,16 +3613,19 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - // tidy-alphabetical-end - // FIXME: move the tidy directive to the end after the next bootstrap bump - #[cfg(bootstrap)] - static_assert_size!(TraitItem<'_>, 88); - #[cfg(not(bootstrap))] static_assert_size!(TraitItem<'_>, 80); - #[cfg(bootstrap)] - static_assert_size!(TraitItemKind<'_>, 48); - #[cfg(not(bootstrap))] static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); + // tidy-alphabetical-end +} + +fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { + struct DebugFn<F>(F); + impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(fmt) + } + } + DebugFn(f) } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 03bcaa69468..5d05adfb556 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,14 +1,21 @@ use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_span::{def_id::DefPathHash, HashStableContext}; -use std::fmt; +use std::fmt::{self, Debug}; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Encodable, Decodable)] pub struct OwnerId { pub def_id: LocalDefId, } +impl Debug for OwnerId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Example: DefId(0:1 ~ aa[7697]::{use#0}) + Debug::fmt(&self.def_id, f) + } +} + impl From<OwnerId> for HirId { fn from(owner: OwnerId) -> HirId { HirId { owner, local_id: ItemLocalId::from_u32(0) } @@ -60,7 +67,7 @@ impl<CTX: HashStableContext> ToStableHashKey<CTX> for OwnerId { /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Encodable, Decodable, HashStable_Generic)] #[rustc_pass_by_value] pub struct HirId { @@ -68,6 +75,14 @@ pub struct HirId { pub local_id: ItemLocalId, } +impl Debug for HirId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10) + // Don't use debug_tuple to always keep this on one line. + write!(f, "HirId({:?}.{:?})", self.owner, self.local_id) + } +} + impl HirId { /// Signal local id which should never be used. pub const INVALID: HirId = diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 938ace2c785..6c475b659eb 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -809,7 +809,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { match typ.kind { TyKind::Slice(ref ty) => visitor.visit_ty(ty), TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty), - TyKind::Rptr(ref lifetime, ref mutable_type) => { + TyKind::Ref(ref lifetime, ref mutable_type) => { visitor.visit_lifetime(lifetime); visitor.visit_ty(mutable_type.ty) } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6f0c5d36a5f..d7ab942665b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2657,7 +2657,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Ptr(ref mt) => { tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) } - hir::TyKind::Rptr(ref region, ref mt) => { + hir::TyKind::Ref(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); let t = self.ast_ty_to_ty_inner(mt.ty, true, false); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a714663741b..28cd18bbb8e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,8 +1,8 @@ use crate::check::intrinsicck::InlineAsmCtxt; use crate::errors::LinkageType; -use super::compare_method::check_type_bounds; -use super::compare_method::{compare_impl_method, compare_ty_impl}; +use super::compare_impl_item::check_type_bounds; +use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; @@ -468,7 +468,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( + let _ = infcx.check_region_obligations_and_report_errors( defining_use_anchor, &outlives_environment, ); @@ -774,7 +774,7 @@ fn check_impl_items_against_trait<'tcx>( let impl_item_full = tcx.hir().impl_item(impl_item.id); match impl_item_full.kind { hir::ImplItemKind::Const(..) => { - let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( + let _ = tcx.compare_impl_const(( impl_item.id.owner_id.def_id, ty_impl_item.trait_item_def_id.unwrap(), )); @@ -791,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( } hir::ImplItemKind::Type(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); - compare_ty_impl( + compare_impl_ty( tcx, &ty_impl_item, impl_ty.span, @@ -1060,10 +1060,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if adt.variants().len() != 1 { bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did()); - if adt.variants().is_empty() { - // Don't bother checking the fields. No variants (and thus no fields) exist. - return; - } + // Don't bother checking the fields. + return; } // For each field, figure out if it's known to be a ZST and align(1), with "known" diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index c6bda9b4641..a767338ab85 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -34,7 +34,7 @@ use std::iter; /// - `impl_m_span`: span to use for reporting errors /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation -pub(crate) fn compare_impl_method<'tcx>( +pub(super) fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, trait_m: &ty::AssocItem, @@ -71,7 +71,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment( + if let Err(_) = compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -150,7 +150,7 @@ pub(crate) fn compare_impl_method<'tcx>( /// Finally we register each of these predicates as an obligation and check that /// they hold. #[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))] -fn compare_predicate_entailment<'tcx>( +fn compare_method_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, impl_m_span: Span, @@ -337,7 +337,7 @@ fn compare_predicate_entailment<'tcx>( if !errors.is_empty() { match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -374,7 +374,7 @@ fn compare_predicate_entailment<'tcx>( // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors` match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -407,7 +407,7 @@ enum CheckImpliedWfMode { /// re-check with `Skip`, and emit a lint if it succeeds. Check, /// Skips checking implied well-formedness of the impl method, but will emit - /// a lint if the `compare_predicate_entailment` succeeded. This means that + /// a lint if the `compare_method_predicate_entailment` succeeded. This means that /// the reason that we had failed earlier during `Check` was due to the impl /// having stronger requirements than the trait. Skip, @@ -441,8 +441,41 @@ fn compare_asyncness<'tcx>( Ok(()) } +/// Given a method def-id in an impl, compare the method signature of the impl +/// against the trait that it's implementing. In doing so, infer the hidden types +/// that this method's signature provides to satisfy each return-position `impl Trait` +/// in the trait signature. +/// +/// The method is also responsible for making sure that the hidden types for each +/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer +/// `impl Trait = Foo`, that `Foo: Trait` holds. +/// +/// For example, given the sample code: +/// +/// ``` +/// #![feature(return_position_impl_trait_in_trait)] +/// +/// use std::ops::Deref; +/// +/// trait Foo { +/// fn bar() -> impl Deref<Target = impl Sized>; +/// // ^- RPITIT #1 ^- RPITIT #2 +/// } +/// +/// impl Foo for () { +/// fn bar() -> Box<String> { Box::new(String::new()) } +/// } +/// ``` +/// +/// The hidden types for the RPITITs in `bar` would be inferred to: +/// * `impl Deref` (RPITIT #1) = `Box<String>` +/// * `impl Sized` (RPITIT #2) = `String` +/// +/// The relationship between these two types is straightforward in this case, but +/// may be more tenuously connected via other `impl`s and normalization rules for +/// cases of more complicated nested RPITITs. #[instrument(skip(tcx), level = "debug", ret)] -pub fn collect_trait_impl_trait_tys<'tcx>( +pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> { @@ -550,13 +583,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from - // `compare_predicate_entailment`. + // `compare_method_predicate_entailment`. match ocx.eq(&cause, param_env, trait_fty, impl_fty) { Ok(()) => {} Err(terr) => { - // This function gets called during `compare_predicate_entailment` when normalizing a + // This function gets called during `compare_method_predicate_entailment` when normalizing a // signature that contains RPITIT. When the method signatures don't match, we have to - // emit an error now because `compare_predicate_entailment` will not report the error + // emit an error now because `compare_method_predicate_entailment` will not report the error // when normalization fails. let emitted = report_trait_method_mismatch( infcx, @@ -589,7 +622,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( infcx.check_region_obligations_and_report_errors( impl_m.def_id.expect_local(), &outlives_environment, - ); + )?; let mut collected_tys = FxHashMap::default(); for (def_id, (ty, substs)) in collector.types { @@ -1516,8 +1549,8 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead -pub(crate) fn raw_compare_const_impl( +/// Use `tcx.compare_impl_const` instead +pub(super) fn compare_impl_const_raw( tcx: TyCtxt<'_>, (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), ) -> Result<(), ErrorGuaranteed> { @@ -1617,13 +1650,13 @@ pub(crate) fn raw_compare_const_impl( return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); } - // FIXME return `ErrorReported` if region obligations error? let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment); + infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; + Ok(()) } -pub(crate) fn compare_ty_impl<'tcx>( +pub(super) fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: &ty::AssocItem, impl_ty_span: Span, @@ -1645,7 +1678,7 @@ pub(crate) fn compare_ty_impl<'tcx>( })(); } -/// The equivalent of [compare_predicate_entailment], but for associated types +/// The equivalent of [compare_method_predicate_entailment], but for associated types /// instead of associated functions. fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, @@ -1730,7 +1763,7 @@ fn compare_type_predicate_entailment<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; Ok(()) } @@ -1749,7 +1782,7 @@ fn compare_type_predicate_entailment<'tcx>( /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. #[instrument(level = "debug", skip(tcx))] -pub fn check_type_bounds<'tcx>( +pub(super) fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, @@ -1944,7 +1977,7 @@ pub fn check_type_bounds<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); for (key, value) in constraints { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index ed2aed293a7..382c3f52945 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -63,7 +63,7 @@ a type parameter). */ mod check; -mod compare_method; +mod compare_impl_item; pub mod dropck; pub mod intrinsic; pub mod intrinsicck; @@ -94,7 +94,7 @@ use std::num::NonZeroU32; use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; -use self::compare_method::collect_trait_impl_trait_tys; +use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys; use self::region::region_scope_tree; pub fn provide(providers: &mut Providers) { @@ -103,8 +103,8 @@ pub fn provide(providers: &mut Providers) { adt_destructor, check_mod_item_types, region_scope_tree, - collect_trait_impl_trait_tys, - compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl, + collect_return_position_impl_trait_in_trait_tys, + compare_impl_const: compare_impl_item::compare_impl_const_raw, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4f27068429c..0d1aa39c5d9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -115,7 +115,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -291,7 +291,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { // Do some rudimentary sanity checking to avoid an ICE later (issue #83471). if let Some(hir::FnSig { decl, span, .. }) = method_sig { if let [self_ty, _] = decl.inputs { - if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) { + if !matches!(self_ty.kind, hir::TyKind::Ref(_, _)) { tcx.sess .struct_span_err( self_ty.span, diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 2790d91572b..bfedf63da97 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -325,7 +325,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -565,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c6d4aeefc80..e8b3f139623 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -53,7 +53,7 @@ fn do_orphan_check_impl<'tcx>( sp, item.span, tr.path.span, - trait_ref.self_ty(), + trait_ref, impl_.self_ty.span, &impl_.generics, err, @@ -154,11 +154,12 @@ fn emit_orphan_check_error<'tcx>( sp: Span, full_impl_span: Span, trait_span: Span, - self_ty: Ty<'tcx>, + trait_ref: ty::TraitRef<'tcx>, self_ty_span: Span, generics: &hir::Generics<'tcx>, err: traits::OrphanCheckErr<'tcx>, ) -> Result<!, ErrorGuaranteed> { + let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { let msg = match self_ty.kind() { @@ -187,7 +188,14 @@ fn emit_orphan_check_error<'tcx>( let msg = |ty: &str, postfix: &str| { format!("{ty} is not defined in the current crate{postfix}") }; - let this = |name: &str| msg("this", &format!(" because {name} are always foreign")); + + let this = |name: &str| { + if !trait_ref.def_id.is_local() && !is_target_ty { + msg("this", &format!(" because this is a foreign trait")) + } else { + msg("this", &format!(" because {name} are always foreign")) + } + }; let msg = match &ty.kind() { ty::Slice(_) => this("slices"), ty::Array(..) => this("arrays"), diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b7d599f57fd..1ff7429e415 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -24,6 +24,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -31,7 +33,9 @@ use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyC use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use rustc_trait_selection::traits::ObligationCtxt; use std::iter; mod generics_of; @@ -1059,7 +1063,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _)) } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), - Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), + Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args), Path(hir::QPath::TypeRelative(ty, segment)) => { is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args) @@ -1224,7 +1228,17 @@ fn infer_return_ty_for_fn_sig<'tcx>( // to prevent the user from getting a papercut while trying to use the unique closure // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); - diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); + diag.note( + "for more information on `Fn` traits and closure types, see \ + https://doc.rust-lang.org/book/ch13-01-closures.html", + ); + } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) { + diag.span_suggestion( + ty.span, + "replace with an appropriate return type", + format!("impl Iterator<Item = {}>", i_ty), + Applicability::MachineApplicable, + ); } diag.emit(); @@ -1242,6 +1256,51 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } +fn suggest_impl_iterator<'tcx>( + tcx: TyCtxt<'tcx>, + ret_ty: Ty<'tcx>, + span: Span, + hir_id: hir::HirId, + def_id: LocalDefId, +) -> Option<Ty<'tcx>> { + let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; }; + let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; }; + if !tcx + .infer_ctxt() + .build() + .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id)) + .must_apply_modulo_regions() + { + return None; + } + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new_in_snapshot(&infcx); + // Find the type of `Iterator::Item`. + let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; + let ty_var = infcx.next_ty_var(origin); + let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( + ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())), + term: ty_var.into(), + }, + ))); + // Add `<ret_ty as Iterator>::Item = _` obligation. + ocx.register_obligation(crate::traits::Obligation::misc( + tcx, + span, + hir_id, + tcx.param_env(def_id), + projection, + )); + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(ty_var) + && item_ty.is_suggestable(tcx, false) + { + return Some(item_ty); + } + None +} + fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id.expect_local()); diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index b63a8ef698d..fb519d6731d 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -617,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { LifetimeName::Error => {} } } - hir::TyKind::Rptr(ref lifetime_ref, ref mt) => { + hir::TyKind::Ref(ref lifetime_ref, ref mt) => { self.visit_lifetime(lifetime_ref); let scope = Scope::ObjectLifetimeDefault { lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index b678990f94e..4bd55a54831 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,6 +5,7 @@ use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; @@ -907,10 +908,10 @@ fn infer_placeholder_type<'a>( Applicability::MachineApplicable, ); } else { - err.span_note( + with_forced_trimmed_paths!(err.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty), - ); + &format!("however, the inferred type `{ty}` cannot be named"), + )); } } @@ -931,10 +932,10 @@ fn infer_placeholder_type<'a>( Applicability::MaybeIncorrect, ); } else { - diag.span_note( + with_forced_trimmed_paths!(diag.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty), - ); + &format!("however, the inferred type `{ty}` cannot be named"), + )); } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index ac60f085304..1aae9e0bd20 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -181,7 +181,7 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 29a6902ccb0..24a67cc14c4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -307,7 +307,7 @@ impl<'a> State<'a> { self.word("*"); self.print_mt(mt, true); } - hir::TyKind::Rptr(ref lifetime, ref mt) => { + hir::TyKind::Ref(ref lifetime, ref mt) => { self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index af14ee08a99..829913d278d 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -241,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some(ok) = self.lookup_method_in_trait( - call_expr.span, + self.misc(call_expr.span), method_name, trait_def_id, adjusted_ty, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index b0cd4a16e98..3fb14e31ea1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -171,6 +171,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Just ignore error types. if a.references_error() || b.references_error() { + // Best-effort try to unify these types -- we're already on the error path, + // so this will have the side-effect of making sure we have no ambiguities + // due to `[type error]` and `_` not coercing together. + let _ = self.commit_if_ok(|_| self.at(&self.cause, self.param_env).eq(a, b)); return success(vec![], self.fcx.tcx.ty_error(), vec![]); } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0335c45a946..1360383a75a 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -74,6 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); + self.check_for_range_as_method_call(err, expr, expr_ty, expected); } /// Requires that the two types unify, and prints an error message if @@ -1607,4 +1608,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } } + + /// Identify when the user has written `foo..bar()` instead of `foo.bar()`. + pub fn check_for_range_as_method_call( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + checked_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) { + if !hir::is_range_literal(expr) { + return; + } + let hir::ExprKind::Struct( + hir::QPath::LangItem(LangItem::Range, ..), + [start, end], + _, + ) = expr.kind else { return; }; + let parent = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) { + // Ignore `Foo { field: a..Default::default() }` + return; + } + let mut expr = end.expr; + while let hir::ExprKind::MethodCall(_, rcvr, ..) = expr.kind { + // Getting to the root receiver and asserting it is a fn call let's us ignore cases in + // `src/test/ui/methods/issues/issue-90315.stderr`. + expr = rcvr; + } + let hir::ExprKind::Call(method_name, _) = expr.kind else { return; }; + let ty::Adt(adt, _) = checked_ty.kind() else { return; }; + if self.tcx.lang_items().range_struct() != Some(adt.did()) { + return; + } + if let ty::Adt(adt, _) = expected_ty.kind() + && self.tcx.lang_items().range_struct() == Some(adt.did()) + { + return; + } + // Check if start has method named end. + let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; }; + let [hir::PathSegment { ident, .. }] = p.segments else { return; }; + let self_ty = self.typeck_results.borrow().expr_ty(start.expr); + let Ok(_pick) = self.probe_for_name( + probe::Mode::MethodCall, + *ident, + probe::IsSuggestion(true), + self_ty, + expr.hir_id, + probe::ProbeScope::AllTraits, + ) else { return; }; + let mut sugg = "."; + let mut span = start.expr.span.between(end.expr.span); + if span.lo() + BytePos(2) == span.hi() { + // There's no space between the start, the range op and the end, suggest removal which + // will be more noticeable than the replacement of `..` with `.`. + span = span.with_lo(span.lo() + BytePos(1)); + sugg = ""; + } + err.span_suggestion_verbose( + span, + "you likely meant to write a method call instead of a range", + sugg, + Applicability::MachineApplicable, + ); + } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ae641b26eee..b8b4e873663 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0614, "type `{oprnd_t}` cannot be dereferenced", ); - let sp = tcx.sess.source_map().start_point(expr.span); + let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 877680053f0..d342d96a10f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1307,7 +1307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the initializer. if let Some(ref init) = decl.init { let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); - self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty); } // Does the expected pattern type originate from an expression and what is the span? @@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); let pat_ty = self.node_ty(decl.pat.hir_id); - self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); if let Some(blk) = decl.els { let previous_diverges = self.diverges.get(); @@ -1627,14 +1627,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, hir_id: hir::HirId, pat: &'tcx hir::Pat<'tcx>, - decl_ty: Ty<'tcx>, ty: Ty<'tcx>, ) { if ty.references_error() { // Override the types everywhere with `err()` to avoid knock on errors. - self.write_ty(hir_id, ty); - self.write_ty(pat.hir_id, ty); - let local_ty = LocalTy { decl_ty, revealed_ty: ty }; + let err = self.tcx.ty_error(); + self.write_ty(hir_id, err); + self.write_ty(pat.hir_id, err); + let local_ty = LocalTy { decl_ty: err, revealed_ty: err }; self.locals.borrow_mut().insert(hir_id, local_ty); self.locals.borrow_mut().insert(pat.hir_id, local_ty); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9a7d753e66b..322e11c978f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::{ TypeVisitable, }; use rustc_session::errors::ExprParenthesesNeeded; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; @@ -973,7 +974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut Diagnostic, expr: &hir::Expr<'_>, ) -> bool { - let sp = self.tcx.sess.source_map().start_point(expr.span); + let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); @@ -1259,6 +1260,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); true } + ExprKind::Lit(Spanned { + node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed), + span, + }) => { + let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; }; + if !(snippet.starts_with("0x") || snippet.starts_with("0X")) { + return false; + } + if snippet.len() <= 5 || !snippet.is_char_boundary(snippet.len() - 3) { + return false; + } + let (_, suffix) = snippet.split_at(snippet.len() - 3); + let value = match suffix { + "f32" => (lit - 0xf32) / (16 * 16 * 16), + "f64" => (lit - 0xf64) / (16 * 16 * 16), + _ => return false, + }; + err.span_suggestions( + expr.span, + "rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float", + [format!("0x{value:X} as {suffix}"), format!("{value}_{suffix}")], + Applicability::MaybeIncorrect, + ); + true + } _ => false, } } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index fddb8a458a7..b9b27e8627a 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -11,7 +11,7 @@ pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::errors::OpMethodGenericParams; -use crate::{Expectation, FnCtxt}; +use crate::FnCtxt; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; @@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(super) fn obligation_for_method( &self, - span: Span, + cause: ObligationCause<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, @@ -282,71 +282,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.var_for_def(span, param) - }); - - let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs); - - // Construct an obligation - let poly_trait_ref = ty::Binder::dummy(trait_ref); - ( - traits::Obligation::misc( - self.tcx, - span, - self.body_id, - self.param_env, - poly_trait_ref.without_const(), - ), - substs, - ) - } - - pub(super) fn obligation_for_op_method( - &self, - span: Span, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - opt_input_type: Option<Ty<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - expected: Expectation<'tcx>, - ) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>) - { - // Construct a trait-reference `self_ty : Trait<input_tys>` - let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { - match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} - GenericParamDefKind::Type { .. } => { - if param.index == 0 { - return self_ty.into(); - } else if let Some(input_type) = opt_input_type { - return input_type.into(); - } - } - } - self.var_for_def(span, param) + self.var_for_def(cause.span, param) }); let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs); // Construct an obligation let poly_trait_ref = ty::Binder::dummy(trait_ref); - let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty)); - ( traits::Obligation::new( self.tcx, - traits::ObligationCause::new( - span, - self.body_id, - traits::BinOp { - rhs_span: opt_input_expr.map(|expr| expr.span), - is_lit: opt_input_expr - .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty, - }, - ), + cause, self.param_env, - poly_trait_ref, + poly_trait_ref.without_const(), ), substs, ) @@ -357,55 +305,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// In particular, it doesn't really do any probing: it simply constructs /// an obligation for a particular trait with the given self type and checks /// whether that trait is implemented. - #[instrument(level = "debug", skip(self, span))] + #[instrument(level = "debug", skip(self))] pub(super) fn lookup_method_in_trait( &self, - span: Span, + cause: ObligationCause<'tcx>, m_name: Ident, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { let (obligation, substs) = - self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types); - self.construct_obligation_for_trait( - span, - m_name, - trait_def_id, - obligation, - substs, - None, - false, - ) - } - - pub(super) fn lookup_op_method_in_trait( - &self, - span: Span, - m_name: Ident, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - opt_input_type: Option<Ty<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - expected: Expectation<'tcx>, - ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { - let (obligation, substs) = self.obligation_for_op_method( - span, - trait_def_id, - self_ty, - opt_input_type, - opt_input_expr, - expected, - ); - self.construct_obligation_for_trait( - span, - m_name, - trait_def_id, - obligation, - substs, - opt_input_expr, - true, - ) + self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types); + self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs) } // FIXME(#18741): it seems likely that we can consolidate some of this @@ -413,13 +324,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // of this method is basically the same as confirmation. fn construct_obligation_for_trait( &self, - span: Span, m_name: Ident, trait_def_id: DefId, obligation: traits::PredicateObligation<'tcx>, substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - is_op: bool, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { debug!(?obligation); @@ -435,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let Some(method_item) = self.associated_value(trait_def_id, m_name) else { tcx.sess.delay_span_bug( - span, + obligation.cause.span, "operator trait does not have corresponding operator method", ); return None; @@ -461,24 +369,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // with bound regions. let fn_sig = tcx.bound_fn_sig(def_id); let fn_sig = fn_sig.subst(self.tcx, substs); - let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig); - - let cause = if is_op { - ObligationCause::new( - span, - self.body_id, - traits::BinOp { - rhs_span: opt_input_expr.map(|expr| expr.span), - is_lit: opt_input_expr - .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty: None, - }, - ) - } else { - traits::ObligationCause::misc(span, self.body_id) - }; + let fn_sig = + self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig); - let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(fn_sig); + let InferOk { value, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(fn_sig); let fn_sig = { obligations.extend(o); value @@ -494,7 +389,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // any late-bound regions appearing in its bounds. let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(bounds); + let InferOk { value, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(bounds); let bounds = { obligations.extend(o); value @@ -502,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(!bounds.has_escaping_bound_vars()); - let predicates_cause = cause.clone(); + let predicates_cause = obligation.cause.clone(); obligations.extend(traits::predicates_for_generics( move |_, _| predicates_cause.clone(), self.param_env, @@ -517,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); obligations.push(traits::Obligation::new( tcx, - cause, + obligation.cause, self.param_env, ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())), )); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6b3fa664d9c..1afaae0e020 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -973,6 +973,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); } else { debug_assert!(self.tcx.is_trait(trait_def_id)); + if self.tcx.trait_is_auto(trait_def_id) { + return; + } for item in self.impl_or_trait_item(trait_def_id) { // Check whether `trait_def_id` defines a method with suitable name. if !self.has_applicable_self(&item) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7c5a9a333fe..7053c180685 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -339,7 +339,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, item_name, rcvr_ty, cal, span, ); } - if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) { + if let Some(span) = + tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None)) + { err.span_suggestion( span.shrink_to_lo(), "you are looking for the module in `std`, not the primitive type", @@ -2306,6 +2308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } }) && (type_is_local || info.def_id.is_local()) + && !self.tcx.trait_is_auto(info.def_id) && self .associated_value(info.def_id, item_name) .filter(|item| { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9f0d175c4c6..78cea1f4d8d 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::FulfillmentError; +use rustc_trait_selection::traits::{self, FulfillmentError}; use rustc_type_ir::sty::TyKind::*; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -48,8 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -60,8 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -248,8 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( lhs_ty, - Some(rhs_ty_var), - Some(rhs_expr), + Some((rhs_expr, rhs_ty_var)), Op::Binary(op, is_assign), expected, ); @@ -382,8 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -410,8 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_compatible = |lhs_ty, rhs_ty| { self.lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -471,8 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let errors = self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -492,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(output_def_id) = output_def_id && let Some(trait_def_id) = trait_def_id && self.tcx.parent(output_def_id) == trait_def_id + && output_ty.is_suggestable(self.tcx, false) { Some(("Output", *output_ty)) } else { @@ -625,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method(operand_ty, None, None, Op::Unary(op, ex.span), expected) { + match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { self.write_method_call(ex.hir_id, method); method.sig.output() @@ -660,7 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let sp = self.tcx.sess.source_map().start_point(ex.span); + let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { @@ -712,8 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn lookup_op_method( &self, lhs_ty: Ty<'tcx>, - other_ty: Option<Ty<'tcx>>, - other_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>, op: Op, expected: Expectation<'tcx>, ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> { @@ -742,20 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Op::Unary(..) => 0, }, ) { + self.tcx + .sess + .delay_span_bug(span, "operator didn't have the right number of generic args"); return Err(vec![]); } let opname = Ident::with_dummy_span(opname); + let input_types = + opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default(); + let cause = self.cause( + span, + traits::BinOp { + rhs_span: opt_rhs.map(|(expr, _)| expr.span), + is_lit: opt_rhs + .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))), + output_ty: expected.only_has_type(self), + }, + ); + let method = trait_did.and_then(|trait_did| { - self.lookup_op_method_in_trait( - span, - opname, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ) + self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types)) }); match (method, trait_did) { @@ -766,14 +769,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (None, None) => Err(vec![]), (None, Some(trait_did)) => { - let (obligation, _) = self.obligation_for_op_method( - span, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ); + let (obligation, _) = + self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 0021fdd7f61..28e959b7c6a 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1921,7 +1921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let expected = self.shallow_resolve(expected); - let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) { + let (ref_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) { // `demand::subtype` would be good enough, but using `eqtype` turns // out to be equally general. See (note_1) for details. @@ -1936,9 +1936,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::TypeInference, span: inner.span, }); - let rptr_ty = self.new_ref_ty(pat.span, mutbl, inner_ty); - debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty); - let err = self.demand_eqtype_pat_diag(pat.span, expected, rptr_ty, ti); + let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty); + debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty); + let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti); // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` @@ -1946,7 +1946,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.borrow_pat_suggestion(&mut err, pat); err.emit(); } - (rptr_ty, inner_ty) + (ref_ty, inner_ty) } } } else { @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, err) }; self.check_pat(inner, inner_ty, def_bm, ti); - rptr_ty + ref_ty } /// Create a reference type with a fresh region variable. diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 952ea14887f..a0f048fc09b 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -225,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { imm_tr.and_then(|trait_did| { self.lookup_method_in_trait( - span, + self.misc(span), Ident::with_dummy_span(imm_op), trait_did, base_ty, @@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut_tr.and_then(|trait_did| { self.lookup_method_in_trait( - span, + self.misc(span), Ident::with_dummy_span(mut_op), trait_did, base_ty, diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index c4f11472d55..4430acf34db 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -369,8 +369,8 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { { let mut mk_suggestion = || { let ( - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, + hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, + hir::Ty { kind: hir::TyKind::Ref(lifetime_sup, _), .. }, ) = (self.ty_sub, self.ty_sup) else { return false; }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 96a976fb89e..7222eb77682 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -729,7 +729,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { format!("this and all prior arms are found to be of type `{}`", t), ); } - let outer_error_span = if any_multiline_arm { + let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) { // Cover just `match` and the scrutinee expression, not // the entire match body, to reduce diagram noise. cause.span.shrink_to_lo().to(scrut_span) @@ -737,7 +737,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause.span }; let msg = "`match` arms have incompatible types"; - err.span_label(outer_error_span, msg); + err.span_label(outer, msg); self.suggest_remove_semi_or_return_binding( err, prior_arm_block_id, @@ -1836,7 +1836,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter + // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index d8f540b7446..39f4d502259 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -96,8 +96,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } } - hir::TyKind::Rptr(ref lifetime, _) => { - // the lifetime of the TyRptr + hir::TyKind::Ref(ref lifetime, _) => { + // the lifetime of the Ref let hir_id = lifetime.hir_id; match (self.tcx.named_region(hir_id), self.bound_region) { // Find the index of the named region that was part of the diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 5d536e982ed..dc1dc898922 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -147,7 +147,7 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { match arg.kind { - hir::TyKind::Rptr(_, ref mut_ty) => { + hir::TyKind::Ref(_, ref mut_ty) => { // We don't want to suggest looking into borrowing `&T` or `&Self`. hir::intravisit::walk_ty(self, mut_ty.ty); return; diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index d2dffa4a0b7..d91ef882bc4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -2,11 +2,14 @@ use crate::errors::RegionOriginNote; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; use rustc_errors::{ - fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, }; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Region}; +use rustc_middle::ty::{self, IsSuggestable, Region}; +use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; @@ -313,55 +316,38 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); err } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self - .report_extra_impl_obligation( + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { + let mut err = self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, &format!("`{}: {}`", sup, sub), - ), + ); + // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause + if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) + && generics.where_clause_span.contains(span) + { + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); + } + err + } infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { let mut err = self.report_concrete_failure(*parent, sub, sup); - let trait_item_span = self.tcx.def_span(trait_item_def_id); let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); err.span_label( trait_item_span, format!("definition of `{}` from trait", item_name), ); - - let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); - let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); - - let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = - impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); - let clauses: Vec<_> = trait_predicates - .predicates - .into_iter() - .filter(|&(pred, _)| !impl_predicates.contains(pred)) - .map(|(pred, _)| format!("{}", pred)) - .collect(); - - if !clauses.is_empty() { - let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); - let where_clause_span = generics.tail_span_for_predicate_suggestion(); - - let suggestion = format!( - "{} {}", - generics.add_where_or_trailing_comma(), - clauses.join(", "), - ); - err.span_suggestion( - where_clause_span, - &format!( - "try copying {} from the trait", - if clauses.len() > 1 { "these clauses" } else { "this clause" } - ), - suggestion, - rustc_errors::Applicability::MaybeIncorrect, - ); - } - + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); err } infer::AscribeUserTypeProvePredicate(span) => { @@ -388,6 +374,65 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } + pub fn suggest_copy_trait_method_bounds( + &self, + trait_item_def_id: DefId, + impl_item_def_id: LocalDefId, + err: &mut Diagnostic, + ) { + // FIXME(compiler-errors): Right now this is only being used for region + // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, + // but right now it's not really very smart when it comes to implicit `Sized` + // predicates and bounds on the trait itself. + + let Some(impl_def_id) = + self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; }; + let Some(trait_ref) = self + .tcx + .impl_trait_ref(impl_def_id) + else { return; }; + let trait_substs = trait_ref + // Replace the explicit self type with `Self` for better suggestion rendering + .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) + .substs; + let trait_item_substs = + ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id.to_def_id()) + .rebase_onto(self.tcx, impl_def_id, trait_substs); + + let Ok(trait_predicates) = self + .tcx + .bound_explicit_predicates_of(trait_item_def_id) + .map_bound(|p| p.predicates) + .subst_iter_copied(self.tcx, trait_item_substs) + .map(|(pred, _)| { + if pred.is_suggestable(self.tcx, false) { + Ok(pred.to_string()) + } else { + Err(()) + } + }) + .collect::<Result<Vec<_>, ()>>() else { return; }; + + let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; }; + + if trait_predicates.is_empty() { + err.span_suggestion_verbose( + generics.where_clause_span, + "remove the `where` clause", + String::new(), + Applicability::MachineApplicable, + ); + } else { + let space = if generics.where_clause_span.is_empty() { " " } else { "" }; + err.span_suggestion_verbose( + generics.where_clause_span, + "copy the `where` clause predicates from the trait", + format!("{space}where {}", trait_predicates.join(", ")), + Applicability::MachineApplicable, + ); + } + } + pub(super) fn report_placeholder_failure( &self, placeholder_origin: SubregionOrigin<'tcx>, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs deleted file mode 100644 index 41b115f3377..00000000000 --- a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs +++ /dev/null @@ -1,427 +0,0 @@ -use crate::errors::RegionOriginNote; -use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; -use crate::infer::{self, SubregionOrigin}; -use rustc_errors::{ - fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, -}; -use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Region}; - -use super::ObligationCauseAsDiagArg; - -impl<'tcx> TypeErrCtxt<'_, 'tcx> { - pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { - match *origin { - infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { - span: trace.cause.span, - requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values), - } - .add_to_diagnostic(err), - infer::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err) - } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - RegionOriginNote::WithName { - span, - msg: fluent::infer_reborrow, - name: &var_name.to_string(), - continues: false, - } - .add_to_diagnostic(err); - } - infer::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } - .add_to_diagnostic(err); - } - infer::DataBorrowed(ty, span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_data_borrowed, - name: &self.ty_to_string(ty), - continues: false, - } - .add_to_diagnostic(err); - } - infer::ReferenceOutlivesReferent(ty, span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_reference_outlives_referent, - name: &self.ty_to_string(ty), - continues: false, - } - .add_to_diagnostic(err); - } - infer::RelateParamBound(span, ty, opt_span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_relate_param_bound, - name: &self.ty_to_string(ty), - continues: opt_span.is_some(), - } - .add_to_diagnostic(err); - if let Some(span) = opt_span { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } - .add_to_diagnostic(err); - } - } - infer::RelateRegionParamBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } - .add_to_diagnostic(err); - } - infer::CompareImplItemObligation { span, .. } => { - RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } - .add_to_diagnostic(err); - } - infer::CheckAssociatedTypeBounds { ref parent, .. } => { - self.note_region_origin(err, &parent); - } - infer::AscribeUserTypeProvePredicate(span) => { - RegionOriginNote::Plain { - span, - msg: fluent::infer_ascribe_user_type_prove_predicate, - } - .add_to_diagnostic(err); - } - } - } - - pub(super) fn report_concrete_failure( - &self, - origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - match origin { - infer::Subtype(box trace) => { - let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - let mut err = self.report_and_explain_type_error(trace, terr); - match (*sub, *sup) { - (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} - (ty::RePlaceholder(_), _) => { - note_and_explain_region( - self.tcx, - &mut err, - "", - sup, - " doesn't meet the lifetime requirements", - None, - ); - } - (_, ty::RePlaceholder(_)) => { - note_and_explain_region( - self.tcx, - &mut err, - "the required lifetime does not necessarily outlive ", - sub, - "", - None, - ); - } - _ => { - note_and_explain_region(self.tcx, &mut err, "", sup, "...", None); - note_and_explain_region( - self.tcx, - &mut err, - "...does not necessarily outlive ", - sub, - "", - None, - ); - } - } - err - } - infer::Reborrow(span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0312, - "lifetime of reference outlives lifetime of borrowed content..." - ); - note_and_explain_region( - self.tcx, - &mut err, - "...the reference is valid for ", - sub, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "...but the borrowed content is only valid for ", - sup, - "", - None, - ); - err - } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0313, - "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", - var_name - ); - note_and_explain_region( - self.tcx, - &mut err, - "...the borrowed pointer is valid for ", - sub, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - &format!("...but `{}` is only valid for ", var_name), - sup, - "", - None, - ); - err - } - infer::RelateObjectBound(span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0476, - "lifetime of the source pointer does not outlive lifetime bound of the \ - object type" - ); - note_and_explain_region( - self.tcx, - &mut err, - "object type is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "source pointer is only valid for ", - sup, - "", - None, - ); - err - } - infer::RelateParamBound(span, ty, opt_span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0477, - "the type `{}` does not fulfill the required lifetime", - self.ty_to_string(ty) - ); - match *sub { - ty::ReStatic => note_and_explain_region( - self.tcx, - &mut err, - "type must satisfy ", - sub, - if opt_span.is_some() { " as required by this binding" } else { "" }, - opt_span, - ), - _ => note_and_explain_region( - self.tcx, - &mut err, - "type must outlive ", - sub, - if opt_span.is_some() { " as required by this binding" } else { "" }, - opt_span, - ), - } - err - } - infer::RelateRegionParamBound(span) => { - let mut err = - struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - note_and_explain_region( - self.tcx, - &mut err, - "lifetime parameter instantiated with ", - sup, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but lifetime parameter must outlive ", - sub, - "", - None, - ); - err - } - infer::DataBorrowed(ty, span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0490, - "a value of type `{}` is borrowed for too long", - self.ty_to_string(ty) - ); - note_and_explain_region( - self.tcx, - &mut err, - "the type is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but the borrow lasts for ", - sup, - "", - None, - ); - err - } - infer::ReferenceOutlivesReferent(ty, span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0491, - "in type `{}`, reference has a longer lifetime than the data it references", - self.ty_to_string(ty) - ); - note_and_explain_region( - self.tcx, - &mut err, - "the pointer is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but the referenced data is only valid for ", - sup, - "", - None, - ); - err - } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self - .report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ), - infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { - let mut err = self.report_concrete_failure(*parent, sub, sup); - - let trait_item_span = self.tcx.def_span(trait_item_def_id); - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label( - trait_item_span, - format!("definition of `{}` from trait", item_name), - ); - - let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); - let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); - - let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = - impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); - let clauses: Vec<_> = trait_predicates - .predicates - .into_iter() - .filter(|&(pred, _)| !impl_predicates.contains(pred)) - .map(|(pred, _)| format!("{}", pred)) - .collect(); - - if !clauses.is_empty() { - let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); - let where_clause_span = generics.tail_span_for_predicate_suggestion(); - - let suggestion = format!( - "{} {}", - generics.add_where_or_trailing_comma(), - clauses.join(", "), - ); - err.span_suggestion( - where_clause_span, - &format!( - "try copying {} from the trait", - if clauses.len() > 1 { "these clauses" } else { "this clause" } - ), - suggestion, - rustc_errors::Applicability::MaybeIncorrect, - ); - } - - err - } - infer::AscribeUserTypeProvePredicate(span) => { - let mut err = - struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - note_and_explain_region( - self.tcx, - &mut err, - "lifetime instantiated with ", - sup, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but lifetime must outlive ", - sub, - "", - None, - ); - err - } - } - } - - pub(super) fn report_placeholder_failure( - &self, - placeholder_origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - // I can't think how to do better than this right now. -nikomatsakis - debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); - match placeholder_origin { - infer::Subtype(box ref trace) - if matches!( - &trace.cause.code().peel_derives(), - ObligationCauseCode::BindingObligation(..) - | ObligationCauseCode::ExprBindingObligation(..) - ) => - { - // Hack to get around the borrow checker because trace.cause has an `Rc`. - if let ObligationCauseCode::BindingObligation(_, span) - | ObligationCauseCode::ExprBindingObligation(_, span, ..) = - &trace.cause.code().peel_derives() - { - let span = *span; - let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); - err.span_note(span, "the lifetime requirement is introduced here"); - err - } else { - unreachable!() - } - } - infer::Subtype(box trace) => { - let terr = TypeError::RegionsPlaceholderMismatch; - return self.report_and_explain_type_error(trace, terr); - } - _ => return self.report_concrete_failure(placeholder_origin, sub, sup), - } - } -} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a9ef91db059..b17a465eb38 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1693,7 +1693,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option<ErrorGuaranteed> { + ) -> Result<(), ErrorGuaranteed> { let errors = self.resolve_regions(outlives_env); if let None = self.tainted_by_errors() { @@ -1705,9 +1705,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_region_errors(generic_param_scope, &errors); } - (!errors.is_empty()).then(|| { - self.tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted") - }) + if errors.is_empty() { + Ok(()) + } else { + Err(self + .tcx + .sess + .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")) + } } // [Note-Type-error-reporting] diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs deleted file mode 100644 index 2ccbd164faa..00000000000 --- a/compiler/rustc_infer/src/infer/note.rs +++ /dev/null @@ -1,203 +0,0 @@ -impl<'tcx> TypeErrCtxt<'_, 'tcx> { - fn note_error_origin( - &self, - err: &mut Diagnostic, - cause: &ObligationCause<'tcx>, - exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, - terr: TypeError<'tcx>, - ) { - match *cause.code() { - ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { - let ty = self.resolve_vars_if_possible(root_ty); - if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))) - { - // don't show type `_` - if span.desugaring_kind() == Some(DesugaringKind::ForLoop) - && let ty::Adt(def, substs) = ty.kind() - && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) - { - err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0))); - } else { - err.span_label(span, format!("this expression has type `{}`", ty)); - } - } - if let Some(ty::error::ExpectedFound { found, .. }) = exp_found - && ty.is_box() && ty.boxed_ty() == found - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - { - err.span_suggestion( - span, - "consider dereferencing the boxed value", - format!("*{}", snippet), - Applicability::MachineApplicable, - ); - } - } - ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { - err.span_label(span, "expected due to this"); - } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - arm_block_id, - arm_span, - arm_ty, - prior_arm_block_id, - prior_arm_span, - prior_arm_ty, - source, - ref prior_arms, - scrut_hir_id, - opt_suggest_box_span, - scrut_span, - .. - }) => match source { - hir::MatchSource::TryDesugar => { - if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found { - let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id); - let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind { - let arg_expr = args.first().expect("try desugaring call w/out arg"); - self.typeck_results.as_ref().and_then(|typeck_results| { - typeck_results.expr_ty_opt(arg_expr) - }) - } else { - bug!("try desugaring w/out call expr as scrutinee"); - }; - - match scrut_ty { - Some(ty) if expected == ty => { - let source_map = self.tcx.sess.source_map(); - err.span_suggestion( - source_map.end_point(cause.span), - "try removing this `?`", - "", - Applicability::MachineApplicable, - ); - } - _ => {} - } - } - } - _ => { - // `prior_arm_ty` can be `!`, `expected` will have better info when present. - let t = self.resolve_vars_if_possible(match exp_found { - Some(ty::error::ExpectedFound { expected, .. }) => expected, - _ => prior_arm_ty, - }); - let source_map = self.tcx.sess.source_map(); - let mut any_multiline_arm = source_map.is_multiline(arm_span); - if prior_arms.len() <= 4 { - for sp in prior_arms { - any_multiline_arm |= source_map.is_multiline(*sp); - err.span_label(*sp, format!("this is found to be of type `{}`", t)); - } - } else if let Some(sp) = prior_arms.last() { - any_multiline_arm |= source_map.is_multiline(*sp); - err.span_label( - *sp, - format!("this and all prior arms are found to be of type `{}`", t), - ); - } - let outer_error_span = if any_multiline_arm { - // Cover just `match` and the scrutinee expression, not - // the entire match body, to reduce diagram noise. - cause.span.shrink_to_lo().to(scrut_span) - } else { - cause.span - }; - let msg = "`match` arms have incompatible types"; - err.span_label(outer_error_span, msg); - self.suggest_remove_semi_or_return_binding( - err, - prior_arm_block_id, - prior_arm_ty, - prior_arm_span, - arm_block_id, - arm_ty, - arm_span, - ); - if let Some(ret_sp) = opt_suggest_box_span { - // Get return type span and point to it. - self.suggest_boxing_for_return_impl_trait( - err, - ret_sp, - prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s), - ); - } - } - }, - ObligationCauseCode::IfExpression(box IfExpressionCause { - then_id, - else_id, - then_ty, - else_ty, - outer_span, - opt_suggest_box_span, - }) => { - let then_span = self.find_block_span_from_hir_id(then_id); - let else_span = self.find_block_span_from_hir_id(else_id); - err.span_label(then_span, "expected because of this"); - if let Some(sp) = outer_span { - err.span_label(sp, "`if` and `else` have incompatible types"); - } - self.suggest_remove_semi_or_return_binding( - err, - Some(then_id), - then_ty, - then_span, - Some(else_id), - else_ty, - else_span, - ); - if let Some(ret_sp) = opt_suggest_box_span { - self.suggest_boxing_for_return_impl_trait( - err, - ret_sp, - [then_span, else_span].into_iter(), - ); - } - } - ObligationCauseCode::LetElse => { - err.help("try adding a diverging expression, such as `return` or `panic!(..)`"); - err.help("...or use `match` instead of `let...else`"); - } - _ => { - if let ObligationCauseCode::BindingObligation(_, span) - | ObligationCauseCode::ExprBindingObligation(_, span, ..) - = cause.code().peel_derives() - && let TypeError::RegionsPlaceholderMismatch = terr - { - err.span_note( * span, - "the lifetime requirement is introduced here"); - } - } - } - } -} - -impl<'tcx> InferCtxt<'tcx> { - /// Given a [`hir::Block`], get the span of its last expression or - /// statement, peeling off any inner blocks. - pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { - let block = block.innermost_block(); - if let Some(expr) = &block.expr { - expr.span - } else if let Some(stmt) = block.stmts.last() { - // possibly incorrect trailing `;` in the else arm - stmt.span - } else { - // empty block; point at its entirety - block.span - } - } - - /// Given a [`hir::HirId`] for a block, get the span of its last expression - /// or statement, peeling off any inner blocks. - pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { - match self.tcx.hir().get(hir_id) { - hir::Node::Block(blk) => self.find_block_span(blk), - // The parser was in a weird state if either of these happen, but - // it's better not to panic. - hir::Node::Expr(e) => e.span, - _ => rustc_span::DUMMY_SP, - } - } -} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 47bd1564f08..f71c39dc0d2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option<ErrorGuaranteed> { + ) -> Result<(), ErrorGuaranteed> { self.process_registered_region_obligations( outlives_env.region_bound_pairs(), outlives_env.param_env, diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 76442de69d3..ee0552d77ce 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -10,6 +10,7 @@ //! origin crate when the `TyCtxt` is not present in TLS. use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; +use rustc_middle::dep_graph::TaskDepsRef; use rustc_middle::ty::tls; use std::fmt; @@ -26,14 +27,22 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { /// This is a callback from `rustc_ast` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. -fn track_diagnostic(diagnostic: &Diagnostic) { +fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics { let mut diagnostics = diagnostics.lock(); diagnostics.extend(Some(diagnostic.clone())); + std::mem::drop(diagnostics); } + + // Diagnostics are tracked, we can ignore the dependency. + let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; + return tls::enter_context(&icx, move |_| (*f)(diagnostic)); } + + // In any other case, invoke diagnostics anyway. + (*f)(diagnostic); }) } @@ -55,5 +64,5 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> pub fn setup_callbacks() { rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); - TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); + TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ff2196d5857..eb3baba999b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -652,7 +652,6 @@ fn test_unstable_options_tracking_hash() { untracked!(future_incompat_test, true); untracked!(hir_stats, true); untracked!(identify_regions, true); - untracked!(incremental_ignore_spans, true); untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); @@ -737,6 +736,7 @@ fn test_unstable_options_tracking_hash() { tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); + tracked!(incremental_ignore_spans, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 50d6d5b9bab..4c65fca29b8 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -851,7 +851,7 @@ impl Cursor<'_> { } // Eats the identifier. Note: succeeds on `_`, which isn't a valid - // identifer. + // identifier. fn eat_identifier(&mut self) { if !is_id_start(self.first()) { return; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d6de6e70ead..cdb901b7f86 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2184,6 +2184,7 @@ impl ExplicitOutlivesRequirements { tcx: TyCtxt<'tcx>, bounds: &hir::GenericBounds<'_>, inferred_outlives: &[ty::Region<'tcx>], + predicate_span: Span, ) -> Vec<(usize, Span)> { use rustc_middle::middle::resolve_lifetime::Region; @@ -2191,23 +2192,28 @@ impl ExplicitOutlivesRequirements { .iter() .enumerate() .filter_map(|(i, bound)| { - if let hir::GenericBound::Outlives(lifetime) = bound { - let is_inferred = match tcx.named_region(lifetime.hir_id) { - Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| { - if let ty::ReEarlyBound(ebr) = **r { - ebr.def_id == def_id - } else { - false - } - }), - _ => false, - }; - is_inferred.then_some((i, bound.span())) - } else { - None + let hir::GenericBound::Outlives(lifetime) = bound else { + return None; + }; + + let is_inferred = match tcx.named_region(lifetime.hir_id) { + Some(Region::EarlyBound(def_id)) => inferred_outlives + .iter() + .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), + _ => false, + }; + + if !is_inferred { + return None; } + + let span = bound.span().find_ancestor_inside(predicate_span)?; + if in_external_macro(tcx.sess, span) { + return None; + } + + Some((i, span)) }) - .filter(|(_, span)| !in_external_macro(tcx.sess, *span)) .collect() } @@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_lifetime::Region; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, ref hir_generics) - | hir::ItemKind::Enum(_, ref hir_generics) - | hir::ItemKind::Union(_, ref hir_generics) = item.kind + if let hir::ItemKind::Struct(_, hir_generics) + | hir::ItemKind::Enum(_, hir_generics) + | hir::ItemKind::Union(_, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let mut dropped_predicate_count = 0; let num_predicates = hir_generics.predicates.len(); for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { - let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate { - hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(region_def_id)) = - cx.tcx.named_region(predicate.lifetime.hir_id) - { - ( - Self::lifetimes_outliving_lifetime( - inferred_outlives, - region_def_id, - ), - &predicate.bounds, - predicate.span, - predicate.in_where_clause, - ) - } else { - continue; - } - } - hir::WherePredicate::BoundPredicate(predicate) => { - // FIXME we can also infer bounds on associated types, - // and should check for them here. - match predicate.bounded_ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { - let Res::Def(DefKind::TyParam, def_id) = path.res else { - continue - }; - let index = ty_generics.param_def_id_to_index[&def_id]; + let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = + match where_predicate { + hir::WherePredicate::RegionPredicate(predicate) => { + if let Some(Region::EarlyBound(region_def_id)) = + cx.tcx.named_region(predicate.lifetime.hir_id) + { ( - Self::lifetimes_outliving_type(inferred_outlives, index), + Self::lifetimes_outliving_lifetime( + inferred_outlives, + region_def_id, + ), &predicate.bounds, predicate.span, - predicate.origin == PredicateOrigin::WhereClause, + predicate.in_where_clause, ) - } - _ => { + } else { continue; } } - } - _ => continue, - }; + hir::WherePredicate::BoundPredicate(predicate) => { + // FIXME we can also infer bounds on associated types, + // and should check for them here. + match predicate.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue; + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + predicate.origin == PredicateOrigin::WhereClause, + ) + } + _ => { + continue; + } + } + } + _ => continue, + }; if relevant_lifetimes.is_empty() { continue; } - let bound_spans = - self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes); + let bound_spans = self.collect_outlives_bound_spans( + cx.tcx, + bounds, + &relevant_lifetimes, + predicate_span, + ); bound_count += bound_spans.len(); let drop_predicate = bound_spans.len() == bounds.len(); @@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } if drop_predicate && !in_where_clause { - lint_spans.push(span); + lint_spans.push(predicate_span); } else if drop_predicate && i + 1 < num_predicates { // If all the bounds on a predicate were inferable and there are // further predicates, we want to eat the trailing comma. let next_predicate_span = hir_generics.predicates[i + 1].span(); - where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo())); + where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo())); } else { where_lint_spans.extend(self.consolidate_outlives_bound_spans( - span.shrink_to_lo(), + predicate_span.shrink_to_lo(), bounds, bound_spans, )); @@ -2374,12 +2385,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } else { hir_generics.span.shrink_to_hi().to(where_span) }; - lint_spans.push(full_where_span); + + // Due to macro expansions, the `full_where_span` might not actually contain all predicates. + if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) { + lint_spans.push(full_where_span); + } else { + lint_spans.extend(where_lint_spans); + } } else { lint_spans.extend(where_lint_spans); } if !lint_spans.is_empty() { + // Do not automatically delete outlives requirements from macros. + let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions()) + { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + cx.struct_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), @@ -2387,11 +2412,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { |lint| { lint.set_arg("count", bound_count).multipart_suggestion( fluent::suggestion, - lint_spans - .into_iter() - .map(|span| (span, String::new())) - .collect::<Vec<_>>(), - Applicability::MachineApplicable, + lint_spans.into_iter().map(|span| (span, String::new())).collect(), + applicability, ) }, ); diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 0fa81b7e4e0..22caadfab17 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -22,7 +22,7 @@ declare_lint_pass!(PassByValue => [PASS_BY_VALUE]); impl<'tcx> LateLintPass<'tcx> for PassByValue { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { match &ty.kind { - TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { + TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index de2a879f1d7..1e08e95c01f 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -486,26 +486,16 @@ impl IntoDiagnostic<'_> for MultipleCandidates { let mut diag = handler.struct_err(rustc_errors::fluent::metadata_multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); - diag.code(error_code!(E0465)); + diag.code(error_code!(E0464)); diag.set_span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { - diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); + diag.note(&format!("candidate #{}: {}", i + 1, candidate.display())); } diag } } #[derive(Diagnostic)] -#[diag(metadata_multiple_matching_crates, code = "E0464")] -#[note] -pub struct MultipleMatchingCrates { - #[primary_span] - pub span: Span, - pub crate_name: Symbol, - pub candidates: String, -} - -#[derive(Diagnostic)] #[diag(metadata_symbol_conflicts_current, code = "E0519")] pub struct SymbolConflictsCurrent { #[primary_span] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index dda5f4bac42..92dc5bd41cb 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -216,9 +216,8 @@ use crate::creader::Library; use crate::errors::{ CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, - LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion, - NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, - SymbolConflictsOthers, + LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, + NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers, }; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; @@ -240,7 +239,6 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::borrow::Cow; -use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; @@ -482,7 +480,22 @@ impl<'a> CrateLocator<'a> { match libraries.len() { 0 => Ok(None), 1 => Ok(Some(libraries.into_iter().next().unwrap().1)), - _ => Err(CrateError::MultipleMatchingCrates(self.crate_name, libraries)), + _ => { + let mut libraries: Vec<_> = libraries.into_values().collect(); + + libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); + let candidates = libraries + .iter() + .map(|lib| lib.source.paths().next().unwrap().clone()) + .collect::<Vec<_>>(); + + Err(CrateError::MultipleCandidates( + self.crate_name, + // these are the same for all candidates + get_flavor_from_path(candidates.first().unwrap()), + candidates, + )) + } } } @@ -882,17 +895,22 @@ pub fn list_file_metadata( metadata_loader: &dyn MetadataLoader, out: &mut dyn Write, ) -> IoResult<()> { + let flavor = get_flavor_from_path(path); + match get_metadata_section(target, flavor, path, metadata_loader) { + Ok(metadata) => metadata.list_crate_metadata(out), + Err(msg) => write!(out, "{}\n", msg), + } +} + +fn get_flavor_from_path(path: &Path) -> CrateFlavor { let filename = path.file_name().unwrap().to_str().unwrap(); - let flavor = if filename.ends_with(".rlib") { + + if filename.ends_with(".rlib") { CrateFlavor::Rlib } else if filename.ends_with(".rmeta") { CrateFlavor::Rmeta } else { CrateFlavor::Dylib - }; - match get_metadata_section(target, flavor, path, metadata_loader) { - Ok(metadata) => metadata.list_crate_metadata(out), - Err(msg) => write!(out, "{}\n", msg), } } @@ -931,7 +949,6 @@ pub(crate) enum CrateError { ExternLocationNotExist(Symbol, PathBuf), ExternLocationNotFile(Symbol, PathBuf), MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>), - MultipleMatchingCrates(Symbol, FxHashMap<Svh, Library>), SymbolConflictsCurrent(Symbol), SymbolConflictsOthers(Symbol), StableCrateIdCollision(Symbol, Symbol), @@ -972,37 +989,7 @@ impl CrateError { sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates }); - } - CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut libraries: Vec<_> = libraries.into_values().collect(); - // Make ordering of candidates deterministic. - // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. - // `sort_by()` could be used instead, but this is in the error path, - // so the performance shouldn't matter. - libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); - let candidates = libraries - .iter() - .map(|lib| { - let crate_name = lib.metadata.get_root().name(); - let crate_name = crate_name.as_str(); - let mut paths = lib.source.paths(); - - // This `unwrap()` should be okay because there has to be at least one - // source file. `CrateSource`'s docs confirm that too. - let mut s = format!( - "\ncrate `{}`: {}", - crate_name, - paths.next().unwrap().display() - ); - let padding = 8 + crate_name.len(); - for path in paths { - write!(s, "\n{:>padding$}", path.display(), padding = padding).unwrap(); - } - s - }) - .collect::<String>(); - sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates }); + sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates }); } CrateError::SymbolConflictsCurrent(root_name) => { sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9d0ccfeb168..e167bbf57e6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -223,7 +223,7 @@ provide! { tcx, def_id, other, cdata, generator_kind => { table } trait_def => { table } deduced_param_attrs => { table } - collect_trait_impl_trait_tys => { + collect_return_position_impl_trait_in_trait_tys => { Ok(cdata .root .tables diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 65beb744cf8..214a5842233 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1197,7 +1197,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.params_in_repr[def_id] <- params_in_repr); } if should_encode_trait_impl_trait_tys(tcx, def_id) - && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 99e692ccb58..d799d3a5ad7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1160,7 +1160,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.unstable_opts.incremental_relative_spans { + if tcx.sess.opts.incremental_relative_spans() { let definitions = tcx.definitions_untracked(); let mut owner_spans: Vec<_> = krate .owners diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 3f6e29ad611..a633201e3d9 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -160,9 +160,13 @@ pub fn provide(providers: &mut Providers) { } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. + }) + | Node::ForeignItem(&ForeignItem { + kind: ForeignItemKind::Fn(_, idents, _), + .. }) = hir.get(hir_id) { - tcx.arena.alloc_slice(idents) + idents } else { span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ab512804330..37db2274f67 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -169,7 +169,7 @@ rustc_queries! { separate_provide_extern } - query collect_trait_impl_trait_tys(key: DefId) + query collect_return_position_impl_trait_in_trait_tys(key: DefId) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } @@ -2117,7 +2117,7 @@ rustc_queries! { desc { "checking to see if `{}` permits being left zeroed", key.ty } } - query compare_assoc_const_impl_item_with_trait_item( + query compare_impl_const( key: (LocalDefId, DefId) ) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6d3b94c1fdb..cc53659f827 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -641,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_trait_impl_trait_tys( + pub fn bound_return_position_impl_trait_in_trait_tys( self, def_id: DefId, ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> { - ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id)) + ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id)) } pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9d560f5c837..4219e6280eb 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1,6 +1,7 @@ //! Inlining pass for MIR functions use crate::deref_separator::deref_finder; use rustc_attr::InlineAttr; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -27,6 +28,8 @@ const RESUME_PENALTY: usize = 45; const UNKNOWN_SIZE_COST: usize = 10; +const TOP_DOWN_DEPTH_LIMIT: usize = 5; + pub struct Inline; #[derive(Copy, Clone, Debug)] @@ -86,8 +89,13 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let param_env = tcx.param_env_reveal_all_normalized(def_id); - let mut this = - Inliner { tcx, param_env, codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), changed: false }; + let mut this = Inliner { + tcx, + param_env, + codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), + history: Vec::new(), + changed: false, + }; let blocks = BasicBlock::new(0)..body.basic_blocks.next_index(); this.process_blocks(body, blocks); this.changed @@ -98,12 +106,26 @@ struct Inliner<'tcx> { param_env: ParamEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, + /// Stack of inlined instances. + /// We only check the `DefId` and not the substs because we want to + /// avoid inlining cases of polymorphic recursion. + /// The number of `DefId`s is finite, so checking history is enough + /// to ensure that we do not loop endlessly while inlining. + history: Vec<DefId>, /// Indicates that the caller body has been modified. changed: bool, } impl<'tcx> Inliner<'tcx> { fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>) { + // How many callsites in this body are we allowed to inline? We need to limit this in order + // to prevent super-linear growth in MIR size + let inline_limit = match self.history.len() { + 0 => usize::MAX, + 1..=TOP_DOWN_DEPTH_LIMIT => 1, + _ => return, + }; + let mut inlined_count = 0; for bb in blocks { let bb_data = &caller_body[bb]; if bb_data.is_cleanup { @@ -122,12 +144,16 @@ impl<'tcx> Inliner<'tcx> { debug!("not-inlined {} [{}]", callsite.callee, reason); continue; } - Ok(_) => { + Ok(new_blocks) => { debug!("inlined {}", callsite.callee); self.changed = true; - // We could process the blocks returned by `try_inlining` here. However, that - // leads to exponential compile times due to the top-down nature of this kind - // of inlining. + inlined_count += 1; + if inlined_count == inline_limit { + return; + } + self.history.push(callsite.callee.def_id()); + self.process_blocks(caller_body, new_blocks); + self.history.pop(); } } } @@ -289,7 +315,7 @@ impl<'tcx> Inliner<'tcx> { ) -> Option<CallSite<'tcx>> { // Only consider direct calls to functions let terminator = bb_data.terminator(); - if let TerminatorKind::Call { ref func, target, .. } = terminator.kind { + if let TerminatorKind::Call { ref func, target, fn_span, .. } = terminator.kind { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, substs) = *func_ty.kind() { // To resolve an instance its substs have to be fully normalized. @@ -301,15 +327,14 @@ impl<'tcx> Inliner<'tcx> { return None; } + if self.history.contains(&callee.def_id()) { + return None; + } + let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs); + let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; - return Some(CallSite { - callee, - fn_sig, - block: bb, - target, - source_info: terminator.source_info, - }); + return Some(CallSite { callee, fn_sig, block: bb, target, source_info }); } } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 18a0bee9c2e..574591529f3 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1229,3 +1229,11 @@ pub(crate) struct FnTypoWithImpl { #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")] pub fn_span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_expected_fn_path_found_fn_keyword)] +pub(crate) struct ExpectedFnPathFoundFnKeyword { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")] + pub fn_token_span: Span, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 61fe379c3e9..b3231f55bc6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -31,7 +31,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, + fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, FatalError, Handler, MultiSpan, + PResult, }; use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1229,7 +1230,7 @@ impl<'a> Parser<'a> { let sum_span = ty.span.to(self.prev_token.span); let sub = match &ty.kind { - TyKind::Rptr(lifetime, mut_ty) => { + TyKind::Ref(lifetime, mut_ty) => { let sum_with_parens = pprust::to_string(|s| { s.s.word("&"); s.print_opt_lifetime(lifetime); @@ -2556,6 +2557,75 @@ impl<'a> Parser<'a> { Ok(()) } + pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool { + (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + && self.look_ahead(3, |tok| tok == short_kind) + } + + fn diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> { + if self.is_diff_marker(long_kind, short_kind) { + let lo = self.token.span; + for _ in 0..4 { + self.bump(); + } + return Some(lo.to(self.prev_token.span)); + } + None + } + + pub fn recover_diff_marker(&mut self) { + let Some(start) = self.diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else { + return; + }; + let mut spans = Vec::with_capacity(3); + spans.push(start); + let mut middlediff3 = None; + let mut middle = None; + let mut end = None; + loop { + if self.token.kind == TokenKind::Eof { + break; + } + if let Some(span) = self.diff_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or)) { + middlediff3 = Some(span); + } + if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) { + middle = Some(span); + } + if let Some(span) = self.diff_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt) { + spans.push(span); + end = Some(span); + break; + } + self.bump(); + } + let mut err = self.struct_span_err(spans, "encountered diff marker"); + err.span_label(start, "after this is the code before the merge"); + if let Some(middle) = middlediff3 { + err.span_label(middle, ""); + } + if let Some(middle) = middle { + err.span_label(middle, ""); + } + if let Some(end) = end { + err.span_label(end, "above this are the incoming code changes"); + } + err.help( + "if you're having merge conflicts after pulling new code, the top section is the code \ + you already had and the bottom section is the remote code", + ); + err.help( + "if you're in the middle of a rebase, the top section is the code being rebased onto \ + and the bottom section is the code coming from the current commit being rebased", + ); + err.note( + "for an explanation on these markers from the `git` documentation, visit \ + <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>", + ); + err.emit(); + FatalError.raise() + } + /// Parse and throw away a parenthesized comma separated /// sequence of patterns until `)` is reached. fn skip_pat_list(&mut self) -> PResult<'a, ()> { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6a115088eca..1fc1ffd6cb6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3039,6 +3039,7 @@ impl<'a> Parser<'a> { /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e1ced2eb965..a958c294930 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -98,7 +98,9 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option<Item>> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) } @@ -704,6 +706,7 @@ impl<'a> Parser<'a> { if self.recover_doc_comment_before_brace() { continue; } + self.recover_diff_marker(); match parse_item(self) { Ok(None) => { let mut is_unnecessary_semicolon = !items.is_empty() @@ -1039,8 +1042,11 @@ impl<'a> Parser<'a> { /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { - self.parse_delim_comma_seq(Delimiter::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID))) - .map(|(r, _)| r) + self.parse_delim_comma_seq(Delimiter::Brace, |p| { + p.recover_diff_marker(); + Ok((p.parse_use_tree()?, DUMMY_NODE_ID)) + }) + .map(|(r, _)| r) } fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { @@ -1379,7 +1385,9 @@ impl<'a> Parser<'a> { } fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> { + self.recover_diff_marker(); let variant_attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token( variant_attrs, ForceCollect::No, @@ -1573,9 +1581,32 @@ impl<'a> Parser<'a> { self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| { + let mut snapshot = None; + if p.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactively error here because + // that can be a valid type start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(p.create_snapshot_for_diagnostic()); + } let lo = p.token.span; - let vis = p.parse_visibility(FollowedByType::Yes)?; - let ty = p.parse_ty()?; + let vis = match p.parse_visibility(FollowedByType::Yes) { + Ok(vis) => vis, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; + let ty = match p.parse_ty() { + Ok(ty) => ty, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; Ok(( FieldDef { @@ -1596,7 +1627,9 @@ impl<'a> Parser<'a> { /// Parses an element of a struct declaration. fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; @@ -2423,10 +2456,11 @@ impl<'a> Parser<'a> { } /// Parses the parameter list of a function, including the `(` and `)` delimiters. - fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { + pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| { + p.recover_diff_marker(); let param = p.parse_param_general(req_name, first_param).or_else(|mut e| { e.emit(); let lo = p.prev_token.span; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 40b88788caa..49d31981539 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -317,7 +317,7 @@ impl TokenCursor { // required to wrap the text. E.g. // - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0) // - `abc "d"` is wrapped as `r#"abc "d""#` (num_of_hashes = 1) - // - `abc "##d##"` is wrapped as `r###"abc "d""###` (num_of_hashes = 3) + // - `abc "##d##"` is wrapped as `r###"abc ##"d"##"###` (num_of_hashes = 3) let mut num_of_hashes = 0; let mut count = 0; for ch in data.as_str().chars() { @@ -1499,6 +1499,10 @@ impl<'a> Parser<'a> { pub fn clear_expected_tokens(&mut self) { self.expected_tokens.clear(); } + + pub fn approx_token_stream_pos(&self) -> usize { + self.token_cursor.num_next_calls + } } pub(crate) fn make_unclosed_delims_error( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index a1981e11477..0b057f2f577 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -491,17 +491,6 @@ impl<'a> Parser<'a> { if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind { // The user inverted the order, so help them fix that. - let mut applicability = Applicability::MachineApplicable; - // FIXME(bindings_after_at): Remove this code when stabilizing the feature. - lhs.walk(&mut |p| match p.kind { - // `check_match` is unhappy if the subpattern has a binding anywhere. - PatKind::Ident(..) => { - applicability = Applicability::MaybeIncorrect; - false // Short-circuit. - } - _ => true, - }); - let lhs_span = lhs.span; // Move the LHS into the RHS as a subpattern. // The RHS is now the full pattern. @@ -510,7 +499,12 @@ impl<'a> Parser<'a> { self.struct_span_err(sp, "pattern on wrong side of `@`") .span_label(lhs_span, "pattern on the left, should be on the right") .span_label(rhs.span, "binding on the right, should be on the left") - .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability) + .span_suggestion( + sp, + "switch the order", + pprust::pat_to_string(&rhs), + Applicability::MachineApplicable, + ) .emit(); } else { // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index bae7f2670cb..0daae457d30 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -531,13 +531,23 @@ impl<'a> Parser<'a> { recover: AttemptLocalParseRecovery, ) -> PResult<'a, P<Block>> { let mut stmts = vec![]; + let mut snapshot = None; while !self.eat(&token::CloseDelim(Delimiter::Brace)) { if self.token == token::Eof { break; } + if self.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactively error here because + // that can be a valid path start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(self.create_snapshot_for_diagnostic()); + } let stmt = match self.parse_full_stmt(recover) { Err(mut err) if recover.yes() => { self.maybe_annotate_with_ascription(&mut err, false); + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } err.emit(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); Some(self.mk_stmt_err(self.token.span)) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index fc26278909c..a6f702e5428 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,8 +1,9 @@ use super::{Parser, PathStyle, TokenType}; -use crate::errors::{FnPtrWithGenerics, FnPtrWithGenericsSugg}; +use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; +use ast::DUMMY_NODE_ID; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; @@ -12,7 +13,9 @@ use rustc_ast::{ }; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::Symbol; +use thin_vec::thin_vec; /// Any `?` or `~const` modifiers that appear at the start of a bound. struct BoundModifiers { @@ -501,7 +504,7 @@ impl<'a> Parser<'a> { self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; - Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })) + Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl })) } // Parses the `typeof(EXPR)`. @@ -930,8 +933,20 @@ impl<'a> Parser<'a> { has_parens: bool, modifiers: BoundModifiers, ) -> PResult<'a, GenericBound> { - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - let path = self.parse_path(PathStyle::Type)?; + let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let mut path = if self.token.is_keyword(kw::Fn) + && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) + && let Some(path) = self.recover_path_from_fn() + { + path + } else { + self.parse_path(PathStyle::Type)? + }; + + if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) { + self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?; + } + if has_parens { if self.token.is_like_plus() { // Someone has written something like `&dyn (Trait + Other)`. The correct code @@ -960,6 +975,38 @@ impl<'a> Parser<'a> { Ok(GenericBound::Trait(poly_trait, modifier)) } + // recovers a `Fn(..)` parenthesized-style path from `fn(..)` + fn recover_path_from_fn(&mut self) -> Option<ast::Path> { + let fn_token_span = self.token.span; + self.bump(); + let args_lo = self.token.span; + let snapshot = self.create_snapshot_for_diagnostic(); + match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { + Ok(decl) => { + self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span }); + Some(ast::Path { + span: fn_token_span.to(self.prev_token.span), + segments: thin_vec![ast::PathSegment { + ident: Ident::new(Symbol::intern("Fn"), fn_token_span), + id: DUMMY_NODE_ID, + args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs { + span: args_lo.to(self.prev_token.span), + inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(), + inputs_span: args_lo.until(decl.output.span()), + output: decl.output.clone(), + }))), + }], + tokens: None, + }) + } + Err(diag) => { + diag.cancel(); + self.restore_snapshot(snapshot); + None + } + } + } + /// Optionally parses `for<$generic_params>`. pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> { if self.eat_keyword(kw::For) { @@ -974,6 +1021,92 @@ impl<'a> Parser<'a> { } } + /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments + /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already + /// been eaten. + fn recover_fn_trait_with_lifetime_params( + &mut self, + fn_path: &mut ast::Path, + lifetime_defs: &mut Vec<GenericParam>, + ) -> PResult<'a, ()> { + let fn_path_segment = fn_path.segments.last_mut().unwrap(); + let generic_args = if let Some(p_args) = &fn_path_segment.args { + p_args.clone().into_inner() + } else { + // Normally it wouldn't come here because the upstream should have parsed + // generic parameters (otherwise it's impossible to call this function). + return Ok(()); + }; + let lifetimes = + if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) = + &generic_args + { + args.into_iter() + .filter_map(|arg| { + if let ast::AngleBracketedArg::Arg(generic_arg) = arg + && let ast::GenericArg::Lifetime(lifetime) = generic_arg { + Some(lifetime) + } else { + None + } + }) + .collect() + } else { + Vec::new() + }; + // Only try to recover if the trait has lifetime params. + if lifetimes.is_empty() { + return Ok(()); + } + + // Parse `(T, U) -> R`. + let inputs_lo = self.token.span; + let inputs: Vec<_> = + self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect(); + let inputs_span = inputs_lo.to(self.prev_token.span); + let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; + let args = ast::ParenthesizedArgs { + span: fn_path_segment.span().to(self.prev_token.span), + inputs, + inputs_span, + output, + } + .into(); + *fn_path_segment = + ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID }; + + // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`. + let mut generic_params = lifetimes + .iter() + .map(|lt| GenericParam { + id: lt.id, + ident: lt.ident, + attrs: ast::AttrVec::new(), + bounds: Vec::new(), + is_placeholder: false, + kind: ast::GenericParamKind::Lifetime, + colon_span: None, + }) + .collect::<Vec<GenericParam>>(); + lifetime_defs.append(&mut generic_params); + + let generic_args_span = generic_args.span(); + let mut err = + self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters"); + let snippet = format!( + "for<{}> ", + lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(), + ); + let before_fn_path = fn_path.span.shrink_to_lo(); + err.multipart_suggestion( + "consider using a higher-ranked trait bound instead", + vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)], + Applicability::MaybeIncorrect, + ) + .emit(); + Ok(()) + } + pub(super) fn check_lifetime(&mut self) -> bool { self.expected_tokens.push(TokenType::Lifetime); self.token.is_lifetime() diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index ab0463045fa..9f2aaca0acf 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -20,6 +20,7 @@ pub use Flag::*; pub use Piece::*; pub use Position::*; +use rustc_lexer::unescape; use std::iter; use std::str; use std::string; @@ -56,6 +57,13 @@ impl InnerWidthMapping { } } +/// Whether the input string is a literal. If yes, it contains the inner width mappings. +#[derive(Clone, PartialEq, Eq)] +enum InputStringKind { + NotALiteral, + Literal { width_mappings: Vec<InnerWidthMapping> }, +} + /// The type of format string that we are parsing. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ParseMode { @@ -306,7 +314,11 @@ impl<'a> Parser<'a> { append_newline: bool, mode: ParseMode, ) -> Parser<'a> { - let (width_map, is_literal) = find_width_map_from_snippet(snippet, style); + let input_string_kind = find_width_map_from_snippet(s, snippet, style); + let (width_map, is_literal) = match input_string_kind { + InputStringKind::Literal { width_mappings } => (width_mappings, true), + InputStringKind::NotALiteral => (Vec::new(), false), + }; Parser { mode, input: s, @@ -844,20 +856,40 @@ impl<'a> Parser<'a> { /// written code (code snippet) and the `InternedString` that gets processed in the `Parser` /// in order to properly synthesise the intra-string `Span`s for error diagnostics. fn find_width_map_from_snippet( + input: &str, snippet: Option<string::String>, str_style: Option<usize>, -) -> (Vec<InnerWidthMapping>, bool) { +) -> InputStringKind { let snippet = match snippet { Some(ref s) if s.starts_with('"') || s.starts_with("r\"") || s.starts_with("r#") => s, - _ => return (vec![], false), + _ => return InputStringKind::NotALiteral, }; if str_style.is_some() { - return (vec![], true); + return InputStringKind::Literal { width_mappings: Vec::new() }; } + // Strip quotes. let snippet = &snippet[1..snippet.len() - 1]; + // Macros like `println` add a newline at the end. That technically doens't make them "literals" anymore, but it's fine + // since we will never need to point our spans there, so we lie about it here by ignoring it. + // Since there might actually be newlines in the source code, we need to normalize away all trailing newlines. + // If we only trimmed it off the input, `format!("\n")` would cause a mismatch as here we they actually match up. + // Alternatively, we could just count the trailing newlines and only trim one from the input if they don't match up. + let input_no_nl = input.trim_end_matches('\n'); + let Ok(unescaped) = unescape_string(snippet) else { + return InputStringKind::NotALiteral; + }; + + let unescaped_no_nl = unescaped.trim_end_matches('\n'); + + if unescaped_no_nl != input_no_nl { + // The source string that we're pointing at isn't our input, so spans pointing at it will be incorrect. + // This can for example happen with proc macros that respan generated literals. + return InputStringKind::NotALiteral; + } + let mut s = snippet.char_indices(); let mut width_mappings = vec![]; while let Some((pos, c)) = s.next() { @@ -936,7 +968,21 @@ fn find_width_map_from_snippet( _ => {} } } - (width_mappings, true) + + InputStringKind::Literal { width_mappings } +} + +fn unescape_string(string: &str) -> Result<string::String, unescape::EscapeError> { + let mut buf = string::String::new(); + let mut error = Ok(()); + unescape::unescape_literal(string, unescape::Mode::Str, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(err) => error = Err(err), + } + }); + + error.map(|_| buf) } // Assert a reasonable size for `Piece` diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 272386f313e..b86d2316820 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -324,7 +324,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Slice, Array, Ptr, - Rptr, + Ref, BareFn, Never, Tup, @@ -580,7 +580,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Slice, Array, Ptr, - Rptr, + Ref, BareFn, Never, Tup, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index d426a2b6b78..2d243e13cc2 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -34,7 +34,6 @@ use rustc_query_system::query::*; pub use rustc_query_system::query::{deadlock, QueryContext}; pub use rustc_query_system::query::QueryConfig; -pub(crate) use rustc_query_system::query::QueryVTable; mod on_disk_cache; pub use on_disk_cache::OnDiskCache; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 9ffcc5672cc..535445e70bc 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -493,28 +493,32 @@ macro_rules! define_queries { &tcx.query_caches.$name } + fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Stored { + tcx.$name(key) + } + #[inline] - fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> - QueryVTable<QueryCtxt<'tcx>, Self::Key, Self::Value> - { - let compute = get_provider!([$($modifiers)*][tcx, $name, key]); - let cache_on_disk = Self::cache_on_disk(tcx.tcx, key); - QueryVTable { - anon: is_anon!([$($modifiers)*]), - eval_always: is_eval_always!([$($modifiers)*]), - depth_limit: depth_limit!([$($modifiers)*]), - feedable: feedable!([$($modifiers)*]), - dep_kind: dep_graph::DepKind::$name, - hash_result: hash_result!([$($modifiers)*]), - handle_cycle_error: handle_cycle_error!([$($modifiers)*]), - compute, - try_load_from_disk: if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None }, - } + // key is only sometimes used + #[allow(unused_variables)] + fn compute(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> fn(TyCtxt<'tcx>, Self::Key) -> Self::Value { + get_provider!([$($modifiers)*][qcx, $name, key]) } - fn execute_query(tcx: TyCtxt<'tcx>, k: Self::Key) -> Self::Stored { - tcx.$name(k) + #[inline] + fn try_load_from_disk(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> { + let cache_on_disk = Self::cache_on_disk(qcx.tcx, key); + if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None } } + + const ANON: bool = is_anon!([$($modifiers)*]); + const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]); + const FEEDABLE: bool = feedable!([$($modifiers)*]); + + const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name; + const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]); + + const HASH_RESULT: rustc_query_system::query::HashResult<QueryCtxt<'tcx>, Self> = hash_result!([$($modifiers)*]); })* #[allow(nonstandard_style)] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 52957ee0222..0b1ff5d709f 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -634,7 +634,7 @@ impl<K: DepKind> DepGraph<K> { if dep_node_debug.borrow().contains_key(&dep_node) { return; } - let debug_str = debug_str_gen(); + let debug_str = self.with_ignore(debug_str_gen); dep_node_debug.borrow_mut().insert(dep_node, debug_str); } @@ -829,7 +829,9 @@ impl<K: DepKind> DepGraph<K> { ); if !side_effects.is_empty() { - self.emit_side_effects(qcx, data, dep_node_index, side_effects); + self.with_query_deserialization(|| { + self.emit_side_effects(qcx, data, dep_node_index, side_effects) + }); } // ... and finally storing a "Green" entry in the color map. diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 24c960765df..8c0330e438d 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -1,7 +1,6 @@ //! Query configuration and description traits. -use crate::dep_graph::DepNode; -use crate::dep_graph::SerializedDepNodeIndex; +use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex}; use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; @@ -11,10 +10,16 @@ use rustc_data_structures::fingerprint::Fingerprint; use std::fmt::Debug; use std::hash::Hash; +pub type HashResult<Qcx, Q> = + Option<fn(&mut StableHashingContext<'_>, &<Q as QueryConfig<Qcx>>::Value) -> Fingerprint>; + +pub type TryLoadFromDisk<Qcx, Q> = + Option<fn(Qcx, SerializedDepNodeIndex) -> Option<<Q as QueryConfig<Qcx>>::Value>>; + pub trait QueryConfig<Qcx: QueryContext> { const NAME: &'static str; - type Key: Eq + Hash + Clone + Debug; + type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug; type Value: Debug; type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>; @@ -30,39 +35,27 @@ pub trait QueryConfig<Qcx: QueryContext> { where Qcx: 'a; - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn make_vtable(tcx: Qcx, key: &Self::Key) -> QueryVTable<Qcx, Self::Key, Self::Value>; - fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored; -} -#[derive(Copy, Clone)] -pub struct QueryVTable<Qcx: QueryContext, K, V> { - pub anon: bool, - pub dep_kind: Qcx::DepKind, - pub eval_always: bool, - pub depth_limit: bool, - pub feedable: bool, - - pub compute: fn(Qcx::DepContext, K) -> V, - pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>, - pub handle_cycle_error: HandleCycleError, - // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query - pub try_load_from_disk: Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>, -} + fn compute(tcx: Qcx, key: &Self::Key) -> fn(Qcx::DepContext, Self::Key) -> Self::Value; -impl<Qcx: QueryContext, K, V> QueryVTable<Qcx, K, V> { - pub(crate) fn to_dep_node(&self, tcx: Qcx::DepContext, key: &K) -> DepNode<Qcx::DepKind> - where - K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, - { - DepNode::construct(tcx, self.dep_kind, key) - } + fn try_load_from_disk(qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self>; + + const ANON: bool; + const EVAL_ALWAYS: bool; + const DEPTH_LIMIT: bool; + const FEEDABLE: bool; + + const DEP_KIND: Qcx::DepKind; + const HANDLE_CYCLE_ERROR: HandleCycleError; + + const HASH_RESULT: HashResult<Qcx, Self>; - pub(crate) fn compute(&self, tcx: Qcx::DepContext, key: K) -> V { - (self.compute)(tcx, key) + // Just here for convernience and checking that the key matches the kind, don't override this. + fn construct_dep_node(tcx: Qcx::DepContext, key: &Self::Key) -> DepNode<Qcx::DepKind> { + DepNode::construct(tcx, Self::DEP_KIND, key) } } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index ce9179ea832..d308af19207 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,7 +12,7 @@ pub use self::caches::{ }; mod config; -pub use self::config::{QueryConfig, QueryVTable}; +pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk}; use crate::dep_graph::DepKind; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 53844dab9db..da1ac6a5fb2 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,10 +2,9 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; +use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; -use crate::query::config::QueryVTable; use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; use crate::values::Value; @@ -361,36 +360,34 @@ where }) } -fn try_execute_query<Qcx, C>( +fn try_execute_query<Q, Qcx>( qcx: Qcx, - state: &QueryState<C::Key, Qcx::DepKind>, - cache: &C, + state: &QueryState<Q::Key, Qcx::DepKind>, + cache: &Q::Cache, span: Span, - key: C::Key, + key: Q::Key, dep_node: Option<DepNode<Qcx::DepKind>>, - query: &QueryVTable<Qcx, C::Key, C::Value>, -) -> (C::Stored, Option<DepNodeIndex>) +) -> (Q::Stored, Option<DepNodeIndex>) where - C: QueryCache, - C::Key: Clone + DepNodeParams<Qcx::DepContext>, - C::Value: Value<Qcx::DepContext, Qcx::DepKind>, - C::Stored: Debug + std::borrow::Borrow<C::Value>, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { - match JobOwner::<'_, C::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) { + match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job(qcx, key.clone(), dep_node, query, job.id); - if query.feedable { + let (result, dep_node_index) = + execute_job::<Q, Qcx>(qcx, key.clone(), dep_node, job.id); + if Q::FEEDABLE { // We may have put a value inside the cache from inside the execution. // Verify that it has the same hash as what we have now, to ensure consistency. let _ = cache.lookup(&key, |cached_result, _| { - let hasher = query.hash_result.expect("feedable forbids no_hash"); + let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash"); + let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow())); let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); debug_assert_eq!( old_hash, new_hash, "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}", - query.dep_kind, key, result, cached_result, + Q::DEP_KIND, key, result, cached_result, ); }); } @@ -398,7 +395,7 @@ where (result, Some(dep_node_index)) } TryGetJob::Cycle(error) => { - let result = mk_cycle(qcx, error, query.handle_cycle_error, cache); + let result = mk_cycle(qcx, error, Q::HANDLE_CYCLE_ERROR, cache); (result, None) } #[cfg(parallel_compiler)] @@ -417,16 +414,14 @@ where } } -fn execute_job<Qcx, K, V>( +fn execute_job<Q, Qcx>( qcx: Qcx, - key: K, + key: Q::Key, mut dep_node_opt: Option<DepNode<Qcx::DepKind>>, - query: &QueryVTable<Qcx, K, V>, job_id: QueryJobId, -) -> (V, DepNodeIndex) +) -> (Q::Value, DepNodeIndex) where - K: Clone + DepNodeParams<Qcx::DepContext>, - V: Debug, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { let dep_graph = qcx.dep_context().dep_graph(); @@ -434,23 +429,23 @@ where // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, query.depth_limit, None, || { - query.compute(*qcx.dep_context(), key) + let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || { + Q::compute(qcx, &key)(*qcx.dep_context(), key) }); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); return (result, dep_node_index); } - if !query.anon && !query.eval_always { + if !Q::ANON && !Q::EVAL_ALWAYS { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.get_or_insert_with(|| query.to_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.get_or_insert_with(|| Q::construct_dep_node(*qcx.dep_context(), &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. if let Some(ret) = qcx.start_query(job_id, false, None, || { - try_load_from_disk_and_cache_in_memory(qcx, &key, &dep_node, query) + try_load_from_disk_and_cache_in_memory::<Q, Qcx>(qcx, &key, &dep_node) }) { return ret; } @@ -460,18 +455,19 @@ where let diagnostics = Lock::new(ThinVec::new()); let (result, dep_node_index) = - qcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { - if query.anon { - return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind, || { - query.compute(*qcx.dep_context(), key) + qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || { + if Q::ANON { + return dep_graph.with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || { + Q::compute(qcx, &key)(*qcx.dep_context(), key) }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.unwrap_or_else(|| query.to_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.unwrap_or_else(|| Q::construct_dep_node(*qcx.dep_context(), &key)); - dep_graph.with_task(dep_node, *qcx.dep_context(), key, query.compute, query.hash_result) + let task = Q::compute(qcx, &key); + dep_graph.with_task(dep_node, *qcx.dep_context(), key, task, Q::HASH_RESULT) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -480,7 +476,7 @@ where let side_effects = QuerySideEffects { diagnostics }; if std::intrinsics::unlikely(!side_effects.is_empty()) { - if query.anon { + if Q::ANON { qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { qcx.store_side_effects(dep_node_index, side_effects); @@ -490,16 +486,14 @@ where (result, dep_node_index) } -fn try_load_from_disk_and_cache_in_memory<Qcx, K, V>( +fn try_load_from_disk_and_cache_in_memory<Q, Qcx>( qcx: Qcx, - key: &K, + key: &Q::Key, dep_node: &DepNode<Qcx::DepKind>, - query: &QueryVTable<Qcx, K, V>, -) -> Option<(V, DepNodeIndex)> +) -> Option<(Q::Value, DepNodeIndex)> where - K: Clone, + Q: QueryConfig<Qcx>, Qcx: QueryContext, - V: Debug, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -511,7 +505,7 @@ where // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if let Some(try_load_from_disk) = query.try_load_from_disk { + if let Some(try_load_from_disk) = Q::try_load_from_disk(qcx, &key) { let prof_timer = qcx.dep_context().profiler().incr_cache_loading(); // The call to `with_query_deserialization` enforces that no new `DepNodes` @@ -545,7 +539,7 @@ where if std::intrinsics::unlikely( try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, ) { - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); } return Some((result, dep_node_index)); @@ -565,7 +559,7 @@ where let prof_timer = qcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| query.compute(*qcx.dep_context(), key.clone())); + let result = dep_graph.with_ignore(|| Q::compute(qcx, key)(*qcx.dep_context(), key.clone())); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -578,7 +572,7 @@ where // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); Some((result, dep_node_index)) } @@ -699,23 +693,19 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run<Qcx, K, V>( - qcx: Qcx, - key: &K, - query: &QueryVTable<Qcx, K, V>, -) -> (bool, Option<DepNode<Qcx::DepKind>>) +fn ensure_must_run<Q, Qcx>(qcx: Qcx, key: &Q::Key) -> (bool, Option<DepNode<Qcx::DepKind>>) where - K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { - if query.eval_always { + if Q::EVAL_ALWAYS { return (true, None); } // Ensuring an anonymous query makes no sense - assert!(!query.anon); + assert!(!Q::ANON); - let dep_node = query.to_dep_node(*qcx.dep_context(), key); + let dep_node = Q::construct_dep_node(*qcx.dep_context(), key); let dep_graph = qcx.dep_context().dep_graph(); match dep_graph.try_mark_green(qcx, &dep_node) { @@ -746,13 +736,11 @@ pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) where D: DepKind, Q: QueryConfig<Qcx>, - Q::Key: DepNodeParams<Qcx::DepContext>, Q::Value: Value<Qcx::DepContext, D>, Qcx: QueryContext, { - let query = Q::make_vtable(qcx, &key); let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run(qcx, &key, &query); + let (must_run, dep_node) = ensure_must_run::<Q, _>(qcx, &key); if !must_run { return None; } @@ -761,14 +749,13 @@ where None }; - let (result, dep_node_index) = try_execute_query( + let (result, dep_node_index) = try_execute_query::<Q, Qcx>( qcx, Q::query_state(qcx), Q::query_cache(qcx), span, key, dep_node, - &query, ); if let Some(dep_node_index) = dep_node_index { qcx.dep_context().dep_graph().read_index(dep_node_index) @@ -780,7 +767,6 @@ pub fn force_query<Q, Qcx, D>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepK where D: DepKind, Q: QueryConfig<Qcx>, - Q::Key: DepNodeParams<Qcx::DepContext>, Q::Value: Value<Qcx::DepContext, D>, Qcx: QueryContext, { @@ -798,9 +784,8 @@ where Err(()) => {} } - let query = Q::make_vtable(qcx, &key); let state = Q::query_state(qcx); - debug_assert!(!query.anon); + debug_assert!(!Q::ANON); - try_execute_query(qcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); + try_execute_query::<Q, _>(qcx, state, cache, DUMMY_SP, key, Some(dep_node)); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5b7a00101e9..c44635b85f8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; +use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> { in_assignment: Option<&'ast Expr>, is_assign_rhs: bool, + /// Used to detect possible `.` -> `..` typo when calling methods. + in_range: Option<(&'ast Expr, &'ast Expr)>, + /// If we are currently in a trait object definition. Used to point at the bounds when /// encountering a struct or enum. current_trait_object: Option<&'ast [ast::GenericBound]>, @@ -648,7 +651,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let prev = self.diagnostic_metadata.current_trait_object; let prev_ty = self.diagnostic_metadata.current_type_path; match ty.kind { - TyKind::Rptr(None, _) => { + TyKind::Ref(None, _) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with // NodeId `ty.id`. // This span will be used in case of elision failure. @@ -2001,7 +2004,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { impl<'a> Visitor<'a> for SelfVisitor<'_, '_> { fn visit_ty(&mut self, ty: &'a Ty) { trace!("SelfVisitor considering ty={:?}", ty); - if let TyKind::Rptr(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) { + if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) { let lt_id = if let Some(lt) = lt { lt.id } else { @@ -3320,6 +3323,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } + #[instrument(level = "debug", skip(self))] fn smart_resolve_path_fragment( &mut self, qself: &Option<P<QSelf>>, @@ -3327,10 +3331,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { source: PathSource<'ast>, finalize: Finalize, ) -> PartialRes { - debug!( - "smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})", - qself, path, finalize, - ); let ns = source.namespace(); let Finalize { node_id, path_span, .. } = finalize; @@ -3341,8 +3341,28 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); - let suggestion = - if res.is_none() { this.report_missing_type_error(path) } else { None }; + let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range + && path[0].ident.span.lo() == end.span.lo() + { + let mut sugg = "."; + let mut span = start.span.between(end.span); + if span.lo() + BytePos(2) == span.hi() { + // There's no space between the start, the range op and the end, suggest + // removal which will look better. + span = span.with_lo(span.lo() + BytePos(1)); + sugg = ""; + } + Some(( + span, + "you might have meant to write `.` instead of `..`", + sugg.to_string(), + Applicability::MaybeIncorrect, + )) + } else if res.is_none() { + this.report_missing_type_error(path) + } else { + None + }; this.r.use_injections.push(UseError { err, @@ -4005,6 +4025,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.visit_expr(rhs); self.diagnostic_metadata.is_assign_rhs = false; } + ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => { + self.diagnostic_metadata.in_range = Some((start, end)); + self.resolve_expr(start, Some(expr)); + self.resolve_expr(end, Some(expr)); + self.diagnostic_metadata.in_range = None; + } _ => { visit::walk_expr(self, expr); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 600308b6508..74522f18542 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1554,7 +1554,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn extract_node_id(t: &Ty) -> Option<NodeId> { match t.kind { TyKind::Path(None, _) => Some(t.id), - TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), + TyKind::Ref(_, ref mut_ty) => extract_node_id(&mut_ty.ty), // This doesn't handle the remaining `Ty` variants as they are not // that commonly the self_type, it might be interesting to provide // support for those in future. @@ -2189,7 +2189,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { Some(LifetimeUseSet::One { use_span, use_ctxt }) => { debug!(?param.ident, ?param.ident.span, ?use_span); - let elidable = matches!(use_ctxt, LifetimeCtxt::Rptr); + let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 9197a28c188..5a1bcb8fdc8 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -165,7 +165,7 @@ impl<'hir> Sig for hir::Ty<'hir> { let text = format!("{}{}", prefix, nested.text); Ok(replace_text(nested, text)) } - hir::TyKind::Rptr(ref lifetime, ref mt) => { + hir::TyKind::Ref(ref lifetime, ref mt) => { let mut prefix = "&".to_owned(); prefix.push_str(&lifetime.ident.to_string()); prefix.push(' '); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3bafd3730bd..02e3992a6a9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -787,6 +787,12 @@ impl Options { pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) } + + #[allow(rustc::bad_opt_access)] + pub fn incremental_relative_spans(&self) -> bool { + self.unstable_opts.incremental_relative_spans + || (self.unstable_features.is_nightly_build() && self.incremental.is_some()) + } } impl UnstableOptions { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ae01efebacc..9bf581ff73d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1332,11 +1332,12 @@ options! { "generate human-readable, predictable names for codegen units (default: no)"), identify_regions: bool = (false, parse_bool, [UNTRACKED], "display unnamed regions as `'<id>`, using a non-ident unique id (default: no)"), - incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], + incremental_ignore_spans: bool = (false, parse_bool, [TRACKED], "ignore spans during ICH computation -- used for testing (default: no)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof) \ (default: no)"), + #[rustc_lint_opt_deny_field_access("use `Session::incremental_relative_spans` instead of this field")] incremental_relative_spans: bool = (false, parse_bool, [TRACKED], "hash spans relative to their parent item for incr. comp. (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index c2d8287f243..4e70dfb6147 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -104,6 +104,10 @@ fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) // `-Z incremental-ignore-spans` option. Normally, this option is disabled, // which will cause us to require that this method always be called with `Span` hashing // enabled. + // + // Span hashing can also be disabled without `-Z incremental-ignore-spans`. + // This is the case for instance when building a hash for name mangling. + // Such configuration must not be used for metadata. HashingControls { hash_spans } if hash_spans == !ctx.unstable_opts_incremental_ignore_spans() => {} other => panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", other), @@ -316,6 +320,7 @@ impl ExpnId { // Stop going up the backtrace once include! is encountered if expn_data.is_root() || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include) + || expn_data.kind == ExpnKind::Inlined { break; } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 2181c090027..bee4b0a2332 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -796,6 +796,9 @@ impl Span { /// Returns a `Span` that would enclose both `self` and `end`. /// + /// Note that this can also be used to extend the span "backwards": + /// `start.to(end)` and `end.to(start)` return the same `Span`. + /// /// ```text /// ____ ___ /// self lorem ipsum end diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index d9c87ac0ba8..fa09b4faa44 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -964,45 +964,40 @@ impl SourceMap { /// Finds the width of the character, either before or after the end of provided span, /// depending on the `forwards` parameter. + #[instrument(skip(self, sp))] fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 { let sp = sp.data(); if sp.lo == sp.hi && !forwards { - debug!("find_width_of_character_at_span: early return empty span"); + debug!("early return empty span"); return 1; } let local_begin = self.lookup_byte_offset(sp.lo); let local_end = self.lookup_byte_offset(sp.hi); - debug!( - "find_width_of_character_at_span: local_begin=`{:?}`, local_end=`{:?}`", - local_begin, local_end - ); + debug!("local_begin=`{:?}`, local_end=`{:?}`", local_begin, local_end); if local_begin.sf.start_pos != local_end.sf.start_pos { - debug!("find_width_of_character_at_span: begin and end are in different files"); + debug!("begin and end are in different files"); return 1; } let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - debug!( - "find_width_of_character_at_span: start_index=`{:?}`, end_index=`{:?}`", - start_index, end_index - ); + debug!("start_index=`{:?}`, end_index=`{:?}`", start_index, end_index); // Disregard indexes that are at the start or end of their spans, they can't fit bigger // characters. if (!forwards && end_index == usize::MIN) || (forwards && start_index == usize::MAX) { - debug!("find_width_of_character_at_span: start or end of span, cannot be multibyte"); + debug!("start or end of span, cannot be multibyte"); return 1; } let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize(); - debug!("find_width_of_character_at_span: source_len=`{:?}`", source_len); + debug!("source_len=`{:?}`", source_len); // Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { - debug!("find_width_of_character_at_span: source indexes are malformed"); + debug!("source indexes are malformed"); return 1; } @@ -1017,10 +1012,10 @@ impl SourceMap { } else { return 1; }; - debug!("find_width_of_character_at_span: snippet=`{:?}`", snippet); + debug!("snippet=`{:?}`", snippet); let mut target = if forwards { end_index + 1 } else { end_index - 1 }; - debug!("find_width_of_character_at_span: initial target=`{:?}`", target); + debug!("initial target=`{:?}`", target); while !snippet.is_char_boundary(target - start_index) && target < source_len { target = if forwards { @@ -1033,9 +1028,9 @@ impl SourceMap { } } }; - debug!("find_width_of_character_at_span: target=`{:?}`", target); + debug!("target=`{:?}`", target); } - debug!("find_width_of_character_at_span: final target=`{:?}`", target); + debug!("final target=`{:?}`", target); if forwards { (target - end_index) as u32 } else { (end_index - target) as u32 } } diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index f0e91e5a6a9..d48c4f7e5a8 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -4,7 +4,7 @@ // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 -use crate::def_id::LocalDefId; +use crate::def_id::{DefIndex, LocalDefId}; use crate::hygiene::SyntaxContext; use crate::SPAN_TRACK; use crate::{BytePos, SpanData}; @@ -13,8 +13,8 @@ use rustc_data_structures::fx::FxIndexSet; /// A compressed span. /// -/// Whereas [`SpanData`] is 12 bytes, which is a bit too big to stick everywhere, `Span` -/// is a form that only takes up 8 bytes, with less space for the length and +/// Whereas [`SpanData`] is 16 bytes, which is a bit too big to stick everywhere, `Span` +/// is a form that only takes up 8 bytes, with less space for the length, parent and /// context. The vast majority (99.9%+) of `SpanData` instances will fit within /// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are /// stored in a separate interner table, and the `Span` will index into that @@ -25,7 +25,7 @@ use rustc_data_structures::fx::FxIndexSet; /// slower because only 80--90% of spans could be stored inline (even less in /// very large crates) and so the interner was used a lot more. /// -/// Inline (compressed) format: +/// Inline (compressed) format with no parent: /// - `span.base_or_index == span_data.lo` /// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`) @@ -35,6 +35,12 @@ use rustc_data_structures::fx::FxIndexSet; /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`) /// +/// Inline (compressed) format with root context: +/// - `span.base_or_index == span_data.lo` +/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) +/// - `span.len_or_tag` has top bit (`PARENT_MASK`) set +/// - `span.ctxt == span_data.parent` (must be `<= MAX_CTXT`) +/// /// Interned format: /// - `span.base_or_index == index` (indexes into the interner table) /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) @@ -73,7 +79,8 @@ pub struct Span { ctxt_or_tag: u16, } -const LEN_TAG: u16 = 0b1000_0000_0000_0000; +const LEN_TAG: u16 = 0b1111_1111_1111_1111; +const PARENT_MASK: u16 = 0b1000_0000_0000_0000; const MAX_LEN: u32 = 0b0111_1111_1111_1111; const CTXT_TAG: u32 = 0b1111_1111_1111_1111; const MAX_CTXT: u32 = CTXT_TAG - 1; @@ -95,16 +102,32 @@ impl Span { let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32()); - if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() { - // Inline format. - Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_tag: ctxt2 as u16 } - } else { - // Interned format. - let index = - with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })); - let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16; - Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_tag } + if len <= MAX_LEN && ctxt2 <= MAX_CTXT { + let len_or_tag = len as u16; + debug_assert_eq!(len_or_tag & PARENT_MASK, 0); + + if let Some(parent) = parent { + // Inline format with parent. + let len_or_tag = len_or_tag | PARENT_MASK; + let parent2 = parent.local_def_index.as_u32(); + if ctxt2 == SyntaxContext::root().as_u32() && parent2 <= MAX_CTXT { + return Span { base_or_index: base, len_or_tag, ctxt_or_tag: parent2 as u16 }; + } + } else { + // Inline format with ctxt. + return Span { + base_or_index: base, + len_or_tag: len as u16, + ctxt_or_tag: ctxt2 as u16, + }; + } } + + // Interned format. + let index = + with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })); + let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16; + Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_tag } } #[inline] @@ -122,12 +145,25 @@ impl Span { pub fn data_untracked(self) -> SpanData { if self.len_or_tag != LEN_TAG { // Inline format. - debug_assert!(self.len_or_tag as u32 <= MAX_LEN); - SpanData { - lo: BytePos(self.base_or_index), - hi: BytePos(self.base_or_index + self.len_or_tag as u32), - ctxt: SyntaxContext::from_u32(self.ctxt_or_tag as u32), - parent: None, + if self.len_or_tag & PARENT_MASK == 0 { + debug_assert!(self.len_or_tag as u32 <= MAX_LEN); + SpanData { + lo: BytePos(self.base_or_index), + hi: BytePos(self.base_or_index + self.len_or_tag as u32), + ctxt: SyntaxContext::from_u32(self.ctxt_or_tag as u32), + parent: None, + } + } else { + let len = self.len_or_tag & !PARENT_MASK; + debug_assert!(len as u32 <= MAX_LEN); + let parent = + LocalDefId { local_def_index: DefIndex::from_u32(self.ctxt_or_tag as u32) }; + SpanData { + lo: BytePos(self.base_or_index), + hi: BytePos(self.base_or_index + len as u32), + ctxt: SyntaxContext::root(), + parent: Some(parent), + } } } else { // Interned format. @@ -141,8 +177,14 @@ impl Span { pub fn ctxt(self) -> SyntaxContext { let ctxt_or_tag = self.ctxt_or_tag as u32; if ctxt_or_tag <= MAX_CTXT { - // Inline format or interned format with inline ctxt. - SyntaxContext::from_u32(ctxt_or_tag) + if self.len_or_tag == LEN_TAG || self.len_or_tag & PARENT_MASK == 0 { + // Inline format or interned format with inline ctxt. + SyntaxContext::from_u32(ctxt_or_tag) + } else { + // Inline format or interned format with inline parent. + // We know that the SyntaxContext is root. + SyntaxContext::root() + } } else { // Interned format. let index = self.base_or_index; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 90f654c68ec..85510fa2c66 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -213,6 +213,7 @@ symbols! { Is, ItemContext, Iterator, + IteratorItem, Layout, Left, LinkedList, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 493e31a688f..e9b85705086 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -164,6 +164,7 @@ fn encode_const<'tcx>( /// Encodes a FnSig using the Itanium C++ ABI with vendor extended type qualifiers and types for /// Rust types that are not used at the FFI boundary. +#[instrument(level = "trace", skip(tcx, dict))] fn encode_fnsig<'tcx>( tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>, @@ -653,6 +654,7 @@ fn encode_ty<'tcx>( // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all // c_void types into unit types unconditionally, and generalizes all pointers if // TransformTyOptions::GENERALIZE_POINTERS option is set. +#[instrument(level = "trace", skip(tcx))] fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptions) -> Ty<'tcx> { let mut ty = ty; @@ -698,7 +700,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio !is_zst }); if let Some(field) = field { - let ty0 = tcx.type_of(field.did); + let ty0 = tcx.bound_type_of(field.did).subst(tcx, substs); // Generalize any repr(transparent) user-defined type that is either a pointer // or reference, and either references itself or any other type that contains or // references itself, to avoid a reference cycle. @@ -827,6 +829,7 @@ fn transform_substs<'tcx>( /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor /// extended type qualifiers and types for Rust types that are not used at the FFI boundary. +#[instrument(level = "trace", skip(tcx))] pub fn typeid_for_fnabi<'tcx>( tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 8f317beaa77..8a08c7533aa 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2771,7 +2771,7 @@ impl<'v> Visitor<'v> for FindTypeParam { // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors // in that case should make what happened clear enough. match ty.kind { - hir::TyKind::Ptr(_) | hir::TyKind::Rptr(..) | hir::TyKind::TraitObject(..) => {} + hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {} hir::TyKind::Path(hir::QPath::Resolved(None, path)) if path.segments.len() == 1 && path.segments[0].ident.name == self.param => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 472086eca8f..7c21a1047bc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2514,6 +2514,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::VariableType(hir_id) => { let parent_node = self.tcx.hir().get_parent_node(hir_id); match self.tcx.hir().find(parent_node) { + Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + err.span_suggestion_verbose( + ty.span.shrink_to_lo(), + "consider borrowing here", + "&", + Applicability::MachineApplicable, + ); + err.note("all local variables must have a statically known size"); + } Some(Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }), .. @@ -2683,7 +2692,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Don't print the tuple of capture types 'print: { if !is_upvar_tys_infer_tuple { - let msg = format!("required because it appears within the type `{}`", ty); + let msg = with_forced_trimmed_paths!(format!( + "required because it appears within the type `{ty}`", + )); match ty.kind() { ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) { Some(ident) => err.span_note(ident.span, &msg), @@ -2724,7 +2735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut msg = "required because it captures the following types: ".to_owned(); for ty in bound_tys.skip_binder() { - write!(msg, "`{}`, ", ty).unwrap(); + with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap()); } err.note(msg.trim_end_matches(", ")) } @@ -2735,7 +2746,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let kind = tcx.generator_kind(def_id).unwrap().descr(); err.span_note( sp, - &format!("required because it's used within this {}", kind), + with_forced_trimmed_paths!(&format!( + "required because it's used within this {kind}", + )), ) } ty::Closure(def_id, _) => err.span_note( @@ -2959,7 +2972,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty)); err.span_label( expr_span, - format!("return type was inferred to be `{expr_ty}` here"), + with_forced_trimmed_paths!(format!( + "return type was inferred to be `{expr_ty}` here", + )), ); } } @@ -3222,7 +3237,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { })) = call_node { if Some(rcvr.span) == err.span.primary_span() { - err.replace_span_with(path.ident.span); + err.replace_span_with(path.ident.span, true); } } if let Some(Node::Expr(hir::Expr { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5276da2e49c..f7614997585 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2284,7 +2284,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( obligation.param_env, cause.clone(), obligation.recursion_depth + 1, - tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id) .map_bound(|tys| { tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id]) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f6fe71fbd4f..466641ea6df 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -12,8 +12,8 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::{ - self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, - ToPolyTraitRef, ToPredicate, Ty, TyCtxt, + self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, + ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, }; use rustc_span::def_id::DefId; @@ -98,8 +98,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Future(vtable_future) } - FnPointerCandidate { .. } => { - let data = self.confirm_fn_pointer_candidate(obligation)?; + FnPointerCandidate { is_const } => { + let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; ImplSource::FnPointer(data) } @@ -597,17 +597,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_fn_pointer_candidate( &mut self, obligation: &TraitObligation<'tcx>, + is_const: bool, ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); + let tcx = self.tcx(); let self_ty = self .infcx .shallow_resolve(obligation.self_ty().no_bound_vars()) .expect("fn pointer should not capture bound vars from predicate"); - let sig = self_ty.fn_sig(self.tcx()); + let sig = self_ty.fn_sig(tcx); let trait_ref = closure_trait_ref_and_return_type( - self.tcx(), + tcx, obligation.predicate.def_id(), self_ty, sig, @@ -616,9 +618,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_bound(|(trait_ref, _)| trait_ref); let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let cause = obligation.derived_cause(BuiltinDerivedObligation); + + if obligation.is_const() && !is_const { + // function is a trait method + if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) { + let trait_ref = TraitRef::from_method(tcx, trait_id, *substs); + let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst); + let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred); + nested.push(obligation); + } + } // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let cause = obligation.derived_cause(BuiltinDerivedObligation); let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output()); let output_ty = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 81e8f9e914c..760b4585f4e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1374,6 +1374,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { FutureCandidate => {} // FnDef where the function is const FnPointerCandidate { is_const: true } => {} + FnPointerCandidate { is_const: false } => { + if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() { + // Trait methods are not seen as const unless the trait is implemented as const. + // We do not filter that out in here, but nested obligations will be needed to confirm this. + } else { + continue + } + } ConstDestructCandidate(_) => {} _ => { // reject all other types of candidates diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2da98d33429..8d46ba320fc 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -194,7 +194,7 @@ fn resolve_associated_item<'tcx>( && trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.compare_assoc_const_impl_item_with_trait_item(( + tcx.compare_impl_const(( leaf_def_item, trait_item_id, ))?; diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e5fbfc55761..a2fdec6fbfe 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -23,7 +23,7 @@ extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call - // the default implementations in libstd (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) + // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) // otherwise. // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them // like `malloc`, `realloc`, and `free`, respectively. @@ -404,19 +404,6 @@ pub mod __alloc_error_handler { pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { panic!("memory allocation of {size} bytes failed") } - - #[cfg(bootstrap)] - #[rustc_std_internal_symbol] - pub unsafe fn __rg_oom(size: usize, align: usize) -> ! { - use crate::alloc::Layout; - - let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; - extern "Rust" { - #[lang = "oom"] - fn oom_impl(layout: Layout) -> !; - } - unsafe { oom_impl(layout) } - } } /// Specialize clones into pre-allocated, uninitialized memory. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b154688fb08..a563b258723 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -158,7 +158,6 @@ use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; -#[cfg(not(bootstrap))] use core::marker::Tuple; use core::marker::{Destruct, Unpin, Unsize}; use core::mem; @@ -954,7 +953,7 @@ impl<T: ?Sized> Box<T> { /// [`Layout`]: crate::Layout #[stable(feature = "box_raw", since = "1.4.0")] #[inline] - #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"] + #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_raw(raw: *mut T) -> Self { unsafe { Self::from_raw_in(raw, Global) } } @@ -1981,17 +1980,6 @@ impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A #[stable(feature = "fused", since = "1.26.0")] impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {} -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { - type Output = <F as FnOnce<Args>>::Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output { - <F as FnOnce<Args>>::call_once(*self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { type Output = <F as FnOnce<Args>>::Output; @@ -2001,15 +1989,6 @@ impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F } } -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { - <F as FnMut<Args>>::call_mut(self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { @@ -2017,15 +1996,6 @@ impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, } } -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { - extern "rust-call" fn call(&self, args: Args) -> Self::Output { - <F as Fn<Args>>::call(self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { extern "rust-call" fn call(&self, args: Args) -> Self::Output { diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index 5a05215aeed..fe08e0e10e8 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -1,8 +1,8 @@ use super::*; use crate::boxed::Box; +use crate::testing::crash_test::{CrashTestDummy, Panic}; use std::iter::TrustedLen; use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::sync::atomic::{AtomicU32, Ordering}; #[test] fn test_iterator() { @@ -291,33 +291,83 @@ fn test_drain_sorted() { #[test] fn test_drain_sorted_leak() { - static DROPS: AtomicU32 = AtomicU32::new(0); - - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] - struct D(u32, bool); - - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - - if self.1 { - panic!("panic in `drop`"); - } - } - } - + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); let mut q = BinaryHeap::from(vec![ - D(0, false), - D(1, false), - D(2, false), - D(3, true), - D(4, false), - D(5, false), + d0.spawn(Panic::Never), + d1.spawn(Panic::Never), + d2.spawn(Panic::Never), + d3.spawn(Panic::InDrop), + d4.spawn(Panic::Never), + d5.spawn(Panic::Never), ]); - catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert!(q.is_empty()); +} - assert_eq!(DROPS.load(Ordering::SeqCst), 6); +#[test] +fn test_drain_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behaviour after leaking is explicitly unspecified and order is arbitrary, + // so it's fine if these start failing, but probably worth knowing. + assert!(q.is_empty()); + assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_drain_sorted_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain_sorted(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behaviour after leaking is explicitly unspecified, + // so it's fine if these start failing, but probably worth knowing. + assert_eq!(q.len(), 2); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); } #[test] diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 4c372b1d60a..700b1463bfd 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1,12 +1,12 @@ -use super::super::testing::crash_test::{CrashTestDummy, Panic}; -use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor}; -use super::super::testing::rng::DeterministicRng; use super::Entry::{Occupied, Vacant}; use super::*; use crate::boxed::Box; use crate::fmt::Debug; use crate::rc::Rc; use crate::string::{String, ToString}; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::ord_chaos::{Cyclic3, Governed, Governor}; +use crate::testing::rng::DeterministicRng; use crate::vec::Vec; use std::cmp::Ordering; use std::convert::TryFrom; diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 9d43ac5c5be..7552f2fc04c 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -21,6 +21,3 @@ trait Recover<Q: ?Sized> { fn take(&mut self, key: &Q) -> Option<Self::Key>; fn replace(&mut self, key: Self::Key) -> Option<Self::Key>; } - -#[cfg(test)] -mod testing; diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index da766b67a32..6912466448f 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -318,7 +318,10 @@ impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> pub fn ascend( self, ) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> { - let _ = BorrowType::TRAVERSAL_PERMIT; + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); @@ -1003,7 +1006,10 @@ impl<BorrowType: marker::BorrowType, K, V> /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should /// both, upon success, do nothing. pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> { - let _ = BorrowType::TRAVERSAL_PERMIT; + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + // We need to use raw pointers to nodes because, if BorrowType is // marker::ValMut, there might be outstanding mutable references to // values that we must not invalidate. There's no worry accessing the @@ -1666,17 +1672,17 @@ pub mod marker { pub struct ValMut<'a>(PhantomData<&'a mut ()>); pub trait BorrowType { - // If node references of this borrow type allow traversing to other - // nodes in the tree, this constant can be evaluated. Thus reading it - // serves as a compile-time assertion. - const TRAVERSAL_PERMIT: () = (); + /// If node references of this borrow type allow traversing to other + /// nodes in the tree, this constant is set to `true`. It can be used + /// for a compile-time assertion. + const TRAVERSAL_PERMIT: bool = true; } impl BorrowType for Owned { - // Reject evaluation, because traversal isn't needed. Instead traversal - // happens using the result of `borrow_mut`. - // By disabling traversal, and only creating new references to roots, - // we know that every reference of the `Owned` type is to a root node. - const TRAVERSAL_PERMIT: () = panic!(); + /// Reject traversal, because it isn't needed. Instead traversal + /// happens using the result of `borrow_mut`. + /// By disabling traversal, and only creating new references to roots, + /// we know that every reference of the `Owned` type is to a root node. + const TRAVERSAL_PERMIT: bool = false; } impl BorrowType for Dying {} impl<'a> BorrowType for Immut<'a> {} diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 502d3e1d126..7b8d41a6031 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -1,6 +1,6 @@ -use super::super::testing::crash_test::{CrashTestDummy, Panic}; -use super::super::testing::rng::DeterministicRng; use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::rng::DeterministicRng; use crate::vec::Vec; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index f8fbfa1bfbc..5d5af22bb29 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; use crate::vec::Vec; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -984,35 +985,34 @@ fn drain_filter_complex() { #[test] fn drain_filter_drop_panic_leak() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); + let d6 = CrashTestDummy::new(6); + let d7 = CrashTestDummy::new(7); let mut q = LinkedList::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(false)); - q.push_front(D(true)); - q.push_front(D(false)); - - catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); - - assert_eq!(unsafe { DROPS }, 8); + q.push_back(d3.spawn(Panic::Never)); + q.push_back(d4.spawn(Panic::Never)); + q.push_back(d5.spawn(Panic::Never)); + q.push_back(d6.spawn(Panic::Never)); + q.push_back(d7.spawn(Panic::Never)); + q.push_front(d2.spawn(Panic::Never)); + q.push_front(d1.spawn(Panic::InDrop)); + q.push_front(d0.spawn(Panic::Never)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert_eq!(d6.dropped(), 1); + assert_eq!(d7.dropped(), 1); assert!(q.is_empty()); } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 96960d43f58..9857f0516ba 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -3,7 +3,7 @@ //! This library provides smart pointers and collections for managing //! heap-allocated values. //! -//! This library, like libcore, normally doesn’t need to be used directly +//! This library, like core, normally doesn’t need to be used directly //! since its contents are re-exported in the [`std` crate](../std/index.html). //! Crates that use the `#![no_std]` attribute however will typically //! not depend on `std`, so they’d use this crate instead. @@ -75,7 +75,7 @@ ))] #![no_std] #![needs_allocator] -// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be +// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -122,6 +122,7 @@ #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(hasher_prefixfree_extras)] +#![feature(inline_const)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] @@ -152,7 +153,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] -#![cfg_attr(not(bootstrap), feature(tuple_trait))] +#![feature(tuple_trait)] #![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] @@ -206,6 +207,8 @@ extern crate std; #[cfg(test)] extern crate test; +#[cfg(test)] +mod testing; // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 1b61ede3476..4cfb2def098 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -653,7 +653,7 @@ impl [u8] { /// /// ```error /// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica -/// --> src/liballoc/slice.rs:608:6 +/// --> library/alloc/src/slice.rs:608:6 /// | /// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] { /// | ^ unconstrained type parameter diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 7a8e6f088f3..24f1b3a1c87 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -363,7 +363,7 @@ use crate::vec::Vec; /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "String")] +#[cfg_attr(not(test), lang = "String")] pub struct String { vec: Vec<u8>, } @@ -2678,7 +2678,7 @@ impl From<&String> for String { } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] impl From<Box<str>> for String { diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs index bcf5f5f7251..bcf5f5f7251 100644 --- a/library/alloc/src/collections/btree/testing/crash_test.rs +++ b/library/alloc/src/testing/crash_test.rs diff --git a/library/alloc/src/collections/btree/testing/mod.rs b/library/alloc/src/testing/mod.rs index 7a094f8a595..7a094f8a595 100644 --- a/library/alloc/src/collections/btree/testing/mod.rs +++ b/library/alloc/src/testing/mod.rs diff --git a/library/alloc/src/collections/btree/testing/ord_chaos.rs b/library/alloc/src/testing/ord_chaos.rs index 96ce7c15790..96ce7c15790 100644 --- a/library/alloc/src/collections/btree/testing/ord_chaos.rs +++ b/library/alloc/src/testing/ord_chaos.rs diff --git a/library/alloc/src/collections/btree/testing/rng.rs b/library/alloc/src/testing/rng.rs index ecf543bee03..ecf543bee03 100644 --- a/library/alloc/src/collections/btree/testing/rng.rs +++ b/library/alloc/src/testing/rng.rs diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ba34ab6800f..1da73862d4a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -166,7 +166,7 @@ mod spec_extend; /// vec[0] = 7; /// assert_eq!(vec[0], 7); /// -/// vec.extend([1, 2, 3].iter().copied()); +/// vec.extend([1, 2, 3]); /// /// for x in &vec { /// println!("{x}"); @@ -3191,7 +3191,7 @@ where } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { @@ -3209,7 +3209,7 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(no_global_oom_handling))] #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs index 8ff5f0abe73..879e32b3fa3 100644 --- a/library/alloc/tests/autotraits.rs +++ b/library/alloc/tests/autotraits.rs @@ -32,7 +32,7 @@ fn test_btree_map() { // spawn(f()); // } // - // where with some unintentionally overconstrained Send impls in liballoc's + // where with some unintentionally overconstrained Send impls in alloc's // internals, the future might incorrectly not be Send even though every // single type involved in the program is Send and Sync. require_send_sync(async { diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 1a379ecc11c..9ca4947ed8f 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -148,7 +148,7 @@ //! ``` //! //! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then -//! the `get_context_ref` call will return a reference to `obj.some_string` with type `&String`. +//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index b4e173ce03d..129213fde74 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -807,7 +807,8 @@ impl<T> RefCell<T> { /// /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently borrowed, or + /// if `self` and `other` point to the same `RefCell`. /// /// # Examples /// @@ -1193,7 +1194,7 @@ impl<T: Default> Default for RefCell<T> { impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn eq(&self, other: &RefCell<T>) -> bool { *self.borrow() == *other.borrow() @@ -1207,7 +1208,7 @@ impl<T: ?Sized + Eq> Eq for RefCell<T> {} impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn partial_cmp(&self, other: &RefCell<T>) -> Option<Ordering> { self.borrow().partial_cmp(&*other.borrow()) @@ -1215,7 +1216,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn lt(&self, other: &RefCell<T>) -> bool { *self.borrow() < *other.borrow() @@ -1223,7 +1224,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn le(&self, other: &RefCell<T>) -> bool { *self.borrow() <= *other.borrow() @@ -1231,7 +1232,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn gt(&self, other: &RefCell<T>) -> bool { *self.borrow() > *other.borrow() @@ -1239,7 +1240,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn ge(&self, other: &RefCell<T>) -> bool { *self.borrow() >= *other.borrow() @@ -1250,7 +1251,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { impl<T: ?Sized + Ord> Ord for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn cmp(&self, other: &RefCell<T>) -> Ordering { self.borrow().cmp(&*other.borrow()) @@ -1783,7 +1784,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// until the reference expires. As a special exception, given an `&T`, any part of it that is /// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the /// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part -/// of what a reference points to, this means the memory an `&T` points to can be deallocted only if +/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if /// *every part of it* (including padding) is inside an `UnsafeCell`. /// /// However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to @@ -1993,7 +1994,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell<T>` to `T` because of - // #[repr(transparent)]. This exploits libstd's special status, there is + // #[repr(transparent)]. This exploits std's special status, there is // no guarantee for user code that this will work in future versions of the compiler! self as *const UnsafeCell<T> as *const T as *mut T } @@ -2051,7 +2052,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell<T>` to `T` because of - // #[repr(transparent)]. This exploits libstd's special status, there is + // #[repr(transparent)]. This exploits std's special status, there is // no guarantee for user code that this will work in future versions of the compiler! this as *const T as *mut T } diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index b355d94ce49..65d12c25c51 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -35,7 +35,7 @@ pub struct LazyCell<T, F = fn() -> T> { init: Cell<Option<F>>, } -impl<T, F> LazyCell<T, F> { +impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// Creates a new lazy value with the given initializing function. /// /// # Examples @@ -51,13 +51,12 @@ impl<T, F> LazyCell<T, F> { /// /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(init: F) -> LazyCell<T, F> { LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } } -} -impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// Forces the evaluation of this lazy value and returns a reference to /// the result. /// @@ -75,6 +74,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// assert_eq!(LazyCell::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyCell<T, F>) -> &T { this.cell.get_or_init(|| match this.init.take() { @@ -87,6 +87,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { type Target = T; + #[inline] fn deref(&self) -> &T { LazyCell::force(self) } @@ -95,6 +96,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Default> Default for LazyCell<T> { /// Creates a new lazy value using `Default` as the initializing function. + #[inline] fn default() -> LazyCell<T> { LazyCell::new(T::default) } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 8c01643c7ac..7757068a4f2 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -37,8 +37,9 @@ pub struct OnceCell<T> { impl<T> OnceCell<T> { /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] + #[inline] #[must_use] + #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> OnceCell<T> { OnceCell { inner: UnsafeCell::new(None) } } @@ -46,6 +47,7 @@ impl<T> OnceCell<T> { /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant @@ -55,6 +57,7 @@ impl<T> OnceCell<T> { /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() @@ -82,6 +85,7 @@ impl<T> OnceCell<T> { /// /// assert!(cell.get().is_some()); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows @@ -123,6 +127,7 @@ impl<T> OnceCell<T> { /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init<F>(&self, f: F) -> &T where @@ -205,6 +210,7 @@ impl<T> OnceCell<T> { /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(self) -> Option<T> { // Because `into_inner` takes `self` by value, the compiler statically verifies @@ -233,6 +239,7 @@ impl<T> OnceCell<T> { /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option<T> { mem::take(self).into_inner() @@ -241,6 +248,7 @@ impl<T> OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T> Default for OnceCell<T> { + #[inline] fn default() -> Self { Self::new() } @@ -258,6 +266,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Clone> Clone for OnceCell<T> { + #[inline] fn clone(&self) -> OnceCell<T> { let res = OnceCell::new(); if let Some(value) = self.get() { @@ -272,6 +281,7 @@ impl<T: Clone> Clone for OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: PartialEq> PartialEq for OnceCell<T> { + #[inline] fn eq(&self, other: &Self) -> bool { self.get() == other.get() } @@ -283,6 +293,7 @@ impl<T: Eq> Eq for OnceCell<T> {} #[unstable(feature = "once_cell", issue = "74465")] impl<T> const From<T> for OnceCell<T> { /// Creates a new `OnceCell<T>` which already contains the given `value`. + #[inline] fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index c05b68e30bc..3e7383b4cd1 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -140,7 +140,7 @@ impl char { /// assert_eq!(None, c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_u32(i: u32) -> Option<char> { @@ -241,7 +241,7 @@ impl char { /// let _c = char::from_digit(1, 37); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_digit(num: u32, radix: u32) -> Option<char> { @@ -338,7 +338,7 @@ impl char { /// let _ = '1'.to_digit(37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 55552376280..af98059cf42 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -110,7 +110,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into /// Converts a `u32` to a `char`. Use [`char::from_u32`] instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_u32(i: u32) -> Option<char> { @@ -130,7 +130,7 @@ pub const unsafe fn from_u32_unchecked(i: u32) -> char { /// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_digit(num: u32, radix: u32) -> Option<char> { diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 949896e5748..ebf5baa3c02 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -24,8 +24,6 @@ use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; -#[cfg(bootstrap)] -use crate::marker::StructuralPartialEq; use self::Ordering::*; @@ -333,7 +331,7 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> { /// assert_eq!(Ordering::Greater, result); /// ``` #[derive(Clone, Copy, Eq, Debug, Hash)] -#[cfg_attr(not(bootstrap), derive_const(PartialOrd, Ord, PartialEq))] +#[derive_const(PartialOrd, Ord, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] #[repr(i8)] pub enum Ordering { @@ -800,9 +798,12 @@ pub trait Ord: Eq + PartialOrd<Self> { Self: Sized, Self: ~const Destruct, { - // HACK(fee1-dead): go back to using `self.max_by(other, Ord::cmp)` - // when trait methods are allowed to be used when a const closure is - // expected. + #[cfg(not(bootstrap))] + { + max_by(self, other, Ord::cmp) + } + + #[cfg(bootstrap)] match self.cmp(&other) { Ordering::Less | Ordering::Equal => other, Ordering::Greater => self, @@ -827,9 +828,12 @@ pub trait Ord: Eq + PartialOrd<Self> { Self: Sized, Self: ~const Destruct, { - // HACK(fee1-dead): go back to using `self.min_by(other, Ord::cmp)` - // when trait methods are allowed to be used when a const closure is - // expected. + #[cfg(not(bootstrap))] + { + min_by(self, other, Ord::cmp) + } + + #[cfg(bootstrap)] match self.cmp(&other) { Ordering::Less | Ordering::Equal => self, Ordering::Greater => other, @@ -879,40 +883,6 @@ pub macro Ord($item:item) { /* compiler built-in */ } -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(bootstrap)] -impl StructuralPartialEq for Ordering {} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const PartialEq for Ordering { - #[inline] - fn eq(&self, other: &Self) -> bool { - (*self as i32).eq(&(*other as i32)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const Ord for Ordering { - #[inline] - fn cmp(&self, other: &Ordering) -> Ordering { - (*self as i32).cmp(&(*other as i32)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const PartialOrd for Ordering { - #[inline] - fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> { - (*self as i32).partial_cmp(&(*other as i32)) - } -} - /// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order). /// /// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 920c31233c1..97900a4862f 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -1,5 +1,4 @@ use crate::marker::Destruct; -#[cfg(not(bootstrap))] use crate::marker::Tuple; /// Struct representing a closure with mutably borrowed data. @@ -46,33 +45,6 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, macro_rules! impl_fn_mut_tuple { ($($var:ident)*) => { - #[cfg(bootstrap)] - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const - FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue + ~const Destruct, - { - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } - } - #[cfg(bootstrap)] - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const - FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue + ~const Destruct, - { - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - #[allow(non_snake_case)] - let ($($var),*) = &mut self.data; - (self.func)(($($var),*), args) - } - } - #[cfg(not(bootstrap))] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -85,7 +57,6 @@ macro_rules! impl_fn_mut_tuple { self.call_mut(args) } } - #[cfg(not(bootstrap))] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 5f4a666de92..51e6a76cea8 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -558,7 +558,7 @@ impl Display for Arguments<'_> { /// /// Derived `Debug` formats are not stable, and so may change with future Rust /// versions. Additionally, `Debug` implementations of types provided by the -/// standard library (`libstd`, `libcore`, `liballoc`, etc.) are not stable, and +/// standard library (`std`, `core`, `alloc`, etc.) are not stable, and /// may also change with future Rust versions. /// /// # Examples diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index f2b961d62e0..5bfe001de46 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn}; /// non-Send/Sync as well, and we don't want that. /// /// It also simplifies the HIR lowering of `.await`. -#[cfg_attr(not(bootstrap), lang = "ResumeTy")] +#[lang = "ResumeTy"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[derive(Debug, Copy, Clone)] @@ -61,7 +61,6 @@ unsafe impl Sync for ResumeTy {} /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). // This is `const` to avoid extra errors after we recover from `const async fn` -#[cfg_attr(bootstrap, lang = "from_generator")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[rustc_const_unstable(feature = "gen_future", issue = "50547")] @@ -113,10 +112,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { unsafe { &mut *cx.0.as_ptr().cast() } } -#[cfg_attr(not(bootstrap), lang = "identity_future")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[inline] +#[lang = "identity_future"] pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut { f } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 6eeaef5ab01..a315a28fb0d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -55,7 +55,6 @@ #![allow(missing_docs)] use crate::marker::DiscriminantKind; -#[cfg(not(bootstrap))] use crate::marker::Tuple; use crate::mem; @@ -2175,66 +2174,6 @@ extern "rust-intrinsic" { /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, /// which violates the principle that a `const fn` must behave the same at /// compile-time and at run-time. The unsafe code in crate B is fine. - #[cfg(bootstrap)] - #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] - pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET - where - G: FnOnce<ARG, Output = RET>, - F: FnOnce<ARG, Output = RET>; - - /// Selects which function to call depending on the context. - /// - /// If this function is evaluated at compile-time, then a call to this - /// intrinsic will be replaced with a call to `called_in_const`. It gets - /// replaced with a call to `called_at_rt` otherwise. - /// - /// # Type Requirements - /// - /// The two functions must be both function items. They cannot be function - /// pointers or closures. The first function must be a `const fn`. - /// - /// `arg` will be the tupled arguments that will be passed to either one of - /// the two functions, therefore, both functions must accept the same type of - /// arguments. Both functions must return RET. - /// - /// # Safety - /// - /// The two functions must behave observably equivalent. Safe code in other - /// crates may assume that calling a `const fn` at compile-time and at run-time - /// produces the same result. A function that produces a different result when - /// evaluated at run-time, or has any other observable side-effects, is - /// *unsound*. - /// - /// Here is an example of how this could cause a problem: - /// ```no_run - /// #![feature(const_eval_select)] - /// #![feature(core_intrinsics)] - /// use std::hint::unreachable_unchecked; - /// use std::intrinsics::const_eval_select; - /// - /// // Crate A - /// pub const fn inconsistent() -> i32 { - /// fn runtime() -> i32 { 1 } - /// const fn compiletime() -> i32 { 2 } - /// - /// unsafe { - // // âš This code violates the required equivalence of `compiletime` - /// // and `runtime`. - /// const_eval_select((), compiletime, runtime) - /// } - /// } - /// - /// // Crate B - /// const X: i32 = inconsistent(); - /// let x = inconsistent(); - /// if x != X { unsafe { unreachable_unchecked(); }} - /// ``` - /// - /// This code causes Undefined Behavior when being run, since the - /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, - /// which violates the principle that a `const fn` must behave the same at - /// compile-time and at run-time. The unsafe code in crate B is fine. - #[cfg(not(bootstrap))] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] pub fn const_eval_select<ARG: Tuple, F, G, RET>( arg: ARG, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 9e7099ddfd1..399d54f18c5 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -60,7 +60,8 @@ //! //! # Examples //! -//! ```rust +#![cfg_attr(bootstrap, doc = "```rust,compile_fail")] +#![cfg_attr(not(bootstrap), doc = "```rust")] //! #![feature(core_intrinsics, custom_mir)] //! //! extern crate core; @@ -291,7 +292,8 @@ define!( /// /// # Examples /// - /// ```rust + #[cfg_attr(bootstrap, doc = "```rust,compile_fail")] + #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(custom_mir, core_intrinsics)] /// /// extern crate core; diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 98734c527f2..617dfd12383 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -22,17 +22,12 @@ pub const fn empty<T>() -> Empty<T> { Empty(marker::PhantomData) } -// Newtype for use in `PhantomData` to avoid -// > error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` -// in `const fn empty<T>()` above. -struct FnReturning<T>(fn() -> T); - /// An iterator that yields nothing. /// /// This `struct` is created by the [`empty()`] function. See its documentation for more. #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iter_empty", since = "1.2.0")] -pub struct Empty<T>(marker::PhantomData<FnReturning<T>>); +pub struct Empty<T>(marker::PhantomData<fn() -> T>); #[stable(feature = "core_impl_debug", since = "1.9.0")] impl<T> fmt::Debug for Empty<T> { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index bac836292f8..fc4d4bff24f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -66,6 +66,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {} #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { /// The type of the elements being iterated over. + #[rustc_diagnostic_item = "IteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] type Item; @@ -803,7 +804,7 @@ pub trait Iterator { /// (0..5).map(|x| x * 2 + 1) /// .for_each(move |x| tx.send(x).unwrap()); /// - /// let v: Vec<_> = rx.iter().collect(); + /// let v: Vec<_> = rx.iter().collect(); /// assert_eq!(v, vec![1, 3, 5, 7, 9]); /// ``` /// @@ -1380,8 +1381,8 @@ pub trait Iterator { Take::new(self, n) } - /// An iterator adapter similar to [`fold`] that holds internal state and - /// produces a new iterator. + /// An iterator adapter which, like [`fold`], holds internal state, but + /// unlike [`fold`], produces a new iterator. /// /// [`fold`]: Iterator::fold /// @@ -1393,20 +1394,25 @@ pub trait Iterator { /// /// On iteration, the closure will be applied to each element of the /// iterator and the return value from the closure, an [`Option`], is - /// yielded by the iterator. + /// returned by the `next` method. Thus the closure can return + /// `Some(value)` to yield `value`, or `None` to end the iteration. /// /// # Examples /// /// Basic usage: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [1, 2, 3, 4]; /// /// let mut iter = a.iter().scan(1, |state, &x| { - /// // each iteration, we'll multiply the state by the element + /// // each iteration, we'll multiply the state by the element ... /// *state = *state * x; /// - /// // then, we'll yield the negation of the state + /// // ... and terminate if the state exceeds 6 + /// if *state > 6 { + /// return None; + /// } + /// // ... else yield the negation of the state /// Some(-*state) /// }); /// @@ -2653,7 +2659,10 @@ pub trait Iterator { /// argument is a double reference. You can see this effect in the /// examples below, with `&&x`. /// + /// If you need the index of the element, see [`position()`]. + /// /// [`Some(element)`]: Some + /// [`position()`]: Iterator::position /// /// # Examples /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1823fd30062..0e3fef4ead3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -38,18 +38,18 @@ //! which do not trigger a panic can be assured that this function is never //! called. The `lang` attribute is called `eh_personality`. -// Since libcore defines many fundamental lang items, all tests live in a -// separate crate, libcoretest, to avoid bizarre issues. +// Since core defines many fundamental lang items, all tests live in a +// separate crate, libcoretest (library/core/tests), to avoid bizarre issues. // // Here we explicitly #[cfg]-out this whole crate when testing. If we don't do // this, both the generated test artifact and the linked libtest (which -// transitively includes libcore) will both define the same set of lang items, +// transitively includes core) will both define the same set of lang items, // and this will cause the E0152 "found duplicate lang item" error. See // discussion in #50466 for details. // // This cfg won't affect doc tests. #![cfg(not(test))] -// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be +// To run core tests without x.py without ending up with two copies of core, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -194,7 +194,7 @@ #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] -#![cfg_attr(not(bootstrap), feature(derive_const))] +#![feature(derive_const)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(rustdoc_internals)] @@ -309,7 +309,7 @@ pub mod f64; #[macro_use] pub mod num; -/* The libcore prelude, not as all-encompassing as the libstd prelude */ +/* The core prelude, not as all-encompassing as the std prelude */ pub mod prelude; @@ -376,12 +376,12 @@ mod const_closure; #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; -// Pull in the `core_arch` crate directly into libcore. The contents of +// Pull in the `core_arch` crate directly into core. The contents of // `core_arch` are in a different repository: rust-lang/stdarch. // -// `core_arch` depends on libcore, but the contents of this module are +// `core_arch` depends on core, but the contents of this module are // set up in such a way that directly pulling it here works such that the -// crate uses the this crate as its libcore. +// crate uses the this crate as its core. #[path = "../../stdarch/crates/core_arch/src/mod.rs"] #[allow( missing_docs, @@ -400,12 +400,12 @@ mod core_arch; #[stable(feature = "simd_arch", since = "1.27.0")] pub mod arch; -// Pull in the `core_simd` crate directly into libcore. The contents of +// Pull in the `core_simd` crate directly into core. The contents of // `core_simd` are in a different repository: rust-lang/portable-simd. // -// `core_simd` depends on libcore, but the contents of this module are +// `core_simd` depends on core, but the contents of this module are // set up in such a way that directly pulling it here works such that the -// crate uses this crate as its libcore. +// crate uses this crate as its core. #[path = "../../portable-simd/crates/core_simd/src/mod.rs"] #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] #[allow(rustdoc::bare_urls)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index f29cd357d6b..cfc1cabe229 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1461,7 +1461,6 @@ pub(crate) mod builtin { /// [the reference]: ../../../reference/attributes/derive.html #[unstable(feature = "derive_const", issue = "none")] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro derive_const($item:item) { /* compiler built-in */ } @@ -1516,7 +1515,6 @@ pub(crate) mod builtin { /// Attribute macro applied to a function to register it as a handler for allocation failure. /// /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html). - #[cfg(not(bootstrap))] #[unstable(feature = "alloc_error_handler", issue = "51540")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] @@ -1553,7 +1551,6 @@ pub(crate) mod builtin { issue = "23416", reason = "placeholder syntax for type ascription" )] - #[cfg(not(bootstrap))] pub macro type_ascribe($expr:expr, $ty:ty) { /* compiler built-in */ } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4b85c1112b9..c0fb954ce2d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -96,7 +96,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {} )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[rustc_specialization_trait] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Sized { // Empty. } @@ -128,7 +128,7 @@ pub trait Sized { /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Unsize<T: ?Sized> { // Empty. } @@ -695,7 +695,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {} reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead" )] #[lang = "discriminant_kind"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. @@ -796,7 +796,7 @@ impl<T: ?Sized> Unpin for *mut T {} #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[const_trait] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Destruct {} /// A marker for tuple types. @@ -806,12 +806,12 @@ pub trait Destruct {} #[unstable(feature = "tuple_trait", issue = "none")] #[lang = "tuple_trait"] #[rustc_on_unimplemented(message = "`{Self}` is not a tuple")] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Tuple {} /// A marker for things #[unstable(feature = "pointer_sized_trait", issue = "none")] -#[cfg_attr(not(bootstrap), lang = "pointer_sized")] +#[lang = "pointer_sized"] #[rustc_on_unimplemented( message = "`{Self}` needs to be a pointer-sized type", label = "`{Self}` needs to be a pointer-sized type" diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2c6a0ba64f2..1308b0770b8 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -428,7 +428,7 @@ impl f32 { self != self } - // FIXME(#50145): `abs` is publicly unavailable in libcore due to + // FIXME(#50145): `abs` is publicly unavailable in core due to // concerns about portability, so this implementation is for // private use internally. #[inline] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index fd3c18ce29b..2a22c4302b9 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -427,7 +427,7 @@ impl f64 { self != self } - // FIXME(#50145): `abs` is publicly unavailable in libcore due to + // FIXME(#50145): `abs` is publicly unavailable in core due to // concerns about portability, so this implementation is for // private use internally. #[inline] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index e1ab7ac5ff0..57096f43974 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2290,8 +2290,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2313,8 +2313,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2335,8 +2335,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2360,8 +2360,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2396,8 +2396,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2420,8 +2420,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6a339b338d9..fbda8f82b1b 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -462,8 +462,8 @@ macro_rules! nonzero_unsigned_operations { #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -486,8 +486,8 @@ macro_rules! nonzero_unsigned_operations { #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1253,7 +1253,7 @@ macro_rules! nonzero_bits { /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] /// ``` - #[stable(feature = "nonzero_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_bits", since = "1.67.0")] pub const BITS: u32 = <$Int>::BITS; } )+ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index af74faa90b1..1c97c468628 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -703,8 +703,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -726,8 +726,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -748,8 +748,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -773,8 +773,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -809,8 +809,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -831,8 +831,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 127b047db91..b7e1aee9d84 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -1,4 +1,3 @@ -#[cfg(not(bootstrap))] use crate::marker::Tuple; /// The version of the call operator that takes an immutable receiver. @@ -54,87 +53,6 @@ use crate::marker::Tuple; /// let double = |x| x * 2; /// assert_eq!(call_with_one(double), 2); /// ``` -#[cfg(bootstrap)] -#[lang = "fn"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", - label = "expected an `Fn<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait Fn<Args>: FnMut<Args> { - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call(&self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes an immutable receiver. -/// -/// Instances of `Fn` can be called repeatedly without mutating state. -/// -/// *This trait (`Fn`) is not to be confused with [function pointers] -/// (`fn`).* -/// -/// `Fn` is implemented automatically by closures which only take immutable -/// references to captured variables or don't capture anything at all, as well -/// as (safe) [function pointers] (with some caveats, see their documentation -/// for more details). Additionally, for any type `F` that implements `Fn`, `&F` -/// implements `Fn`, too. -/// -/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any -/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`] -/// is expected. -/// -/// Use `Fn` as a bound when you want to accept a parameter of function-like -/// type and need to call it repeatedly and without mutating state (e.g., when -/// calling it concurrently). If you do not need such strict requirements, use -/// [`FnMut`] or [`FnOnce`] as bounds. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Calling a closure -/// -/// ``` -/// let square = |x| x * x; -/// assert_eq!(square(5), 25); -/// ``` -/// -/// ## Using a `Fn` parameter -/// -/// ``` -/// fn call_with_one<F>(func: F) -> usize -/// where F: Fn(usize) -> usize { -/// func(1) -/// } -/// -/// let double = |x| x * 2; -/// assert_eq!(call_with_one(double), 2); -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -222,95 +140,6 @@ pub trait Fn<Args: Tuple>: FnMut<Args> { /// /// assert_eq!(x, 5); /// ``` -#[cfg(bootstrap)] -#[lang = "fn_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", - label = "expected an `FnMut<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait FnMut<Args>: FnOnce<Args> { - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes a mutable receiver. -/// -/// Instances of `FnMut` can be called repeatedly and may mutate state. -/// -/// `FnMut` is implemented automatically by closures which take mutable -/// references to captured variables, as well as all types that implement -/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of -/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` -/// implements `FnMut`, too. -/// -/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be -/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of -/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected. -/// -/// Use `FnMut` as a bound when you want to accept a parameter of function-like -/// type and need to call it repeatedly, while allowing it to mutate state. -/// If you don't want the parameter to mutate state, use [`Fn`] as a -/// bound; if you don't need to call it repeatedly, use [`FnOnce`]. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Calling a mutably capturing closure -/// -/// ``` -/// let mut x = 5; -/// { -/// let mut square_x = || x *= x; -/// square_x(); -/// } -/// assert_eq!(x, 25); -/// ``` -/// -/// ## Using a `FnMut` parameter -/// -/// ``` -/// fn do_twice<F>(mut func: F) -/// where F: FnMut() -/// { -/// func(); -/// func(); -/// } -/// -/// let mut x: usize = 1; -/// { -/// let add_two_to_x = || x += 2; -/// do_twice(add_two_to_x); -/// } -/// -/// assert_eq!(x, 5); -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -390,92 +219,6 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> { /// /// // `consume_and_return_x` can no longer be invoked at this point /// ``` -#[cfg(bootstrap)] -#[lang = "fn_once"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", - label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait FnOnce<Args> { - /// The returned type after the call operator is used. - #[lang = "fn_once_output"] - #[stable(feature = "fn_once_output", since = "1.12.0")] - type Output; - - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes a by-value receiver. -/// -/// Instances of `FnOnce` can be called, but might not be callable multiple -/// times. Because of this, if the only thing known about a type is that it -/// implements `FnOnce`, it can only be called once. -/// -/// `FnOnce` is implemented automatically by closures that might consume captured -/// variables, as well as all types that implement [`FnMut`], e.g., (safe) -/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]). -/// -/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of -/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. -/// -/// Use `FnOnce` as a bound when you want to accept a parameter of function-like -/// type and only need to call it once. If you need to call the parameter -/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate -/// state, use [`Fn`]. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Using a `FnOnce` parameter -/// -/// ``` -/// fn consume_with_relish<F>(func: F) -/// where F: FnOnce() -> String -/// { -/// // `func` consumes its captured variables, so it cannot be run more -/// // than once. -/// println!("Consumed: {}", func()); -/// -/// println!("Delicious!"); -/// -/// // Attempting to invoke `func()` again will throw a `use of moved -/// // value` error for `func`. -/// } -/// -/// let x = String::from("x"); -/// let consume_and_return_x = move || x; -/// consume_with_relish(consume_and_return_x); -/// -/// // `consume_and_return_x` can no longer be invoked at this point -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -507,68 +250,6 @@ pub trait FnOnce<Args: Tuple> { extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } -#[cfg(bootstrap)] -mod impls { - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const Fn<A> for &F - where - F: ~const Fn<A>, - { - extern "rust-call" fn call(&self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnMut<A> for &F - where - F: ~const Fn<A>, - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnOnce<A> for &F - where - F: ~const Fn<A>, - { - type Output = F::Output; - - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnMut<A> for &mut F - where - F: ~const FnMut<A>, - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnOnce<A> for &mut F - where - F: ~const FnMut<A>, - { - type Output = F::Output; - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call_mut(args) - } - } -} - -#[cfg(not(bootstrap))] mod impls { use crate::marker::Tuple; diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 461b70c32f3..8338a5d7e5a 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -90,14 +90,14 @@ pub macro unreachable_2021 { ), } -/// An internal trait used by libstd to pass data from libstd to `panic_unwind` -/// and other panic runtimes. Not intended to be stabilized any time soon, do -/// not use. +/// An internal trait used by std to pass data from std to `panic_unwind` and +/// other panic runtimes. Not intended to be stabilized any time soon, do not +/// use. #[unstable(feature = "std_internals", issue = "none")] #[doc(hidden)] pub unsafe trait BoxMeUp { /// Take full ownership of the contents. - /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in libcore. + /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core. /// /// After this method got called, only some dummy default value is left in `self`. /// Calling this method twice, or calling `get` after calling this method, is an error. diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 1923155ebc1..0d385c9d187 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -157,7 +157,7 @@ impl fmt::Display for PanicInfo<'_> { write!(formatter, "'{}', ", payload)? } // NOTE: we cannot use downcast_ref::<String>() here - // since String is not available in libcore! + // since String is not available in core! // The payload is a String when `std::panic!` is called with multiple arguments, // but in that case the message is also available. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 9fce78d076b..0146a3c2fbf 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -1,8 +1,8 @@ -//! Panic support for libcore +//! Panic support for core //! //! The core library cannot define panicking, but it does *declare* panicking. This -//! means that the functions inside of libcore are allowed to panic, but to be -//! useful an upstream crate must define panicking for libcore to use. The current +//! means that the functions inside of core are allowed to panic, but to be +//! useful an upstream crate must define panicking for core to use. The current //! interface for panicking is: //! //! ``` @@ -13,7 +13,7 @@ //! This definition allows for panicking with any general message, but it does not //! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, //! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) -//! The reason for this is that libcore is not allowed to allocate. +//! The reason for this is that core is not allowed to allocate. //! //! This module contains a few other panicking functions, but these are just the //! necessary lang items for the compiler. All panics are funneled through this @@ -94,7 +94,7 @@ pub fn panic_nounwind(msg: &'static str) -> ! { // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions // above. -/// The underlying implementation of libcore's `panic!` macro when no formatting is used. +/// The underlying implementation of core's `panic!` macro when no formatting is used. // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 3cd3a3b780e..12f762ef193 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -1,8 +1,8 @@ -//! The libcore prelude +//! The core prelude //! -//! This module is intended for users of libcore which do not link to libstd as -//! well. This module is imported by default when `#![no_std]` is used in the -//! same manner as the standard library's prelude. +//! This module is intended for users of core which do not link to std as well. +//! This module is imported by default when `#![no_std]` is used in the same +//! manner as the standard library's prelude. #![stable(feature = "core_prelude", since = "1.4.0")] diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 2d67d742c68..10525a16f3a 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -75,14 +75,12 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::macros::builtin::alloc_error_handler; -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; +pub use crate::macros::builtin::{ + alloc_error_handler, bench, derive, global_allocator, test, test_case, +}; #[unstable(feature = "derive_const", issue = "none")] -#[cfg(not(bootstrap))] pub use crate::macros::builtin::derive_const; #[unstable( @@ -104,5 +102,4 @@ pub use crate::macros::builtin::cfg_eval; issue = "23416", reason = "placeholder syntax for type ascription" )] -#[cfg(not(bootstrap))] pub use crate::macros::builtin::type_ascribe; diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 64a5290c3a2..2123147c7e4 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -10,8 +10,7 @@ use crate::{cmp, fmt, hash, mem, num}; /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -203,8 +202,7 @@ type AlignmentEnum = AlignmentEnum32; type AlignmentEnum = AlignmentEnum64; #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u16)] enum AlignmentEnum16 { _Align1Shl0 = 1 << 0, @@ -226,8 +224,7 @@ enum AlignmentEnum16 { } #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u32)] enum AlignmentEnum32 { _Align1Shl0 = 1 << 0, @@ -265,8 +262,7 @@ enum AlignmentEnum32 { } #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u64)] enum AlignmentEnum64 { _Align1Shl0 = 1 << 0, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b6373beac5f..0a74c03d70f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1,6 +1,6 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics; +use crate::intrinsics::{self, const_eval_select}; use crate::mem; use crate::slice::{self, SliceIndex}; @@ -34,12 +34,23 @@ impl<T: ?Sized> *const T { #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const fn is_null(self) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (self as *const u8).guaranteed_eq(null()) { - None => false, - Some(res) => res, + #[inline] + fn runtime_impl(ptr: *const u8) -> bool { + ptr.addr() == 0 } + + #[inline] + const fn const_impl(ptr: *const u8) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + match (ptr).guaranteed_eq(null_mut()) { + None => false, + Some(res) => res, + } + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self as *const u8,), const_impl, runtime_impl) } } /// Casts to a pointer of another type. @@ -1350,26 +1361,6 @@ impl<T: ?Sized> *const T { panic!("align_offset: align is not a power-of-two"); } - #[cfg(bootstrap)] - { - fn rt_impl<T>(p: *const T, align: usize) -> usize { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(p, align) } - } - - const fn ctfe_impl<T>(_: *const T, _: usize) -> usize { - usize::MAX - } - - // SAFETY: - // It is permissible for `align_offset` to always return `usize::MAX`, - // algorithm correctness can not depend on `align_offset` returning non-max values. - // - // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. - unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } - } - - #[cfg(not(bootstrap))] { // SAFETY: `align` has been checked to be a power of 2 above unsafe { align_offset(self, align) } @@ -1406,8 +1397,7 @@ impl<T: ?Sized> *const T { /// is never aligned if cast to a type with a stricter alignment than the reference's /// underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1433,8 +1423,7 @@ impl<T: ?Sized> *const T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1460,8 +1449,7 @@ impl<T: ?Sized> *const T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1537,8 +1525,7 @@ impl<T: ?Sized> *const T { /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer /// cannot be stricter aligned than the reference's underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1563,8 +1550,7 @@ impl<T: ?Sized> *const T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1588,8 +1574,7 @@ impl<T: ?Sized> *const T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1613,11 +1598,22 @@ impl<T: ?Sized> *const T { panic!("is_aligned_to: align is not a power-of-two"); } - // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. - // The cast to `()` is used to - // 1. deal with fat pointers; and - // 2. ensure that `align_offset` doesn't actually try to compute an offset. - self.cast::<()>().align_offset(align) == 0 + #[inline] + fn runtime_impl(ptr: *const (), align: usize) -> bool { + ptr.addr() & (align - 1) == 0 + } + + #[inline] + const fn const_impl(ptr: *const (), align: usize) -> bool { + // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. + // The cast to `()` is used to + // 1. deal with fat pointers; and + // 2. ensure that `align_offset` doesn't actually try to compute an offset. + ptr.align_offset(align) == 0 + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) } } } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index a8604843e96..2ea032d4aff 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -50,7 +50,7 @@ use crate::hash::{Hash, Hasher}; /// /// [`to_raw_parts`]: *const::to_raw_parts #[lang = "pointee_trait"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Pointee { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 7a5d9a70594..d70fb70c79f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1,6 +1,6 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics; +use crate::intrinsics::{self, const_eval_select}; use crate::slice::{self, SliceIndex}; impl<T: ?Sized> *mut T { @@ -33,12 +33,23 @@ impl<T: ?Sized> *mut T { #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const fn is_null(self) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (self as *mut u8).guaranteed_eq(null_mut()) { - None => false, - Some(res) => res, + #[inline] + fn runtime_impl(ptr: *mut u8) -> bool { + ptr.addr() == 0 } + + #[inline] + const fn const_impl(ptr: *mut u8) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + match (ptr).guaranteed_eq(null_mut()) { + None => false, + Some(res) => res, + } + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self as *mut u8,), const_impl, runtime_impl) } } /// Casts to a pointer of another type. @@ -1618,26 +1629,6 @@ impl<T: ?Sized> *mut T { panic!("align_offset: align is not a power-of-two"); } - #[cfg(bootstrap)] - { - fn rt_impl<T>(p: *mut T, align: usize) -> usize { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(p, align) } - } - - const fn ctfe_impl<T>(_: *mut T, _: usize) -> usize { - usize::MAX - } - - // SAFETY: - // It is permissible for `align_offset` to always return `usize::MAX`, - // algorithm correctness can not depend on `align_offset` returning non-max values. - // - // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. - unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } - } - - #[cfg(not(bootstrap))] { // SAFETY: `align` has been checked to be a power of 2 above unsafe { align_offset(self, align) } @@ -1674,8 +1665,7 @@ impl<T: ?Sized> *mut T { /// is never aligned if cast to a type with a stricter alignment than the reference's /// underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// #![feature(const_mut_refs)] @@ -1702,8 +1692,7 @@ impl<T: ?Sized> *mut T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1730,8 +1719,7 @@ impl<T: ?Sized> *mut T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1807,8 +1795,7 @@ impl<T: ?Sized> *mut T { /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer /// cannot be stricter aligned than the reference's underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// #![feature(const_mut_refs)] @@ -1834,8 +1821,7 @@ impl<T: ?Sized> *mut T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1860,8 +1846,7 @@ impl<T: ?Sized> *mut T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1885,11 +1870,22 @@ impl<T: ?Sized> *mut T { panic!("is_aligned_to: align is not a power-of-two"); } - // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. - // The cast to `()` is used to - // 1. deal with fat pointers; and - // 2. ensure that `align_offset` doesn't actually try to compute an offset. - self.cast::<()>().align_offset(align) == 0 + #[inline] + fn runtime_impl(ptr: *mut (), align: usize) -> bool { + ptr.addr() & (align - 1) == 0 + } + + #[inline] + const fn const_impl(ptr: *mut (), align: usize) -> bool { + // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. + // The cast to `()` is used to + // 1. deal with fat pointers; and + // 2. ensure that `align_offset` doesn't actually try to compute an offset. + ptr.align_offset(align) == 0 + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) } } } diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 87f77b7f21d..b8c0c3fd949 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -3,7 +3,7 @@ //! This module contains a sorting algorithm based on Orson Peters' pattern-defeating quicksort, //! published at: <https://github.com/orlp/pdqsort> //! -//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our +//! Unstable sorting is compatible with core because it doesn't allocate memory, unlike our //! stable sorting implementation. use crate::cmp; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 863ded5e5ec..ab2f8520ecb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -368,7 +368,7 @@ impl str { #[inline(always)] pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` - // has the same layout as `&[u8]` (only libstd can make this guarantee). + // has the same layout as `&[u8]` (only std can make this guarantee). // The pointer dereference is safe since it comes from a mutable reference which // is guaranteed to be valid for writes. unsafe { &mut *(self as *mut str as *mut [u8]) } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index f1dc4f7b575..25b61c0e666 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -9,7 +9,7 @@ use crate::task::Ready; /// scheduled to receive a wakeup instead. #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[cfg_attr(not(bootstrap), lang = "Poll")] +#[lang = "Poll"] #[stable(feature = "futures_api", since = "1.36.0")] pub enum Poll<T> { /// Represents that a value is immediately ready. diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 1b7578376b4..a4425fd234a 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -181,6 +181,9 @@ pub struct Context<'a> { // are contravariant while return-position lifetimes are // covariant). _marker: PhantomData<fn(&'a ()) -> &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, } impl<'a> Context<'a> { @@ -190,7 +193,7 @@ impl<'a> Context<'a> { #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { - Context { waker, _marker: PhantomData } + Context { waker, _marker: PhantomData, _marker2: PhantomData } } /// Returns a reference to the [`Waker`] for the current task. diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 72fa059b787..e1faa407d54 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -17,7 +17,7 @@ mod unicode_data; #[stable(feature = "unicode_version", since = "1.45.0")] pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; -// For use in liballoc, not re-exported in libstd. +// For use in alloc, not re-exported in std. pub use unicode_data::{ case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, }; diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index e98dac8d12e..a8f6b7ebb92 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -131,7 +131,6 @@ fn distinct_type_names() { assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),); } -#[cfg(not(bootstrap))] #[test] fn dyn_type_name() { trait Foo { diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index 70fcc6d2d4b..c7c3c479b71 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -106,6 +106,12 @@ fn lazy_new() { assert_eq!(called.get(), 1); } +// Check that we can infer `T` from closure's type. +#[test] +fn lazy_type_inference() { + let _ = LazyCell::new(|| ()); +} + #[test] fn aliasing_in_get() { let x = OnceCell::new(); diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 1cfb4fd9fd1..f7740a114e7 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -77,7 +77,6 @@ fn align_of_val_basic() { } #[test] -#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails fn align_of_val_raw_packed() { #[repr(C, packed)] struct B { diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 90bc8351080..80d30f14c66 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -359,7 +359,6 @@ fn align_offset_zst() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_zst_const() { const { // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at @@ -397,7 +396,6 @@ fn align_offset_stride_one() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_stride_one_const() { const { // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to @@ -493,7 +491,6 @@ fn align_offset_various_strides() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_various_strides_const() { const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) { let mut expected = usize::MAX; @@ -561,7 +558,6 @@ fn align_offset_various_strides_const() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_with_provenance_const() { const { // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4. @@ -681,7 +677,6 @@ fn align_offset_issue_103361() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_issue_103361_const() { #[cfg(target_pointer_width = "64")] const SIZE: usize = 1 << 47; @@ -715,7 +710,6 @@ fn is_aligned() { } #[test] -#[cfg(not(bootstrap))] fn is_aligned_const() { const { let data = 42; @@ -735,18 +729,6 @@ fn is_aligned_const() { } #[test] -#[cfg(bootstrap)] -fn is_aligned_const() { - const { - let data = 42; - let ptr: *const i32 = &data; - // The bootstrap compiler always returns false for is_aligned. - assert!(!ptr.is_aligned()); - assert!(!ptr.is_aligned_to(1)); - } -} - -#[test] fn offset_from() { let mut a = [0; 5]; let ptr1: *mut i32 = &mut a[1]; @@ -825,7 +807,7 @@ fn ptr_metadata_bounds() { } // "Synthetic" trait impls generated by the compiler like those of `Pointee` // are not checked for bounds of associated type. - // So with a buggy libcore we could have both: + // So with a buggy core we could have both: // * `<dyn Display as Pointee>::Metadata == DynMetadata` // * `DynMetadata: !PartialEq` // … and cause an ICE here: diff --git a/library/core/tests/str.rs b/library/core/tests/str.rs index ed939ca7139..f5066343af2 100644 --- a/library/core/tests/str.rs +++ b/library/core/tests/str.rs @@ -1 +1 @@ -// All `str` tests live in liballoc/tests +// All `str` tests live in library/alloc/tests/str.rs diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs index 56be30e9282..163b34c9648 100644 --- a/library/core/tests/task.rs +++ b/library/core/tests/task.rs @@ -1,4 +1,4 @@ -use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; +use core::task::{Poll, RawWaker, RawWakerVTable, Waker}; #[test] fn poll_const() { @@ -21,9 +21,5 @@ fn waker_const() { static WAKER: Waker = unsafe { Waker::from_raw(VOID_WAKER) }; - static CONTEXT: Context<'static> = Context::from_waker(&WAKER); - - static WAKER_REF: &'static Waker = CONTEXT.waker(); - - WAKER_REF.wake_by_ref(); + WAKER.wake_by_ref(); } diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index cba8ef25db6..a3cebf99c53 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -61,7 +61,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail // - // Note: this is the same implementation as in libstd's `abort_internal` + // Note: this is the same implementation as in std's `abort_internal` unsafe fn abort() -> ! { #[allow(unused)] const FAST_FAIL_FATAL_APP_EXIT: usize = 7; @@ -89,7 +89,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // This... is a bit of an oddity. The tl;dr; is that this is required to link // correctly, the longer explanation is below. // -// Right now the binaries of libcore/libstd that we ship are all compiled with +// Right now the binaries of core/std that we ship are all compiled with // `-C panic=unwind`. This is done to ensure that the binaries are maximally // compatible with as many situations as possible. The compiler, however, // requires a "personality function" for all functions compiled with `-C @@ -109,7 +109,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // library just defines this symbol so there's at least some personality // somewhere. // -// Essentially this symbol is just defined to get wired up to libcore/libstd +// Essentially this symbol is just defined to get wired up to core/std // binaries, but it should never be called as we don't link in an unwinding // runtime at all. pub mod personalities { diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 7e7180a38e2..ea3c9a7a663 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -82,11 +82,11 @@ cfg_if::cfg_if! { } extern "C" { - /// Handler in libstd called when a panic object is dropped outside of + /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. fn __rust_drop_panic() -> !; - /// Handler in libstd called when a foreign exception is caught. + /// Handler in std called when a foreign exception is caught. fn __rust_foreign_exception() -> !; } diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 506b2a773cc..52a08cad911 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -356,7 +356,7 @@ impl<I, O> Clone for Client<I, O> { fn maybe_install_panic_hook(force_show_panics: bool) { // Hide the default panic output within `proc_macro` expansions. - // NB. the server can't do this because it may use a different libstd. + // NB. the server can't do this because it may use a different std. static HIDE_PANICS_DURING_EXPANSION: Once = Once::new(); HIDE_PANICS_DURING_EXPANSION.call_once(|| { let prev = panic::take_hook(); diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index 4b1e412e24b..17bd0a1b336 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -15,9 +15,9 @@ use std::ops::BitXor; /// Type alias for a hashmap using the `fx` hash algorithm. pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>; -/// A speedy hash algorithm for use within rustc. The hashmap in liballoc -/// by default uses SipHash which isn't quite as speedy as we want. In the -/// compiler we're not really worried about DOS attempts, so we use a fast +/// A speedy hash algorithm for use within rustc. The hashmap in alloc by +/// default uses SipHash which isn't quite as speedy as we want. In the compiler +/// we're not really worried about DOS attempts, so we use a fast /// non-cryptographic hash. /// /// This is the same as the algorithm used by Firefox -- which is a homespun diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 8202c40d631..2ea87d866ff 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -112,7 +112,7 @@ macro_rules! define_dispatcher_impl { $name::$method(server, $($arg),*) }; // HACK(eddyb) don't use `panic::catch_unwind` in a panic. - // If client and server happen to use the same `libstd`, + // If client and server happen to use the same `std`, // `catch_unwind` asserts that the panic counter was 0, // even when the closure passed to it didn't panic. let r = if thread::panicking() { diff --git a/library/rustc-std-workspace-alloc/lib.rs b/library/rustc-std-workspace-alloc/lib.rs index c38a8d2f204..87db7af44ae 100644 --- a/library/rustc-std-workspace-alloc/lib.rs +++ b/library/rustc-std-workspace-alloc/lib.rs @@ -3,7 +3,7 @@ // See rustc-std-workspace-core for why this crate is needed. -// Rename the crate to avoid conflicting with the alloc module in liballoc. +// Rename the crate to avoid conflicting with the alloc module in alloc. extern crate alloc as foo; pub use foo::*; diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 9cb74f951dd..7543ffadd41 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -23,10 +23,10 @@ //! //! ## Platform support //! -//! Not all platforms that libstd compiles for support capturing backtraces. -//! Some platforms simply do nothing when capturing a backtrace. To check -//! whether the platform supports capturing backtraces you can consult the -//! `BacktraceStatus` enum as a result of `Backtrace::status`. +//! Not all platforms that std compiles for support capturing backtraces. Some +//! platforms simply do nothing when capturing a backtrace. To check whether the +//! platform supports capturing backtraces you can consult the `BacktraceStatus` +//! enum as a result of `Backtrace::status`. //! //! Like above with accuracy platform support is done on a best effort basis. //! Sometimes libraries might not be available at runtime or something may go diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 781ae03ad45..601c01c2128 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -166,7 +166,7 @@ impl Repr { // `new_unchecked` is safe. let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed"); res } @@ -177,7 +177,7 @@ impl Repr { // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!( matches!(res.data(), ErrorData::Os(c) if c == code), "repr(os) encoding failed for {code}" @@ -191,7 +191,7 @@ impl Repr { // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!( matches!(res.data(), ErrorData::Simple(k) if k == kind), "repr(simple) encoding failed {:?}", @@ -348,7 +348,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> { // that our encoding relies on for correctness and soundness. (Some of these are // a bit overly thorough/cautious, admittedly) // -// If any of these are hit on a platform that libstd supports, we should likely +// If any of these are hit on a platform that std supports, we should likely // just use `repr_unpacked.rs` there instead (unless the fix is easy). macro_rules! static_assert { ($condition:expr) => { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 23a13523fc2..de528e85368 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2137,8 +2137,10 @@ pub trait BufRead: Read { } /// Read all bytes until a newline (the `0xA` byte) is reached, and append - /// them to the provided buffer. You do not need to clear the buffer before - /// appending. + /// them to the provided `String` buffer. + /// + /// Previous content of the buffer will be preserved. To avoid appending to + /// the buffer, you need to [`clear`] it first. /// /// This function will read bytes from the underlying stream until the /// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes @@ -2151,9 +2153,11 @@ pub trait BufRead: Read { /// /// This function is blocking and should be used carefully: it is possible for /// an attacker to continuously send bytes without ever sending a newline - /// or EOF. + /// or EOF. You can use [`take`] to limit the maximum number of bytes read. /// /// [`Ok(0)`]: Ok + /// [`clear`]: String::clear + /// [`take`]: crate::io::Read::take /// /// # Errors /// diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 1141a957d87..14bfef4c7aa 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -10,9 +10,8 @@ use crate::fmt; use crate::fs::File; use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; use crate::sync::atomic::{AtomicBool, Ordering}; -use crate::sync::{Arc, Mutex, MutexGuard, OnceLock}; +use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard}; use crate::sys::stdio; -use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; type LocalStream = Arc<Mutex<Vec<u8>>>; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65d4c3c891e..13dfd41abbf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -202,7 +202,7 @@ no_global_oom_handling, not(no_global_oom_handling) ))] -// To run libstd tests without x.py without ending up with two copies of libstd, Miri needs to be +// To run std tests without x.py without ending up with two copies of std, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -532,7 +532,7 @@ pub mod process; pub mod sync; pub mod time; -// Pull in `std_float` crate into libstd. The contents of +// Pull in `std_float` crate into std. The contents of // `std_float` are in a different repository: rust-lang/portable-simd. #[path = "../../portable-simd/crates/std_float/src/lib.rs"] #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] @@ -602,7 +602,7 @@ mod personality; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] mod backtrace_rs; -// Re-export macros defined in libcore. +// Re-export macros defined in core. #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ @@ -610,7 +610,7 @@ pub use core::{ unimplemented, unreachable, write, writeln, }; -// Re-export built-in macros defined through libcore. +// Re-export built-in macros defined through core. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] pub use core::{ diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs index 5453853e138..07f08c1b586 100644 --- a/library/std/src/net/ip_addr.rs +++ b/library/std/src/net/ip_addr.rs @@ -1195,6 +1195,9 @@ impl Ipv6Addr { /// An IPv6 address representing localhost: `::1`. /// + /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other + /// languages. + /// /// # Examples /// /// ``` @@ -1203,11 +1206,15 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::LOCALHOST; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` + #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] + #[doc(alias = "in6addr_loopback")] #[stable(feature = "ip_constructors", since = "1.30.0")] pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); /// An IPv6 address representing the unspecified address: `::` /// + /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. + /// /// # Examples /// /// ``` @@ -1216,6 +1223,8 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::UNSPECIFIED; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); /// ``` + #[doc(alias = "IN6ADDR_ANY_INIT")] + #[doc(alias = "in6addr_any")] #[stable(feature = "ip_constructors", since = "1.30.0")] pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index c4f022de021..9fa8f5702a8 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -114,6 +114,9 @@ where /// aborting the process as well. This function *only* catches unwinding panics, /// not those that abort the process. /// +/// Note that if a custom panic hook has been set, it will be invoked before +/// the panic is caught, before unwinding. +/// /// Also note that unwinding into Rust code with a foreign exception (e.g. /// an exception thrown from C++ code) is undefined behavior. /// diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 1039835bbbd..b30dd8eecd8 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -517,7 +517,7 @@ pub fn panicking() -> bool { !panic_count::count_is_zero() } -/// Entry point of panics from the libcore crate (`panic_impl` lang item). +/// Entry point of panics from the core crate (`panic_impl` lang item). #[cfg(not(test))] #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { @@ -699,7 +699,11 @@ fn rust_panic_with_hook( // have limited options. Currently our preference is to // just abort. In the future we may consider resuming // unwinding or otherwise exiting the thread cleanly. - rtprintpanic!("thread panicked while panicking. aborting.\n"); + if !can_unwind { + rtprintpanic!("thread caused non-unwinding panic. aborting.\n"); + } else { + rtprintpanic!("thread panicked while panicking. aborting.\n"); + } crate::sys::abort_internal(); } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 73b5056e932..19d8f1edaf4 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -306,7 +306,7 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { // This casts are safe as OsStr is internally a wrapper around [u8] on all // platforms. // - // Note that currently this relies on the special knowledge that libstd has; + // Note that currently this relies on the special knowledge that std has; // these types are single-element structs but are not marked // repr(transparent) or repr(C) which would make these casts not allowable // outside std. @@ -1246,6 +1246,9 @@ impl PathBuf { /// and `path` is not empty, the new path is normalized: all references /// to `.` and `..` are removed. /// + /// Consider using [`Path::join`] if you need a new `PathBuf` instead of + /// using this function on a cloned `PathBuf`. + /// /// # Examples /// /// Pushing a relative path extends the existing path: @@ -1411,7 +1414,8 @@ impl PathBuf { self.push(file_name); } - /// Updates [`self.extension`] to `extension`. + /// Updates [`self.extension`] to `Some(extension)` or to `None` if + /// `extension` is empty. /// /// Returns `false` and does nothing if [`self.file_name`] is [`None`], /// returns `true` and updates the extension otherwise. @@ -1419,6 +1423,20 @@ impl PathBuf { /// If [`self.extension`] is [`None`], the extension is added; otherwise /// it is replaced. /// + /// If `extension` is the empty string, [`self.extension`] will be [`None`] + /// afterwards, not `Some("")`. + /// + /// # Caveats + /// + /// The new `extension` may contain dots and will be used in its entirety, + /// but only the part after the final dot will be reflected in + /// [`self.extension`]. + /// + /// If the file stem contains internal dots and `extension` is empty, part + /// of the old file stem will be considered the new [`self.extension`]. + /// + /// See the examples below. + /// /// [`self.file_name`]: Path::file_name /// [`self.extension`]: Path::extension /// @@ -1432,8 +1450,20 @@ impl PathBuf { /// p.set_extension("force"); /// assert_eq!(Path::new("/feel/the.force"), p.as_path()); /// - /// p.set_extension("dark_side"); - /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path()); + /// p.set_extension("dark.side"); + /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path()); + /// + /// p.set_extension("cookie"); + /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the.dark"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the"), p.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool { diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index a5a798078eb..2aefd7c513d 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -59,14 +59,12 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use core::prelude::v1::alloc_error_handler; -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; +pub use core::prelude::v1::{ + alloc_error_handler, bench, derive, global_allocator, test, test_case, +}; #[unstable(feature = "derive_const", issue = "none")] -#[cfg(not(bootstrap))] pub use core::prelude::v1::derive_const; // Do not `doc(no_inline)` either. @@ -91,7 +89,6 @@ pub use core::prelude::v1::cfg_eval; issue = "23416", reason = "placeholder syntax for type ascription" )] -#[cfg(not(bootstrap))] pub use core::prelude::v1::type_ascribe; // The file so far is equivalent to src/libcore/prelude/v1.rs, diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 17aff342c15..62ce2cb33dc 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1038,6 +1038,15 @@ impl fmt::Debug for Command { /// Format the program and arguments of a Command for display. Any /// non-utf8 data is lossily converted using the utf8 replacement /// character. + /// + /// The default format approximates a shell invocation of the program along with its + /// arguments. It does not include most of the other command properties. The output is not guaranteed to work + /// (e.g. due to lack of shell-escaping or differences in path resolution) + /// On some platforms you can use [the alternate syntax] to show more fields. + /// + /// Note that the debug implementation is platform-specific. + /// + /// [the alternate syntax]: fmt#sign0 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } @@ -2155,18 +2164,11 @@ pub fn id() -> u32 { /// to provide similar functionality. #[cfg_attr(not(test), lang = "termination")] #[stable(feature = "termination_trait_lib", since = "1.61.0")] -#[rustc_on_unimplemented( - on( - all(not(bootstrap), cause = "MainFunctionType"), - message = "`main` has invalid return type `{Self}`", - label = "`main` can only return types that implement `{Termination}`" - ), - on( - bootstrap, - message = "`main` has invalid return type `{Self}`", - label = "`main` can only return types that implement `{Termination}`" - ) -)] +#[rustc_on_unimplemented(on( + cause = "MainFunctionType", + message = "`main` has invalid return type `{Self}`", + label = "`main` can only return types that implement `{Termination}`" +))] pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 955ad68916c..b4f6cc2daba 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -417,6 +417,100 @@ fn env_empty() { assert!(p.is_ok()); } +#[test] +#[cfg(not(windows))] +#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] +fn main() { + const PIDFD: &'static str = + if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" }; + + let mut command = Command::new("some-boring-name"); + + assert_eq!(format!("{command:?}"), format!(r#""some-boring-name""#)); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "some-boring-name", + ], +{PIDFD}}}"# + ) + ); + + command.args(&["1", "2", "3"]); + + assert_eq!(format!("{command:?}"), format!(r#""some-boring-name" "1" "2" "3""#)); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "some-boring-name", + "1", + "2", + "3", + ], +{PIDFD}}}"# + ) + ); + + crate::os::unix::process::CommandExt::arg0(&mut command, "exciting-name"); + + assert_eq!( + format!("{command:?}"), + format!(r#"["some-boring-name"] "exciting-name" "1" "2" "3""#) + ); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "exciting-name", + "1", + "2", + "3", + ], +{PIDFD}}}"# + ) + ); + + let mut command_with_env_and_cwd = Command::new("boring-name"); + command_with_env_and_cwd.current_dir("/some/path").env("FOO", "bar"); + assert_eq!( + format!("{command_with_env_and_cwd:?}"), + r#"cd "/some/path" && FOO="bar" "boring-name""# + ); + assert_eq!( + format!("{command_with_env_and_cwd:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: false, + vars: {{ + "FOO": Some( + "bar", + ), + }}, + }}, + cwd: Some( + "/some/path", + ), +{PIDFD}}}"# + ) + ); +} + // See issue #91991 #[test] #[cfg(windows)] diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 9c2f0c1dd3e..f1eeb75be7c 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -139,9 +139,9 @@ fn lang_start_internal( // mechanism itself. // // There are a couple of instances where unwinding can begin. First is inside of the - // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a - // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to - // prevent libstd from accidentally introducing a panic to these functions. Another is from + // `rt::init`, `rt::cleanup` and similar functions controlled by bstd. In those instances a + // panic is a std implementation bug. A quite likely one too, as there isn't any way to + // prevent std from accidentally introducing a panic to these functions. Another is from // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index c8d3289ca4a..4a15305301d 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -46,17 +46,15 @@ pub struct LazyLock<T, F = fn() -> T> { cell: OnceLock<T>, init: Cell<Option<F>>, } - -impl<T, F> LazyLock<T, F> { +impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Creates a new lazy value with the given initializing /// function. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(f: F) -> LazyLock<T, F> { LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) } } -} -impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Forces the evaluation of this lazy value and /// returns a reference to result. This is equivalent /// to the `Deref` impl, but is explicit. @@ -73,6 +71,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// assert_eq!(LazyLock::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyLock<T, F>) -> &T { this.cell.get_or_init(|| match this.init.take() { @@ -85,6 +84,8 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { type Target = T; + + #[inline] fn deref(&self) -> &T { LazyLock::force(self) } @@ -93,6 +94,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Default> Default for LazyLock<T> { /// Creates a new lazy value using `Default` as the initializing function. + #[inline] fn default() -> LazyLock<T> { LazyLock::new(T::default) } diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs index f11b66bfca5..a5d4e25c596 100644 --- a/library/std/src/sync/lazy_lock/tests.rs +++ b/library/std/src/sync/lazy_lock/tests.rs @@ -136,6 +136,12 @@ fn sync_lazy_poisoning() { } } +// Check that we can infer `T` from closure's type. +#[test] +fn lazy_type_inference() { + let _ = LazyCell::new(|| ()); +} + #[test] fn is_sync_send() { fn assert_traits<T: Send + Sync>() {} diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 4fee8d3e92f..ba20bab87a4 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -177,6 +177,8 @@ pub use self::lazy_lock::LazyLock; #[unstable(feature = "once_cell", issue = "74465")] pub use self::once_lock::OnceLock; +pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; + pub mod mpsc; mod barrier; @@ -187,4 +189,5 @@ mod mutex; mod once; mod once_lock; mod poison; +mod remutex; mod rwlock; diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index d0904b4b94c..e030c55ce8f 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -136,7 +136,7 @@ impl Backoff { } } - /// Returns `true` if exponential backoff has completed and blocking the thread is advised. + /// Returns `true` if quadratic backoff has completed and blocking the thread is advised. #[inline] pub fn is_completed(&self) -> bool { self.step.get() > YIELD_LIMIT diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 16d1fd2a576..ed339ca5df6 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -61,8 +61,9 @@ pub struct OnceLock<T> { impl<T> OnceLock<T> { /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] + #[inline] #[must_use] + #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> OnceLock<T> { OnceLock { once: Once::new(), @@ -75,6 +76,7 @@ impl<T> OnceLock<T> { /// /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { @@ -88,6 +90,7 @@ impl<T> OnceLock<T> { /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. This method never blocks. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { if self.is_initialized() { @@ -125,6 +128,7 @@ impl<T> OnceLock<T> { /// assert_eq!(CELL.get(), Some(&92)); /// } /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn set(&self, value: T) -> Result<(), T> { let mut value = Some(value); @@ -164,6 +168,7 @@ impl<T> OnceLock<T> { /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init<F>(&self, f: F) -> &T where @@ -203,6 +208,7 @@ impl<T> OnceLock<T> { /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where @@ -241,6 +247,7 @@ impl<T> OnceLock<T> { /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(mut self) -> Option<T> { self.take() @@ -267,6 +274,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option<T> { if self.is_initialized() { @@ -315,6 +323,7 @@ impl<T> OnceLock<T> { /// # Safety /// /// The value must be initialized + #[inline] unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); (&*self.value.get()).assume_init_ref() @@ -323,6 +332,7 @@ impl<T> OnceLock<T> { /// # Safety /// /// The value must be initialized + #[inline] unsafe fn get_unchecked_mut(&mut self) -> &mut T { debug_assert!(self.is_initialized()); (&mut *self.value.get()).assume_init_mut() @@ -360,6 +370,7 @@ impl<T> const Default for OnceLock<T> { /// assert_eq!(OnceLock::<()>::new(), OnceLock::default()); /// } /// ``` + #[inline] fn default() -> OnceLock<T> { OnceLock::new() } @@ -377,6 +388,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Clone> Clone for OnceLock<T> { + #[inline] fn clone(&self) -> OnceLock<T> { let cell = Self::new(); if let Some(value) = self.get() { @@ -408,6 +420,7 @@ impl<T> From<T> for OnceLock<T> { /// Ok(()) /// # } /// ``` + #[inline] fn from(value: T) -> Self { let cell = Self::new(); match cell.set(value) { @@ -419,6 +432,7 @@ impl<T> From<T> for OnceLock<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: PartialEq> PartialEq for OnceLock<T> { + #[inline] fn eq(&self, other: &OnceLock<T>) -> bool { self.get() == other.get() } @@ -429,6 +443,7 @@ impl<T: Eq> Eq for OnceLock<T> {} #[unstable(feature = "once_cell", issue = "74465")] unsafe impl<#[may_dangle] T> Drop for OnceLock<T> { + #[inline] fn drop(&mut self) { if self.is_initialized() { // SAFETY: The cell is initialized and being dropped, so it can't diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sync/remutex.rs index 4c054da6471..4c054da6471 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sync/remutex.rs diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sync/remutex/tests.rs index 8e97ce11c34..fc553081d42 100644 --- a/library/std/src/sys_common/remutex/tests.rs +++ b/library/std/src/sync/remutex/tests.rs @@ -1,6 +1,6 @@ +use super::{ReentrantMutex, ReentrantMutexGuard}; use crate::cell::RefCell; use crate::sync::Arc; -use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread; #[test] diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index c2b36680872..535703be33f 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -119,7 +119,7 @@ impl Thread { let old_lifecycle = inner .lifecycle - .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::Release); + .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::AcqRel); match old_lifecycle { LIFECYCLE_DETACHED => { @@ -129,9 +129,9 @@ impl Thread { // In this case, `*p_inner`'s ownership has been moved to // us, and we are responsible for dropping it. The acquire - // ordering is not necessary because the parent thread made - // no memory access needing synchronization since the call - // to `acre_tsk`. + // ordering ensures that the swap operation that wrote + // `LIFECYCLE_DETACHED` happens-before `Box::from_raw( + // p_inner)`. // Safety: See above. let _ = unsafe { Box::from_raw(p_inner) }; @@ -151,6 +151,9 @@ impl Thread { // Since the parent might drop `*inner` and terminate us as // soon as it sees `JOIN_FINALIZE`, the release ordering // must be used in the above `swap` call. + // + // To make the task referred to by `parent_tid` visible, we + // must use the acquire ordering in the above `swap` call. // [JOINING → JOIN_FINALIZE] // Wake up the parent task. @@ -218,11 +221,15 @@ impl Thread { let current_task = current_task as usize; - match inner.lifecycle.swap(current_task, Ordering::Acquire) { + match inner.lifecycle.swap(current_task, Ordering::AcqRel) { LIFECYCLE_INIT => { // [INIT → JOINING] // The child task will transition the state to `JOIN_FINALIZE` // and wake us up. + // + // To make the task referred to by `current_task` visible from + // the child task's point of view, we must use the release + // ordering in the above `swap` call. loop { expect_success_aborting(unsafe { abi::slp_tsk() }, &"slp_tsk"); // To synchronize with the child task's memory accesses to @@ -267,15 +274,15 @@ impl Drop for Thread { let inner = unsafe { self.p_inner.as_ref() }; // Detach the thread. - match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { + match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::AcqRel) { LIFECYCLE_INIT => { // [INIT → DETACHED] // When the time comes, the child will figure out that no // one will ever join it. // The ownership of `*p_inner` is moved to the child thread. - // However, the release ordering is not necessary because we - // made no memory access needing synchronization since the call - // to `acre_tsk`. + // The release ordering ensures that the above swap operation on + // `lifecycle` happens-before the child thread's + // `Box::from_raw(p_inner)`. } LIFECYCLE_FINISHED => { // [FINISHED → JOINED] diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 63e070207cd..9865a945bad 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -34,7 +34,7 @@ pub mod process; pub mod stdio; pub mod thread; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; mod condvar; diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 579f758c6cc..1608b8cb642 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -65,9 +65,9 @@ mod task_queue { /// execution. The signal is sent once all TLS destructors have finished at /// which point no new thread locals should be created. pub mod wait_notify { - use super::super::thread_parker::Parker; use crate::pin::Pin; use crate::sync::Arc; + use crate::sys_common::thread_parking::Parker; pub struct Notifier(Arc<Parker>); @@ -87,14 +87,14 @@ pub mod wait_notify { /// called, this will return immediately, otherwise the current thread /// is blocked until notified. pub fn wait(self) { - // This is not actually `unsafe`, but it uses the `Parker` API, - // which needs `unsafe` on some platforms. + // SAFETY: + // This is only ever called on one thread. unsafe { Pin::new(&*self.0).park() } } } pub fn new() -> (Notifier, Waiter) { - let inner = Arc::new(Parker::new_internal()); + let inner = Arc::new(Parker::new()); (Notifier(inner.clone()), Waiter(inner)) } } diff --git a/library/std/src/sys/sgx/thread_parker.rs b/library/std/src/sys/sgx/thread_parker.rs deleted file mode 100644 index 1c55bcffb1e..00000000000 --- a/library/std/src/sys/sgx/thread_parker.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Thread parking based on SGX events. - -use super::abi::{thread, usercalls}; -use crate::io::ErrorKind; -use crate::pin::Pin; -use crate::ptr::{self, NonNull}; -use crate::sync::atomic::AtomicPtr; -use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::time::Duration; -use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE}; - -// The TCS structure must be page-aligned (this is checked by EENTER), so these cannot -// be valid pointers -const EMPTY: *mut u8 = ptr::invalid_mut(1); -const NOTIFIED: *mut u8 = ptr::invalid_mut(2); - -pub struct Parker { - /// The park state. One of EMPTY, NOTIFIED or a TCS address. - /// A state change to NOTIFIED must be done with release ordering - /// and be observed with acquire ordering so that operations after - /// `thread::park` returns will not occur before the unpark message - /// was sent. - state: AtomicPtr<u8>, -} - -impl Parker { - /// Construct the thread parker. The UNIX parker implementation - /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { - unsafe { parker.write(Parker::new_internal()) } - } - - pub(super) fn new_internal() -> Parker { - Parker { state: AtomicPtr::new(EMPTY) } - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park(self: Pin<&Self>) { - if self.state.load(Acquire) != NOTIFIED { - let mut prev = EMPTY; - loop { - // Guard against changing TCS addresses by always setting the state to - // the current value. - let tcs = thread::current().as_ptr(); - if self.state.compare_exchange(prev, tcs, Relaxed, Acquire).is_ok() { - let event = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap(); - assert!(event & EV_UNPARK == EV_UNPARK); - prev = tcs; - } else { - // The state was definitely changed by another thread at this point. - // The only time this occurs is when the state is changed to NOTIFIED. - // We observed this change with acquire ordering, so we can simply - // change the state to EMPTY with a relaxed store. - break; - } - } - } - - // At this point, the token was definately read with acquire ordering, - // so this can be a relaxed store. - self.state.store(EMPTY, Relaxed); - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64; - let tcs = thread::current().as_ptr(); - - if self.state.load(Acquire) != NOTIFIED { - if self.state.compare_exchange(EMPTY, tcs, Relaxed, Acquire).is_ok() { - match usercalls::wait(EV_UNPARK, timeout) { - Ok(event) => assert!(event & EV_UNPARK == EV_UNPARK), - Err(e) => { - assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock)) - } - } - - // Swap to provide acquire ordering even if the timeout occurred - // before the token was set. This situation can result in spurious - // wakeups on the next call to `park_timeout`, but it is better to let - // those be handled by the user than do some perhaps unnecessary, but - // always expensive guarding. - self.state.swap(EMPTY, Acquire); - return; - } - } - - // The token was already read with `acquire` ordering, this can be a store. - self.state.store(EMPTY, Relaxed); - } - - // This implementation doesn't require `Pin`, but other implementations do. - pub fn unpark(self: Pin<&Self>) { - let state = self.state.swap(NOTIFIED, Release); - - if !matches!(state, EMPTY | NOTIFIED) { - // There is a thread waiting, wake it up. - let tcs = NonNull::new(state).unwrap(); - // This will fail if the thread has already terminated or its TCS is destroyed - // by the time the signal is sent, but that is fine. If another thread receives - // the same TCS, it will receive this notification as a spurious wakeup, but - // all users of `wait` should and (internally) do guard against those where - // necessary. - let _ = usercalls::send(EV_UNPARK, Some(tcs)); - } - } -} diff --git a/library/std/src/sys/sgx/thread_parking.rs b/library/std/src/sys/sgx/thread_parking.rs new file mode 100644 index 00000000000..0006cd4f1be --- /dev/null +++ b/library/std/src/sys/sgx/thread_parking.rs @@ -0,0 +1,23 @@ +use super::abi::usercalls; +use crate::io::ErrorKind; +use crate::time::Duration; +use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE}; + +pub type ThreadId = fortanix_sgx_abi::Tcs; + +pub use super::abi::thread::current; + +pub fn park(_hint: usize) { + usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap(); +} + +pub fn park_timeout(dur: Duration, _hint: usize) { + let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64; + if let Err(e) = usercalls::wait(EV_UNPARK, timeout) { + assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock)) + } +} + +pub fn unpark(tid: ThreadId, _hint: usize) { + let _ = usercalls::send(EV_UNPARK, Some(tid)); +} diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index 73ff10ab8a2..0f704994f55 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -1,7 +1,7 @@ //! Android ABI-compatibility module //! -//! The ABI of Android has changed quite a bit over time, and libstd attempts to -//! be both forwards and backwards compatible as much as possible. We want to +//! The ABI of Android has changed quite a bit over time, and std attempts to be +//! both forwards and backwards compatible as much as possible. We want to //! always work with the most recent version of Android, but we also want to //! work with older versions of Android for whenever projects need to. //! diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 83a43b6ee26..30a96be1430 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -40,7 +40,7 @@ pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; #[cfg(target_os = "espidf")] @@ -164,7 +164,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] { - // We don't want to add this as a public type to libstd, nor do we + // We don't want to add this as a public type to std, nor do we // want to `include!` a file from the compiler (which would break // Miri and xargo for example), so we choose to duplicate these // constants from `compiler/rustc_session/src/config/sigpipe.rs`. @@ -184,12 +184,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)), _ => unreachable!(), }; - // The bootstrap compiler doesn't know about sigpipe::DEFAULT, and always passes in - // SIG_IGN. This causes some tests to fail because they expect SIGPIPE to be reset to - // default on process spawning (which doesn't happen if #[unix_sigpipe] is specified). - // Since we can't differentiate between the cases here, treat SIG_IGN as DEFAULT - // unconditionally. - if sigpipe_attr_specified && !(cfg!(bootstrap) && sigpipe == sigpipe::SIG_IGN) { + if sigpipe_attr_specified { UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index b84bf8f9264..c86f80972a6 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -512,7 +512,7 @@ impl FromRawFd for Socket { // A workaround for this bug is to call the res_init libc function, to clear // the cached configs. Unfortunately, while we believe glibc's implementation // of res_init is thread-safe, we know that other implementations are not -// (https://github.com/rust-lang/rust/issues/43592). Code here in libstd could +// (https://github.com/rust-lang/rust/issues/43592). Code here in std could // try to synchronize its res_init calls with a Mutex, but that wouldn't // protect programs that call into libc in other ways. So instead of calling // res_init unconditionally, we call it only when we detect we're linking diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 848adca78c0..afd03d79c0b 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -144,6 +144,7 @@ pub enum ChildStdio { Null, } +#[derive(Debug)] pub enum Stdio { Inherit, Null, @@ -510,16 +511,68 @@ impl ChildStdio { } impl fmt::Debug for Command { + // show all attributes but `self.closures` which does not implement `Debug` + // and `self.argv` which is not useful for debugging fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.program != self.args[0] { - write!(f, "[{:?}] ", self.program)?; - } - write!(f, "{:?}", self.args[0])?; + if f.alternate() { + let mut debug_command = f.debug_struct("Command"); + debug_command.field("program", &self.program).field("args", &self.args); + if !self.env.is_unchanged() { + debug_command.field("env", &self.env); + } + + if self.cwd.is_some() { + debug_command.field("cwd", &self.cwd); + } + if self.uid.is_some() { + debug_command.field("uid", &self.uid); + } + if self.gid.is_some() { + debug_command.field("gid", &self.gid); + } + + if self.groups.is_some() { + debug_command.field("groups", &self.groups); + } + + if self.stdin.is_some() { + debug_command.field("stdin", &self.stdin); + } + if self.stdout.is_some() { + debug_command.field("stdout", &self.stdout); + } + if self.stderr.is_some() { + debug_command.field("stderr", &self.stderr); + } + if self.pgroup.is_some() { + debug_command.field("pgroup", &self.pgroup); + } + + #[cfg(target_os = "linux")] + { + debug_command.field("create_pidfd", &self.create_pidfd); + } - for arg in &self.args[1..] { - write!(f, " {:?}", arg)?; + debug_command.finish() + } else { + if let Some(ref cwd) = self.cwd { + write!(f, "cd {cwd:?} && ")?; + } + for (key, value_opt) in self.get_envs() { + if let Some(value) = value_opt { + write!(f, "{}={value:?} ", key.to_string_lossy())?; + } + } + if self.program != self.args[0] { + write!(f, "[{:?}] ", self.program)?; + } + write!(f, "{:?}", self.args[0])?; + + for arg in &self.args[1..] { + write!(f, " {:?}", arg)?; + } + Ok(()) } - Ok(()) } } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index d847f2775ab..b251949bda2 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -505,7 +505,7 @@ mod cgroups { let limit = raw_quota.next()?; let period = raw_quota.next()?; match (limit.parse::<usize>(), period.parse::<usize>()) { - (Ok(limit), Ok(period)) => { + (Ok(limit), Ok(period)) if period > 0 => { quota = quota.min(limit / period); } _ => {} @@ -565,7 +565,7 @@ mod cgroups { let period = parse_file("cpu.cfs_period_us"); match (limit, period) { - (Some(limit), Some(period)) => quota = quota.min(limit / period), + (Some(limit), Some(period)) if period > 0 => quota = quota.min(limit / period), _ => {} } diff --git a/library/std/src/sys/unix/thread_parker/netbsd.rs b/library/std/src/sys/unix/thread_parker/netbsd.rs deleted file mode 100644 index 7657605b52f..00000000000 --- a/library/std/src/sys/unix/thread_parker/netbsd.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::ffi::{c_int, c_void}; -use crate::pin::Pin; -use crate::ptr::{null, null_mut}; -use crate::sync::atomic::{ - AtomicU64, - Ordering::{Acquire, Relaxed, Release}, -}; -use crate::time::Duration; -use libc::{_lwp_self, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC}; - -extern "C" { - fn ___lwp_park60( - clock_id: clockid_t, - flags: c_int, - ts: *mut timespec, - unpark: lwpid_t, - hint: *const c_void, - unparkhint: *const c_void, - ) -> c_int; - fn _lwp_unpark(lwp: lwpid_t, hint: *const c_void) -> c_int; -} - -/// The thread is not parked and the token is not available. -/// -/// Zero cannot be a valid LWP id, since it is used as empty value for the unpark -/// argument in _lwp_park. -const EMPTY: u64 = 0; -/// The token is available. Do not park anymore. -const NOTIFIED: u64 = u64::MAX; - -pub struct Parker { - /// The parker state. Contains either one of the two state values above or the LWP - /// id of the parked thread. - state: AtomicU64, -} - -impl Parker { - pub unsafe fn new(parker: *mut Parker) { - parker.write(Parker { state: AtomicU64::new(EMPTY) }) - } - - // Does not actually need `unsafe` or `Pin`, but the pthread implementation does. - pub unsafe fn park(self: Pin<&Self>) { - // If the token has already been made available, we can skip - // a bit of work, so check for it here. - if self.state.load(Acquire) != NOTIFIED { - let parked = _lwp_self() as u64; - let hint = self.state.as_mut_ptr().cast(); - if self.state.compare_exchange(EMPTY, parked, Relaxed, Acquire).is_ok() { - // Loop to guard against spurious wakeups. - loop { - ___lwp_park60(0, 0, null_mut(), 0, hint, null()); - if self.state.load(Acquire) == NOTIFIED { - break; - } - } - } - } - - // At this point, the change to NOTIFIED has always been observed with acquire - // ordering, so we can just use a relaxed store here (instead of a swap). - self.state.store(EMPTY, Relaxed); - } - - // Does not actually need `unsafe` or `Pin`, but the pthread implementation does. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - if self.state.load(Acquire) != NOTIFIED { - let parked = _lwp_self() as u64; - let hint = self.state.as_mut_ptr().cast(); - let mut timeout = timespec { - // Saturate so that the operation will definitely time out - // (even if it is after the heat death of the universe). - tv_sec: dur.as_secs().try_into().ok().unwrap_or(time_t::MAX), - tv_nsec: dur.subsec_nanos().into(), - }; - - if self.state.compare_exchange(EMPTY, parked, Relaxed, Acquire).is_ok() { - // Timeout needs to be mutable since it is modified on NetBSD 9.0 and - // above. - ___lwp_park60(CLOCK_MONOTONIC, 0, &mut timeout, 0, hint, null()); - // Use a swap to get acquire ordering even if the token was set after - // the timeout occurred. - self.state.swap(EMPTY, Acquire); - return; - } - } - - self.state.store(EMPTY, Relaxed); - } - - // Does not actually need `Pin`, but the pthread implementation does. - pub fn unpark(self: Pin<&Self>) { - let state = self.state.swap(NOTIFIED, Release); - if !matches!(state, EMPTY | NOTIFIED) { - let lwp = state as lwpid_t; - let hint = self.state.as_mut_ptr().cast(); - - // If the parking thread terminated and did not actually park, this will - // probably return an error, which is OK. In the worst case, another - // thread has received the same LWP id. It will then receive a spurious - // wakeup, but those are allowable per the API contract. The same reasoning - // applies if a timeout occurred before this call, but the state was not - // yet reset. - - // SAFETY: - // The syscall has no invariants to hold. Only unsafe because it is an - // extern function. - unsafe { - _lwp_unpark(lwp, hint); - } - } - } -} diff --git a/library/std/src/sys/unix/thread_parker/darwin.rs b/library/std/src/sys/unix/thread_parking/darwin.rs index 2f5356fe227..b709fada3b4 100644 --- a/library/std/src/sys/unix/thread_parker/darwin.rs +++ b/library/std/src/sys/unix/thread_parking/darwin.rs @@ -46,7 +46,7 @@ unsafe impl Sync for Parker {} unsafe impl Send for Parker {} impl Parker { - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { let semaphore = dispatch_semaphore_create(0); assert!( !semaphore.is_null(), diff --git a/library/std/src/sys/unix/thread_parker/mod.rs b/library/std/src/sys/unix/thread_parking/mod.rs index 35f1e68a87e..185333c072f 100644 --- a/library/std/src/sys/unix/thread_parker/mod.rs +++ b/library/std/src/sys/unix/thread_parking/mod.rs @@ -24,7 +24,7 @@ cfg_if::cfg_if! { pub use darwin::Parker; } else if #[cfg(target_os = "netbsd")] { mod netbsd; - pub use netbsd::Parker; + pub use netbsd::{current, park, park_timeout, unpark, ThreadId}; } else { mod pthread; pub use pthread::Parker; diff --git a/library/std/src/sys/unix/thread_parking/netbsd.rs b/library/std/src/sys/unix/thread_parking/netbsd.rs new file mode 100644 index 00000000000..3be08122138 --- /dev/null +++ b/library/std/src/sys/unix/thread_parking/netbsd.rs @@ -0,0 +1,52 @@ +use crate::ffi::{c_int, c_void}; +use crate::ptr; +use crate::time::Duration; +use libc::{_lwp_self, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC}; + +extern "C" { + fn ___lwp_park60( + clock_id: clockid_t, + flags: c_int, + ts: *mut timespec, + unpark: lwpid_t, + hint: *const c_void, + unparkhint: *const c_void, + ) -> c_int; + fn _lwp_unpark(lwp: lwpid_t, hint: *const c_void) -> c_int; +} + +pub type ThreadId = lwpid_t; + +#[inline] +pub fn current() -> ThreadId { + unsafe { _lwp_self() } +} + +#[inline] +pub fn park(hint: usize) { + unsafe { + ___lwp_park60(0, 0, ptr::null_mut(), 0, ptr::invalid(hint), ptr::null()); + } +} + +pub fn park_timeout(dur: Duration, hint: usize) { + let mut timeout = timespec { + // Saturate so that the operation will definitely time out + // (even if it is after the heat death of the universe). + tv_sec: dur.as_secs().try_into().ok().unwrap_or(time_t::MAX), + tv_nsec: dur.subsec_nanos().into(), + }; + + // Timeout needs to be mutable since it is modified on NetBSD 9.0 and + // above. + unsafe { + ___lwp_park60(CLOCK_MONOTONIC, 0, &mut timeout, 0, ptr::invalid(hint), ptr::null()); + } +} + +#[inline] +pub fn unpark(tid: ThreadId, hint: usize) { + unsafe { + _lwp_unpark(tid, ptr::invalid(hint)); + } +} diff --git a/library/std/src/sys/unix/thread_parker/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs index c400c771567..082d25e68f5 100644 --- a/library/std/src/sys/unix/thread_parker/pthread.rs +++ b/library/std/src/sys/unix/thread_parking/pthread.rs @@ -44,7 +44,8 @@ unsafe fn wait_timeout( target_os = "macos", target_os = "ios", target_os = "watchos", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon", ))] let (now, dur) = { use crate::cmp::min; @@ -70,7 +71,8 @@ unsafe fn wait_timeout( target_os = "macos", target_os = "ios", target_os = "watchos", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon", )))] let (now, dur) = { use crate::sys::time::Timespec; @@ -97,7 +99,7 @@ impl Parker { /// /// # Safety /// The constructed parker must never be moved. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { // Use the default mutex implementation to allow for simpler initialization. // This could lead to undefined behaviour when deadlocking. This is avoided // by not deadlocking. Note in particular the unlocking operation before any diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index f5a4ce929b2..62ffee70bec 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -1,9 +1,8 @@ //! Support for "weak linkage" to symbols on Unix //! -//! Some I/O operations we do in libstd require newer versions of OSes but we -//! need to maintain binary compatibility with older releases for now. In order -//! to use the new functionality when available we use this module for -//! detection. +//! Some I/O operations we do in std require newer versions of OSes but we need +//! to maintain binary compatibility with older releases for now. In order to +//! use the new functionality when available we use this module for detection. //! //! One option to use here is weak linkage, but that is unfortunately only //! really workable with ELF. Otherwise, use dlsym to get the symbol value at @@ -29,7 +28,7 @@ use crate::ptr; use crate::sync::atomic::{self, AtomicPtr, Ordering}; // We can use true weak linkage on ELF targets. -#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))] +#[cfg(not(any(target_os = "macos", target_os = "ios")))] pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { @@ -43,30 +42,14 @@ pub(crate) macro weak { ) } -#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))] -pub(crate) macro weak { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { - extern "C" { - #[linkage = "extern_weak"] - static $name: *const libc::c_void; - } - #[allow(unused_unsafe)] - ExternWeak::new(unsafe { $name }) - }; - ) -} - // On non-ELF targets, use the dlsym approximation of weak linkage. #[cfg(any(target_os = "macos", target_os = "ios"))] pub(crate) use self::dlsym as weak; -#[cfg(not(bootstrap))] pub(crate) struct ExternWeak<F: Copy> { weak_ptr: Option<F>, } -#[cfg(not(bootstrap))] impl<F: Copy> ExternWeak<F> { #[inline] pub(crate) fn new(weak_ptr: Option<F>) -> Self { @@ -79,34 +62,6 @@ impl<F: Copy> ExternWeak<F> { } } -#[cfg(bootstrap)] -pub(crate) struct ExternWeak<F> { - weak_ptr: *const libc::c_void, - _marker: PhantomData<F>, -} - -#[cfg(bootstrap)] -impl<F> ExternWeak<F> { - #[inline] - pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self { - ExternWeak { weak_ptr, _marker: PhantomData } - } -} - -#[cfg(bootstrap)] -impl<F> ExternWeak<F> { - #[inline] - pub(crate) fn get(&self) -> Option<F> { - unsafe { - if self.weak_ptr.is_null() { - None - } else { - Some(mem::transmute_copy::<*const libc::c_void, F>(&self.weak_ptr)) - } - } - } -} - pub(crate) macro dlsym { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index e67411e1686..77359abe429 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -33,7 +33,7 @@ pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parking.rs index 2f7ae863b6a..5d43676adbb 100644 --- a/library/std/src/sys/windows/thread_parker.rs +++ b/library/std/src/sys/windows/thread_parking.rs @@ -97,7 +97,7 @@ const NOTIFIED: i8 = 1; impl Parker { /// Construct the Windows parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Self { state: AtomicI8::new(EMPTY) }); } diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 8807077cb49..f1d804ef40c 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -20,7 +20,7 @@ pub fn lock() -> impl Drop { /// Prints the current backtrace. pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { // There are issues currently linking libbacktrace into tests, and in - // general during libstd's own unit tests we're not testing this path. In + // general during std's own unit tests we're not testing this path. In // test mode immediately return here to optimize away any references to the // libbacktrace symbols if cfg!(test) { @@ -111,7 +111,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that -/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// this is only inline(never) when backtraces in std are enabled, otherwise /// it's fine to optimize away. #[cfg_attr(feature = "backtrace", inline(never))] pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T @@ -127,7 +127,7 @@ where } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that -/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// this is only inline(never) when backtraces in std are enabled, otherwise /// it's fine to optimize away. #[cfg_attr(feature = "backtrace", inline(never))] pub fn __rust_end_short_backtrace<F, T>(f: F) -> T diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index b1987aa0f62..6b24b0e9aa8 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -27,11 +27,10 @@ pub mod lazy_box; pub mod memchr; pub mod once; pub mod process; -pub mod remutex; pub mod thread; pub mod thread_info; pub mod thread_local_dtor; -pub mod thread_parker; +pub mod thread_parking; pub mod wstr; pub mod wtf8; diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index ae11412067b..18883048dae 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -4,12 +4,13 @@ use crate::collections::BTreeMap; use crate::env; use crate::ffi::{OsStr, OsString}; +use crate::fmt; use crate::io; use crate::sys::pipe::read2; use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes}; // Stores a set of changes to an environment -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct CommandEnv { clear: bool, saw_path: bool, @@ -22,6 +23,14 @@ impl Default for CommandEnv { } } +impl fmt::Debug for CommandEnv { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut debug_command_env = f.debug_struct("CommandEnv"); + debug_command_env.field("clear", &self.clear).field("vars", &self.vars); + debug_command_env.finish() + } +} + impl CommandEnv { // Capture the current environment with these changes applied pub fn capture(&self) -> BTreeMap<EnvKey, OsString> { diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index 747579f1781..2672a2a75b0 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -117,10 +117,14 @@ pub struct Key { /// This value specifies no destructor by default. pub const INIT: StaticKey = StaticKey::new(None); +// Define a sentinel value that is unlikely to be returned +// as a TLS key (but it may be returned). +const KEY_SENTVAL: usize = 0; + impl StaticKey { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> StaticKey { - StaticKey { key: atomic::AtomicUsize::new(0), dtor } + StaticKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } /// Gets the value associated with this TLS key @@ -144,31 +148,36 @@ impl StaticKey { #[inline] unsafe fn key(&self) -> imp::Key { match self.key.load(Ordering::Relaxed) { - 0 => self.lazy_init() as imp::Key, + KEY_SENTVAL => self.lazy_init() as imp::Key, n => n as imp::Key, } } unsafe fn lazy_init(&self) -> usize { - // POSIX allows the key created here to be 0, but the compare_exchange - // below relies on using 0 as a sentinel value to check who won the + // POSIX allows the key created here to be KEY_SENTVAL, but the compare_exchange + // below relies on using KEY_SENTVAL as a sentinel value to check who won the // race to set the shared TLS key. As far as I know, there is no // guaranteed value that cannot be returned as a posix_key_create key, // so there is no value we can initialize the inner key with to // prove that it has not yet been set. As such, we'll continue using a - // value of 0, but with some gyrations to make sure we have a non-0 + // value of KEY_SENTVAL, but with some gyrations to make sure we have a non-KEY_SENTVAL // value returned from the creation routine. // FIXME: this is clearly a hack, and should be cleaned up. let key1 = imp::create(self.dtor); - let key = if key1 != 0 { + let key = if key1 as usize != KEY_SENTVAL { key1 } else { let key2 = imp::create(self.dtor); imp::destroy(key1); key2 }; - rtassert!(key != 0); - match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) { + rtassert!(key as usize != KEY_SENTVAL); + match self.key.compare_exchange( + KEY_SENTVAL, + key as usize, + Ordering::SeqCst, + Ordering::SeqCst, + ) { // The CAS succeeded, so we've created the actual key Ok(_) => key as usize, // If someone beat us to the punch, use their key instead diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parking/futex.rs index d9e2f39e345..588e7b27826 100644 --- a/library/std/src/sys_common/thread_parker/futex.rs +++ b/library/std/src/sys_common/thread_parking/futex.rs @@ -35,7 +35,7 @@ pub struct Parker { impl Parker { /// Construct the futex parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Self { state: AtomicU32::new(EMPTY) }); } diff --git a/library/std/src/sys_common/thread_parker/generic.rs b/library/std/src/sys_common/thread_parking/generic.rs index f3d8b34d3fd..3209bffe353 100644 --- a/library/std/src/sys_common/thread_parker/generic.rs +++ b/library/std/src/sys_common/thread_parking/generic.rs @@ -19,7 +19,7 @@ pub struct Parker { impl Parker { /// Construct the generic parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Parker { state: AtomicUsize::new(EMPTY), lock: Mutex::new(()), diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs new file mode 100644 index 00000000000..e98169597c3 --- /dev/null +++ b/library/std/src/sys_common/thread_parking/id.rs @@ -0,0 +1,108 @@ +//! Thread parking using thread ids. +//! +//! Some platforms (notably NetBSD) have thread parking primitives whose semantics +//! match those offered by `thread::park`, with the difference that the thread to +//! be unparked is referenced by a platform-specific thread id. Since the thread +//! parker is constructed before that id is known, an atomic state variable is used +//! to manage the park state and propagate the thread id. This also avoids platform +//! calls in the case where `unpark` is called before `park`. + +use crate::cell::UnsafeCell; +use crate::pin::Pin; +use crate::sync::atomic::{ + fence, AtomicI8, + Ordering::{Acquire, Relaxed, Release}, +}; +use crate::sys::thread_parking::{current, park, park_timeout, unpark, ThreadId}; +use crate::time::Duration; + +pub struct Parker { + state: AtomicI8, + tid: UnsafeCell<Option<ThreadId>>, +} + +const PARKED: i8 = -1; +const EMPTY: i8 = 0; +const NOTIFIED: i8 = 1; + +impl Parker { + pub fn new() -> Parker { + Parker { state: AtomicI8::new(EMPTY), tid: UnsafeCell::new(None) } + } + + /// Create a new thread parker. UNIX requires this to happen in-place. + pub unsafe fn new_in_place(parker: *mut Parker) { + parker.write(Parker::new()) + } + + /// # Safety + /// * must always be called from the same thread + /// * must be called before the state is set to PARKED + unsafe fn init_tid(&self) { + // The field is only ever written to from this thread, so we don't need + // synchronization to read it here. + if self.tid.get().read().is_none() { + // Because this point is only reached once, before the state is set + // to PARKED for the first time, the non-atomic write here can not + // conflict with reads by other threads. + self.tid.get().write(Some(current())); + // Ensure that the write can be observed by all threads reading the + // state. Synchronizes with the acquire barrier in `unpark`. + fence(Release); + } + } + + pub unsafe fn park(self: Pin<&Self>) { + self.init_tid(); + + // Changes NOTIFIED to EMPTY and EMPTY to PARKED. + let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); + if state == PARKED { + // Loop to guard against spurious wakeups. + while state == PARKED { + park(self.state.as_mut_ptr().addr()); + state = self.state.load(Acquire); + } + + // Since the state change has already been observed with acquire + // ordering, the state can be reset with a relaxed store instead + // of a swap. + self.state.store(EMPTY, Relaxed); + } + } + + pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { + self.init_tid(); + + let state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); + if state == PARKED { + park_timeout(dur, self.state.as_mut_ptr().addr()); + // Swap to ensure that we observe all state changes with acquire + // ordering, even if the state has been changed after the timeout + // occured. + self.state.swap(EMPTY, Acquire); + } + } + + pub fn unpark(self: Pin<&Self>) { + let state = self.state.swap(NOTIFIED, Release); + if state == PARKED { + // Synchronize with the release fence in `init_tid` to observe the + // write to `tid`. + fence(Acquire); + // # Safety + // The thread id is initialized before the state is set to `PARKED` + // for the first time and is not written to from that point on + // (negating the need for an atomic read). + let tid = unsafe { self.tid.get().read().unwrap_unchecked() }; + // It is possible that the waiting thread woke up because of a timeout + // and terminated before this call is made. This call then returns an + // error or wakes up an unrelated thread. The platform API and + // environment does allow this, however. + unpark(tid, self.state.as_mut_ptr().addr()); + } + } +} + +unsafe impl Send for Parker {} +unsafe impl Sync for Parker {} diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parking/mod.rs index 08a2bdd8229..0ead6633c35 100644 --- a/library/std/src/sys_common/thread_parker/mod.rs +++ b/library/std/src/sys_common/thread_parking/mod.rs @@ -11,13 +11,17 @@ cfg_if::cfg_if! { ))] { mod futex; pub use futex::Parker; + } else if #[cfg(any( + target_os = "netbsd", + all(target_vendor = "fortanix", target_env = "sgx"), + ))] { + mod id; + pub use id::Parker; } else if #[cfg(target_os = "solid_asp3")] { mod wait_flag; pub use wait_flag::Parker; } else if #[cfg(any(windows, target_family = "unix"))] { - pub use crate::sys::thread_parker::Parker; - } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { - pub use crate::sys::thread_parker::Parker; + pub use crate::sys::thread_parking::Parker; } else { mod generic; pub use generic::Parker; diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parking/wait_flag.rs index 6561c186655..d0f8899a94e 100644 --- a/library/std/src/sys_common/thread_parker/wait_flag.rs +++ b/library/std/src/sys_common/thread_parking/wait_flag.rs @@ -41,7 +41,7 @@ pub struct Parker { impl Parker { /// Construct a parker for the current thread. The UNIX parker /// implementation requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() }) } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 5d267891bb0..b30bb7b77ef 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -905,9 +905,8 @@ pub mod statik { pub mod fast { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::mem; use crate::sys::thread_local_dtor::register_dtor; + use crate::{fmt, mem, panic}; #[derive(Copy, Clone)] enum DtorState { @@ -950,7 +949,7 @@ pub mod fast { // note that this is just a publicly-callable function only for the // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in libstd. + // free `register_dtor` function defined elsewhere in std. pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { unsafe { register_dtor(a, dtor); @@ -1028,10 +1027,15 @@ pub mod fast { // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This // causes future calls to `get` to run `try_initialize_drop` again, // which will now fail, and return `None`. - unsafe { + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { let value = (*ptr).inner.take(); (*ptr).dtor_state.set(DtorState::RunningOrHasRun); drop(value); + })) { + rtabort!("thread local panicked on drop"); } } } @@ -1044,10 +1048,8 @@ pub mod fast { pub mod os { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::marker; - use crate::ptr; use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; + use crate::{fmt, marker, panic, ptr}; /// Use a regular global static to store this key; the state provided will then be /// thread-local. @@ -1137,12 +1139,17 @@ pub mod os { // // Note that to prevent an infinite loop we reset it back to null right // before we return from the destructor ourselves. - unsafe { + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(|| unsafe { let ptr = Box::from_raw(ptr as *mut Value<T>); let key = ptr.key; key.os.set(ptr::invalid_mut(1)); drop(ptr); key.os.set(ptr::null_mut()); + }) { + rtabort!("thread local panicked on drop"); } } } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 34bdb8bd461..7acda8e98f1 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -173,7 +173,7 @@ use crate::sync::Arc; use crate::sys::thread as imp; use crate::sys_common::thread; use crate::sys_common::thread_info; -use crate::sys_common::thread_parker::Parker; +use crate::sys_common::thread_parking::Parker; use crate::sys_common::{AsInner, IntoInner}; use crate::time::Duration; @@ -1216,7 +1216,7 @@ impl Thread { let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); addr_of_mut!((*ptr).name).write(name); addr_of_mut!((*ptr).id).write(ThreadId::new()); - Parker::new(addr_of_mut!((*ptr).parker)); + Parker::new_in_place(addr_of_mut!((*ptr).parker)); Pin::new_unchecked(arc.assume_init()) }; diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 02c076f1bb5..1a2c1255661 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -1,9 +1,8 @@ -//! These tests just check that the macros are available in libstd. +//! These tests just check that the macros are available in std. #![cfg_attr( any( all(target_arch = "arm", any(target_os = "linux", target_os = "android")), - all(bootstrap, target_arch = "aarch64", any(target_os = "linux", target_os = "android")), all(target_arch = "powerpc", target_os = "linux"), all(target_arch = "powerpc64", target_os = "linux"), ), diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 0fa11f3761a..036a35869a5 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -88,7 +88,7 @@ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); // FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in -// the block are reexported in dylib build of libstd. This is needed when build rustc with +// the block are reexported in dylib build of std. This is needed when build rustc with // feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols. // However the `link` attribute is duplicated multiple times and does not just export symbol, // a better way to manually export symbol would be another attribute like `#[export]`. diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 64b74ecc9de..4105fa5ec96 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended. - `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag - `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. +- `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702) ### Non-breaking changes diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2d5018d934e..9cf43fc7a21 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -753,6 +753,9 @@ class RustBuild(object): target_features += ["-crt-static"] if target_features: env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features)) + target_linker = self.get_toml("linker", build_section) + if target_linker is not None: + env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros" if self.get_toml("deny-warnings", "rust") != "false": diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 707e4169002..b54bf432621 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -97,18 +97,36 @@ impl RunConfig<'_> { self.builder.build.build } - /// Return a `-p=x -p=y` string suitable for passing to a cargo invocation. + /// Return a list of crate names selected by `run.paths`. pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> { let mut crates = Vec::new(); for krate in &self.paths { let path = krate.assert_single_path(); let crate_name = self.builder.crate_paths[&path.path]; - crates.push(format!("-p={crate_name}")); + crates.push(crate_name.to_string()); } INTERNER.intern_list(crates) } } +/// A description of the crates in this set, suitable for passing to `builder.info`. +/// +/// `crates` should be generated by [`RunConfig::cargo_crates_in_set`]. +pub fn crate_description(crates: &[impl AsRef<str>]) -> String { + if crates.is_empty() { + return "".into(); + } + + let mut descr = String::from(" {"); + descr.push_str(crates[0].as_ref()); + for krate in &crates[1..] { + descr.push_str(", "); + descr.push_str(krate.as_ref()); + } + descr.push('}'); + descr +} + struct StepDescription { default: bool, only_hosts: bool, @@ -644,6 +662,7 @@ impl<'a> Builder<'a> { crate::toolstate::ToolStateCheck, test::ExpandYamlAnchors, test::Tidy, + test::TidySelfTest, test::Ui, test::RunPassValgrind, test::MirOpt, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2e1bd8d6d1f..32e5d414061 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -99,19 +99,13 @@ impl Step for Std { cargo_subcommand(builder.kind), ); std_cargo(builder, target, compiler.stage, &mut cargo); + cargo.args(args(builder)); builder.info(&format!( - "Checking stage{} std artifacts ({} -> {})", + "Checking stage{} library artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo( - builder, - cargo, - args(builder), - &libstd_stamp(builder, compiler, target), - vec![], - true, - ); + run_cargo(builder, cargo, &libstd_stamp(builder, compiler, target), vec![], true); // We skip populating the sysroot in non-zero stage because that'll lead // to rlib/rmeta conflicts if std gets built during this session. @@ -155,19 +149,13 @@ impl Step for Std { for krate in builder.in_tree_crates("test", Some(target)) { cargo.arg("-p").arg(krate.name); } + cargo.args(args(builder)); builder.info(&format!( - "Checking stage{} std test/bench/example targets ({} -> {})", + "Checking stage{} library test/bench/example targets ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo( - builder, - cargo, - args(builder), - &libstd_test_stamp(builder, compiler, target), - vec![], - true, - ); + run_cargo(builder, cargo, &libstd_test_stamp(builder, compiler, target), vec![], true); } } @@ -231,19 +219,13 @@ impl Step for Rustc { for krate in builder.in_tree_crates("rustc-main", Some(target)) { cargo.arg("-p").arg(krate.name); } + cargo.args(args(builder)); builder.info(&format!( "Checking stage{} compiler artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo( - builder, - cargo, - args(builder), - &librustc_stamp(builder, compiler, target), - vec![], - true, - ); + run_cargo(builder, cargo, &librustc_stamp(builder, compiler, target), vec![], true); let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); @@ -290,6 +272,7 @@ impl Step for CodegenBackend { .arg("--manifest-path") .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); rustc_cargo_env(builder, &mut cargo, target); + cargo.args(args(builder)); builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", @@ -299,7 +282,6 @@ impl Step for CodegenBackend { run_cargo( builder, cargo, - args(builder), &codegen_backend_stamp(builder, compiler, target, backend), vec![], true, @@ -355,11 +337,13 @@ impl Step for RustAnalyzer { cargo.arg("--benches"); } + cargo.args(args(builder)); + builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple )); - run_cargo(builder, cargo, args(builder), &stamp(builder, compiler, target), vec![], true); + run_cargo(builder, cargo, &stamp(builder, compiler, target), vec![], true); /// Cargo's output path in a given stage, compiled by a particular /// compiler for the specified target. @@ -413,6 +397,8 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } + cargo.args(args(builder)); + // Enable internal lints for clippy and rustdoc // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 @@ -428,7 +414,6 @@ macro_rules! tool_check_step { run_cargo( builder, cargo, - args(builder), &stamp(builder, compiler, target), vec![], true, diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 303c5603be7..468efc1114c 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -9,11 +9,10 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; -use crate::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; use crate::cache::Interned; -use crate::config::TargetSelection; use crate::util::t; -use crate::{Build, Mode, Subcommand}; +use crate::{Build, Compiler, Mode, Subcommand}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct CleanAll {} @@ -40,7 +39,7 @@ macro_rules! clean_crate_tree { ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $( #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct $name { - target: TargetSelection, + compiler: Compiler, crates: Interned<Vec<String>>, } @@ -54,22 +53,21 @@ macro_rules! clean_crate_tree { fn make_run(run: RunConfig<'_>) { let builder = run.builder; - if builder.top_stage != 0 { - panic!("non-stage-0 clean not supported for individual crates"); - } - builder.ensure(Self { crates: run.cargo_crates_in_set(), target: run.target }); + let compiler = builder.compiler(builder.top_stage, run.target); + builder.ensure(Self { crates: run.cargo_crates_in_set(), compiler }); } fn run(self, builder: &Builder<'_>) -> Self::Output { - let compiler = builder.compiler(0, self.target); - let mut cargo = builder.bare_cargo(compiler, $mode, self.target, "clean"); + let compiler = self.compiler; + let target = compiler.host; + let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean"); for krate in &*self.crates { cargo.arg(krate); } builder.info(&format!( - "Cleaning stage{} {} artifacts ({} -> {})", - compiler.stage, stringify!($name).to_lowercase(), &compiler.host, self.target + "Cleaning{} stage{} {} artifacts ({} -> {})", + crate_description(&self.crates), compiler.stage, stringify!($name).to_lowercase(), &compiler.host, target, )); // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file, @@ -94,6 +92,7 @@ fn clean_default(build: &Build, all: bool) { rm_rf(&build.out.join("tmp")); rm_rf(&build.out.join("dist")); rm_rf(&build.out.join("bootstrap")); + rm_rf(&build.out.join("rustfmt.stamp")); for host in &build.hosts { let entries = match build.out.join(host.triple).read_dir() { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 427e1a3863e..f9a04f2e91d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -18,6 +18,7 @@ use std::str; use serde::Deserialize; +use crate::builder::crate_description; use crate::builder::Cargo; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; @@ -110,7 +111,10 @@ impl Step for Std { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { builder.ensure(Std::new(compiler_to_use, target)); - builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target)); + builder.info(&format!( + "Uplifting stage1 library ({} -> {})", + compiler_to_use.host, target + )); // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. @@ -126,19 +130,18 @@ impl Step for Std { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build"); std_cargo(builder, target, compiler.stage, &mut cargo); + for krate in &*self.crates { + cargo.arg("-p").arg(krate); + } builder.info(&format!( - "Building stage{} std artifacts ({} -> {})", - compiler.stage, &compiler.host, target + "Building{} stage{} library artifacts ({} -> {})", + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target, )); - run_cargo( - builder, - cargo, - self.crates.to_vec(), - &libstd_stamp(builder, compiler, target), - target_deps, - false, - ); + run_cargo(builder, cargo, &libstd_stamp(builder, compiler, target), target_deps, false); builder.ensure(StdLink::from_std( self, @@ -425,7 +428,7 @@ impl Step for StdLink { let target_compiler = self.target_compiler; let target = self.target; builder.info(&format!( - "Copying stage{} std from stage{} ({} -> {} / {})", + "Copying stage{} library from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target )); let libdir = builder.sysroot_libdir(target_compiler, target); @@ -691,7 +694,8 @@ impl Step for Rustc { )); } - // cfg(bootstrap): remove if condition once the bootstrap compiler supports dylib LTO + // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary + // and may just be a time sink. if compiler.stage != 0 { match builder.config.rust_lto { RustcLto::Thin | RustcLto::Fat => { @@ -713,18 +717,18 @@ impl Step for Rustc { } } + for krate in &*self.crates { + cargo.arg("-p").arg(krate); + } + builder.info(&format!( - "Building stage{} compiler artifacts ({} -> {})", - compiler.stage, &compiler.host, target + "Building{} stage{} compiler artifacts ({} -> {})", + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target, )); - run_cargo( - builder, - cargo, - self.crates.to_vec(), - &librustc_stamp(builder, compiler, target), - vec![], - false, - ); + run_cargo(builder, cargo, &librustc_stamp(builder, compiler, target), vec![], false); builder.ensure(RustcLink::from_rustc( self, @@ -980,7 +984,7 @@ impl Step for CodegenBackend { "Building stage{} codegen backend {} ({} -> {})", compiler.stage, backend, &compiler.host, target )); - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); + let files = run_cargo(builder, cargo, &tmp_stamp, vec![], false); if builder.config.dry_run() { return; } @@ -1404,7 +1408,6 @@ pub fn add_to_sysroot( pub fn run_cargo( builder: &Builder<'_>, cargo: Cargo, - tail_args: Vec<String>, stamp: &Path, additional_target_deps: Vec<(PathBuf, DependencyType)>, is_check: bool, @@ -1430,7 +1433,7 @@ pub fn run_cargo( // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { + let ok = stream_cargo(builder, cargo, &mut |msg| { let (filenames, crate_types) = match msg { CargoMessage::CompilerArtifact { filenames, @@ -1545,7 +1548,6 @@ pub fn run_cargo( pub fn stream_cargo( builder: &Builder<'_>, cargo: Cargo, - tail_args: Vec<String>, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { let mut cargo = Command::from(cargo); @@ -1565,10 +1567,6 @@ pub fn stream_cargo( } cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); - for arg in tail_args { - cargo.arg(arg); - } - builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 6b139decb55..31cc4aa57bb 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -405,7 +405,9 @@ if 'target' in config: configured_targets.append(target) for target in configured_targets: targets[target] = sections['target'][:] - targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target)) + # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target. + # Avoid using quotes unless it's necessary. + targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) def is_number(value): diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5838049aa5c..9bad9046ecc 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -12,6 +12,7 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; +use crate::builder::crate_description; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; @@ -506,7 +507,11 @@ impl Step for Std { // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. for requested_crate in requested_crates { - if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) { + if requested_crate == "library" { + // For `x.py doc library --open`, open `std` by default. + let index = out.join("std").join("index.html"); + builder.open_in_browser(index); + } else if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { let index = out.join(requested_crate).join("index.html"); builder.open_in_browser(index); } @@ -554,7 +559,8 @@ fn doc_std( requested_crates: &[String], ) { builder.info(&format!( - "Documenting stage{} std ({}) in {} format", + "Documenting{} stage{} library ({}) in {} format", + crate_description(requested_crates), stage, target, format.as_str() diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 3be7ad4075e..2c6d201d18f 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -352,32 +352,32 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", // fn usage() let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! { - // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths. - // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out. - // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors. - // `Build::new` won't load submodules for the `setup` command. - let cmd = if verbose { - println!("note: updating submodules before printing available paths"); - "build" - } else { - "setup" - }; - let config = Config::parse(&[cmd.to_string()]); - let build = Build::new(config); - let paths = Builder::get_help(&build, subcommand); - println!("{}", opts.usage(subcommand_help)); - if let Some(s) = paths { - if verbose { + if verbose { + // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths. + // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out. + // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors. + // `Build::new` won't load submodules for the `setup` command. + let cmd = if verbose { + println!("note: updating submodules before printing available paths"); + "build" + } else { + "setup" + }; + let config = Config::parse(&[cmd.to_string()]); + let build = Build::new(config); + let paths = Builder::get_help(&build, subcommand); + + if let Some(s) = paths { println!("{}", s); } else { - println!( - "Run `./x.py {} -h -v` to see a list of available paths.", - subcommand.as_str() - ); + panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - } else if verbose { - panic!("No paths available for subcommand `{}`", subcommand.as_str()); + } else { + println!( + "Run `./x.py {} -h -v` to see a list of available paths.", + subcommand.as_str() + ); } crate::detail_exit(exit_code); }; diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index b2f6afead79..84e46118959 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. use crate::builder::Builder; -use crate::util::{output, t}; +use crate::util::{output, program_out_of_date, t}; use ignore::WalkBuilder; use std::collections::VecDeque; use std::path::{Path, PathBuf}; @@ -44,6 +44,86 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F } } +fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { + let stamp_file = build.out.join("rustfmt.stamp"); + + let mut cmd = Command::new(match build.initial_rustfmt() { + Some(p) => p, + None => return None, + }); + cmd.arg("--version"); + let output = match cmd.output() { + Ok(status) => status, + Err(_) => return None, + }; + if !output.status.success() { + return None; + } + Some((String::from_utf8(output.stdout).unwrap(), stamp_file)) +} + +/// Return whether the format cache can be reused. +fn verify_rustfmt_version(build: &Builder<'_>) -> bool { + let Some((version, stamp_file)) = get_rustfmt_version(build) else {return false;}; + !program_out_of_date(&stamp_file, &version) +} + +/// Updates the last rustfmt version used +fn update_rustfmt_version(build: &Builder<'_>) { + let Some((version, stamp_file)) = get_rustfmt_version(build) else {return;}; + t!(std::fs::write(stamp_file, version)) +} + +/// Returns the Rust files modified between the `merge-base` of HEAD and +/// rust-lang/master and what is now on the disk. +/// +/// Returns `None` if all files should be formatted. +fn get_modified_rs_files(build: &Builder<'_>) -> Option<Vec<String>> { + let Ok(remote) = get_rust_lang_rust_remote() else { return None; }; + if !verify_rustfmt_version(build) { + return None; + } + + let merge_base = + output(build.config.git().arg("merge-base").arg(&format!("{remote}/master")).arg("HEAD")); + Some( + output(build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim())) + .lines() + .map(|s| s.trim().to_owned()) + .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs")) + .collect(), + ) +} + +/// Finds the remote for rust-lang/rust. +/// For example for these remotes it will return `upstream`. +/// ```text +/// origin https://github.com/Nilstrieb/rust.git (fetch) +/// origin https://github.com/Nilstrieb/rust.git (push) +/// upstream https://github.com/rust-lang/rust (fetch) +/// upstream https://github.com/rust-lang/rust (push) +/// ``` +fn get_rust_lang_rust_remote() -> Result<String, String> { + let mut git = Command::new("git"); + git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]); + + let output = git.output().map_err(|err| format!("{err:?}"))?; + if !output.status.success() { + return Err("failed to execute git config command".to_owned()); + } + + let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?; + + let rust_lang_remote = stdout + .lines() + .find(|remote| remote.contains("rust-lang")) + .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; + + let remote_name = + rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; + Ok(remote_name.into()) +} + #[derive(serde::Deserialize)] struct RustfmtConfig { ignore: Vec<String>, @@ -110,6 +190,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // preventing the latter from being formatted. ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path); } + if !check && paths.is_empty() { + if let Some(files) = get_modified_rs_files(build) { + for file in files { + println!("formatting modified file {file}"); + ignore_fmt.add(&format!("/{file}")).expect(&file); + } + } + } } else { println!("Not in git tree. Skipping git-aware format checks"); } @@ -187,4 +275,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { drop(tx); thread.join().unwrap(); + if !check { + update_rustfmt_version(build); + } } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0d9c22e210f..ea906be7e3a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -11,6 +11,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use crate::builder::crate_description; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::Interned; use crate::compile; @@ -1048,7 +1049,7 @@ impl Step for RustdocGUI { if entry.file_name() == "link_to_definition" { cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition"); } else if entry.file_name() == "scrape_examples" { - cargo.arg("-Zrustdoc-scrape-examples=examples"); + cargo.arg("-Zrustdoc-scrape-examples"); } builder.run(&mut cargo); } @@ -1142,6 +1143,40 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` } } +/// Runs tidy's own tests. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TidySelfTest; + +impl Step for TidySelfTest { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("tidyselftest") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(TidySelfTest); + } + + fn run(self, builder: &Builder<'_>) { + let bootstrap_host = builder.config.build; + let compiler = builder.compiler(0, bootstrap_host); + let cargo = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolBootstrap, + bootstrap_host, + "test", + "src/tools/tidy", + SourceType::InTree, + &[], + ); + try_run(builder, &mut cargo.into()); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ExpandYamlAnchors; @@ -2154,8 +2189,12 @@ impl Step for Crate { } builder.info(&format!( - "{} {:?} stage{} ({} -> {})", - test_kind, self.crates, compiler.stage, &compiler.host, target + "{}{} stage{} ({} -> {})", + test_kind, + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target )); let _time = util::timeit(&builder); try_run(builder, &mut cargo.into()); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 24b033cc0dc..63026bd44d4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -72,7 +72,7 @@ impl Step for ToolBuild { builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { + let is_expected = compile::stream_cargo(builder, cargo, &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {} diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index 78fee152eb9..dc0e591cad6 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -32,5 +32,4 @@ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-require COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ -ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 -ENV SCRIPT python3 ../x.py test --stage 0 src/tools/tidy +ENV SCRIPT python3 ../x.py test --stage 0 src/tools/tidy tidyselftest diff --git a/src/ci/run.sh b/src/ci/run.sh index b6430027750..0db9c993eec 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -184,11 +184,11 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then $SRC/configure --set rust.parallel-compiler # Save the build metrics before we wipe the directory - if [ $HAS_METRICS = 1 ]; then + if [ "$HAS_METRICS" = 1 ]; then mv build/metrics.json . fi rm -rf build - if [ $HAS_METRICS = 1 ]; then + if [ "$HAS_METRICS" = 1 ]; then mkdir build mv metrics.json build fi diff --git a/src/doc/book b/src/doc/book -Subproject a60f4316ec923a5ac2ed6a2eba6960edb832d85 +Subproject 2bd5d42c9956369132228da6409f0e68da56c51 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject dd37e21ccee43918ed18a71581bb2af537ffe4f +Subproject 8ca261268068d80c0969260fff15199bad87b58 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 995df09b65c582eb6290ab7ea5d9485983eb4c3 +Subproject 8888f9428fe9a48f31de6bd2cef9b9bf80791ed diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 8b42eb5f57d3d8ed2257a22d0e850d9db52afed +Subproject b3e2a6e6c8a3aae5b5d950c63046f23bae07096 diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 5859df83f64..f291cde2e5a 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -1,7 +1,10 @@ # Targets `rustc` is a cross-compiler by default. This means that you can use any compiler to build for any -architecture. The list of *targets* are the possible architectures that you can build for. +architecture. The list of *targets* are the possible architectures that you can build for. See +the [Platform Support](../platform-support.md) page for a detailed list of targets, or +[Built-in Targets](built-in.md) for instructions on how to view what is available for your version +of `rustc`. To see all the options that you can set with a target, see the docs [here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.Target.html). diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index e3b08648999..8ecf05f0e12 100644 --- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -9,11 +9,11 @@ are the same: ```rust,no_run /// This is a doc comment. -#[doc = " This is a doc comment."] +#[doc = r" This is a doc comment."] # fn f() {} ``` -(Note the leading space in the attribute version.) +(Note the leading space and the raw string literal in the attribute version.) In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is when generating documentation in macros; the `collapse-docs` pass will combine multiple diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 92886bbfe26..07a9c48365f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1612,7 +1612,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T match ty.kind { TyKind::Never => Primitive(PrimitiveType::Never), TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))), - TyKind::Rptr(ref l, ref m) => { + TyKind::Ref(ref l, ref m) => { let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) }; BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } @@ -1853,7 +1853,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Placeholder(..) => panic!("Placeholder"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), - ty::Error(_) => panic!("Error"), + ty::Error(_) => rustc_errors::FatalError.raise(), } } @@ -1949,20 +1949,28 @@ pub(crate) fn clean_field_with_def_id( } pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item { + let discriminant = match variant.discr { + ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), + ty::VariantDiscr::Relative(_) => None, + }; + let kind = match variant.ctor_kind() { - Some(CtorKind::Const) => Variant::CLike(match variant.discr { - ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), - ty::VariantDiscr::Relative(_) => None, - }), - Some(CtorKind::Fn) => Variant::Tuple( + Some(CtorKind::Const) => VariantKind::CLike, + Some(CtorKind::Fn) => VariantKind::Tuple( variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), ), - None => Variant::Struct(VariantStruct { + None => VariantKind::Struct(VariantStruct { ctor_kind: None, fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), }), }; - Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx) + + Item::from_def_id_and_parts( + variant.def_id, + Some(variant.name), + VariantItem(Variant { kind, discriminant }), + cx, + ) } fn clean_variant_data<'tcx>( @@ -1970,19 +1978,23 @@ fn clean_variant_data<'tcx>( disr_expr: &Option<hir::AnonConst>, cx: &mut DocContext<'tcx>, ) -> Variant { - match variant { - hir::VariantData::Struct(..) => Variant::Struct(VariantStruct { + let discriminant = disr_expr.map(|disr| Discriminant { + expr: Some(disr.body), + value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(), + }); + + let kind = match variant { + hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct { ctor_kind: None, fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(), }), hir::VariantData::Tuple(..) => { - Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect()) + VariantKind::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect()) } - hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant { - expr: Some(disr.body), - value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(), - })), - } + hir::VariantData::Unit(..) => VariantKind::CLike, + }; + + Variant { discriminant, kind } } fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7a13e7e36d1..77ec0242621 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -807,8 +807,11 @@ impl ItemKind { match self { StructItem(s) => s.fields.iter(), UnionItem(u) => u.fields.iter(), - VariantItem(Variant::Struct(v)) => v.fields.iter(), - VariantItem(Variant::Tuple(v)) => v.iter(), + VariantItem(v) => match &v.kind { + VariantKind::CLike => [].iter(), + VariantKind::Tuple(t) => t.iter(), + VariantKind::Struct(s) => s.fields.iter(), + }, EnumItem(e) => e.variants.iter(), TraitItem(t) => t.items.iter(), ImplItem(i) => i.items.iter(), @@ -824,7 +827,6 @@ impl ItemKind { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | VariantItem(_) | ForeignFunctionItem(_) | ForeignStaticItem(_) | ForeignTypeItem @@ -1740,7 +1742,7 @@ impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> { let t: PrimitiveType = match *self { Type::Path { ref path } => return Some(path.def_id()), - DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()), + DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), @@ -2136,17 +2138,23 @@ impl Enum { } #[derive(Clone, Debug)] -pub(crate) enum Variant { - CLike(Option<Discriminant>), +pub(crate) struct Variant { + pub kind: VariantKind, + pub discriminant: Option<Discriminant>, +} + +#[derive(Clone, Debug)] +pub(crate) enum VariantKind { + CLike, Tuple(Vec<Item>), Struct(VariantStruct), } impl Variant { pub(crate) fn has_stripped_entries(&self) -> Option<bool> { - match *self { - Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()), - Self::CLike(..) | Self::Tuple(_) => None, + match &self.kind { + VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()), + VariantKind::CLike | VariantKind::Tuple(_) => None, } } } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index c6f1f9de51a..656aeefb01a 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -37,17 +37,21 @@ pub(crate) trait DocFolder: Sized { i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect(); ImplItem(i) } - VariantItem(i) => match i { - Variant::Struct(mut j) => { - j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - VariantItem(Variant::Struct(j)) - } - Variant::Tuple(fields) => { - let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - VariantItem(Variant::Tuple(fields)) - } - Variant::CLike(disr) => VariantItem(Variant::CLike(disr)), - }, + VariantItem(Variant { kind, discriminant }) => { + let kind = match kind { + VariantKind::Struct(mut j) => { + j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantKind::Struct(j) + } + VariantKind::Tuple(fields) => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantKind::Tuple(fields) + } + VariantKind::CLike => VariantKind::CLike, + }; + + VariantItem(Variant { kind, discriminant }) + } ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a7b57c373e3..40dfb069750 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1220,15 +1220,15 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(" "); let name = v.name.unwrap(); match *v.kind { - clean::VariantItem(ref var) => match var { - // FIXME(#101337): Show discriminant - clean::Variant::CLike(..) => write!(w, "{}", name), - clean::Variant::Tuple(ref s) => { + // FIXME(#101337): Show discriminant + clean::VariantItem(ref var) => match var.kind { + clean::VariantKind::CLike => write!(w, "{}", name), + clean::VariantKind::Tuple(ref s) => { write!(w, "{}(", name); print_tuple_struct_fields(w, cx, s); w.write_str(")"); } - clean::Variant::Struct(ref s) => { + clean::VariantKind::Struct(ref s) => { render_struct( w, v, @@ -1286,25 +1286,28 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: " rightside", ); write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); - if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind { + + let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + + if let clean::VariantKind::Tuple(ref s) = variant_data.kind { w.write_str("("); print_tuple_struct_fields(w, cx, s); w.write_str(")"); } w.write_str("</h3></section>"); - use crate::clean::Variant; - - let heading_and_fields = match &*variant.kind { - clean::VariantItem(Variant::Struct(s)) => Some(("Fields", &s.fields)), - // Documentation on tuple variant fields is rare, so to reduce noise we only emit - // the section if at least one field is documented. - clean::VariantItem(Variant::Tuple(fields)) - if fields.iter().any(|f| f.doc_value().is_some()) => - { - Some(("Tuple Fields", fields)) + let heading_and_fields = match &variant_data.kind { + clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), + clean::VariantKind::Tuple(fields) => { + // Documentation on tuple variant fields is rare, so to reduce noise we only emit + // the section if at least one field is documented. + if fields.iter().any(|f| f.doc_value().is_some()) { + Some(("Tuple Fields", fields)) + } else { + None + } } - _ => None, + clean::VariantKind::CLike => None, }; if let Some((heading, fields)) = heading_and_fields { diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 8eb9c07f8a7..2d61519d6c9 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -322,8 +322,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option<RenderTypeId> { match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { - let path = &bounds[0].trait_; - Some(RenderTypeId::DefId(path.def_id())) + bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id())) } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 1ba8d118b76..bc0458bcd28 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -355,10 +355,6 @@ img { max-width: 100%; } -.source .content { - overflow: visible; -} - .sub-logo-container, .logo-container { /* zero text boxes so that computed line height = image height exactly */ line-height: 0; @@ -378,10 +374,6 @@ img { filter: var(--rust-logo-filter); } -.sidebar, .mobile-topbar, .sidebar-menu-toggle { - background-color: var(--sidebar-background-color); -} - .sidebar { font-size: 0.875rem; flex: 0 0 200px; @@ -400,7 +392,8 @@ img { overflow-y: hidden; } -.source .sidebar, #src-sidebar-toggle, #source-sidebar { +.sidebar, .mobile-topbar, .sidebar-menu-toggle, +#src-sidebar-toggle, #source-sidebar { background-color: var(--sidebar-background-color); } @@ -1109,7 +1102,6 @@ pre.rust .doccomment { } .example-wrap .tooltip:hover::after { - text-align: center; padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; @@ -1321,15 +1313,11 @@ a.test-arrow:hover { -webkit-appearance: none; opacity: 1; } + #settings-menu, #help-button { margin-left: 4px; display: flex; } - -#settings-menu > a, #help-button > a, #copy-path { - width: 33px; -} - #settings-menu > a, #help-button > a { display: flex; align-items: center; @@ -1341,6 +1329,7 @@ a.test-arrow:hover { /* Rare exception to specifying font sizes in rem. Since this is acting as an icon, it's okay to specify their sizes in pixels. */ font-size: 20px; + width: 33px; } #settings-menu > a:hover, #settings-menu > a:focus, @@ -1356,6 +1345,7 @@ a.test-arrow:hover { padding: 0; padding-left: 2px; border: 0; + width: 33px; } #copy-path > img { filter: var(--copy-path-img-filter); @@ -1397,31 +1387,10 @@ details.dir-entry { padding-left: 4px; } -details.dir-entry > summary::after { - content: " â–º"; - position: absolute; - left: -15px; - top: 0px; - font-size: 80%; - padding: 2px 0px; - /* set width to cover gap between arrow and text */ - width: 25px; -} - -details[open].dir-entry > summary::after { - content: " â–¼"; -} - -details.dir-entry > summary::-webkit-details-marker, -details.dir-entry > summary::marker { - display: none; -} - details.dir-entry > summary { - margin: 0 0 0 13px; - list-style: none; + margin: 0 0 0 -4px; + padding: 0 0 0 4px; cursor: pointer; - position: relative; } details.dir-entry div.folders, details.dir-entry div.files { @@ -1871,9 +1840,13 @@ in storage.js font-size: 12px; position: relative; bottom: 1px; - border-width: 1px; - border-style: solid; + border: 1px solid var(--scrape-example-help-border-color); border-radius: 50px; + color: var(--scrape-example-help-color); +} +.scraped-example-list .scrape-help:hover { + border-color: var(--scrape-example-help-hover-border-color); + color: var(--scrape-example-help-hover-color); } .scraped-example { @@ -1959,6 +1932,13 @@ in storage.js overflow-x: hidden; } +.scraped-example .example-wrap .rust span.highlight { + background: var(--scrape-example-code-line-highlight); +} +.scraped-example .example-wrap .rust span.highlight.focus { + background: var(--scrape-example-code-line-highlight-focus); +} + .more-examples-toggle { max-width: calc(100% + 25px); margin-top: 10px; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 7d7bdfb92ce..979e7e0f999 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -91,6 +91,12 @@ Original by Dempfi (https://github.com/dempfi/ayu) --codeblock-link-background: #333; --scrape-example-toggle-line-background: #999; --scrape-example-toggle-line-hover-background: #c5c5c5; + --scrape-example-code-line-highlight: rgb(91, 59, 1); + --scrape-example-code-line-highlight-focus: rgb(124, 75, 15); + --scrape-example-help-border-color: #aaa; + --scrape-example-help-color: #eee; + --scrape-example-help-hover-border-color: #fff; + --scrape-example-help-hover-color: #fff; } h1, h2, h3, h4 { @@ -198,20 +204,6 @@ above the `@media (max-width: 700px)` rules due to a bug in the css checker */ color: #ffb44c; } -.scraped-example-list .scrape-help { - border-color: #aaa; - color: #eee; -} -.scraped-example-list .scrape-help:hover { - border-color: white; - color: white; -} -.scraped-example .example-wrap .rust span.highlight { - background: rgb(91, 59, 1); -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: rgb(124, 75, 15); -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 6dd15d2e1bb..fb15863b027 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -86,6 +86,12 @@ --codeblock-link-background: #333; --scrape-example-toggle-line-background: #999; --scrape-example-toggle-line-hover-background: #c5c5c5; + --scrape-example-code-line-highlight: rgb(91, 59, 1); + --scrape-example-code-line-highlight-focus: rgb(124, 75, 15); + --scrape-example-help-border-color: #aaa; + --scrape-example-help-color: #eee; + --scrape-example-help-hover-border-color: #fff; + --scrape-example-help-hover-color: #fff; } #search-tabs > button:not(.selected) { @@ -98,20 +104,6 @@ background-color: #353535; } -.scraped-example-list .scrape-help { - border-color: #aaa; - color: #eee; -} -.scraped-example-list .scrape-help:hover { - border-color: white; - color: white; -} -.scraped-example .example-wrap .rust span.highlight { - background: rgb(91, 59, 1); -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: rgb(124, 75, 15); -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 804e20d0d44..053fa78d1dc 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -83,6 +83,12 @@ --codeblock-link-background: #eee; --scrape-example-toggle-line-background: #ccc; --scrape-example-toggle-line-hover-background: #999; + --scrape-example-code-line-highlight: #fcffd6; + --scrape-example-code-line-highlight-focus: #f6fdb0; + --scrape-example-help-border-color: #555; + --scrape-example-help-color: #333; + --scrape-example-help-hover-border-color: #000; + --scrape-example-help-hover-color: #000; } #search-tabs > button:not(.selected) { @@ -95,20 +101,6 @@ border-top-color: #0089ff; } -.scraped-example-list .scrape-help { - border-color: #555; - color: #333; -} -.scraped-example-list .scrape-help:hover { - border-color: black; - color: black; -} -.scraped-example .example-wrap .rust span.highlight { - background: #fcffd6; -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: #f6fdb0; -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index d7184053c87..84af194904d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -646,15 +646,20 @@ impl FromWithTcx<clean::Enum> for Enum { impl FromWithTcx<clean::Variant> for Variant { fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { - use clean::Variant::*; - match variant { - CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))), - Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)), - Struct(s) => Variant::Struct { + use clean::VariantKind::*; + + let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx)); + + let kind = match variant.kind { + CLike => VariantKind::Plain, + Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), + Struct(s) => VariantKind::Struct { fields_stripped: s.has_stripped_entries(), fields: ids(s.fields, tcx), }, - } + }; + + Variant { kind, discriminant } } } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 995fb5dcc1c..bf111133b9f 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -132,7 +132,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { // implementations of traits are always public. clean::ImplItem(ref imp) if imp.trait_.is_some() => true, // Variant fields have inherited visibility - clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true, + clean::VariantItem(clean::Variant { + kind: clean::VariantKind::Struct(..) | clean::VariantKind::Tuple(..), + .. + }) => true, _ => false, }; diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index d29ceead4f3..390b9436121 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -17,10 +17,10 @@ pub(crate) trait DocVisitor: Sized { EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)), TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), - VariantItem(i) => match i { - Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)), - Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)), - Variant::CLike(_) => {} + VariantItem(i) => match &i.kind { + VariantKind::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)), + VariantKind::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)), + VariantKind::CLike => {} }, ExternCrateItem { src: _ } | ImportItem(_) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 1ee96b8231c..387d5787dfc 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 23; +pub const FORMAT_VERSION: u32 = 24; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -334,10 +334,17 @@ pub struct Enum { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Variant { + /// Whether the variant is plain, a tuple-like, or struct-like. Contains the fields. + pub kind: VariantKind, + /// The discriminant, if explicitly specified. + pub discriminant: Option<Discriminant>, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -#[serde(tag = "variant_kind", content = "variant_inner")] -pub enum Variant { - /// A variant with no parentheses, and possible discriminant. +pub enum VariantKind { + /// A variant with no parentheses /// /// ```rust /// enum Demo { @@ -345,7 +352,7 @@ pub enum Variant { /// PlainWithDiscriminant = 1, /// } /// ``` - Plain(Option<Discriminant>), + Plain, /// A variant with unnamed fields. /// /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None` diff --git a/src/stage0.json b/src/stage0.json index c3f50272b67..6a389a64406 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -17,349 +17,355 @@ "tool is executed." ], "compiler": { - "date": "2022-11-01", + "date": "2022-12-27", "version": "beta" }, "rustfmt": { - "date": "2022-11-01", + "date": "2022-12-27", "version": "nightly" }, "checksums_sha256": { - "dist/2022-11-01/cargo-beta-aarch64-apple-darwin.tar.gz": "ebc0b11a2af0385bf11a5183dc159d890161be45d231acc34c6326aa25b84b95", - "dist/2022-11-01/cargo-beta-aarch64-apple-darwin.tar.xz": "a0e44bf77337518e2200c34cb297a91dd4db51f0d331ca4cc496989da61676b3", - "dist/2022-11-01/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "a4beae1c53df4d35fe991ebc713e37246d4d89e5543ec740274605a7124806b3", - "dist/2022-11-01/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "5f8ec5c8b012d7e6bc28ca3d700c1c7c742f6532adb044539cee3b2280c1056c", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "54d8fc5ce70b1f06164e17e34d33abde7260c6b1f3356d98d77271ec89766fb1", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "f2debb6ae264fefc49380997759bb0b5022ac1c65ced9bc17bc146671be37116", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "7a8e10be17c8cd624fb3ae2bb7eaab3c493b637c2c1c1100b5333982d1dfd962", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "553decfc64b56d9967ae067bc942ef7117c81d6976b5fa4cf8e5171397836af7", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "64bdb603cdc05b983393d707e9e6e6cd1c71dd8213d08b3d0d1cdf168ceb165b", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "0afe4ca54c65668257dcad5941c678498ab917bbf82a808f39c093719a53f2ed", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "c7fe3bacc9c4acb9b42677281655904b5ed5aec27042b9a8cf9743b737b6b657", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "57f985ccaa2452778c90733e2586a991969dc15697bdbc9547da8a62c871b674", - "dist/2022-11-01/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "873b2a0c2990eef29d689984293394e6972b4659bd6e4c31fb9bc9c8f1c679f9", - "dist/2022-11-01/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "f8a9e74159594d57ce8dda1f7ce7ee4e1d494b9135a0f32b3afc89a637cad8ae", - "dist/2022-11-01/cargo-beta-i686-pc-windows-gnu.tar.gz": "9570141b118c2339237aac12c1e6d71c138ccef784db2effdfd9d02fb12d0d0d", - "dist/2022-11-01/cargo-beta-i686-pc-windows-gnu.tar.xz": "183b63cded6c4cc26feaa14be036a619289b155a6718f4964f94c38a9208742b", - "dist/2022-11-01/cargo-beta-i686-pc-windows-msvc.tar.gz": "9382bf364c5fc9400fb22b046c0a951001961efac221f5cd0f9bf45b1005d36e", - "dist/2022-11-01/cargo-beta-i686-pc-windows-msvc.tar.xz": "aae0a58b9711365ce1d76966af7387f310b496859a9e02ddbff8e23da93226c7", - "dist/2022-11-01/cargo-beta-i686-unknown-linux-gnu.tar.gz": "507727f9b5a920ea28e7104c9aae681c50fa8aaea446a3e10b991a9408adaefc", - "dist/2022-11-01/cargo-beta-i686-unknown-linux-gnu.tar.xz": "4ebfaf11ffc346eec9f05b2d93123483b784b83a322cca6f5fd406066ecf0fcc", - "dist/2022-11-01/cargo-beta-mips-unknown-linux-gnu.tar.gz": "6407889854bee2e45a00585abb4fc8b387103e33e3e67244dba4e140abe46480", - "dist/2022-11-01/cargo-beta-mips-unknown-linux-gnu.tar.xz": "1aeba894f0ca756dd9c3d9b99c7c94bf1f49d5d87ea919249fd0fcf195eb9c52", - "dist/2022-11-01/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "292a95a8de3387832173d9adde633b3d34a019879f97bf196cb41556c3909337", - "dist/2022-11-01/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "872819f00ab0a848401d7dfbb18cf139f85b3d8e48eee0a034cf7f0b970bd865", - "dist/2022-11-01/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "15eb49c334688e48e83f2565c620b3f1af29775599406efa1814c78ee80673cc", - "dist/2022-11-01/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "e74f6884e71109d36d03f7147b7e506f374ba291aadbe4246f6c429bd6fffd1f", - "dist/2022-11-01/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "7f3cf8b35465e4df5fc18cc7cb4f4db6e1b240a39f7583126d7f8ad6d18e8bf0", - "dist/2022-11-01/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "c59f2893999dd88a55c0a5bdb4436640ae9c18f943baf48f63eff6069f7a3e8d", - "dist/2022-11-01/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "566c315b6206a63bf33acf178547bb757a8803e3cfc71f1f63ee033eb6a17138", - "dist/2022-11-01/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "814a8e8f8f5caf5bb4018e54ffc2c1bd9d23df94dcaffbc04881b91bb3c8aefe", - "dist/2022-11-01/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "5db8a63532be5fb9511238d7976075496aba6c732302dcc27bed9ae61188f917", - "dist/2022-11-01/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "6b95c8cc4dda3847f53fb62ea711ca99c1b1b1639249b8b01d54a9ecbc4421ec", - "dist/2022-11-01/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "2ad497be28760f7e4ec6dfa6421a6c10ab049e0dbf45ecb3a2dbde5db7a959de", - "dist/2022-11-01/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "6e9b982857c64518c10392779528e7065191262a95e091ee289c8668b6cbfc4c", - "dist/2022-11-01/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "88a0751ef36816f9e26e9f6d72809687b1f6821b32a3a17c58feaa32f882aecf", - "dist/2022-11-01/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bd6f626002a0c5a3af975419a1258a77c9db91e0db5d4acccbc7dbf25ffd17c8", - "dist/2022-11-01/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "69bad5758f27f53d3e48abcd5aa70b16eb29d5445233c65ab50a8ad0a1629077", - "dist/2022-11-01/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "06212f4cb605fb79d811060d3096bc4b43cf00e1a4fe4a375154b56ff60c92f5", - "dist/2022-11-01/cargo-beta-x86_64-apple-darwin.tar.gz": "741f3490b5562afd57cdda846ab322c69e20940bcc11f3ca5690d662d5de280b", - "dist/2022-11-01/cargo-beta-x86_64-apple-darwin.tar.xz": "2d698df7c00b7c227ca388830732a8787b2a85b328b554c0f8c417813d97ef46", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "9c22b476f25c3f0946cb834da3904516248137cf22c5eed30432401ff061a4cf", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "1604c5d60379227d26d819bd2f7a57c79a9e000a6077ec06e95b418bb0351180", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "673d8941202c2113a431fcef396e604d7ea79000c97a64ef6e93b26956f75fe7", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "3d613d04b48a2eb8644e2bfbb07a88cefe02c7b5cc7bf061b8ef307980230d47", - "dist/2022-11-01/cargo-beta-x86_64-unknown-freebsd.tar.gz": "e0ce6fa69af565e3b79f7059a4de88e39955d7ea6866d56c2b0946b47929192f", - "dist/2022-11-01/cargo-beta-x86_64-unknown-freebsd.tar.xz": "de602b7802b1448a861df05c41430dcde4f07358a05711784a1ca37836525b74", - "dist/2022-11-01/cargo-beta-x86_64-unknown-illumos.tar.gz": "c4eacf4821c126b321a67e0233d2f84571b3dcf25686165cad00d9645787f03d", - "dist/2022-11-01/cargo-beta-x86_64-unknown-illumos.tar.xz": "01ec5ab637010498b784ea2fe6aacea626fc341792eaa5a50756f9b483a765e5", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "2e6efadbcf138ab72750c1375bfeaf2d5102559aa9b745294b9973821e193703", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "e089b1b4248ad8e05ba54cfb278101a74aa34154bd2d44dd50119026bf436d1d", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "ca079fce260accce11c1fb27e550421cd0900027e29b18e24e54a298d78031c3", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "ff33e9fd6f06e02277f580f13d82f753987f4dad7d7926405b63dcb362eec498", - "dist/2022-11-01/cargo-beta-x86_64-unknown-netbsd.tar.gz": "46101fc5f53595ae53f3ceb755cc72c078471479a337b5319c85e629e5df3b28", - "dist/2022-11-01/cargo-beta-x86_64-unknown-netbsd.tar.xz": "b063425ccc69284e8788211bbde5a7843bd16a3b9c779fab68a11d22ebdf319b", - "dist/2022-11-01/rust-std-beta-aarch64-apple-darwin.tar.gz": "77bb5db904089e087032c24fa2e011536e13d3982299285a7515beb97f445078", - "dist/2022-11-01/rust-std-beta-aarch64-apple-darwin.tar.xz": "63aae4b9f10f15fb48b2ac20aa7f112a685d49bdf94d8997d036472e928fcbde", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "8f63b6be668e6a25411582db9145c9de8192d58acb42c490b0de89489a3e36c6", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "d862bdeaf2c78b15babaf74cf1c6feaa5c4871a90095f3d4239d81f44217cff4", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios.tar.gz": "e5b1e9420d387a1442c77bed10efebd7b0268713820a728a067bb4ead6088041", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios.tar.xz": "569c667e422ca7ac373d59b6e13c299cdb7f334164c84e6f0c8d0f076352fbf0", - "dist/2022-11-01/rust-std-beta-aarch64-fuchsia.tar.gz": "3f945c43c09704b3df6af66a2132da12243b13752094383965d6a8a83c6edb0a", - "dist/2022-11-01/rust-std-beta-aarch64-fuchsia.tar.xz": "3662f02892ab184be99f93a9d0f99e030a73cc61447934b74fcba84e05b022b1", - "dist/2022-11-01/rust-std-beta-aarch64-linux-android.tar.gz": "ab04a0228074e974d70a15e594d57479fe22ed37c8acfa5104201dbbe57747a7", - "dist/2022-11-01/rust-std-beta-aarch64-linux-android.tar.xz": "fb96925878a24dc9e90d356e96cf4fd1fc9152c39f8914f9a9bb676d78069cba", - "dist/2022-11-01/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "45e824f75ac530ee9eaf0b0a01cacd5b8dd64ddf5203c032c49fd2bc4fabb245", - "dist/2022-11-01/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "a6488faf4c87cabb4467f4cbe7348d553045c2f10f450bc6e000fcf18ca9b073", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "e2a66e04b24aad8a8898d6c0270d8dcff63205213cea3b893807ef186e8c0936", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "a4244ac1600726b5abe6b5f9a171fc2e4cc57bbe7cecdeaf23b69e906f05e303", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "9e3e0f675ca50b7a2a1afeacdaf5d7f2f4ec1536f596ff99aadacfcb59fd42f5", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "7e7a8fb4fe0283b71deb79c5ccb1ae61b2099392b3c8e09d03d4a68fbab7a184", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "7543df1d71d805b079d19ccd785f777918b3f11b131bca05d079cb5d3952a38b", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "eb082e894047cd77ac3fcc9c03eaaef77e6bafbd075cb0d62ba3a3ba277f5d64", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none.tar.gz": "144fc6973b06ffb12b5ad0bbfc9fcdcb2a0732de50bb140d62d6af3d6b462908", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none.tar.xz": "8ee2ba2d4eca35a426fb089e0f0b50b2ac3ad1ab036c5f8f4786e2953405092f", - "dist/2022-11-01/rust-std-beta-arm-linux-androideabi.tar.gz": "4a46d6591c1983d0853f7596f7b76e7c82b6b0cbfd97802b565a17aece0d13be", - "dist/2022-11-01/rust-std-beta-arm-linux-androideabi.tar.xz": "3888fe036b5fa9a5dfa009462a002a05c70e56eb70db3a0c872fab1432e9c9ed", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "529d668389506443f87bd93e98dc72d12be9a4ab41675dc6a1c7373e934ca017", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "dffa1a94f4166435d6fe2a76a4d35deb8c128cc93146f181979416816e77e29a", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "2913bc06d6b49c52804a8dc18d1d3cb1b564e0272cba93f8594747731d360f9c", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "c12bb97fcbeeb0a9a71b2575b2d5113948c515616f720dae3891e2aa886d03a7", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "a844ad8a80fa07b9196dc040d5171749daf94443c57348bca04e69b8dad37cba", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "c261662fa988748ed03722d6034228c893e02a0e473f906bba61c1f43be7cd79", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "1ae5967f4fb80047711519dafea21fed8d6afd308566033e468c11587073d216", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "150393cde94d8349eb488a161572589c53fed456c8401e5b1a59d1dd87003f7c", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabi.tar.gz": "b1777a389e4db0ccd80ece774865bc99731c4b483be80c909f1b5a2a185dc5a1", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabi.tar.xz": "877a00491650bac92e93760c2457b644d2b5ee28d410c1e29fc4b40c05da493a", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabihf.tar.gz": "3dfbf001db319a41874e2c0de2f55407285d88156fa0563cfe3c3bb1939998fb", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabihf.tar.xz": "b2d6a543cdf64a5c147001ea30d07bd13b98e2918a343bff08bb57eed1f81462", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "cd8f0803ef86052d09606601b09dde05d1997a93fad7a22604fda1176157040e", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "748cef6595fcd30da6735c29476639ac80cba94eb627d6654665d656da2979ec", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "1dcae3588a3e552778ff1079a92750bee15835f08f8b9ff1123e4e6c5a73c087", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "3711105029d28fd91f413f488b7041ea42c70e5a244f992e9259b4e9d52abed1", - "dist/2022-11-01/rust-std-beta-armv7-linux-androideabi.tar.gz": "a2af3f6d3681e1c545d0c21bf04fbfe3de1cdb2273fadcbbb4408f5590054d11", - "dist/2022-11-01/rust-std-beta-armv7-linux-androideabi.tar.xz": "23e658070e1cbe8011d48678f57bedbbde819cd64f43509858af563a7073a3fd", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "ff7b429d5a6d33f0e467b333225f7c42de279ccf3e91f3ef7c5463dc06939579", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "8d41b293656c5cf93f46754499e5723a89dd997d3723bfbe56f953a7d864c435", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6dd89ed0f20a0ea4a279dd4f810c7908c3e8a377da8a2983f8890efeea169177", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "504fb533fca6c46ad98c728781ab31170d65e5b35cbc9199aab97b1146a24702", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "f9a731fd3ea961f0c5eff24e6290aed19d79d5444bf562670abc0cd46ee309fe", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "825acb16e4bbba0c9b535e635b972ec581fe6ef115c5a41bace9b85c704eccad", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "41da8404f0e3cef386f6efef9b27fde27de77de71140dceeaddd8e15260ce45d", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "c8f81fa9cfb40ce92f2c95ef8b57e8a62d819628111e1dfe0c6760fb48802be3", - "dist/2022-11-01/rust-std-beta-armv7a-none-eabi.tar.gz": "fa8c3168dff5c167c6ed25f9c605941ab51e73e70c0dd162a5fd17287c5fd5a5", - "dist/2022-11-01/rust-std-beta-armv7a-none-eabi.tar.xz": "36a5ff7865f8a16b867ab3fff4ac32f0c62c260a5c27385098e67b75b21790fb", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabi.tar.gz": "0417cef6468fd66bf626729e7c0089b47b149cfc43e8e0d4281f76f73ed17edc", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabi.tar.xz": "1de6cb38a68ef336e1edf2c1c51d999482898df99e2bc078cafe6ac5380bf3f2", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabihf.tar.gz": "91003d4648fb01306d6e0a0214e089d444a57c5ff09138040f07cc81e89af639", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabihf.tar.xz": "884306ac77518ece0cb2f22d898e3d2aa50698bd4181ca23a1dada6d82778682", - "dist/2022-11-01/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "f17ca8f54eca5d73006659fd08142d537eff23731b6e5a35bd67efafe0dc8cb1", - "dist/2022-11-01/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "b04a17d33d7b9b1caae666dfa5ee9a98e5dc079773b6345f6c49733731e14bfe", - "dist/2022-11-01/rust-std-beta-i586-pc-windows-msvc.tar.gz": "55e61aa74bdb50df54394a0f62b9edc88682c37b51fe9d8d5c05c0619eacd1e3", - "dist/2022-11-01/rust-std-beta-i586-pc-windows-msvc.tar.xz": "ec3d887742289ef9c171ae56ca20c3e9cf1972cc3e6c511611404070c55dac8a", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "a36444f0ba0e7e03d06fbf65d830cb7067c675ed061e8f6efd6ed445d5955e88", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "dfc07297ee8cb63f76d2019ae822352e6b42e5cccd225eaa5597a63ecff3624f", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8de9f830cf277be584b54d86d6621a249fb2987fdf32d5f16cde9b492722d45", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-musl.tar.xz": "f9d8bd74788e2209ecb8d0cc49d94b4e2752c9239f89bcdff3e8fae315d1d923", - "dist/2022-11-01/rust-std-beta-i686-linux-android.tar.gz": "b15636654925fdba1e9ec1704573e4af1fc5f1158a0657b245901e22c06cd378", - "dist/2022-11-01/rust-std-beta-i686-linux-android.tar.xz": "9abbfcaa40d86e8a4cf49f2a58b1c7b2f422b6890303cb43feb83cfb8f650a42", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-gnu.tar.gz": "30953eb457a397966221dad058ff7ebd99ca4497f184016b5a61db0f122bdee9", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f9d6d266eb3bb46c058615786483d817138aa29efc3c62c3cd9c87e572956b12", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-msvc.tar.gz": "b55202c349a4e9a493a2de7a3d48788befce32274998d3dfc1d1b6f4a96ba9e3", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-msvc.tar.xz": "6dd8d42e5712d699704e85bb90cd42e0142a4fab7cf7f80132cb0902cc415ccb", - "dist/2022-11-01/rust-std-beta-i686-unknown-freebsd.tar.gz": "d2a7c9e7f1dba3a317692a46f8efec8d7ba1e9e943c88d3f342a820c34829aa0", - "dist/2022-11-01/rust-std-beta-i686-unknown-freebsd.tar.xz": "ecf6abb631dd6887b5630d1ea0b8778fc1539405e6c00d7585c8afa2230ef9ec", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "93c5912258a49a003a12ca01101f5935d5894f9a133301a47047cca934a7439e", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "f8a6e67723cb968e874827a6148a5e25d3d45c56577faee627010347d0f03d92", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-musl.tar.gz": "8838592167a8d68f463dc18e55d5d2d55c474426e8a4ec0f28fd2cd4230cf638", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-musl.tar.xz": "c8330a06862a7f375b57774b382a54a1280c33ddc1b94d5d5ec45eb6ff0de8cb", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "4b50cc174eb1da9dc831de828e6ee2fc8a81abf8e6dd52b041e4ab00eaff73ac", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4820db058569be7350a81396fdedf9a28233b8061c9bcf607cf2d1058cbf437a", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-musl.tar.gz": "dfbc460e8322114bde5614b0b45e90066805adbaca999ccdc4f2aae456fc3f1f", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-musl.tar.xz": "d98c19268b0c84f44f1224f432847a93eb809a85ca48fbe2e4b68fb436bc36aa", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "8617edc6d62591d50dbadc4a7bc41b31b66bee6fee830af46636c5206027217f", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "98a6132c8dd7558eb5f44007fa681a3a91b2dfd98d1f68e59f0a4660dc37b500", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "81f794c54d7a8c680c52a8fc1a0e479526744205d51266007fc3c542496957ba", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "dedc5b1a76f8454d1b3d7fda0a05398e5a9ae4cf16ddc4b44477799217a1fb75", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "6d9b3d469ae92e38144d9578de8cf0c891e4bf3e667e4e465eb6f0d498140c3c", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "f9deb84c24bd0f21ed02d763d3ad8dd92c009de4ceb2b78ec06d90d66609c5f6", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "073882815493668dd484b8f107efc047f6e07d8c563703d0e7f73ef33dae0efc", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "d1ab3758d1b08937a3f98737ff9fad20377e5bc43d7ab3a9359b4131ea11dcbc", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "bc82f3d23dfb7b331558180f474c334ca3798322e19cc64657cbe894d0682901", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "fcc12f82ea0c02e8434420165f1ee072bf4587a82ff5ecf34d19f754ffc091ef", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "1c4507c7824c02b1af2857c88ff1624e9ead3f38c1456aa031586b43223e9490", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "932598fbcc35ee4958be4778450f5b809ce9eabb2aa3d7573fd79744ed4d18ad", - "dist/2022-11-01/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "c17f11707c1edef2353fba7e3f4800cecb8a273233825817b6d07ed78d6acd50", - "dist/2022-11-01/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "7e90a819b8887f0b1a3ab02fb9a56a9b9eb752408a7bb934c99c7f6ddda48a71", - "dist/2022-11-01/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "c437a6fc7cd7869df7cdbb52c51ae1e602ed1206517c38689deb73da6d7b4877", - "dist/2022-11-01/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "76c1fc55b16a809ab1c8dfce894899f40d24b20dc670d318a7679953beb6c3a1", - "dist/2022-11-01/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "d62396390fb85d5543a80ffbeaf7c32b5297a513dce14790124c35835813032b", - "dist/2022-11-01/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "4595485492c650aa53bb9deaeb425ea956f2052c5b5503bb477778f7bcaf6ac6", - "dist/2022-11-01/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "ee841bb8fbb0075a0bf51db2007bee2962830a89649c00fd15c67b31fd9226a3", - "dist/2022-11-01/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "cac036fafa93f2860a5a2622394e12938c35e629ff81d7cc5930d99c980f9321", - "dist/2022-11-01/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "025d70e57d608b81d61799c84ccce9bca3603736c4d3e006fc662c3a7b39e8db", - "dist/2022-11-01/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "9450b1b1f95e188bcb9050085d612c8bef36e819881255fc20d70da1f45fa61e", - "dist/2022-11-01/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "ff707c6d209f9d8e421fc530a11d41a46daaebdb4aebd5cfbaab761b2cf192ff", - "dist/2022-11-01/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "8eb48a94c58440e2afc8ef7bbdbc725f403fe38724c0afde4e7c29a1ba2c7591", - "dist/2022-11-01/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "e921a841b7a9e02e28182e91c921746042330d90f0478fc7e01230cb1b881c1c", - "dist/2022-11-01/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "122135e161a4cc7dd857e3cb35b64ff7db450dcc07cbb990c8aa83e06bb4b346", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "084824d6daeca6a0662ef1e11df84c651138d8d4e7d5c8ef66c5811354b16211", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "09e3df606e10a0a59a67bf7b49825a04c23062e6050cebed674e0bdb2c396fcc", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "f9929f62ffec9c6b3342da8dd21b1c14526e033174a4f86015182acdbb93a985", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "932450fc6b5e8fa4813886baa389b53c6ff1c5b1e71f7370017b9658b04fd13c", - "dist/2022-11-01/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "e7776d188a04779e7f6a7257bf367d8671e7d5d804d74db426592f683cabf562", - "dist/2022-11-01/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "bbc765adc116c6a1bcbf659853b7169d95b240ffc15227cbb1d60b46d63e120a", - "dist/2022-11-01/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "a0ff6e9ea827d7f93563aaec213eacd00efe4be9c921b448405b2af8bbf0066e", - "dist/2022-11-01/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "7603744cbbbbdec5b2a322aabe68751e848ac7379c710866c59dcc22e4b873bd", - "dist/2022-11-01/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "1f67446eb09505e87a5218b8504dfc678d0a712a5add763362f3c74306010bea", - "dist/2022-11-01/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "1baca6f0e7f18a8eb9efcf35bca4320a493d51f08e62bf96a31036e2f2c433fc", - "dist/2022-11-01/rust-std-beta-sparcv9-sun-solaris.tar.gz": "455e52fa3f232c2239112030483c0a657e7f69754d8d36ab72423c76c056fb68", - "dist/2022-11-01/rust-std-beta-sparcv9-sun-solaris.tar.xz": "913801ca45eb1d70c9ddfcdd66aa21edaafccc85acf9864e88991bf8a5a7cf25", - "dist/2022-11-01/rust-std-beta-thumbv6m-none-eabi.tar.gz": "14e4f69fbf710f16275ccb582a90eee1399ea1226945c7c96f75335df9118966", - "dist/2022-11-01/rust-std-beta-thumbv6m-none-eabi.tar.xz": "40549d9d9c923a73381b8e45628cfa1896d0e78caabf2aa921c767e0bc979136", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabi.tar.gz": "d40bd56883abc142155188674580c4e29100fd7303fccc70b0c55b964721a156", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabi.tar.xz": "874c97a01d06e1516a89797d7a6effeabf34afb4933956aa34e907a65ea78690", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "cf7acd2b4a083522c01f1909891aaba27502ea0a3a5eff93dfb41971f832bba6", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "e9544acbefa3effe55537de85311b00077a0567d64345aa80414752037212b5f", - "dist/2022-11-01/rust-std-beta-thumbv7m-none-eabi.tar.gz": "247e9dae16f46c64da895528f3e902030110e2aad8270f169c636ca14bfc28aa", - "dist/2022-11-01/rust-std-beta-thumbv7m-none-eabi.tar.xz": "b7de9e8bf7b7d04fc9575390d69eacbcc62a39c35c81f37d2170424cffe6a356", - "dist/2022-11-01/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "bd3dc986a11967e8ed050a88d03d1c0814b08cc1ab0cf929561fbf5a941a335e", - "dist/2022-11-01/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "262b4c4ccbe20c9e913a7417c8ca72c6fb7e71f187103929057dcd0fc0b49cea", - "dist/2022-11-01/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "85f6a725e5a726afab9ae019944567b42ee769db98a8d3c335d449eca92344e0", - "dist/2022-11-01/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "07e897f4320f249b3f458e44e5440591962105a3b6032b54f4448c0bd21da964", - "dist/2022-11-01/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "e92855841ae93990f88f3893a1bf511853fc3f10938eda767d5c7ff7d310aa4f", - "dist/2022-11-01/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "3c3412a67f769ead9e8bafbcb5ff6dfc8ef89f0d8234baee7b39ab9df9fadebf", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "f3cd623fdd466e5c0b5749dc4e90a75122f1989f6fcae0ace8c76f3b394a0752", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "3793ab2a42f1bc59ad560ad1af75ed90c49e25f665330b5b8ce50ed73ef88508", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "cc6c715e320c7fc5fd90f446f7c2ce6b356e95934d05f79c4e2d0fc304f212bd", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "42a47ce6768b24c2b40c6a724003a401bfb37201a773e3c31ee413cc559cda70", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "4c09e5b03a921d8c1d8a10d9535e81be3b3bbed961d229311cc691396ae10cbb", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "775f7223bc5d962b5356a4884565a948d3cb5289fafe3e2eb2b8ad67550d72b4", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-unknown.tar.gz": "bc027d9170132c36faa47da1ff8f26d26d383a5145cb9dd2dce20e769ea300ba", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-unknown.tar.xz": "9a721d3550132930820d9b809074535d2b63ecb91d5c061effded92b503bf0c2", - "dist/2022-11-01/rust-std-beta-wasm32-wasi.tar.gz": "047d58ef5e10ab51a81dbc11646fca184945a1c52e7a91552449c67952c8d898", - "dist/2022-11-01/rust-std-beta-wasm32-wasi.tar.xz": "a490ce6ebc77a4a49c2fdeec471dd9e586b2aa26f1e7f2fc1323cc06b2b336d5", - "dist/2022-11-01/rust-std-beta-x86_64-apple-darwin.tar.gz": "df73bc81d446792d9366772944a04f69ad32f427e1949e05d4f7c202c350c269", - "dist/2022-11-01/rust-std-beta-x86_64-apple-darwin.tar.xz": "450aec3ec53594869bbf16ffe1713dfa19b8dcadd812a4af811bd56f1f58c929", - "dist/2022-11-01/rust-std-beta-x86_64-apple-ios.tar.gz": "fb698f63336a186983b09c2c49109dd080c22653f3367dabfcbae564144aff35", - "dist/2022-11-01/rust-std-beta-x86_64-apple-ios.tar.xz": "0d475ba4a4444f4da5fb39d26c9cdbc0352ea799d7e30f57e2e79d8c3c7a7021", - "dist/2022-11-01/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "137234fc37b93ef4fa543f4e33217079137b4dbb51efbea669b93e561932b5e9", - "dist/2022-11-01/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "01e1978d9359a5112aa77409ff17c3d0e0dec774815f679065db6c6293aaa623", - "dist/2022-11-01/rust-std-beta-x86_64-fuchsia.tar.gz": "662e62862b1586f29372339319680c88b7cebe41e98401b5dd62e320755f0d62", - "dist/2022-11-01/rust-std-beta-x86_64-fuchsia.tar.xz": "4a644c6c85c8e427d68a669b0f598669023e2c0db2b69b94a7124c18772052dd", - "dist/2022-11-01/rust-std-beta-x86_64-linux-android.tar.gz": "752a57eb3de0060c1ffc6eb0af71d88d5f881b543b11b209593be2b18af1f902", - "dist/2022-11-01/rust-std-beta-x86_64-linux-android.tar.xz": "19effccfd9d63e955cb0736968c4c300c6d919217a64cde464c30a499ae9fd9c", - "dist/2022-11-01/rust-std-beta-x86_64-pc-solaris.tar.gz": "aa8a36ec1892c68a1c1ea0d9ac1b92b03c975a0d8ee538aaee5d757ad84d5b2e", - "dist/2022-11-01/rust-std-beta-x86_64-pc-solaris.tar.xz": "955ad79007d397a9e24d819e95017880b25424bdac01386cb8fc6d50247b1274", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "9f15bf80a2384f2fd333dee41289fdd8529170192dcbdd8cba0a73d32715ccc3", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "539bcefcd6b888c5f38abca47792dcff1676ef31eeb9a4a045703582262758c1", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "748fd22a993be659f85c3799871c4de09a99fcd7805c6d0e9d5a18dddfd2e26b", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "68c22dfa2ef5ecd2d43661716e8a8394eaa36e8e960d34dc421bbbe57c3e0d23", - "dist/2022-11-01/rust-std-beta-x86_64-sun-solaris.tar.gz": "f06118445fc6671d491c61dd8e6ff83ca21fc1d692058eea072cbe01ff798fb2", - "dist/2022-11-01/rust-std-beta-x86_64-sun-solaris.tar.xz": "b3fdd56baadf3a8bffd17730d61b2ccef25ffa25d5cd826bb9a45940bf573fb5", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "2dfab0336a523182d200c7a6096fb29c199339b282ba03b469a9a1e5c5a5bb0b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "ee5b9158ca0c2e829bb79ac526d17a2ba27ca4e305e134241ba1f8347a9bace5", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-illumos.tar.gz": "fe62b766d11e9ac55db5011a63086af5d87ce560c0656dc214c668db752675e4", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-illumos.tar.xz": "e4b1068de2812c62e7ac0ec080f605fa90123a94563dc4f898221275fbd5178b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "c5ce6885405ba4d1694a7eb767837320ece5a02133e94c1c22ac07143d6f752c", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "eac46cc9200125be2548d6b9f2c2d37b046b8b43b25dd7f7347d88ef6795a3c7", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "1b3d1d051cf355eb26bf9de5096d984f83dc92fdeab3bdcd18d88152c0e2a2bf", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "a17cf4a9df1b1be17f5163f05665bc40638e62210d8e0623fb1afeeb96acad2a", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "90a2e5712bc37f28a0d1f71c54cc04233049c638e4f0592b50adea352e21038f", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "ad76d090357f5e272b1598c35dd24137fb9950e1bdc50b9332fa1d2fcc33a00b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "37e0954add559b24c08ad284fb80294e435491159db63ea78a6183af5926dcec", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "d6542bd592edd3924999e690416b6bc559486388add76fa77044114b70700fac", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-none.tar.gz": "d021e49b68b8321354d99ae0fe80a6b042ec798ca7fe37cc92d4f0c0480f7ebf", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-none.tar.xz": "f6202c50c6d3575fdb398a8c98adeb0d86794b60c3951887c90a9e4acb6a89c0", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-redox.tar.gz": "b8ca678975c0c18d0fda1bb118b35366d1261e366639b8bb455b6bc59388082f", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-redox.tar.xz": "119f9e65dc3484f677064e068da42a1e7b8dc0be21d0cbf5185c9836589b39be", - "dist/2022-11-01/rustc-beta-aarch64-apple-darwin.tar.gz": "11aa79c56a9dea2d5305ed049485a1257912fc0dfca1feff37b768971f4c1701", - "dist/2022-11-01/rustc-beta-aarch64-apple-darwin.tar.xz": "a031051ccf97100bd8b4d2e4df7a67371cdf300df4697e1d05a7cec33a7d8c09", - "dist/2022-11-01/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "4d015042d7d06929488f607bc56d925002e6f352d74fe192dc30e7feebb9947c", - "dist/2022-11-01/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "d72824112c96514d927df46f6e755898d26ddd5b805f6c2c0411c773105ad61f", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "3e70261ed7c130cb7256717cec0c37476961932be228e46e028818f9076dfccf", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "452f07f63888cf27ca2d061751602bb07a43348eca9cab30db27940a36f496e5", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "995a6410305d43234eb94710ddc251bafd9f5fe4ecacc51c4dc1447f364be30a", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "2d586e5d1a72194ce2798d4f07c873d52ea441cabe5040ff682664d618b98d4e", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "65954bc862cd149cae2702f25b186fa2166d80cb45bfe6867d075381f2614464", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "f3a5f8318efee7eb9ba4d861876b0a5415f308c9dc2cea751a10b2e259303627", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "d4be89140f0bd4ef9f73a1b54f949973ce560c4dd62c664974f82278ca0d6079", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "5b381b513c27f95f9d170e9c532839a27facfe6eb4dd215c078b44fde40e3ba3", - "dist/2022-11-01/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "ffdf714a07408901962c861103b062adf334e0febc1abfa8c538c40b0070793e", - "dist/2022-11-01/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ada55533236ef8c629ca72f929bb87db4b68f8c3d4c6fb3e7001f892a84a2b82", - "dist/2022-11-01/rustc-beta-i686-pc-windows-gnu.tar.gz": "b7e059973b61a4d7a0c96b4642629bf72668380a5ad8a2962181b1229ac2174c", - "dist/2022-11-01/rustc-beta-i686-pc-windows-gnu.tar.xz": "9aa3bc05e1782b8ff5d278f5b5baac4b0ae523ad8bba2bacd46e1bca11cd38b9", - "dist/2022-11-01/rustc-beta-i686-pc-windows-msvc.tar.gz": "acab77f5641be0d7102e6b911f134aa36b6fcad5ac594100889ed0e494eccca3", - "dist/2022-11-01/rustc-beta-i686-pc-windows-msvc.tar.xz": "e9af106c009e5fa0da36450a7a89a148ec176bd672ff636010846ab978804e4a", - "dist/2022-11-01/rustc-beta-i686-unknown-linux-gnu.tar.gz": "546e7b52f7f9e8c9a99163265dbc8a5ce65dac0fef4f6e1dc8b1bed79f0a24c3", - "dist/2022-11-01/rustc-beta-i686-unknown-linux-gnu.tar.xz": "b5ea7fc6016a4abcae3337261724ca2bd21025856134e1c2a1a1922d12ec19a8", - "dist/2022-11-01/rustc-beta-mips-unknown-linux-gnu.tar.gz": "0f3e0c8e7883dc7ebbec38e1f3446a33651ebba9a725443856b09ae7e8bcfec0", - "dist/2022-11-01/rustc-beta-mips-unknown-linux-gnu.tar.xz": "42871f7f098008f61f6cfd3cf78240156280cc7f5e52860d8125e22b3733a207", - "dist/2022-11-01/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "ded0d4da36a0658d46c6705c04fa40d0894b6e113776d2ef8e954e9675e98f9a", - "dist/2022-11-01/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "2f9ec1ba69a7abbe4efbc5fa00715f520b4c69792b96e98ed8a72e3f798eb137", - "dist/2022-11-01/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "090431409021fa0167576c717cf5daac750f9baf7badc3bc031547dad8dedb18", - "dist/2022-11-01/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "0542d0336c8cdacf8a830d2a7c3218b76a00ae37db23fb2f12b928bb7b7dd488", - "dist/2022-11-01/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "2d6db76bc5242af8c2199c5e74f152bbd8103477855379e7c5c200b498ccf901", - "dist/2022-11-01/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "0dc803a305497cc905f3937691e4f1679c72a385b57ee931b19ac5347052c502", - "dist/2022-11-01/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "809f547fb5c27c7d15816642839f9ff5fee20f03a3ce390d5b2bfdc983a7c7e2", - "dist/2022-11-01/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bd8403226676b78b40c7a494b3a89f9bed956e7eedf3a65a61cba41a6382f5b6", - "dist/2022-11-01/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "12cd357dc72d67911a521dc0ea44a8d05bc4c214a7f6b9e88872ddc03811dc15", - "dist/2022-11-01/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "d92f790cabb85373455b5adee9e692dc934dff60eccb70c077f29cde35e7cd00", - "dist/2022-11-01/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "a175a2b7d948459c12f44592c1ee5c79825a120557ff0c488fb0bd4e45c7ee99", - "dist/2022-11-01/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d047a4ed562cc91469785fed44d97061d60e1f9c677b5de05245648373df111f", - "dist/2022-11-01/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "1b1f20032337e6a0b5e4745a3542a5638747bf2f3b62b2eb855c0ea1ac54d81c", - "dist/2022-11-01/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c8a46c9c002ce19e940a449a4787055b4ad45076a606bd68626a1c8d892d8191", - "dist/2022-11-01/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "547c670fd6a5f38f98e7b47daaf6822fd5a1abd5a7c11b6f2b5838cb145c615e", - "dist/2022-11-01/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "16a0783135c22b64541cbf9201e5f84ab4befbc9ec0117f3e9639cd42dcb81bf", - "dist/2022-11-01/rustc-beta-x86_64-apple-darwin.tar.gz": "3121d060a0306c539334fb42c0c6edb6295eb4b5d05b63e55df98d5dc1cb0eba", - "dist/2022-11-01/rustc-beta-x86_64-apple-darwin.tar.xz": "4697febb60fdecb5cd70bde0cffad77cdcf8cce057349b4e1f26e3dd4f2f4a51", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "c33bb5e98d83f0a7393c631b6b53eb4a8517bdbf506e1ceb6f0bdd8493fa24b9", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "167e1ab52c4478e6aa8b2bea563f2d8caf3605158731a892181f9d24b027ffff", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "efbe536d85810f2edb6bb7232617f12d3f208e077d177c24f507ff02c8e83a11", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b6acaa3206a3af7fe0e97d4d9211fc76ba972afcdd188443a72027dd34236658", - "dist/2022-11-01/rustc-beta-x86_64-unknown-freebsd.tar.gz": "8eb739094411afb56ad791b84aa2ddcd2c98b6ca5a4c1cd7fa631571702f1d67", - "dist/2022-11-01/rustc-beta-x86_64-unknown-freebsd.tar.xz": "4572c19bf416c188a3691cc9542422b92a124594bdf83c82213d07a3aaeef465", - "dist/2022-11-01/rustc-beta-x86_64-unknown-illumos.tar.gz": "eca080758173b3bee5a1ed7d04473a8334422fc58c762031877e690a255202c8", - "dist/2022-11-01/rustc-beta-x86_64-unknown-illumos.tar.xz": "68b1ced7efbd6bb4cac647e7417b2ad982f58a1cc546b9391213e85e5852ce6c", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "3a4870b33c0f223dc295fcf3f1c4e331a2631dbc07279f4ca7452d86c5f6e730", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "556821823576a5c0387f0dc89139d3cddc2a17072199607c352fe4b190b7f02f", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "4e1723c8f268eecc9bf3efb16241ce03bf109b9f7c6f4f62e430b7ccd1c092cb", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "47bb3fb8f8529f19fa9725a43a57abd8bc3c7b2a30e17f86b137df0c57a3c549", - "dist/2022-11-01/rustc-beta-x86_64-unknown-netbsd.tar.gz": "530c24d950028d0745110672fad230da8a2a0e4cd4e5ac5afcf1ff8562288925", - "dist/2022-11-01/rustc-beta-x86_64-unknown-netbsd.tar.xz": "cd3654b33b3a8e7fbcde2e380bf2914cb07fe6f8355c8810a5bcfe3a05d63f84", - "dist/2022-11-01/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "47527c62b813c0612b80c864b3720b7e0673eb2dd762887254fd6a80f11c94b0", - "dist/2022-11-01/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "82248dd276ecc0fd45031ba131cb2c870a4b3c09b822d8ad4454f26f506d7810", - "dist/2022-11-01/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "fdc9cc842850023e7c22ac22173a18aa5383a2e2fecb713c802e59d55cc5232d", - "dist/2022-11-01/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "10ddbe6a89cadde47f6f52ef0c4f9ab08f4ced2281fadd1ecbc6a0e4736c9787", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "2135c6d129fa7ecd831e451e173c38677ea39975a91cd6092252e4c0bd93eeaa", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "387d43021bd0ec1586155d1b977470646a68e2625fc192331b76180755687d37", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "41da916cbac667f5f238c3aee3bfb230c3345a4d625779c1fcf57813c9138696", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "f28cf712bc617f1755e78a7a442633a7aff78857b98d9aae473effc5684ce8aa", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "065fd7fdcb9f38a9c08b256b46627c8ce38a6433dc162034a306f4d4f4627a31", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "1fc14261867b540e6d014cc5a21c557d0a4bb31d2619ae98a330585915365614", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "1a9ebea072c333e99a3339a87ac3971deb4fe2baca9bd0e8429321a81cce847f", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1c7a72cf8e9cda52d02bd5f4244164aea829914087501cb0bedd75f05f464a91", - "dist/2022-11-01/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "1f8405178138601f65dbe10f93d326c705ea91f9e7200f253d6123f618d09ad8", - "dist/2022-11-01/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "00365767eb739ecd82c6264795768baba07a101aacec59e137a7495afd0b3288", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "b2e4c4672f440e1f97913497ee158280cb8ed70c81cb47a85e5382cb3de0b03c", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "01bea91a3ab8203b32cbd1fb2945a1eca68179e8f4011e387a230587fc2736a4", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "2d0db2a9f187d300c183cfe2ac6778547ab6492720c0e9df3e78f5b06004e758", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "b89b02b9fdedb9a93dee602dd9c818e97c397ef73c3f1d0164ddd2ab809cddc2", - "dist/2022-11-01/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4498a8e6d0ae7a793a9f3c84e3bbe9218c37053a1f3dd6a0b4ad7edd1a41493f", - "dist/2022-11-01/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "27041aa61921b767be6670f0f08aad1a1ab8d09d0e86cd2e431e54744ed25d0b", - "dist/2022-11-01/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "870923556049bd4be8da03fa6d876fa8249e4acf0ea2c83850c4e23a09fe577f", - "dist/2022-11-01/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "8c05e1f60a59064c05db7522245d482b559ae858a5c9c772db81a05daa60a4c6", - "dist/2022-11-01/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "1a88c20701cc6f7dd2b3e32bef72a78936c39095a35237fc4a4b5a497790a048", - "dist/2022-11-01/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "9b5ccf5413650144a79f382efd12204aeddf3421ea6f06615afc489cdf30691e", - "dist/2022-11-01/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "4bcf264ba7ce42aee79d76ba0f19818aff71ee666ac4ac417c2a60b0dafa8865", - "dist/2022-11-01/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "fd6ff248063cd53ee6b0538c8b3c8af1758ae5c42cc2f5fc805ab96799033f7d", - "dist/2022-11-01/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "a03cf4d831ba58d1e562d6fd48dd7558d9034046ae7050883eb1d0fc2cad6895", - "dist/2022-11-01/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "30be7166fa091929d1a4b5eed4b72c4b5c94898861f4e91fb45a2b9ad4333ca6", - "dist/2022-11-01/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "59f3910a559994863f1910ffcf34cae348d0c07128d00ce5ac085bbca349f7f5", - "dist/2022-11-01/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "817df1ddab344e47df34c73918c5bbb3a7b33048f8ac5c5794cb35624f5bce24", - "dist/2022-11-01/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7825a5f19cb29245de96eb22183fbfc38b75eda0ba63d2255fa062f9c6764bbf", - "dist/2022-11-01/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "0d6384aa1162d821edb6d22326b0a1d481e6735d4343a70df7bead694bb71567", - "dist/2022-11-01/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "aef195c86920cfecafc29f80ce6a88c704f09d72011ad1fd462564bf858c75a6", - "dist/2022-11-01/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "da43e621a113d88f7c4805f70cb5208bac66f97c68485a60f95cf11f5ae0f55c", - "dist/2022-11-01/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "2603b5061d059655e3298df94875fa4876d5ea9af1e04dd197ec5cefa3e1eb4c", - "dist/2022-11-01/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "f79606c20ce3bf64a9ede63e878cda199e7f1b0b13f40bd51d7108b3d4c72cb0", - "dist/2022-11-01/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "f6c46ffbb38f8838c496e1eddea7d6f27392699abfafd0d13b234eee39238181", - "dist/2022-11-01/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "9244fc29cd3c32c971f44fcdaa26623b8976efaf0a4705b573798af5b0b0896e", - "dist/2022-11-01/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "bd502f9105d56af252da1038687a4e942a477c7047cac9730de7414cdbbfbc48", - "dist/2022-11-01/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "426785558da44683a554c542475c9402932c72d63148c37917e8cc6e429ad413", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "52646c86ad464c5803f74ab37166dc1692383bc5fd94818bd579e518c327251e", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "67d1490a41932c2a89981e18c9735d4437faedd1e708e26f75dfd21d4709488b", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "9feb7b704a6d3e6b019a99ecd033042ce81a4b126e4288e0b4772266c6e0a65e", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "fba240009d3f27e04200133120c46112ac64281e99952da44d6fe8a01557f236", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "ce15bda4992ada52f94dae6b1a0e220f26324acefb62094035abe112aa878fec", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "189a8579cf3fe99b9c084821ce1ee9bec6977470341e2ae45b859dcdacf65d21", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "15abcd9e43f2c87fc894b3e280a99865508f9079badcbe7be07c6b79e85f01b4", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "f52dab31a428e568518b00d3afc1426569810bcd20a7db1c0093200c6db86d24", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "57ec35b95a5fd803b2d4dacf7657847111a6cc9bda3cda962174965cd6005085", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "96987349e20e3f602bb6f518924660c09a4575887730b1bbe36adee921921956", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "76d6f5882573169985f5b8a9e13cee8bbe3bd3b423ad287280a0809c6a5efc5a", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9a2c79685b4ac57efea65e43dafa28b59cead1c14e98f10e0196cb2cfd2fa0b6", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0be98b45af7e666955e6e0adb5b4cc3f5517c8d144702b10daedd053450cd5d5", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "ae9ac6e1c0e14bfba746f3a85bfa3f009113d0edbf880a2cf20ece6046ee27bb" + "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.gz": "00b7df89de07931d150940536a1e6c980897ed0e9880bb6f24d5ebbad896c8f2", + "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.xz": "17e1e9cf2c4dad4fec7f420f43cea21923d76ba2d6f87ad67c90ea9c8e4a04f6", + "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "783b7e2569490dffc953d4b24e659fec384739ceb8bad37e3a97df374945a91d", + "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "a9402480620b03c010cb18dacca9a95c82e7b6078d2c1163543bc4292d7dd300", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "7fa9aa92c2b1268420f60af2826dffa50b61c9926a2a1cd1c8273fe5861cde11", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "97d583ed82db1fd5a03ce44a660f1163d0812b6f352adc6d78e61d7ae4fbfe23", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "69236898b091d6ef31445eb1223acfc01adf21fb1aa277a7d441eaa300c0c9ad", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "4a92788cdba1705b79ce9999d45a62d4631dbc59cc980437e1635dc908458b66", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "b35b72b16c59b38e38acddf2c06c2c819ca78f146bbf4f3ce9d7ff982b86655e", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "81d7fbe3f50cbad04c2ad0e118001976a880d23ad2a894ee49c6f6c10583d10d", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "942f6860e2cf9da7c5399d308acad43f862750bf7d383444c2dd636b86553e14", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "5f2f3c7186a2cb28f96bba8db7d404b0f3338bbe57edd631bb16fe4d2c8d493a", + "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "f15932518f114587c3639ed270cab3e4ef4eb28e0abb6b59b5f63138fa43e829", + "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "41116748ab087e0c7a5354508fb95e1a966212ef5cac40da59e363108077c3a9", + "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.gz": "37bbf0a9dcc1b3fbc11a5f72de922fb0f5dc80a632d803fa0a892d72bdd457c1", + "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.xz": "7a8afd8a69e1e25e47122096920217bbe765e82e831583420487702831241d5c", + "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.gz": "c40ec16780156f6568bf8f1353a3bb367d4bec09dc6e98b03de44bd2ed301ae8", + "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.xz": "94320949f071236d828fb1252159f0f2b1f18030303af1ae0b7ca06cd9567de0", + "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.gz": "1fb3fc33289ae716f950feca832196bb32cde0556e41e501d05c84116836d916", + "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.xz": "4f112ea5a91abbf63db484368090fdf8fbc6b7abc1a5d7c8353df15e7908c2e3", + "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.gz": "b90f3c17c73f4dd7b36e0ff56b17be8e1c90f82b33c9be28b7b813fc5c788e05", + "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.xz": "8754bb3f116b09a8b38ac0684014532a19ccb57e4e94d1097a8484e8d67e31ce", + "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "549733dbbc3ec23976d6975e78ec8b8a30396eb45e4a8f5eef6d4c846cf04da1", + "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "f5997ebe7c67969b7d14a2233897b6014ebd9b38010eee101d9e484d42b220c9", + "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3450c71c082bf84115fb035239453e39230afa0575dca0fc52586222b474a0c2", + "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "a16c397c5e980a926e0122cff5f8d30c4b54c2dba7f48ef00b587c5cda8f500d", + "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "62e025463eca2dac0547275c7827e6ecd109d1b84d056526e647abd220b3e1fc", + "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "99c5f5511b23d93707df394c2ab90ddd98e7876c9ee74c861dc919cdd498399b", + "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "eee574420f365d02d52f5f4754563bc1fe4f0b07d02a554f6aa886bccbe4c092", + "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "64e53a591e2d4dee9935fca4a2df18fbbed1b00b74dd6631473ba2d5b257891b", + "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "37d2a5f1c496c8ad8d2b5af5e89a4a325ddcef32ebd7087ef3cc9e653e5a8f4a", + "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "8753d9bfdda6decdcc4f58d2391956609e0aeb75ce4368c7ed52c23ed3f28943", + "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "303c63a294f2112fceb70cee063f35cbee3296b93ca91e43300e72b064d80da7", + "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "96b752dd307d2709dbf2b91c687a55992f4e0e5a143223a8c2a267883b4a2832", + "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "e5c279922e9adb47e6ecaee191ad291bfc627aa05e4c026628664bc47e5ce254", + "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "7e0145fe22bfca7070dcace196e3229a86f9f5b31ab1cfc4fd7ff158db5b1388", + "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "49df0b5774471ced53703942c6551c045ed56c92a3a224615f583511bc845a61", + "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "955e67ac19fc7a2a882f759339343c466da9658b2cd95799dd78328c13d6527e", + "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.gz": "a0e01a9ded551ea1f411da70d4481627579e870c2ff7592efde1d8be83ca46d5", + "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.xz": "a9205d81dff07cbf2468fa6f6999fd0f1266ad4faf84f5688e3e5cb330bdce0f", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "d6406b59361cdc97df606901beeafe6660a4cf557b9de4a313d4659c83f10255", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "ae15fd38cfcd149de306280a48785fe269ea36b1a958de6815adc7a80792d798", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "d75a793188af608b8bbd92907ff69294bc66b85b7ffe03882abcb661fd8c27f9", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "26f4ed51fc227dccc67d4c68fcac78374fb1441093d3524ec157b1b6b6e90012", + "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.gz": "6503b65a5258b5517c5213f0fb858aeff7e00c453a3633749d1a72f7f645050b", + "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.xz": "75ba61fe1670d0e4cf9f9f35460c663701c75ceca95917ed25e98f20cc2f0ef5", + "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.gz": "e003c3a1ed8b57546e6ecdcbbcb58a97896a8e511b6a8fdc31100c24b8dd5a17", + "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.xz": "b377d76b8fae7ebc607f33400cc0b37974fbf02a4d29187b1f0f6f668c12ff01", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0dcfb9c65b5ad5c6af905c78d6914f5d7f8a62def817e64192b29c957b848783", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "1ca64be7777194c3191350723e8a909cce93d8ac28ceafb5df641f3066c6a8b9", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "9c24ff865929e88db27285fcb4a10adf97289a388f93ff5fa421211f35267047", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "b794e0397ca0ec274e307468ed56b8116438c0b8a444f593eb56350d687e8137", + "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.gz": "0fc5f8716933c46509cc05492e5bf75f6d06575dd6f803882397929b95394e12", + "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.xz": "0cfe7415cb4c0a96019eefe0363c1d61934d76f3b5fb72a113b9de1401ecfad9", + "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.gz": "777b016bebe68ea79bfb336eedb595174466bfd54321523b9913f5c2741d0135", + "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.xz": "c4ab94494052bf3fb37a226e1313886546bde1ec4d7188049cb95dbf2963e1fa", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "884004f47fea38414ed805abda4afce3adf5a83fcd072ddececfa888e55bdef4", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "db0858bd63fa8609ceb6ee42cbddc31f31b2a0ce0c02e1fe1c2d32f0c8d607c6", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.gz": "996c8612a39bddb3047ce0f23f761deeca61d15b36f2ea270f5a220d14c1ed27", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.xz": "c06360094800d069261d363b709ca552d3899d50c12d39c23eb58d75015c980a", + "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.gz": "891f1909fcc78019f77d704c3b3b1031c605dee01a116f04e7f4f402d6b9b2af", + "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.xz": "3033d409735b299b6754852c28c1dac378a94ad892144ed76199d542a265c8a7", + "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.gz": "080c97ad158327dfdd24a3c17477614de1dfe27f1236c73ed43b1e7e881f6b06", + "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.xz": "80b89416148f4ed917978686ba337ebdbb3d4a50903a792831fa3b83032c43cb", + "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "854badcf35650c196b2051be46254d2f4e86b4522dbfa9f1d1a64148cae7bf1e", + "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e4ccf358da4cb13b281c999318816fc99948a3531e9ecd6d0abad9b819c117be", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "9473f12fc35106ab9144b38bddc3c35d56b0413bec06c2d1d5f43d4fde614331", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "5cb44be7d8adc0589afca90ef0669c42f03a61a622d856fb057d450554d24c01", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "25ebf045fc59488abc07ed24aa3364fb64cc186f6c852b12cb5c094f81d5fd69", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "d43bca65f55159d6eafb7e342ec5d4598d63bc8fad0c9fc15b6bd88743321d4e", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "91198741990d9300024da5113843cbeff02ed9ea344d9feb57736e9334136d27", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "0aee6204d34246480be1d0f6efd6a66eb10d83a9dd1c215433e840949687c598", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.gz": "97f3193bfde82b997346b49231a0f24a6960da88773bf27c73f57f40ec4f84e6", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.xz": "1d2122442cc0a6595c901831e8cbaaeafd2043fbc8c4b028265310d2086673cb", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.gz": "6d351f35cb9252c2825311eb22049283534cc2877cfd673fc1b5b3c94c6ef864", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.xz": "054bb5a98df25830201ab04e81f63630dc329f48daa0d715a3443f95d2c0f442", + "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.gz": "93b70e7c6b686ed5695bcf2f0b2da14e89a50e54304d445ebfc35107f689c442", + "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.xz": "9b8983be6089216428007e968844f57bd88e2371dd592b1ca06aed2aa6479d8c", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "753ef462dd47349fee5f45adadc073363250fbcbf566ff337250466d0ce73343", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "c19389db997fd0e158e5a5e847f566f6b03f06b3161ce5644ca0178fae25d0f5", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "c819d6a3de743f54e28eab0f2c7744dd5a5be7c6677bb712bfd3f93938435194", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4ca09f9df5476449c3510c82e284026329411253e2a02c90e6239f30a9a6074a", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "f7994d565baee0fbdb010211fcd30398f7f90bd97770ce72e5ba34bf1f06a466", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "f54e1efdb9a088a13371e5fd7e1599a7bcadc5db4247e8811ab9d374c17fac8a", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "add3333e892ccfc31b8fa506e79d5633261daf13e7902549ac5ecfe8f3655bbd", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "bfa9a7cb0de16ecef093d593677e32164e4e68042806f543824c16f2a12b55ae", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.gz": "81c958b4ba5933c02cb2872efc4d5de86a2bc1a1d326bf563256ec74e256fd8f", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.xz": "634d2e35b2314826198eb2a7fd6f253cac5c2bbe7a5a7c7cdecc09949db23b3a", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.gz": "62dd020647cfa88c6719b4b9a803d07f3ccae7c2f94c924e1529def264db1be8", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.xz": "53a03694b610146cb80e0ef0033600ea4dd6f8b7d413c3ac675cb57c9b4c5cde", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "ac7c396d35406501eda50191b92abab74e19148ec6caa2d5171bba35f2d3ec96", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "058c514636a2063193d278e16fc683dbe9c1dadcbca45707152d150dba71065a", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "bc5400e734bc4747b3ea44bb5c3cf9af5f11d5b5f2e970bd4626a25a276f15f7", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0079d1cb3d1fd5be99bed480e6ec0b451dd9e2a2299e3347cbee33344cd8c718", + "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.gz": "9dbc9e97f9990f03efe67c817c9dda7fcdc931c7605742182f4d128859c1a53f", + "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.xz": "d0119bed6cb41629aa65d83f7c1021e05e2f90bd21a28e6f0d3b6f0ea9127dd4", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "09cab74e4a6e38d07622fd80e97d424d7437d554c05ce1896acaaddad0e3b637", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "4602ca768e8ba85cfc5a4d4a2964cccd048ad82f349b7453f077e38de918cb0d", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b983a7699fce4c6f9c7f16ea3fd2905a8ddf21623bae71a9e7515b5cd5b288ec", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ca2d6d4c09326559a1528cf32c7a899f985c7e3b7751cec8911d0facac149e51", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "dfa375f608f297f4dd0fc39921609ecebb31101850d73a8bb8b67ce98e319f3d", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "3159afaebb2b17f6b12128e2829944f9406e26cc7019eb33839fda311ea0b809", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "5a2c2361c944d85455b7a037bc820fbfe824180106f5a6d6fbf4066ef78236a3", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "0bd7ac1cada0a3a3894d404ad5871ef3abc4963eeb5a1f05f59e6264b1e6cc3c", + "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.gz": "1f9daa0af4695c51e4cda38235497923b9adfefd1a6eb4be086d720cffab7594", + "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.xz": "b9e5b75720d71bc9e0e16b73b7cf04cd3e5a57da7a6b842926ffcf273308543b", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.gz": "4837b13f144f12e9edb5b49ddf5169d1cd13cff0a3ec3e54160714d45138448e", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.xz": "32a56e92757a9ee82ff71962c7c8144e4240133d44de77d5955510640a31061b", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.gz": "d31ed0250a195a8043e71c8ae3b2e86111ec07b00892ae05c3783761b20774ee", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.xz": "06b70c26d9161b17c2e4ca9255ae1a73f7bbeadb24d733c320875e3dbbc77caf", + "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6271afcf4b05fb4de2ed08ba441b3ee0b476e2e33dbda8a5efa3d7540475bca5", + "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "131c51bb571df676dbafd84d5015888c4bc15130bd7300d4c53c1667907f7f51", + "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.gz": "d6bca2e8ba737a4704dc01dd6fca58a7c8dc8a065107f9fa98588c5fbdfe39a3", + "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.xz": "d64aa029d4209256e18d7bed6e0e28156a965b1d50cb3eb8d70abab57be55a97", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "f48248f5fedc961ea4050254cf9bdbbe70420ebdaf712847a5374a3c97e21df3", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "c9287bc9be332f084a2779803964ae374930d3bec787155ac3c8d1d6be6a587d", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.gz": "1914ba0edb77b0bc7cd83dd93d8a6ca53b29800844cdec9a976342982aad8b27", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.xz": "30d5d1bf54eb6758e0bd3a3f48f186a957fdb1310ba8b3625b5f33994c8a58fb", + "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.gz": "6c05a59ff653bcde6a71dfcbd38718ca3cfeb89b7ec09d1cd380fdb589941d27", + "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.xz": "80b6b57ff73a9483046380c0d4cfc8c090fca5fc4174d5c47f71fffccb7178a6", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.gz": "941bb6f5107630a0b26b8749be29c6df920ccb467df367a5f55491b062352f4a", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f3f2ece3bb0080980e099c176a8a1366171741450fa8b8e515362572b519e19f", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.gz": "a94fcee79bd5941e718a112d855163563f6e5377b59a9c1405ac8804131b0383", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.xz": "4bea862e2d998e976526cb741b7d674a7d620fc7e4838955ef4c53d000cf24aa", + "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.gz": "e5cc60f1c00d966809cd76fd452bbb03452c5cc94a487ef4ad14af12608ae5fa", + "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.xz": "df8df7d1750cf9e92b3e4b57b83b195c1eea6ca62f38ad317882a69e2e813ba9", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "4ff8fc04b63f7a80587d4f75376c74ade7721369ad1508faf5c0f83930e1cf7a", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "4716141a8be8017adb8540c05f88e6463b2add95439320b0084ffb290bc0d943", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.gz": "d7cff128c80db94aaaa2bb708bafa3f857fe8b819ff21a85f7c6c7c5170576be", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.xz": "bc83b17627e87ee4b555e9cc5912dbfbba74586f46719994be6832e22f70424b", + "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.gz": "ec6723c138565c4d9ca87bcda199aceb7b3a42ddf979658cf9e8433a4dae9c70", + "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.xz": "0e67f10a29f2826399604839a4dcbd173f8de39a755283a0c245c54b8a658210", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "a78f899f6fae1671e41aa7d76b37d9041cc32dfa6e9315dabff3afe21f93700b", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4c74cece45b9271c77c4b328d1b3d876b50429077074580d771fc2b03f0d4738", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.gz": "a854fbab503a0541d593cf9496a4e4cf8b9edb49422406b3a7f34e3fa21905f6", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.xz": "f42a81564e7366d5d630632af3113b99c5de6d147d7eb9e31da762bb9d35d4ea", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "de070d1ae3fb8a825092a9a78c26db553839c6d862e451a497d5f94230414bc5", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0a7092c99c587ef69801af713ef834bae809e4868dfcff43babd44bec532717e", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "7077c20142082b0e2b8d6299ffcd8739c8295d315b917563cffe6d42e129cd08", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "86f0988f3baf0b5bbed81483e7d68004651f227ab22d1d36b34c73f132191dfb", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "536fe3059a8095bcc1c44391c27b7d9832d6a057388b4de089915810cbe1baae", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "6b4e397a3a175f4cbbddabb750df14d668c1f4c8520577d35fbcb9dfa8613097", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "30f42499ab4f21caf21551e0e92bb5db9a2e0f42fd0b3e59ee9789dd40d10391", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "1190cfa1023a8d35d202979a1070863bb713495c2c9b720d0371b6d70d23bd7c", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "4ac79a395ba5d70e1a09d0e1ce232b9405b9995f7c459d176be52eade40bbab7", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "42f3666885680cbb2d15ec85cfbc9103e5b170346a9b8cff63a2d15f78472c67", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0b1c979205f8476ad6f0e35c05acb1976cb4c44006c25931e73c35025939f1ff", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "7b6c76ae46ca56746b0bdea404125256636f05c1354e5dcf32c2a487d25e0ee1", + "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ad9cb2ec325e2a2f14ac4db6a5df53a7c06adfe8c4c58f0f2c83748a34d0c550", + "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "1d507bb0cd8c80ee4e9155a0740c2319027ee5280552c1056ee7921a82bb9aa7", + "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "e8d3b7bb483d7b3b737840ddf7a27a28c216d9d0b3ffc7ccded547f76bc932c5", + "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "130edffa27b82def2876fb5562fc7a3971d33855e3ce023e18507b3e1bd47d10", + "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "b5659dcc18fb0e5849acb13df7153518c8df5ca9566852cabaeee33583321d1f", + "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "6bdfae3e9cf07608c862f4c042c47ed318c388bfcfb4cabfa233580b90c7a459", + "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "f28795f8c2823bd817df63486d8a11b6b7cfb9538110e87d8d008ed979a81a3c", + "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "695f6acb6ddb4c4a87515646157b88d2f58e2114b100f22bedcd4e2fa8de00b8", + "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "5f004e4b265efae872e8b0d8fda81f4e65cc50452d558ef90b9bef7639f6ba6d", + "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "c93c1cb534e83d43c40c62ed6623559e3e380f177c4bd151a0d1389a80a58139", + "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "79988bb7bfa27dcacae0c459143be6a34f328ec6bcb73c2267d41a6f022fc045", + "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "11235a96e7e8e14a173db0be71cd1ce7955c79f5a7d20b7436238256a06342fd", + "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "a315accc791f1247e92a6362eb7bd6ab899c4688db7decb36b8d892c200186b1", + "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "a4f6ac1d21ecda00c9d3e34d900771a4c5a50e3e5071d2eba837c9e4738edc80", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "06dd8941f63c3031fa0383dd34981c655b26fd10d5510cd06bdcabb4a592a435", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "882e464b44acb7e286f49d45a4f5a41fbf570ee0d78f1915fd6f94ac392fa928", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "734d6f54d143ddddc2141da72ee02a32d4d505e20eaf0041c86c89f8ad8730ea", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "be32ca1ddb2d48877c70c9a128dba02bfdca7a00e93c114c3c99127e7be04adf", + "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "a6c70d3715b7e50ff15f5473348d8e1c5a061036055a85784b5e84a99e4008ee", + "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "0dbbf637d310f7ef44cb1bc08122c172606c8ff1c886195eebbd52cad5789597", + "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "3e2f7751028f9123d94ff72b08f8ce0b40da36eada77e1414d4178756b46313a", + "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "382a35c79a03f7abebb9c5788f9dd19bd0973cb89e9b07a971eaafc611c3645a", + "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3eb49f766b206966433eecc7cdbbf709e75991644eae6f44596e5ec893fb3e8b", + "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "9162e50f2ddb12fefecdc7c4c2d60e76874e78fd89b45d7fd81a6c95a856ee28", + "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.gz": "dbf20b8fd52e1b6a553369a1690344574e6c660996ddd5121d4a05bfb71c87aa", + "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.xz": "a40d8d444e57eabeecf8acf0b59f24b5d4e2c97ee538bfe38904a1f81a48fb14", + "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.gz": "1e63244aa865e6a115e603f238b64410606453fb38802b1684fa6397660a1501", + "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.xz": "ecd94de3f4a3aff8f9f920ff68383e342dc293ad2fb2584c9d9e48bf60eb82d5", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ad21ab2584999c7c528dcde2e435d0ee73686b9b94c4f31dfeb3abf3cf9b9821", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.xz": "9394854e14bc3e671060630c01b6977ab5afcf9022790986c492fe58f0509191", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "1cbabb457c0546da725a548a88b3268bb0feca4269af2b9cd0b98455c2e0c468", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "1bb23d8d2783554e2043ed71cf982d9750bafa3ccac6e387b25d279137042867", + "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.gz": "076a918e524cc33a02ab2c94e3a607dd293d5d6d63e0797b16f2246057d1082c", + "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.xz": "de8f3e8907fde91bfcbff0c353eb3d1cb9d06dec31142479ef1ad2c6c368d5c6", + "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "658d66031594324821649058e16e3e0b06542e8c9dd17c5fe705c487b5915ffe", + "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "56a9a0235c0aacf561cfc9e7981c57a4d174dbedf5ed943d266302662246b10e", + "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "3318c23ea42624e26cf2a25dd5fae206ccb96137d6833f28d7bfebe3ba7e327c", + "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "b91396e82a9c30711608c3650d637a3ad56ea90d682460c791210f8bfb5a6854", + "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "55b45e9863e197262bd97a9bcb80991c9c34385acaa228b062546b690621b530", + "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "dc0b7ed56a142475759164713bcdd7c64958c7e7febcafa5371414082ae495b2", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "b2bed92d03b295035e4bc4e0fd63b44ee1cc634edb394cfbd7afdc00353a73e9", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "bcce53fd7c0c494ea1c45227190a959e992f07851dd064b2a9c599fafb07077c", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "d6df9026c218b906671e89e433b165552a9486e41399a8f01a12d10495afc8dc", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "f5f2411e3ff94f6e524a14ee46e6e6bc2e9ec91e395b0382f7a40bc6e970d623", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "c766ec36907ce0a7e76ba9a227fdd57eae7a744bc5679b67a6ce1d6ab41ea19f", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "de5f398bc34fb22489e9f6f2a9847954d8231ff5732f2595e8be93eaf7849986", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.gz": "e3ed4bc39da4731443b3bbd584106444aceaf91720546ac66e98712fe65dfa93", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.xz": "704a65e4f3e1afea9d1bd6a60c4d3e5fd57e3e14ba0dd2e2b94305c3e1c92cb8", + "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.gz": "03e2ca41c758fb4f9a2ea562ac4ed7186e27607458bdd7b575d786368336ea11", + "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.xz": "1ebc2ac44181d6d26928cbd550c64c5b496008e97356c68497f15f8cc8351f37", + "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.gz": "0f0520f7163ef3d659e5761b2f0c7a9f2de00b2f769eeec8d1e7e9b3b08daf6d", + "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.xz": "25795f1876330666b7fd6dd724661b364643448d0688d479f492c02faf2f7a4a", + "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.gz": "014a022bbb524d8c550d5dc7d678b9764adcc9962538980e9596ebced9c5614d", + "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.xz": "9b38e214e203c959eba0e8d651410f6cafc9e4b5725228c2bb4ac8f562e6cfa7", + "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "afd9236304892945334183b31072b9b9f9b4faef8b7cdc4ad1f45a9b3e080a58", + "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "33a7e5fd18f2166fb2b6cbe7630d80915533d59afc0080f1370bcfad1114eaa1", + "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.gz": "7e91e1298da3676c4c051d7f34eec21f2fffa0a34af212c785b79c2d1048fe92", + "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.xz": "fff70ed752d0760990f7a90bc3c50ac6586e8b012e61a15b6dfb325dd081b9a9", + "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.gz": "f9183794392422fbe8cfd61ea7bae0dadd8731e82b1d15a59f4e93acccd2048f", + "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.xz": "4fce2ab0dacac153de7d9805786b17d517863b0ff04a8224540daee86eff4056", + "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.gz": "d5b64111b3763063c38ae63915ca366a4fdb63f0dcf8121588a8953f01ebc669", + "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.xz": "c396b086773dc06db2e59bcdaff8ffbb7069efee5841b9e3cdd4dfb05fd95ce4", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "e851812f69bcb2fe606bfbda125fa6b3f55752fd1a2330878c48ca99eedbb8b6", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "689738a0952a0eab27ba3d3f9bc9b531ec29f338ea373bfa783a83786d5c2885", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "b51f78199bfc1417f020e2d0dd16044f63f6b6675b2b6856f669f8604e44a6bf", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "7713269f3c51717f6231cf4100043eca2330512b602c2962da81af561e90193b", + "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.gz": "9f0a129f4c2ea324e2dc94fad3f7acbc7bf2b988f66d9c42dd8abbc60c569acf", + "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.xz": "6ca71851fd0a7879aa750a63deb4ee587f82c28b27486f716e4fae5ebe599086", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "6cfbf0f85757854fba1551c3312baac820e398b573d50b005cc3958723db7c82", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "2e2dfb82fa7e23f888ae9541a30d15ba978cb29bbdfec6afb00590a39c16df5d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.gz": "92650856a7e74c8b912d5c84cd1002a490f9c8e3fa4506733fcbedb3cd42792b", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.xz": "3dd302996bd3fb9f8b077e6d5fe3dc6f7dd9590d5fc3eb3bab2cffaada4e99d3", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "3a1faf905ffc7263e725ce7571cb84dd8698adbc45b6902da86350299b2e3ccb", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "daef635cdf88c8d9c924c0d66e2b26db1f56bda9b48ca0c21e089060b07dc997", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "567bb99f67737cca721d1dc6975daefd3dad29b13d531d3b939405ef4e7aee84", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "aa218c4547e77f33ba4bc45bba0b6fcf3cce9355c2cf11d74a3a4c5e49f9b3cd", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "de43b04cccb3c2bdcd2a7993c391299a4bde5041102ce0eb5e32b6cfae86cd79", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "f99963704b4c3189361925ec8b53daa2ca15ae4af9215cbd87cfec23e044cefa", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "3d4949e63f137552e3b74e50b366f95d7a153e7c61cf5587634be51516fdc610", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "5b48095a35f862190536e64eff726327e25c23981c0bc1224c8c44bfccbb705d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.gz": "12b5c69138260daf976e963ba503c66ec4432f11cf7506bc9ba691ac2c1df4a1", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.xz": "5c334a67f6586dc406b6e55c7f9d64b7701e1c7879bf5860b378069301c57854", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.gz": "58c15f9119e5f78d7c70b24e67af57ce10bb2d2cb1347b9b4631478665c624de", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.xz": "a2f8b635254d53ec5b902dbeb8ac63c6c3982f94dfbcaec3d093f17f0f5fa896", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.gz": "1ce5c25480e97699b12c180ed6198766a0c12a3543dd317ba6f4a52538027b0d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.xz": "e4d9ffe34ba40e5ccf87007085dc4daa20a8a52944f092e2a075527702b55072", + "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.gz": "f5c8dadb8eb0335a50326a94f858625e4f01e3159e933d58f9d24338d47943be", + "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.xz": "0a6eeb32e4d85b628044c3e075e5f1414a42bb582905b199d360addae466d3ae", + "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0f7ce917f14a1d42637fbbbc343473596becceb22634cb7c7cdee6beaa2b9ca1", + "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "49667bd902fb5fb2855e843ca5c1dcd453171f164a3dee2dcd9e09b0d9e1e57e", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d5a03695685afff4debff8e09f2d91db02d2ac29981a9ec230619c3e388ce1c9", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "db1aeb772a08f111d8f024164b570322f45ecab0f6db4e931b91971b2b982323", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "0e51f97b677b5c813862bba3e5a3b0884f0ecdf9b7c3676089625431a3d0cb2c", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "f88c6c33ac3682f340ed60b4f62ee8ed61eb21069a1f0a912024d19e41c0d5c7", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "25abe3158ec3ab7c064341247d78ea265ad7e0dc2063837fb5cf0a3bea9d011e", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "1d430b8e35ebd63a79b34917edacebb76b2fa8f1cea4772ba2c4ef0340485fb3", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "1858d5ed21a3132af4b56c841cbabc9fb834d501946956a0e9aeeddfa095344f", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "17cc52dbd6ccbed4677ad52fa666ea10295c11209528e78ac190f01b5d509f87", + "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "3440edd99025f24f2640528d2d1c10047c834b93cb09a935c65ecfb72012e7d0", + "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7e1ff0a950db0ecbadef3a9ee55a593891f11a42c6c0ff59637074c8b5c4da74", + "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.gz": "90487ff490c4e71ae62e28492cf49600f8f92e0f35f5d76a50eafcf4bbcf4bcb", + "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.xz": "8b44fb934aba0eef296098bfc5a9f2994cdd595420ce10f4f310c5ee9d481071", + "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.gz": "0fefda6b62234a43976ebf18d7cd62057cad5b494c750f2d9730f5df64cadb00", + "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.xz": "c9eecbc06e7456bf5e383557a8e5720d00d09de640b8c46139121faadc354d74", + "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.gz": "8b17d032192aa17e52a3f08a074079561ad7ad6c439f9274aef228af93adacc3", + "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.xz": "c70638cad594097450a469837411b110e979c303727341623427e3c9e4e4f507", + "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.gz": "3669ff9024092ab467a1b95aec2cb1692810ee716739f31e3aee7d89e6bd6d7f", + "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.xz": "165859e42492e33bff634c80b6c96b13fd2252981b4be2821b96a6593933e22a", + "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2ac418c0cdeb2382aea7296169d747f65349d7e6d5aebbdde7b377e985de354e", + "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "21ae51357508398527b6edd2e5fbb1745fda1c8db2683c40847216c0ce251d47", + "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3eb68935676424aa8c68bc32b06c010c5c1302fa6f77e9b33e5543565562d176", + "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "0eeb58035b510a166b8506168f67850993e278888986773c779bee24d7a6ec11", + "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f41d878b2e49beb9ee3a1bb8863ce1b81fae7100a786a78d9922bf8a4fd0dfc8", + "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "e0cd18973c7651cd2e1e041f92900375a045bef62754d432df539000aa5946c4", + "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "7206be82ba39971c6a734f4a89f7f750d581768d82253e31cd985fecd1d17c3e", + "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "f9ec2a3e98a3b94b170237386256c763d62925b430d0e12a289982c7c79d2bfc", + "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "32be7fe5f359cb2312c9bd966eb43b143b336b4acbdf118bf09221574f157b16", + "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "a8163a5b527b1ee932e06589d690c17d8848dbfa8504de6984a718579698abb2", + "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3e875cb943dd0ffff907f6a582a64f923cb84a07ddd8b5e6f1ec2e1d4228342f", + "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "22537364de01be77a2a5d79486b1090dbee7b3273fc634073031f82576a61a14", + "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "230041ec7d0d4debc841abafe2f3314de51793d281a1077835d9190286a558f7", + "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "2dafdb1a97469737123149608476c248a77ccebeb22834b6a2166fc30551a7ce", + "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "0bd96121550321138dad9f74f331eaefd77ab388843e5561c5c0cb32e9d80072", + "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "ecb02c8535c1518e589eefb10be17830010c40be61f3184576abe93e098d793d", + "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.gz": "600b83ea5c832dc6ad9746d74b7dbc8ea566adb9208c4260b183ef05078d2bff", + "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.xz": "175930f3062b433fc0a2b959917933bf3347d3f3e0900684785493d0ee9dc6f3", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "d1701678ee1d2f2e91f3c1f898f852593ec1b109e430c53c13bc2898b08bca3f", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3400e923af537d28139b9d5d780caa039828e06677cbf499322614006552778c", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "d462ca50803b13e136fbfd49ac4a6e186e416041f3cdaa8b4fe72e628cc10555", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "81ca0992ec8306ff67b00f5f85f31c6617f78b7350116dd56df082c477c9069d", + "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.gz": "65fe64154264ab76bb94aa7f107efa9b58cb801c9aaabcc7e6ffa0ce14319ef9", + "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.xz": "cd6e9bfb6e8c08a46dce7bc623cfdc5a04e55c8377eaa3a75fae0bfe8e00b43e", + "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.gz": "a66bb4b0d9dd9a21b54857c4fa7eb48a88789f0414fec4a1e36c798546c4b71f", + "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.xz": "b63e6299e961b75d9c9bcb46e1dbc22b8fec89292ee6c8758edd43f4b89cb12e", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "c768beca1350bdcbcc31c7d3f30c3ccec0ab2bea0c28bc4c89cdd32d9780cd00", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "62a675d74274ddb4d8a9146c20942cb91b86e0c94a902169c2cf77f4d471d645", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "8f2b81b37bc34291f3d90bb6aec621da0ac760c39727bfd24449c288cc8cb3c3", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "053c313c9a751bf0102448866fad2a80ca67b9f79afce82ce03805430e2e695b", + "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.gz": "a9f42eb0ffdc4bef87669d8fb5163e81a5d82ff6baf631f159b7bccafe9df453", + "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.xz": "d1ea529e56d57132de1782396a767f8f00f30e2b5f7c9a5fa96c3289b43e3515", + "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "411b96fddfbcc90b4522e3f4e2d6e174f3440960e89193c97fcd5ca8afd62809", + "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "29db6fb11b411dc8351a8a8d1b148e81d9c87f9fb234b3a18722ee470b4d36c0", + "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "32ab437117791eb7113ac522ee4119e2e43722528141302772adf9cda7306b24", + "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "4d892f3c65ef8e32670ab3c3e8fb39a2ae623c59d1ff555ec94644254e954474", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "8bff3a1591d25d3e1acb70600e6cd54d712772247376ac5eb90a4b2aafd21a6a", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "b81b094d128a37b178da1eda7c72399a9da4bd614e697c53e9c4d78589f859f5", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "b3a685d1abe4ac639a0a3ea187b83ec660cd838e7c5c010ed60f8620d17df906", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "10b7563202520708fd27cc221ee8db34b368563eb1586be1395955ebf4313d6e", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "34e5ca3d51b51ccd97ded5e0c31c999a84f9d5ca5ee3d010e15212a97ab40567", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "16638ba8478861276c10847b989fd23de942cb82a9d4da9d92858c6800a39a9e", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "13fa3bf29e9d20291703bf2c03bc97cd8e2081d1c747b6835eb0a06f94dd5d19", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "98dd01d90657e43ab3a2b91673137cd6ae4c171633db1f1e4b68b2e90bcb9bab", + "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "1370e4c8ad5bab425c02fc924d5ac079ac1387368a3ea5d22c1cdc2edc9c6ba0", + "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8c312da4ccd992c303fa3f181dc46f9b01022f72061ef43b2fd5848736547870", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "0d7a87816f50452349bd26cefdd9f53f2d93a53243290ac59bd5de414407aa1e", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "982fc6783ad07235d375c4c8964104fdc64a009ea359cca532cc268a8249e88c", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "a5b76840e49a912a819809a2b4c73a0e750422fad4876d11b409a8ed49a77911", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "9566b6417a0bdb4c73272d167cc743b297db62f625449343a6f1ab60c52d5327", + "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "bf6cb5e886ce02a3f9b4b00a3696da0ee277af8f690f5a31119c5fce5779cd4d", + "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "7afa5129bc43346614869721e7094f65eba6681bb9b8ca8a3559925f29433f10", + "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "f9805697506a0c730299492fe04c53433c8c4deb70ca245ff1c2cf5151fe306e", + "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "f5d7d5a841a7e7a5d749e52cdb118d2f2cec09de68835a42748db4b3a0a79979", + "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "dc903c64c969a3c21664263c2a30e9cb0dc42069a95f755545ce9648240a376e", + "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "de6591cc73244d99b3469d88439ad442f00037a1cdcaf5fdc5a694b52e47b2fb", + "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "f4e8dba56a1b90d5871bf8722a5ecd2027a4f101299880a8689f5cf46df2606a", + "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "496c19042848726db446cd3df4c52f3e8a5527002ca5492e2d6ef72528d6887a", + "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "58742a5c8230e8749b01058acea639d92d45090bcec6fb7eb1d8f356b0f08631", + "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bbbdaa32d8d29c407133b0ef2851970da884032effeb85c271d57e58b7d38a44", + "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "1a8a59193dc15d331c3243a2cfaf5c81c023464becc4da63201583d2d2cdc27d", + "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "ee86ae7621804a7b57ccab06dc73b7d87453b53814d482ea43dc26dd01dae1c5", + "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "21a79a050e4461305e280ed7de7c0ade2774ad5230f671c76667be7bdbdc47af", + "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "033afa47c24a4887d40d62391f9f66b76dffdc1bd8f1ad622bfb14db91d7df03", + "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "01cea51850a7f676803f5f8f9a556a71bfb8e7a7e04cc5fc0e7d1b706473338b", + "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "720bf138fb2c541d8d8d0c60d6584cff692c932c6f383901f999e7b3d4078770", + "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "8c3f3fd601bc7d8670f6acfcda29206fd5590fb3a2a6cbb3794ba29cf749144d", + "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "8f1b43479a724197c7ac051c6a6d2a10bd87c6b24fed1d38c9e93f503c87e5b6", + "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "b38b6dc1e65cc0f5031d2045a90404f3b2ce2648884db1f658641e76168d0109", + "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "ed635e2388fcd3bbe94f497404b6787edd5e7471d6c6471345386a43444f46d1", + "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "457995f055ef35a2491326f95caf31376b21e3cc4c0316cf4536cb7604e472d3", + "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "d80b01e8c007da58250f7affea8d034a536437efd766eeb8de6d5b7feba9b0d5", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "ee2ab7683e75fa68ad482c81e546cd71b9209497f16a0590507e5de884f1e627", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "d08326f42bf7f38855e37c624a38923d09cbf162b666e8058891aff06ec017c8", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "e42ee4dfdd0aa342dd8192204fd6cfb503eaa0069f70776adbbca352d7e7b661", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "76ec230ae507729fb4ced016a45b0020775a9eef068c2b2e5ae6e3fcb451d32d", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "55f5c89950a81b00efc542c19b42cbfeb9c969af63280106fc78e8893df3d568", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "5a4cf3589d06e562ebed70bf0015af3e80f83de1c4d311c810ebf09feac640bf", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "fb44bc69be6c89c7245b914324e23284dbd9887ac0c1c4a65379344ce78cfb28", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "8d34915b54cd8ea6abf0bff01546f31f74342e1d21128b1e14c32cdfd3505afd", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "d15403f81b36c0a2829ad2dee5c1edf39a993a13ccc57f01bb45c77898e3b9ec", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "4c0c61f404ec6bb87ab044c0850d116c577a2ff3cfda9ac1598a7858b4fe1a7d", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "8bc1fe0e2496769f52a576ccd13f706b26f706f060bebb2618e2c64c3831e2d3", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "bcb527bb736bea88bbbb6974ba388b11fe20596c2c178314bbfdad5e2db65fcc", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "8bffdf816b12c53d5443e2523c0960a37ab67c93590b0bb753fd5a026e67d368", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "bb5c947ab6dfa28fa7c3d7050e9c14c02eaedf2a4e06d290bee554f569be2c30" } } diff --git a/src/test/codegen/issue-103840.rs b/src/test/codegen/issue-103840.rs new file mode 100644 index 00000000000..f19d7031bb3 --- /dev/null +++ b/src/test/codegen/issue-103840.rs @@ -0,0 +1,9 @@ +// compile-flags: -O +#![crate_type = "lib"] + +pub fn foo(t: &mut Vec<usize>) { + // CHECK-NOT: __rust_dealloc + let mut taken = std::mem::take(t); + taken.pop(); + *t = taken; +} diff --git a/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs index ece2adbdf43..b9c33914360 100644 --- a/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -131,6 +131,13 @@ pub struct Type13<'a> { member3: &'a Type13<'a>, } +// Helper type to allow `Type14<Bar>` to be a unique ID +pub struct Bar; + +// repr(transparent) parameterized type +#[repr(transparent)] +pub struct Type14<T>(T); + pub fn foo0(_: ()) { } // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] pub fn foo1(_: c_void, _: ()) { } @@ -425,6 +432,12 @@ pub fn foo145(_: Type13, _: Type13) { } // CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] pub fn foo146(_: Type13, _: Type13, _: Type13) { } // CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] +pub fn foo147(_: Type14<Bar>) { } +// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] +pub fn foo148(_: Type14<Bar>, _: Type14<Bar>) { } +// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] +pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { } +// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"} @@ -570,6 +583,9 @@ pub fn foo146(_: Type13, _: Type13, _: Type13) { } // CHECK: ![[TYPE141]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooE"} // CHECK: ![[TYPE142]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_E"} // CHECK: ![[TYPE143]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_S_E"} -// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIu3refIvEEE"} -// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIu3refIvEES0_E"} -// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIu3refIvEES0_S0_E"} +// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIvEE"} +// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIvES_E"} +// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} +// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarE +// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_E +// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_S_E diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs index dd3dce4e720..83737a02200 100644 --- a/src/test/incremental/change_symbol_export_status.rs +++ b/src/test/incremental/change_symbol_export_status.rs @@ -2,8 +2,6 @@ // compile-flags: -Zquery-dep-graph // [rpass1]compile-flags: -Zincremental-ignore-spans // [rpass2]compile-flags: -Zincremental-ignore-spans -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] #![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")] diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index f3a7722cdca..65df2e8292a 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index c769246b29b..7bf99f6112e 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 70ef10645f1..db367d07094 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 0f8898c389b..bc83723a908 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index 87fd21fd1b8..9ac9ae24f81 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -4,9 +4,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 3121abbea36..1906843c7a2 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 16d6af01695..193e792c843 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 3ff949fbb3f..182ca7d926c 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(linkage)] diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index cff557dcb74..937fd3ac879 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 9ef46847243..b1ac6f6fa6c 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 1abbff32c6f..285f857c9cb 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index dc878d6827c..3118aa13564 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -12,9 +12,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 01320cd51f4..180bf6fec87 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index ada541e644a..87b86479d07 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index fa054c7decc..4429df6833e 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 67d87f5c4ed..bb83f8300d0 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index fc9671cb41b..e50e5674c66 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 7a91722d70f..4a2706b4f01 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index c453eeceb77..b583bee2f24 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index f555f555f92..3b2e18d17a9 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 18fb716353f..58af51eef07 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 88fd4d89b28..c81b0d0afb8 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 9b4d23757b8..c1cc0b62bc2 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index 639454cc975..38ab2846191 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -1,21 +1,17 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 rpass3 rpass4 +// revisions:rpass1 rpass2 // ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g -Z query-dep-graph -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] #![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")] -#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")] -#[cfg(any(rpass1, rpass3))] +#[cfg(rpass1)] pub fn main() {} -#[cfg(any(rpass2, rpass4))] -#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] -#[rustc_clean(cfg = "rpass4")] +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] pub fn main() {} diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index 6f51c9729e3..085e4cd78ca 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -1,26 +1,22 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 rpass3 rpass4 -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans +// revisions:rpass1 rpass2 // compile-flags: -C overflow-checks=on -Z query-dep-graph #![feature(rustc_attrs)] #![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")] -#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")] -#[cfg(any(rpass1, rpass3))] +#[cfg(rpass1)] pub fn main() { if std::hint::black_box(false) { panic!() } } -#[cfg(any(rpass2, rpass4))] -#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] -#[rustc_clean(cfg = "rpass4")] +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] pub fn main() { if std::hint::black_box(false) { panic!() diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index cae7b4aab75..e15a8d18f85 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -1,7 +1,5 @@ -// revisions: cfail1 cfail2 cfail3 cfail4 +// revisions: cfail1 cfail2 // compile-flags: -Z query-dep-graph -// [cfail3]compile-flags: -Zincremental-relative-spans -// [cfail4]compile-flags: -Zincremental-relative-spans // build-pass (FIXME(62277): could be check-pass?) #![allow(warnings)] @@ -13,14 +11,13 @@ // needed even for callers of `x`. pub mod x { - #[cfg(any(cfail1, cfail3))] + #[cfg(cfail1)] pub fn x() { println!("{}", "1"); } - #[cfg(any(cfail2, cfail4))] - #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")] - #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")] + #[cfg(cfail2)] + #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail2")] pub fn x() { println!("{}", "2"); } @@ -30,7 +27,6 @@ pub mod y { use x; #[rustc_clean(cfg = "cfail2")] - #[rustc_clean(cfg = "cfail4")] pub fn y() { x::x(); } @@ -40,7 +36,6 @@ pub mod z { use y; #[rustc_clean(cfg = "cfail2")] - #[rustc_clean(cfg = "cfail4")] pub fn z() { y::y(); } diff --git a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs index 31f329a7f72..368a726ea90 100644 --- a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs +++ b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs @@ -3,10 +3,7 @@ // ends up with any spans in its LLVM bitecode, so LLVM is able to skip // re-building any modules which import 'inlined_fn' -// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans +// revisions: cfail1 cfail2 cfail3 // compile-flags: -Z query-dep-graph -O // build-pass (FIXME(62277): could be check-pass?) @@ -19,16 +16,6 @@ kind = "post-lto" )] #![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-foo", - cfg = "cfail5", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-foo", - cfg = "cfail6", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( module = "cgu_keeps_identical_fn-bar", cfg = "cfail2", kind = "post-lto" @@ -38,16 +25,6 @@ cfg = "cfail3", kind = "post-lto" )] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-bar", - cfg = "cfail5", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-bar", - cfg = "cfail6", - kind = "post-lto" -)] mod foo { diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff index afe157ccd7f..5f3ee467c88 100644 --- a/src/test/mir-opt/inline/cycle.g.Inline.diff +++ b/src/test/mir-opt/inline/cycle.g.Inline.diff @@ -10,6 +10,8 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } + } bb0: { @@ -27,10 +29,7 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ _3 = <fn() {main} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ // mir::Constant -+ // + span: $DIR/cycle.rs:6:5: 6:6 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {main}, ()) -> <fn() {main} as FnOnce<()>>::Output {<fn() {main} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { @@ -40,19 +39,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2: { -+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 -+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 + } + -+ bb4 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 } } diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff index bd89e09ecd1..6b4c63bbd91 100644 --- a/src/test/mir-opt/inline/cycle.main.Inline.diff +++ b/src/test/mir-opt/inline/cycle.main.Inline.diff @@ -10,6 +10,8 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } + } bb0: { @@ -27,10 +29,7 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ _3 = <fn() {g} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ // mir::Constant -+ // + span: $DIR/cycle.rs:6:5: 6:6 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {g}, ()) -> <fn() {g} as FnOnce<()>>::Output {<fn() {g} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { @@ -40,19 +39,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2: { -+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 -+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 + } + -+ bb4 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 } } diff --git a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff index d9fd7b324c7..7fd62be7ab9 100644 --- a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff +++ b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff @@ -8,43 +8,68 @@ + let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 + let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 + let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25 ++ let _5: (); // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ let _6: (); // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ let _7: (); // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 - _1 = <() as G>::call() -> bb1; // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 + StorageLive(_2); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ _2 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ StorageLive(_5); // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ _5 = <() as E>::call() -> bb3; // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 // mir::Constant - // + span: $DIR/exponential_runtime.rs:86:5: 86:20 - // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) } -+ // + span: $DIR/exponential_runtime.rs:73:9: 73:23 -+ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } ++ // + span: $DIR/exponential_runtime.rs:61:9: 61:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } } bb1: { -+ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 -+ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 -+ _3 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 -+ // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 -+ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } -+ } -+ -+ bb2: { + StorageDead(_3); // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26 + StorageLive(_4); // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 -+ _4 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ _4 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 + // mir::Constant + // + span: $DIR/exponential_runtime.rs:75:9: 75:23 + // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } + } + -+ bb3: { ++ bb2: { + StorageDead(_4); // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26 StorageDead(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23 _0 = const (); // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2 return; // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2 ++ } ++ ++ bb3: { ++ StorageDead(_5); // scope 2 at $DIR/exponential_runtime.rs:61:25: 61:26 ++ StorageLive(_6); // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ _6 = <() as E>::call() -> bb4; // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:62:9: 62:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb4: { ++ StorageDead(_6); // scope 2 at $DIR/exponential_runtime.rs:62:25: 62:26 ++ StorageLive(_7); // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ _7 = <() as E>::call() -> bb5; // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:63:9: 63:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb5: { ++ StorageDead(_7); // scope 2 at $DIR/exponential_runtime.rs:63:25: 63:26 ++ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 ++ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _3 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } } } diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff index f54a1a747d4..5510cd7bc8c 100644 --- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -5,17 +5,20 @@ let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 + scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 ++ } ++ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 -+ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline_cycle.rs:43:9: 43:23 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 // mir::Constant - // + span: $DIR/inline_cycle.rs:14:5: 14:22 -- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } -+ // + span: $DIR/inline_cycle.rs:43:9: 43:21 -+ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(<ZST>) } ++ // + span: $DIR/inline_cycle.rs:36:9: 36:26 + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff index a940848c269..64c0065b543 100644 --- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -9,6 +9,8 @@ + debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 + let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 ++ } + } bb0: { @@ -24,10 +26,7 @@ // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } + StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, move _4) -> bb1; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ // mir::Constant -+ // + span: $DIR/inline_cycle.rs:54:5: 54:6 -+ // + literal: Const { ty: extern "rust-call" fn(fn() {f}, ()) -> <fn() {f} as FnOnce<()>>::Output {<fn() {f} as FnOnce<()>>::call_once}, val: Value(<ZST>) } ++ _3 = move _2() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 04de3e61e5f..52debab4dd1 100644 --- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -6,18 +6,21 @@ let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 + scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 + scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 ++ scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 ++ } ++ } + } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 // mir::Constant - // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 -- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } + // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 -+ // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) } + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index a01bcf1645b..f82fcf4c821 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -20,6 +20,8 @@ + debug b => _9; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10 + } + } ++ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16 ++ } + } bb0: { @@ -38,25 +40,10 @@ + StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 -+ _3 = <fn() -> ! {sleep} as Fn<()>>::call(move _4, move _5) -> [return: bb1, unwind: bb5]; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 -+ // mir::Constant -+ // + span: $DIR/inline_diverging.rs:27:13: 27:14 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb6, unwind: bb4]; // scope 4 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb1: { -+ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 -+ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 -+ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 -+ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 -+ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 -+ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb2, unwind: bb4]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 -+ // mir::Constant -+ // + span: $DIR/inline_diverging.rs:28:13: 28:14 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } -+ } -+ -+ bb2: { + StorageDead(_7); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 + StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 + StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 @@ -66,23 +53,35 @@ + (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 + StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11 + StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 -+ drop(_2) -> bb3; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + -+ bb3: { ++ bb2: { + unreachable; // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2 + } + ++ bb3 (cleanup): { ++ drop(_3) -> bb4; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ + bb4 (cleanup): { -+ drop(_3) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + + bb5 (cleanup): { -+ drop(_2) -> bb6; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 + } + -+ bb6 (cleanup): { -+ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 ++ bb6: { ++ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb1, unwind: bb3]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ // mir::Constant ++ // + span: $DIR/inline_diverging.rs:28:13: 28:14 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } } } diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index bd21405f14b..f27b64c3054 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -7,7 +7,7 @@ let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 -+ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 scope 1 { debug _r => _1; // in scope 1 at $DIR/inline_generator.rs:+1:9: +1:11 } @@ -23,7 +23,7 @@ + } + } + } -+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:14: 9:46 ++ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:33: 9:46 + debug a => _7; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7 + let mut _8: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39 + let mut _9: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 @@ -68,8 +68,8 @@ - // mir::Constant - // + span: $DIR/inline_generator.rs:9:33: 9:39 - // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) } -+ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 -+ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 ++ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 + _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + _9 = discriminant((*_10)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 @@ -77,7 +77,7 @@ - bb3: { + bb1: { -+ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 StorageDead(_2); // scope 0 at $DIR/inline_generator.rs:+1:45: +1:46 StorageDead(_4); // scope 0 at $DIR/inline_generator.rs:+1:46: +1:47 _0 = const (); // scope 0 at $DIR/inline_generator.rs:+0:11: +2:2 diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index 969573ba325..09dd35c4c68 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -5,7 +5,7 @@ debug f => _1; // in scope 0 at $DIR/inline_shims.rs:+0:20: +0:21 let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline_shims.rs:+0:36: +0:44 let mut _2: &fn(A, B); // in scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 -+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:5: 6:14 ++ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:7: 6:14 + } bb0: { diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index 777681e1ce7..dc0c3235043 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -6,7 +6,7 @@ fn a(_1: &mut [T]) -> &mut [T] { let mut _2: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:5: 3:15 + scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15 debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 83545c99100..b6aff30149f 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -6,7 +6,7 @@ fn b(_1: &mut Box<T>) -> &mut T { let mut _2: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:5: 8:15 + scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15 debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir index ed4e9927ce9..af830d2494e 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -5,7 +5,7 @@ fn c(_1: &[T]) -> &[T] { let mut _0: &[T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:25: +0:29 let _2: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:5: 13:15 + scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:7: 13:15 debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 18a2670be21..4f9342247d7 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -5,7 +5,7 @@ fn d(_1: &Box<T>) -> &T { let mut _0: &T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:28: +0:30 let _2: &T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:5: 18:15 + scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:7: 18:15 debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _4: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/mir-opt/issue_101973.inner.ConstProp.diff b/src/test/mir-opt/issue_101973.inner.ConstProp.diff index 8fe60a0245d..b2706e5a436 100644 --- a/src/test/mir-opt/issue_101973.inner.ConstProp.diff +++ b/src/test/mir-opt/issue_101973.inner.ConstProp.diff @@ -23,7 +23,7 @@ debug out => _4; // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16 } } - scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:5: 14:58 + scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58 debug self => _4; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL debug n => _6; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _15: u32; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index e0d6b58f229..c17d221f86a 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -4,9 +4,9 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; // in scope 0 at $DIR/issue_59352.rs:+0:21: +0:24 let mut _0: u32; // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38 let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 - let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 let mut _9: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:8: 14:23 + scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23 debug self => _1; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL debug radix => _3; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -16,7 +16,7 @@ fn num_to_digit(_1: char) -> u32 { debug self => _4; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL } } - scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:26: 14:50 + scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50 debug self => _2; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _7: isize; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _8: !; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL @@ -26,7 +26,7 @@ fn num_to_digit(_1: char) -> u32 { } bb0: { - StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 StorageLive(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -65,7 +65,7 @@ fn num_to_digit(_1: char) -> u32 { _9 = discriminant((*_4)); // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL StorageDead(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageDead(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 } diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index 6ae16bdb5b8..e57544e09e2 100644 --- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -22,6 +22,9 @@ let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL scope 9 { debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL + debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + } } } } @@ -92,11 +95,18 @@ StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL -- _17 = <i32 as From<i32>>::from(move _18) -> bb8; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL -+ _17 = <i32 as From<i32>>::from(move _18) -> bb7; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/result.rs:LL:COL - // + literal: Const { ty: fn(i32) -> i32 {<i32 as From<i32>>::from}, val: Value(<ZST>) } + _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 + StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 + return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 } - bb5: { @@ -142,20 +152,5 @@ + _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 } - -- bb8: { -+ bb7: { - StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } } diff --git a/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir new file mode 100644 index 00000000000..916f99049c6 --- /dev/null +++ b/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir @@ -0,0 +1,52 @@ +// MIR for `ezmap` after PreCodegen + +fn ezmap(_1: Option<i32>) -> Option<i32> { + debug x => _1; // in scope 0 at $DIR/simple_option_map_e2e.rs:+0:14: +0:15 + let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/simple_option_map_e2e.rs:+0:33: +0:44 + let mut _2: [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]; // in scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]>) { // at $DIR/simple_option_map_e2e.rs:14:5: 14:22 + debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20 + debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34 + let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16 + let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + scope 2 { + debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + _3 = discriminant(_1); // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 + switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map_e2e.rs:6:5: 6:14 + } + + bb1: { + Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + } + + bb2: { + unreachable; // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 + } + + bb3: { + _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + _4 = Add(move _5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 + Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 + goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2 + } + + bb4: { + StorageDead(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:21: +1:22 + return; // scope 0 at $DIR/simple_option_map_e2e.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/simple_option_map_e2e.rs b/src/test/mir-opt/simple_option_map_e2e.rs new file mode 100644 index 00000000000..2acd2a227b8 --- /dev/null +++ b/src/test/mir-opt/simple_option_map_e2e.rs @@ -0,0 +1,19 @@ +#[inline(always)] +fn map<T, U, F>(slf: Option<T>, f: F) -> Option<U> +where + F: FnOnce(T) -> U, +{ + match slf { + Some(x) => Some(f(x)), + None => None, + } +} + +// EMIT_MIR simple_option_map_e2e.ezmap.PreCodegen.after.mir +pub fn ezmap(x: Option<i32>) -> Option<i32> { + map(x, |n| n + 1) +} + +fn main() { + assert_eq!(None, ezmap(None)); +} diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml index aab27394eb1..d4443f821d2 100644 --- a/src/test/rustdoc-gui/codeblock-tooltip.goml +++ b/src/test/rustdoc-gui/codeblock-tooltip.goml @@ -34,7 +34,6 @@ define-function: ( ".docblock .example-wrap.compile_fail .tooltip::after", { "content": '"This example deliberately fails to compile"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, @@ -74,7 +73,6 @@ define-function: ( ".docblock .example-wrap.should_panic .tooltip::after", { "content": '"This example panics"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, @@ -114,7 +112,6 @@ define-function: ( ".docblock .example-wrap.ignore .tooltip::after", { "content": '"This example is not tested"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml index 8645c1b1949..6f9209e0ab4 100644 --- a/src/test/rustdoc-gui/docblock-table.goml +++ b/src/test/rustdoc-gui/docblock-table.goml @@ -1,3 +1,4 @@ +// This test checks the appearance of the tables in the doc comments. goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.html#method.func" compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"]) diff --git a/src/test/rustdoc-gui/scrape-examples-color.goml b/src/test/rustdoc-gui/scrape-examples-color.goml new file mode 100644 index 00000000000..360e2af8ba4 --- /dev/null +++ b/src/test/rustdoc-gui/scrape-examples-color.goml @@ -0,0 +1,60 @@ +// Check that scrape example code blocks have the expected colors. +goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" +show-text: true + +define-function: ( + "check-colors", + (theme, highlight, highlight_focus, help_border, help_color, help_hover_border, + help_hover_color), + [ + ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }), + ("reload"), + ("wait-for", ".more-examples-toggle"), + ("assert-css", (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { + "background-color": |highlight|, + }, ALL)), + ("assert-css", (".scraped-example .example-wrap .rust span.highlight.focus", { + "background-color": |highlight_focus|, + }, ALL)), + + ("assert-css", (".scraped-example-list .scrape-help", { + "border-color": |help_border|, + "color": |help_color|, + })), + ("move-cursor-to", ".scraped-example-list .scrape-help"), + ("assert-css", (".scraped-example-list .scrape-help:hover", { + "border-color": |help_hover_border|, + "color": |help_hover_color|, + })), + // Moving the cursor to another item to not break next runs. + ("move-cursor-to", ".search-input"), + ] +) + +call-function: ("check-colors", { + "theme": "ayu", + "highlight": "rgb(91, 59, 1)", + "highlight_focus": "rgb(124, 75, 15)", + "help_border": "rgb(170, 170, 170)", + "help_color": "rgb(238, 238, 238)", + "help_hover_border": "rgb(255, 255, 255)", + "help_hover_color": "rgb(255, 255, 255)", +}) +call-function: ("check-colors", { + "theme": "dark", + "highlight": "rgb(91, 59, 1)", + "highlight_focus": "rgb(124, 75, 15)", + "help_border": "rgb(170, 170, 170)", + "help_color": "rgb(238, 238, 238)", + "help_hover_border": "rgb(255, 255, 255)", + "help_hover_color": "rgb(255, 255, 255)", +}) +call-function: ("check-colors", { + "theme": "light", + "highlight": "rgb(252, 255, 214)", + "highlight_focus": "rgb(246, 253, 176)", + "help_border": "rgb(85, 85, 85)", + "help_color": "rgb(51, 51, 51)", + "help_hover_border": "rgb(0, 0, 0)", + "help_hover_color": "rgb(0, 0, 0)", +}) diff --git a/src/test/rustdoc-gui/scrape-examples-fonts.goml b/src/test/rustdoc-gui/scrape-examples-fonts.goml index b7d7f4ccb4a..142f337cb74 100644 --- a/src/test/rustdoc-gui/scrape-examples-fonts.goml +++ b/src/test/rustdoc-gui/scrape-examples-fonts.goml @@ -1,3 +1,4 @@ +// This test ensures that the correct font is used in scraped examples. goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" store-value: (font, '"Fira Sans", Arial, NanumBarunGothic, sans-serif') diff --git a/src/test/rustdoc-gui/scrape-examples-layout.goml b/src/test/rustdoc-gui/scrape-examples-layout.goml index fde9a0ab0bc..95102528ec1 100644 --- a/src/test/rustdoc-gui/scrape-examples-layout.goml +++ b/src/test/rustdoc-gui/scrape-examples-layout.goml @@ -33,3 +33,17 @@ assert-property: ( ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers", {"clientWidth": |clientWidth|} ) + +// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed +// correctly. + +store-value: (offset_y, 4) + +// First with desktop +assert-position: (".scraped-example .code-wrapper", {"y": 255}) +assert-position: (".scraped-example .code-wrapper .prev", {"y": 255 + |offset_y|}) + +// Then with mobile +size: (600, 600) +assert-position: (".scraped-example .code-wrapper", {"y": 314}) +assert-position: (".scraped-example .code-wrapper .prev", {"y": 314 + |offset_y|}) diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 36e4d555b8e..d5f57ed6102 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -1,7 +1,52 @@ // The goal of this test is to ensure that the sidebar is working as expected in the source // code pages. goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" -// First: desktop mode. +show-text: true + +// First, check the sidebar colors. +define-function: ( + "check-colors", + (theme, color, background_color), + [ + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + }), + ("reload"), + // Checking results colors. + ("assert-css", (".source .sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL)), + ], +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } +) +call-function: ( + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } +) +call-function: ( + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } +) + +// Next, desktop mode layout. size: (1100, 800) // We check that the sidebar isn't expanded and has the expected width. assert-css: ("nav.sidebar", {"width": "50px"}) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 5058630f469..bfd7567a224 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -2,6 +2,50 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" assert-property: (".sidebar", {"clientWidth": "200"}) show-text: true + +// First, check the sidebar colors. +define-function: ( + "check-colors", + (theme, color, background_color), + [ + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + }), + ("reload"), + // Checking results colors. + ("assert-css", (".sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL)), + ], +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } +) +call-function: ( + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } +) +call-function: ( + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } +) + local-storage: {"rustdoc-theme": "light"} // We reload the page so the local storage settings are being used. reload: diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 8a33e713191..aa792196960 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -111,8 +111,57 @@ assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) -// Check the spacing. -assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"}) +// And open it again, since it'll be the reference we use to check positions. +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) + +// Check the sidebar directory entries have a marker and spacing (desktop). +store-property: ( + link_height, + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + "offsetHeight" +) +define-function: ( + "check-sidebar-dir-entry", + (x, y), + [ + ("assert", "details:first-of-type.dir-entry[open] > summary::marker"), + ("assert-css", ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})), + // This check ensures that the summary is only one line. + ("assert-property", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > summary", + {"offsetHeight": |link_height|} + )), + ("assert-position", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > summary", + {"x": |x|, "y": |y|} + )), + ("assert-property", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + {"offsetHeight": |link_height|} + )), + ("assert-position", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + // left margin + {"x": |x| + 27, "y": |y| + |link_height|} + )), + ] +) +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + // border + margin = 6 + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) // Check the search form assert-css: ("nav.sub", {"flex-direction": "row"}) @@ -125,13 +174,45 @@ assert-property: ("nav.sub form", {"offsetTop": 28, "offsetHeight": 34}) assert-property: ("#main-content", {"offsetTop": 90}) // 28 = 90 - 34 - 28 -// Now do the same check on moderately-sized mobile. +// Now do the same check on moderately-sized, tablet mobile. size: (700, 700) assert-css: ("nav.sub", {"flex-direction": "row"}) assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34}) assert-property: ("#main-content", {"offsetTop": 76}) // 21 = 76 - 34 - 21 -// Tiny mobile gets a different display where the logo is stacked on top. +// Check the sidebar directory entries have a marker and spacing (tablet). +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) + +// Tiny, phone mobile gets a different display where the logo is stacked on top. size: (450, 700) assert-css: ("nav.sub", {"flex-direction": "column"}) + +// Check the sidebar directory entries have a marker and spacing (phone). +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) diff --git a/src/test/rustdoc-json/enums/discriminant/basic.rs b/src/test/rustdoc-json/enums/discriminant/basic.rs index 8c221615aa7..06906df3b2c 100644 --- a/src/test/rustdoc-json/enums/discriminant/basic.rs +++ b/src/test/rustdoc-json/enums/discriminant/basic.rs @@ -1,12 +1,12 @@ #[repr(i8)] pub enum Ordering { - // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"' - // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"' + // @is "$.index[*][?(@.name=='Less')].inner.discriminant.expr" '"-1"' + // @is "$.index[*][?(@.name=='Less')].inner.discriminant.value" '"-1"' Less = -1, - // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"' - // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"' + // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.expr" '"0"' + // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.value" '"0"' Equal = 0, - // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"' - // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"' + // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.expr" '"1"' + // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.value" '"1"' Greater = 1, } diff --git a/src/test/rustdoc-json/enums/discriminant/expr.rs b/src/test/rustdoc-json/enums/discriminant/expr.rs index 235b0b47381..e639965e79b 100644 --- a/src/test/rustdoc-json/enums/discriminant/expr.rs +++ b/src/test/rustdoc-json/enums/discriminant/expr.rs @@ -1,30 +1,30 @@ pub enum Foo { - // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.expr" '"{ _ }"' Addition = 0 + 0, - // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"' - // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"' + // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.value" '"1"' + // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.expr" '"0b1"' Bin = 0b1, - // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"' - // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"' + // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.value" '"2"' + // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.expr" '"0o2"' Oct = 0o2, - // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"' - // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"' + // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.value" '"3"' + // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.expr" '"THREE"' PubConst = THREE, - // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"' - // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"' + // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.value" '"4"' + // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.expr" '"0x4"' Hex = 0x4, - // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"' - // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.value" '"5"' + // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.expr" '"{ _ }"' Cast = 5 as isize, - // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"' - // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.value" '"6"' + // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.expr" '"{ _ }"' PubCall = six(), - // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"' - // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.value" '"7"' + // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.expr" '"{ _ }"' PrivCall = seven(), - // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"' - // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"' + // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.value" '"8"' + // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.expr" '"EIGHT"' PrivConst = EIGHT, } diff --git a/src/test/rustdoc-json/enums/discriminant/limits.rs b/src/test/rustdoc-json/enums/discriminant/limits.rs index 8df73d78d23..e56d5594f2f 100644 --- a/src/test/rustdoc-json/enums/discriminant/limits.rs +++ b/src/test/rustdoc-json/enums/discriminant/limits.rs @@ -4,40 +4,40 @@ #[repr(u64)] pub enum U64 { - // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.expr" '"u64::MIN"' + // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.expr" '"u64::MIN"' U64Min = u64::MIN, - // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.value" '"18446744073709551615"' - // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.expr" '"u64::MAX"' + // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.value" '"18446744073709551615"' + // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.expr" '"u64::MAX"' U64Max = u64::MAX, } #[repr(i64)] pub enum I64 { - // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.value" '"-9223372036854775808"' - // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.expr" '"i64::MIN"' + // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.value" '"-9223372036854775808"' + // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.expr" '"i64::MIN"' I64Min = i64::MIN, - // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.value" '"9223372036854775807"' - // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.expr" '"i64::MAX"' + // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.value" '"9223372036854775807"' + // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.expr" '"i64::MAX"' I64Max = i64::MAX, } #[repr(u128)] pub enum U128 { - // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.expr" '"u128::MIN"' + // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.expr" '"u128::MIN"' U128Min = u128::MIN, - // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.value" '"340282366920938463463374607431768211455"' - // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.expr" '"u128::MAX"' + // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.value" '"340282366920938463463374607431768211455"' + // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.expr" '"u128::MAX"' U128Max = u128::MAX, } #[repr(i128)] pub enum I128 { - // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.value" '"-170141183460469231731687303715884105728"' - // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.expr" '"i128::MIN"' + // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.value" '"-170141183460469231731687303715884105728"' + // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.expr" '"i128::MIN"' I128Min = i128::MIN, - // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.value" '"170141183460469231731687303715884105727"' - // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.expr" '"i128::MAX"' + // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.value" '"170141183460469231731687303715884105727"' + // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.expr" '"i128::MAX"' I128Max = i128::MAX, } diff --git a/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs index 3417baa0760..6889b305ffb 100644 --- a/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs +++ b/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs @@ -1,15 +1,15 @@ #[repr(u32)] pub enum Foo { - // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.expr" '"0"' + // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.expr" '"0"' Basic = 0, - // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.value" '"10"' - // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.expr" '"10u32"' + // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.value" '"10"' + // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.expr" '"10u32"' Suffix = 10u32, - // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.value" '"100"' - // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.expr" '"1_0_0"' + // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.value" '"100"' + // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.expr" '"1_0_0"' Underscore = 1_0_0, - // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.value" '"1000"' - // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.expr" '"1_0_0_0u32"' + // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.value" '"1000"' + // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.expr" '"1_0_0_0u32"' SuffixUnderscore = 1_0_0_0u32, } diff --git a/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs index 6af944a2219..6a4f54de617 100644 --- a/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs +++ b/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs @@ -1,10 +1,10 @@ pub enum Foo { - // @is "$.index[*][?(@.name=='Has')].inner.variant_inner" '{"expr":"0", "value":"0"}' + // @is "$.index[*][?(@.name=='Has')].inner.discriminant" '{"expr":"0", "value":"0"}' Has = 0, - // @is "$.index[*][?(@.name=='Doesnt')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='Doesnt')].inner.discriminant" null Doesnt, - // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.discriminant" null AlsoDoesnt, - // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant_inner" '{"expr":"44", "value":"44"}' + // @is "$.index[*][?(@.name=='AlsoHas')].inner.discriminant" '{"expr":"44", "value":"44"}' AlsoHas = 44, } diff --git a/src/test/rustdoc-json/enums/discriminant/struct.rs b/src/test/rustdoc-json/enums/discriminant/struct.rs new file mode 100644 index 00000000000..e91a632a3b3 --- /dev/null +++ b/src/test/rustdoc-json/enums/discriminant/struct.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#[repr(i32)] +// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]' +pub enum Foo { + // @is "$.index[*][?(@.name=='Struct')].inner.discriminant" null + // @count "$.index[*][?(@.name=='Struct')].inner.kind.struct.fields[*]" 0 + Struct {}, + // @is "$.index[*][?(@.name=='StructWithDiscr')].inner.discriminant" '{"expr": "42", "value": "42"}' + // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.kind.struct.fields[*]" 1 + StructWithDiscr { x: i32 } = 42, + // @is "$.index[*][?(@.name=='StructWithHexDiscr')].inner.discriminant" '{"expr": "0x42", "value": "66"}' + // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.kind.struct.fields[*]" 2 + StructWithHexDiscr { x: i32, y: bool } = 0x42, +} diff --git a/src/test/rustdoc-json/enums/discriminant/tuple.rs b/src/test/rustdoc-json/enums/discriminant/tuple.rs new file mode 100644 index 00000000000..b94d5739eab --- /dev/null +++ b/src/test/rustdoc-json/enums/discriminant/tuple.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#[repr(u32)] +// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]' +pub enum Foo { + // @is "$.index[*][?(@.name=='Tuple')].inner.discriminant" null + // @count "$.index[*][?(@.name=='Tuple')].inner.kind.tuple[*]" 0 + Tuple(), + // @is "$.index[*][?(@.name=='TupleWithDiscr')].inner.discriminant" '{"expr": "1", "value": "1"}' + // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.kind.tuple[*]" 1 + TupleWithDiscr(i32) = 1, + // @is "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.discriminant" '{"expr": "0b10", "value": "2"}' + // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.kind.tuple[*]" 2 + TupleWithBinDiscr(i32, i32) = 0b10, +} diff --git a/src/test/rustdoc-json/enums/field_hidden.rs b/src/test/rustdoc-json/enums/field_hidden.rs index e6310cc3b99..78a05431472 100644 --- a/src/test/rustdoc-json/enums/field_hidden.rs +++ b/src/test/rustdoc-json/enums/field_hidden.rs @@ -5,8 +5,8 @@ // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [null] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.kind.tuple" [null] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.discriminant" null pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/src/test/rustdoc-json/enums/kind.rs b/src/test/rustdoc-json/enums/kind.rs index e9ea3ae23c2..1787a859c8b 100644 --- a/src/test/rustdoc-json/enums/kind.rs +++ b/src/test/rustdoc-json/enums/kind.rs @@ -5,27 +5,22 @@ pub enum Foo { // @set Unit = "$.index[*][?(@.name=='Unit')].id" - // @is "$.index[*][?(@.name=='Unit')].inner.variant_kind" '"plain"' - // @is "$.index[*][?(@.name=='Unit')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='Unit')].inner.kind" '"plain"' Unit, // @set Named = "$.index[*][?(@.name=='Named')].id" - // @is "$.index[*][?(@.name=='Named')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='Named')].inner.variant_inner" '{"fields": [], "fields_stripped": false}' + // @is "$.index[*][?(@.name=='Named')].inner.kind.struct" '{"fields": [], "fields_stripped": false}' Named {}, // @set Tuple = "$.index[*][?(@.name=='Tuple')].id" - // @is "$.index[*][?(@.name=='Tuple')].inner.variant_kind" '"tuple"' - // @is "$.index[*][?(@.name=='Tuple')].inner.variant_inner" [] + // @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" [] Tuple(), // @set NamedField = "$.index[*][?(@.name=='NamedField')].id" // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id" - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields[*]" $x - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields_stripped" false + // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields[*]" $x + // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields_stripped" false NamedField { x: i32 }, // @set TupleField = "$.index[*][?(@.name=='TupleField')].id" - // @is "$.index[*][?(@.name=='TupleField')].inner.variant_kind" '"tuple"' // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id" - // @is "$.index[*][?(@.name=='TupleField')].inner.variant_inner[*]" $tup_field + // @is "$.index[*][?(@.name=='TupleField')].inner.kind.tuple[*]" $tup_field TupleField(i32), } diff --git a/src/test/rustdoc-json/enums/struct_field_hidden.rs b/src/test/rustdoc-json/enums/struct_field_hidden.rs index f612a34a492..de939cde2e7 100644 --- a/src/test/rustdoc-json/enums/struct_field_hidden.rs +++ b/src/test/rustdoc-json/enums/struct_field_hidden.rs @@ -9,9 +9,8 @@ pub enum Foo { // @set y = "$.index[*][?(@.name=='y')].id" y: i32, }, - // @is "$.index[*][?(@.name=='Variant')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields_stripped" true - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[0]" $b - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[1]" $y - // @count "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[*]" 2 + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields_stripped" true + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[0]" $b + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[1]" $y + // @count "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[*]" 2 } diff --git a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs index f546eaa0d17..70bfbb81826 100644 --- a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs +++ b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs @@ -14,61 +14,50 @@ // @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id" pub enum EnumWithStrippedTupleVariants { - // @is "$.index[*][?(@.name=='None')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='None')].inner.variant_inner[*]" 0 + // @count "$.index[*][?(@.name=='None')].inner.kind.tuple[*]" 0 None(), - // @is "$.index[*][?(@.name=='One')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='One')].inner.variant_inner[*]" 1 - // @is "$.index[*][?(@.name=='One')].inner.variant_inner[0]" $1.1.0 + // @count "$.index[*][?(@.name=='One')].inner.kind.tuple[*]" 1 + // @is "$.index[*][?(@.name=='One')].inner.kind.tuple[0]" $1.1.0 One(/** 1.1.0*/ bool), - // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[*]" 1 - // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[0]" null + // @count "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[*]" 1 + // @is "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[0]" null OneHidden(#[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='Two')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Two')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[0]" $2.1.0 - // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[1]" $2.1.1 + // @count "$.index[*][?(@.name=='Two')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='Two')].inner.kind.tuple[0]" $2.1.0 + // @is "$.index[*][?(@.name=='Two')].inner.kind.tuple[1]" $2.1.1 Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool), - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[1]" $2.2.1 + // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[1]" $2.2.1 TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool), - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[0]" $2.3.0 - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[1]" null + // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[0]" $2.3.0 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[1]" null TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[1]" null + // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[1]" null TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='Three1')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three1')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[1]" $3.1.1 - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[2]" $3.1.2 + // @count "$.index[*][?(@.name=='Three1')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[1]" $3.1.1 + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[2]" $3.1.2 Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool), - // @is "$.index[*][?(@.name=='Three2')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three2')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[0]" $3.2.0 - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[1]" null - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[2]" $3.2.2 + // @count "$.index[*][?(@.name=='Three2')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[0]" $3.2.0 + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[1]" null + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[2]" $3.2.2 Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool), - // @is "$.index[*][?(@.name=='Three3')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three3')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[0]" $3.3.0 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[1]" $3.3.1 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[2]" null + // @count "$.index[*][?(@.name=='Three3')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[0]" $3.3.0 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[1]" $3.3.1 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[2]" null Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool), } - // @is "$.index[*][?(@.docs=='1.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.1')].name" '"1"' diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs index 23b854d8d17..bc870c502a0 100644 --- a/src/test/rustdoc-json/enums/variant_struct.rs +++ b/src/test/rustdoc-json/enums/variant_struct.rs @@ -1,11 +1,10 @@ // @is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" // @is "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\" pub enum EnumStruct { - // @is "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\" // @is "$.index[*][?(@.name=='x')].kind" \"struct_field\" + // @set x = "$.index[*][?(@.name=='x')].id" // @is "$.index[*][?(@.name=='y')].kind" \"struct_field\" - VariantS { - x: u32, - y: String, - }, + // @set y = "$.index[*][?(@.name=='y')].id" + // @ismany "$.index[*][?(@.name=='VariantS')].inner.kind.struct.fields[*]" $x $y + VariantS { x: u32, y: String }, } diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs index b71ec47a804..d1207bbfb18 100644 --- a/src/test/rustdoc-json/enums/variant_tuple_struct.rs +++ b/src/test/rustdoc-json/enums/variant_tuple_struct.rs @@ -1,8 +1,10 @@ // @is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" // @is "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\" pub enum EnumTupleStruct { - // @is "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\" // @is "$.index[*][?(@.name=='0')].kind" \"struct_field\" + // @set f0 = "$.index[*][?(@.name=='0')].id" // @is "$.index[*][?(@.name=='1')].kind" \"struct_field\" + // @set f1 = "$.index[*][?(@.name=='1')].id" + // @ismany "$.index[*][?(@.name=='VariantA')].inner.kind.tuple[*]" $f0 $f1 VariantA(u32, String), } diff --git a/src/test/rustdoc-ui/issue-105334.rs b/src/test/rustdoc-ui/issue-105334.rs new file mode 100644 index 00000000000..ee1adc6a029 --- /dev/null +++ b/src/test/rustdoc-ui/issue-105334.rs @@ -0,0 +1,2 @@ +impl Vec< br##"*.."## > {} +//~^ ERROR diff --git a/src/test/rustdoc-ui/issue-105334.stderr b/src/test/rustdoc-ui/issue-105334.stderr new file mode 100644 index 00000000000..e163bb4db9e --- /dev/null +++ b/src/test/rustdoc-ui/issue-105334.stderr @@ -0,0 +1,9 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/issue-105334.rs:1:11 + | +LL | impl Vec< br##"*.."## > {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/rustdoc-ui/issue-105737.rs b/src/test/rustdoc-ui/issue-105737.rs new file mode 100644 index 00000000000..154f069d8ff --- /dev/null +++ b/src/test/rustdoc-ui/issue-105737.rs @@ -0,0 +1,4 @@ +impl Vec<lol> {} +//~^ ERROR + +pub fn lol() {} diff --git a/src/test/rustdoc-ui/issue-105737.stderr b/src/test/rustdoc-ui/issue-105737.stderr new file mode 100644 index 00000000000..2dd9beb17da --- /dev/null +++ b/src/test/rustdoc-ui/issue-105737.stderr @@ -0,0 +1,12 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/issue-105737.rs:1:10 + | +LL | impl Vec<lol> {} + | ^^^ + | + = help: `lol` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/rustdoc-ui/issue-105742.rs b/src/test/rustdoc-ui/issue-105742.rs new file mode 100644 index 00000000000..cb1de7433cf --- /dev/null +++ b/src/test/rustdoc-ui/issue-105742.rs @@ -0,0 +1,40 @@ +// compile-flags: -Znormalize-docs + +use std::ops::Index; + +pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR + let _ = s; +} + +pub trait SVec: Index< + <Self as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR + Output = <Index<<Self as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR + Output = <Self as SVec>::Item> as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR +//~^^^^^ ERROR +//~^^^^^^ ERROR +//~^^^^^^^ ERROR +//~^^^^^^^^ ERROR +> { + type Item<'a, T>; + + fn len(&self) -> <Self as SVec>::Item; + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + //~^^^^ ERROR +} diff --git a/src/test/rustdoc-ui/issue-105742.stderr b/src/test/rustdoc-ui/issue-105742.stderr new file mode 100644 index 00000000000..cc101b7ff37 --- /dev/null +++ b/src/test/rustdoc-ui/issue-105742.stderr @@ -0,0 +1,385 @@ +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | <Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | <Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Index<<Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Index<<Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item<T>> as SVec>::Item, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:5:40 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) { + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:5:40 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) { + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | <Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | <Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Index<<Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Index<<Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item<T>> as SVec>::Item, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<T>, + | ~~~~~~~ + +error[E0038]: the trait `SVec` cannot be made into an object + --> $DIR/issue-105742.rs:5:31 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-105742.rs:12:17 + | +LL | pub trait SVec: Index< + | ____________----__^ + | | | + | | this trait cannot be made into an object... +LL | | <Self as SVec>::Item, +LL | | +LL | | +... | +LL | |/ Output = <Index<<Self as SVec>::Item, +LL | || +LL | || +LL | || +LL | || +LL | || Output = <Self as SVec>::Item> as SVec>::Item, + | ||_________________________________________________^ ...because it uses `Self` as a type parameter +... | +LL | | +LL | | > { + | |__^ ...because it uses `Self` as a type parameter + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn len(&self) -> <Self as SVec>::Item<'_>; + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | fn len(&self) -> <Self as SVec>::Item<T>; + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn len(&self) -> <Self as SVec>::Item<'_>; + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | fn len(&self) -> <Self as SVec>::Item<T>; + | ~~~~~~~ + +error: aborting due to 23 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/rustdoc-ui/issue-106213.rs b/src/test/rustdoc-ui/issue-106213.rs new file mode 100644 index 00000000000..6d51846b7d0 --- /dev/null +++ b/src/test/rustdoc-ui/issue-106213.rs @@ -0,0 +1,7 @@ +// compile-flags: --document-private-items +// edition:2021 + +fn use_avx() -> dyn { + //~^ ERROR at least one trait is required for an object type + !( ident_error ) +} diff --git a/src/test/rustdoc-ui/issue-106213.stderr b/src/test/rustdoc-ui/issue-106213.stderr new file mode 100644 index 00000000000..0a4ff69bafb --- /dev/null +++ b/src/test/rustdoc-ui/issue-106213.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-106213.rs:4:17 + | +LL | fn use_avx() -> dyn { + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/rustdoc-ui/issue-106226.rs b/src/test/rustdoc-ui/issue-106226.rs new file mode 100644 index 00000000000..71b497a9adc --- /dev/null +++ b/src/test/rustdoc-ui/issue-106226.rs @@ -0,0 +1,3 @@ +// This is a regression test for <https://github.com/rust-lang/rust/issues/106226>. +type F = [_; ()]; +//~^ ERROR diff --git a/src/test/rustdoc-ui/issue-106226.stderr b/src/test/rustdoc-ui/issue-106226.stderr new file mode 100644 index 00000000000..2beffbc125b --- /dev/null +++ b/src/test/rustdoc-ui/issue-106226.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-106226.rs:2:14 + | +LL | type F = [_; ()]; + | ^^ expected `usize`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/rustdoc-ui/issue-96287.rs b/src/test/rustdoc-ui/issue-96287.rs new file mode 100644 index 00000000000..8d8b4456e63 --- /dev/null +++ b/src/test/rustdoc-ui/issue-96287.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +pub trait TraitWithAssoc { + type Assoc; +} + +pub type Foo<V> = impl Trait<V::Assoc>; +//~^ ERROR +//~^^ ERROR + +pub trait Trait<U> {} + +impl<W> Trait<W> for () {} + +pub fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T> { + () +} diff --git a/src/test/rustdoc-ui/issue-96287.stderr b/src/test/rustdoc-ui/issue-96287.stderr new file mode 100644 index 00000000000..0236b9fe647 --- /dev/null +++ b/src/test/rustdoc-ui/issue-96287.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/issue-96287.rs:7:33 + | +LL | pub type Foo<V> = impl Trait<V::Assoc>; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/issue-96287.rs:7:33 + | +LL | pub type Foo<V> = impl Trait<V::Assoc>; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 0277501de09..af765c51ace 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -59,7 +59,7 @@ pub async fn const_generics<const N: usize>(_: impl Trait<N>) {} // @has - '//pre[@class="rust fn"]' 'pub async fn elided(foo: &str) -> &str' pub async fn elided(foo: &str) -> &str {} // This should really be shown as written, but for implementation reasons it's difficult. -// See `impl Clean for TyKind::Rptr`. +// See `impl Clean for TyKind::Ref`. // @has async_fn/fn.user_elided.html // @has - '//pre[@class="rust fn"]' 'pub async fn user_elided(foo: &str) -> &str' pub async fn user_elided(foo: &'_ str) -> &str {} diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index dd3665f22ac..59192a1ecc3 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -3,10 +3,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______- arguments to this function are incorrect @@ -29,10 +26,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______^ expected `!`, found `()` diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 2673ee9f937..7d23c2fc05a 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -3,10 +3,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: Layout, LL | || ) { | ||_- arguments to this function are incorrect @@ -36,10 +33,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: Layout, LL | || ) { | ||_^ expected `!`, found `()` diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.rs b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs new file mode 100644 index 00000000000..6c925a3d653 --- /dev/null +++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs @@ -0,0 +1,9 @@ +extern "Rust" { + fn dstfn(src: i32, dst: err); + //~^ ERROR cannot find type `err` in this scope +} + +fn main() { + dstfn(1); + //~^ ERROR this function takes 2 arguments but 1 argument was supplied +} diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr new file mode 100644 index 00000000000..f6bc84c1203 --- /dev/null +++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `err` in this scope + --> $DIR/extern-fn-arg-names.rs:2:29 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^ not found in this scope + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/extern-fn-arg-names.rs:7:5 + | +LL | dstfn(1); + | ^^^^^--- an argument is missing + | +note: function defined here + --> $DIR/extern-fn-arg-names.rs:2:8 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^^^ +help: provide the argument + | +LL | dstfn(1, /* dst */); + | ~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0412. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/array-slice-vec/slice-mut-2.stderr b/src/test/ui/array-slice-vec/slice-mut-2.stderr index bad0268772b..5b040d3e4d3 100644 --- a/src/test/ui/array-slice-vec/slice-mut-2.stderr +++ b/src/test/ui/array-slice-vec/slice-mut-2.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/slice-mut-2.rs:7:18 | -LL | let x: &[isize] = &[1, 2, 3, 4, 5]; - | ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]` -... LL | let _ = &mut x[2..4]; | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x: &[isize] = &mut [1, 2, 3, 4, 5]; + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/asm/aarch64/interpolated-idents.stderr b/src/test/ui/asm/aarch64/interpolated-idents.stderr index 2df17f2e036..f6c50c2e1fd 100644 --- a/src/test/ui/asm/aarch64/interpolated-idents.stderr +++ b/src/test/ui/asm/aarch64/interpolated-idents.stderr @@ -30,12 +30,7 @@ error: asm outputs are not allowed with the `noreturn` option LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... -LL | m!(in out lateout inout inlateout const sym - | _____- - | |_____| - | |_____| - | |_____| - | | +LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack options); | | - diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs index 0ce1f1d8f7f..89f2b3bb7d0 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.rs +++ b/src/test/ui/asm/aarch64/type-check-2-2.rs @@ -25,12 +25,10 @@ fn main() { // Outputs require mutable places - let v: Vec<u64> = vec![0, 1, 2]; + let v: Vec<u64> = vec![0, 1, 2]; //~ ERROR cannot borrow `v` as mutable asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", inout(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable // Sym operands must point to a function or static } diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr index eef16a165a8..41f7c01dc82 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.stderr +++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr @@ -25,24 +25,22 @@ LL | let mut y: u64 = 0; | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-2-2.rs:30:29 + --> $DIR/type-check-2-2.rs:28:13 | LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` + | ^ not mutable LL | asm!("{}", in(reg) v[0]); LL | asm!("{}", out(reg) v[0]); - | ^ cannot borrow as mutable - -error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-2-2.rs:32:31 - | -LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` -... + | - cannot borrow as mutable LL | asm!("{}", inout(reg) v[0]); - | ^ cannot borrow as mutable + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<u64> = vec![0, 1, 2]; + | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/asm/x86_64/interpolated-idents.stderr b/src/test/ui/asm/x86_64/interpolated-idents.stderr index 6ac2ac5a779..80a8c8c77cf 100644 --- a/src/test/ui/asm/x86_64/interpolated-idents.stderr +++ b/src/test/ui/asm/x86_64/interpolated-idents.stderr @@ -30,12 +30,7 @@ error: asm outputs are not allowed with the `noreturn` option LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... -LL | m!(in out lateout inout inlateout const sym - | _____- - | |_____| - | |_____| - | |_____| - | | +LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); | | - diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs index 8198df91095..1d579ccc90e 100644 --- a/src/test/ui/asm/x86_64/type-check-5.rs +++ b/src/test/ui/asm/x86_64/type-check-5.rs @@ -22,11 +22,10 @@ fn main() { // Outputs require mutable places let v: Vec<u64> = vec![0, 1, 2]; + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", inout(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable // Sym operands must point to a function or static diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr index bd90461e52c..7970e76d6a1 100644 --- a/src/test/ui/asm/x86_64/type-check-5.stderr +++ b/src/test/ui/asm/x86_64/type-check-5.stderr @@ -25,24 +25,22 @@ LL | let mut y: u64 = 0; | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:26:29 + --> $DIR/type-check-5.rs:24:13 | LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` -LL | asm!("{}", in(reg) v[0]); -LL | asm!("{}", out(reg) v[0]); - | ^ cannot borrow as mutable - -error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:28:31 - | -LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` + | ^ not mutable ... +LL | asm!("{}", out(reg) v[0]); + | - cannot borrow as mutable LL | asm!("{}", inout(reg) v[0]); - | ^ cannot borrow as mutable + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<u64> = vec![0, 1, 2]; + | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/async-await/issue-105501.rs b/src/test/ui/async-await/issue-105501.rs new file mode 100644 index 00000000000..f30d2a9d81a --- /dev/null +++ b/src/test/ui/async-await/issue-105501.rs @@ -0,0 +1,165 @@ +// check-pass +// edition:2018 + +// This is a regression test for https://github.com/rust-lang/rust/issues/105501. +// It was minified from the published `msf-ice:0.2.1` crate which failed in a crater run. +// A faulty compiler was triggering a `higher-ranked lifetime error`: +// +// > could not prove `[async block@...]: Send` + +use mini_futures::Stream; + +fn is_send(_: impl Send) {} + +pub fn main() { + let fut = async { + let mut stream = mini_futures::iter([()]) + .then(|_| async {}) + .map(|_| async { None }) + .buffered() + .filter_map(std::future::ready); + + stream.next().await + }; + + is_send(async move { + let _: Option<()> = fut.await; + }); +} + +// this is a simplified subset of `futures::StreamExt` and related types +mod mini_futures { + use std::future::Future; + use std::pin::Pin; + use std::task::{Context, Poll}; + + pub fn iter<I>(_: I) -> Iter<I::IntoIter> + where + I: IntoIterator, + { + todo!() + } + + pub trait Stream { + type Item; + + fn then<Fut, F>(self, _: F) -> Then<Self, Fut, F> + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + todo!() + } + + fn map<T, F>(self, _: F) -> Map<Self, F> + where + F: FnMut(Self::Item) -> T, + Self: Sized, + { + todo!() + } + + fn buffered(self) -> Buffered<Self> + where + Self::Item: Future, + Self: Sized, + { + todo!() + } + + fn filter_map<Fut, T, F>(self, _: F) -> FilterMap<Self, Fut, F> + where + F: FnMut(Self::Item) -> Fut, + Fut: Future<Output = Option<T>>, + Self: Sized, + { + todo!() + } + + fn next(&mut self) -> Next<'_, Self> { + todo!() + } + } + + pub struct Iter<I> { + __: I, + } + impl<I> Stream for Iter<I> + where + I: Iterator, + { + type Item = I::Item; + } + + pub struct Then<St, Fut, F> { + __: (St, Fut, F), + } + impl<St, Fut, F> Stream for Then<St, Fut, F> + where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, + { + type Item = Fut::Output; + } + + pub struct Map<St, F> { + __: (St, F), + } + impl<St, F> Stream for Map<St, F> + where + St: Stream, + F: FnMut1<St::Item>, + { + type Item = F::Output; + } + + pub trait FnMut1<A> { + type Output; + } + impl<T, A, R> FnMut1<A> for T + where + T: FnMut(A) -> R, + { + type Output = R; + } + + pub struct Buffered<St> + where + St: Stream, + St::Item: Future, + { + __: (St, St::Item), + } + impl<St> Stream for Buffered<St> + where + St: Stream, + St::Item: Future, + { + type Item = <St::Item as Future>::Output; + } + + pub struct FilterMap<St, Fut, F> { + __: (St, Fut, F), + } + impl<St, Fut, F, T> Stream for FilterMap<St, Fut, F> + where + St: Stream, + F: FnMut1<St::Item, Output = Fut>, + Fut: Future<Output = Option<T>>, + { + type Item = T; + } + + pub struct Next<'a, St: ?Sized> { + __: &'a mut St, + } + impl<St: ?Sized + Stream> Future for Next<'_, St> { + type Output = Option<St::Item>; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { + todo!() + } + } +} diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index 2d3bb48e03b..bf504432880 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/issue-61452.rs:4:5 | -LL | pub async fn f(x: Option<usize>) { - | - help: consider changing this to be mutable: `mut x` LL | x.take(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub async fn f(mut x: Option<usize>) { + | +++ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/issue-61452.rs:9:5 diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr index 163053471b5..e58f7454689 100644 --- a/src/test/ui/async-await/issues/issue-61187.stderr +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable --> $DIR/issue-61187.rs:6:5 | -LL | async fn response(data: Vec<u8>) { - | ---- help: consider changing this to be mutable: `mut data` LL | data.reverse(); | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | async fn response(mut data: Vec<u8>) { + | +++ error: aborting due to previous error diff --git a/src/test/ui/z-crate-attr.rs b/src/test/ui/attributes/z-crate-attr.rs index 1021774fc5f..1021774fc5f 100644 --- a/src/test/ui/z-crate-attr.rs +++ b/src/test/ui/attributes/z-crate-attr.rs diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs index 1b4ac6edcb0..20c7fb3a983 100644 --- a/src/test/ui/augmented-assignments.rs +++ b/src/test/ui/augmented-assignments.rs @@ -19,7 +19,7 @@ fn main() { let y = Int(2); //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut y + //~| SUGGESTION mut y //~ ERROR cannot borrow `y` as mutable, as it is not declared as mutable //~| cannot borrow as mutable += diff --git a/src/test/ui/augmented-assignments.stderr b/src/test/ui/augmented-assignments.stderr index ce555da8975..2910c910d55 100644 --- a/src/test/ui/augmented-assignments.stderr +++ b/src/test/ui/augmented-assignments.stderr @@ -10,11 +10,13 @@ LL | x; error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/augmented-assignments.rs:23:5 | -LL | let y = Int(2); - | - help: consider changing this to be mutable: `mut y` -... LL | y | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut y = Int(2); + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr index 5963dab9f4a..4cc1d821d0a 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 | -LL | let x = &0; - | -- help: consider changing this to be a mutable reference: `&mut 0` -LL | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x = &mut 0; + | ~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 | -LL | let x = &0 as *const i32; - | -- help: consider changing this to be a mutable pointer: `&mut 0` -LL | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let x = &mut 0 as *const i32; + | ~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index 869375cb2c6..a7748209187 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:5:13 | -LL | let x = 0; - | - help: consider changing this to be mutable: `mut x` LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 0; + | +++ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:11:17 @@ -18,13 +21,16 @@ LL | let y = &raw mut x; error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:21:5 | -LL | let f = || { - | - help: consider changing this to be mutable: `mut f` LL | let y = &raw mut x; | - calling `f` requires mutable binding due to mutable borrow of `x` LL | }; LL | f(); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || { + | +++ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:29:17 diff --git a/src/test/ui/borrowck/borrowck-access-permissions.stderr b/src/test/ui/borrowck/borrowck-access-permissions.stderr index e3a35c38a7c..26f3e2bbdb7 100644 --- a/src/test/ui/borrowck/borrowck-access-permissions.stderr +++ b/src/test/ui/borrowck/borrowck-access-permissions.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-access-permissions.rs:9:19 | -LL | let x = 1; - | - help: consider changing this to be mutable: `mut x` -... LL | let _y1 = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ error[E0596]: cannot borrow immutable static item `static_x` as mutable --> $DIR/borrowck-access-permissions.rs:14:19 @@ -16,37 +18,46 @@ LL | let _y1 = &mut static_x; error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable --> $DIR/borrowck-access-permissions.rs:22:19 | -LL | let box_x = Box::new(1); - | ----- help: consider changing this to be mutable: `mut box_x` -... LL | let _y1 = &mut *box_x; | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut box_x = Box::new(1); + | +++ error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-access-permissions.rs:30:19 | -LL | let ref_x = &x; - | -- help: consider changing this to be a mutable reference: `&mut x` -... LL | let _y1 = &mut *ref_x; | ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let ref_x = &mut x; + | ~~~~~~ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer --> $DIR/borrowck-access-permissions.rs:39:23 | -LL | let ptr_x : *const _ = &x; - | -- help: consider changing this to be a mutable pointer: `&mut x` -... LL | let _y1 = &mut *ptr_x; | ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let ptr_x : *const _ = &mut x; + | ~~~~~~ error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-access-permissions.rs:48:18 | -LL | let foo_ref = &foo; - | ---- help: consider changing this to be a mutable reference: `&mut foo` LL | let _y = &mut *foo_ref.f; | ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let foo_ref = &mut foo; + | ~~~~~~~~ error: aborting due to 6 previous errors diff --git a/src/test/ui/borrowck/borrowck-argument.stderr b/src/test/ui/borrowck/borrowck-argument.stderr index d4d646e390c..1c992dfcceb 100644 --- a/src/test/ui/borrowck/borrowck-argument.stderr +++ b/src/test/ui/borrowck/borrowck-argument.stderr @@ -1,34 +1,46 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:10:5 | -LL | fn func(arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:15:9 | -LL | fn method(&self, arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn method(&self, mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:21:9 | -LL | fn default(&self, arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn default(&self, mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:32:17 | LL | (|arg: S| { arg.mutate() })(s); - | --- ^^^^^^^^^^^^ cannot borrow as mutable - | | - | help: consider changing this to be mutable: `mut arg` + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | (|mut arg: S| { arg.mutate() })(s); + | +++ error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr index 0475df44744..cbacc87a0e8 100644 --- a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr @@ -1,18 +1,24 @@ error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5 | -LL | fn a(s: &S) { - | -- help: consider changing this to be a mutable reference: `&mut S<'_>` LL | *s.pointer += 1; | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn a(s: &mut S<'_>) { + | ~~~~~~~~~~ error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5 | -LL | fn c(s: & &mut S) { - | -------- help: consider changing this to be a mutable reference: `&mut &mut S<'_>` LL | *s.pointer += 1; | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn c(s: &mut &mut S<'_>) { + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr index 186ecddd6d6..19ef0301a2d 100644 --- a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr +++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:15:5 | -LL | let x = Foo { x: 3 }; - | - help: consider changing this to be mutable: `mut x` LL | x.printme(); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Foo { x: 3 }; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr index e00d69f89d3..c2351aacdae 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr @@ -105,10 +105,13 @@ LL | *bar1; error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable --> $DIR/borrowck-borrow-from-owned-ptr.rs:122:16 | -LL | let foo = make_foo(); - | --- help: consider changing this to be mutable: `mut foo` LL | let bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr index ce5ce56dea2..8fcaaa883b2 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr @@ -105,10 +105,13 @@ LL | *bar1; error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable --> $DIR/borrowck-borrow-from-stack-variable.rs:120:16 | -LL | let foo = make_foo(); - | --- help: consider changing this to be mutable: `mut foo` LL | let bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr index 237071e16fc..3c28ff56e41 100644 --- a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5 | -LL | let a: Box<_> = Box::new(A); - | - help: consider changing this to be mutable: `mut a` LL | a.foo(); | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut a: Box<_> = Box::new(A); + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index c99c0f77982..ce9f7aa050a 100644 --- a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -20,10 +20,13 @@ LL | **t1 = 22; error[E0596]: cannot borrow `**t0` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:19:26 | -LL | fn foo4(t0: & &mut isize) { - | ------------ help: consider changing this to be a mutable reference: `&mut &mut isize` LL | let x: &mut isize = &mut **t0; | ^^^^^^^^^ `t0` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(t0: &mut &mut isize) { + | ~~~~~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-issue-14498.stderr b/src/test/ui/borrowck/borrowck-issue-14498.stderr index 4c0e46d4531..42a55b7a854 100644 --- a/src/test/ui/borrowck/borrowck-issue-14498.stderr +++ b/src/test/ui/borrowck/borrowck-issue-14498.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `***p`, which is behind a `&` reference --> $DIR/borrowck-issue-14498.rs:16:5 | -LL | let p = &y; - | -- help: consider changing this to be a mutable reference: `&mut y` LL | ***p = 2; | ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let p = &mut y; + | ~~~~~~ error[E0506]: cannot assign to `**y` because it is borrowed --> $DIR/borrowck-issue-14498.rs:25:5 diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr index d58548f2204..20528e3f0ee 100644 --- a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr +++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-mut-addr-of-imm-var.rs:3:25 | -LL | let x: isize = 3; - | - help: consider changing this to be mutable: `mut x` LL | let y: &mut isize = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x: isize = 3; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr index 8e7ffdc6819..8ab472e64c7 100644 --- a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr +++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/borrowck-mut-slice-of-imm-vec.rs:7:11 | -LL | let v = vec![1, 2, 3]; - | - help: consider changing this to be mutable: `mut v` LL | write(&mut v); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v = vec![1, 2, 3]; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.stderr index ddb63b5ec0f..723b19f4124 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-call.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-call.stderr @@ -11,11 +11,13 @@ LL | use_mut(sp); error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable --> $DIR/borrowck-overloaded-call.rs:67:5 | -LL | let s = SFnMut { - | - help: consider changing this to be mutable: `mut s` -... LL | s(3); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut s = SFnMut { + | +++ error[E0382]: use of moved value: `s` --> $DIR/borrowck-overloaded-call.rs:75:5 diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr index 284cab29608..d9590e446c7 100644 --- a/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr +++ b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr @@ -105,10 +105,13 @@ LL | use_imm(_bar1); error[E0596]: cannot borrow `foo.bar1` as mutable, as it is behind a `&` reference --> $DIR/borrowck-reborrow-from-mut.rs:88:17 | -LL | fn borrow_mut_from_imm(foo: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo` LL | let _bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrow_mut_from_imm(foo: &mut Foo) { + | ~~~~~~~~ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr index e744fc6b54b..5cfd81bd004 100644 --- a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable --> $DIR/borrowck-ref-mut-of-imm.rs:4:12 | -LL | fn destructure(x: Option<isize>) -> isize { - | - help: consider changing this to be mutable: `mut x` -... LL | Some(ref mut v) => *v | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn destructure(mut x: Option<isize>) -> isize { + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr index d46ef126da4..3634676463c 100644 --- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr +++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr @@ -11,10 +11,13 @@ LL | use_mut(g); error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/borrowck-unboxed-closures.rs:7:5 | -LL | fn b<F:FnMut(isize, isize) -> isize>(f: F) { - | - help: consider changing this to be mutable: `mut f` LL | f(1, 2); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn b<F:FnMut(isize, isize) -> isize>(mut f: F) { + | +++ error[E0382]: use of moved value: `f` --> $DIR/borrowck-unboxed-closures.rs:12:5 diff --git a/src/test/ui/borrowck/immut-function-arguments.stderr b/src/test/ui/borrowck/immut-function-arguments.stderr index 7238dd14433..d5392e7d66f 100644 --- a/src/test/ui/borrowck/immut-function-arguments.stderr +++ b/src/test/ui/borrowck/immut-function-arguments.stderr @@ -1,18 +1,24 @@ error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable --> $DIR/immut-function-arguments.rs:2:5 | -LL | fn f(y: Box<isize>) { - | - help: consider changing this to be mutable: `mut y` LL | *y = 5; | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn f(mut y: Box<isize>) { + | +++ error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable --> $DIR/immut-function-arguments.rs:6:35 | LL | let _frob = |q: Box<isize>| { *q = 2; }; - | - ^^^^^^ cannot assign - | | - | help: consider changing this to be mutable: `mut q` + | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let _frob = |mut q: Box<isize>| { *q = 2; }; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr index b7623a54056..774b6cf0ea6 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 | -LL | let t: Tuple = (S(0), 0); - | - help: consider changing this to be mutable: `mut t` -LL | drop(t); LL | t.0 = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ error[E0382]: assign to part of moved value: `t` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 @@ -20,20 +22,24 @@ LL | t.0 = S(1); error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:16:9 | -LL | let t: Tuple = (S(0), 0); - | - help: consider changing this to be mutable: `mut t` -... LL | t.1 = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 | -LL | let u: Tpair = Tpair(S(0), 0); - | - help: consider changing this to be mutable: `mut u` -LL | drop(u); LL | u.0 = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ error[E0382]: assign to part of moved value: `u` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 @@ -48,20 +54,24 @@ LL | u.0 = S(1); error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 | -LL | let u: Tpair = Tpair(S(0), 0); - | - help: consider changing this to be mutable: `mut u` -... LL | u.1 = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 | -LL | let v: Spair = Spair { x: S(0), y: 0 }; - | - help: consider changing this to be mutable: `mut v` -LL | drop(v); LL | v.x = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ error[E0382]: assign to part of moved value: `v` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 @@ -76,11 +86,13 @@ LL | v.x = S(1); error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 | -LL | let v: Spair = Spair { x: S(0), y: 0 }; - | - help: consider changing this to be mutable: `mut v` -... LL | v.y = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ error: aborting due to 9 previous errors diff --git a/src/test/ui/borrowck/issue-85765.stderr b/src/test/ui/borrowck/issue-85765.stderr index 13033962142..7da7dba68ab 100644 --- a/src/test/ui/borrowck/issue-85765.stderr +++ b/src/test/ui/borrowck/issue-85765.stderr @@ -10,11 +10,13 @@ LL | rofl.push(Vec::new()); error[E0594]: cannot assign to `*r`, which is behind a `&` reference --> $DIR/issue-85765.rs:12:5 | -LL | let r = &mutvar; - | ------- help: consider changing this to be a mutable reference: `&mut mutvar` -LL | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let r = &mut mutvar; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-85765.rs:19:5 diff --git a/src/test/ui/borrowck/issue-93093.stderr b/src/test/ui/borrowck/issue-93093.stderr index 031128af476..afa76594f0b 100644 --- a/src/test/ui/borrowck/issue-93093.stderr +++ b/src/test/ui/borrowck/issue-93093.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `self.foo`, which is behind a `&` reference --> $DIR/issue-93093.rs:8:9 | -LL | async fn bar(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` -LL | LL | self.foo += 1; | ^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | async fn bar(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/borrowck/many-mutable-borrows.rs b/src/test/ui/borrowck/many-mutable-borrows.rs new file mode 100644 index 00000000000..3e6ea9d25d9 --- /dev/null +++ b/src/test/ui/borrowck/many-mutable-borrows.rs @@ -0,0 +1,18 @@ +fn main() { + let v = Vec::new(); //~ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); +} diff --git a/src/test/ui/borrowck/many-mutable-borrows.stderr b/src/test/ui/borrowck/many-mutable-borrows.stderr new file mode 100644 index 00000000000..aa0cbcffd95 --- /dev/null +++ b/src/test/ui/borrowck/many-mutable-borrows.stderr @@ -0,0 +1,33 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/many-mutable-borrows.rs:2:9 + | +LL | let v = Vec::new(); + | ^ not mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable + | + = note: ...and 5 other attempted mutable borrows +help: consider changing this to be mutable + | +LL | let mut v = Vec::new(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs index 7cdb16b282d..477a2aa48d5 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs @@ -2,15 +2,14 @@ #![crate_type = "rlib"] pub fn f(b: &mut i32) { - //~^ NOTE the binding is already a mutable borrow + //~^ ERROR cannot borrow + //~| NOTE not mutable //~| NOTE the binding is already a mutable borrow h(&mut b); - //~^ ERROR cannot borrow - //~| NOTE cannot borrow as mutable + //~^ NOTE cannot borrow as mutable //~| HELP try removing `&mut` here g(&mut &mut b); - //~^ ERROR cannot borrow - //~| NOTE cannot borrow as mutable + //~^ NOTE cannot borrow as mutable //~| HELP try removing `&mut` here } diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr index 7782047574c..c6f75b1c0d0 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -1,8 +1,14 @@ error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:7:7 + --> $DIR/mut-borrow-of-mut-ref.rs:4:10 | +LL | pub fn f(b: &mut i32) { + | ^ not mutable +... LL | h(&mut b); - | ^^^^^^ cannot borrow as mutable + | ------ cannot borrow as mutable +... +LL | g(&mut &mut b); + | ------ cannot borrow as mutable | note: the binding is already a mutable borrow --> $DIR/mut-borrow-of-mut-ref.rs:4:13 @@ -14,18 +20,6 @@ help: try removing `&mut` here LL - h(&mut b); LL + h(b); | - -error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:11:12 - | -LL | g(&mut &mut b); - | ^^^^^^ cannot borrow as mutable - | -note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:4:13 - | -LL | pub fn f(b: &mut i32) { - | ^^^^^^^^ help: try removing `&mut` here | LL - g(&mut &mut b); @@ -33,13 +27,13 @@ LL + g(&mut b); | error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:18:12 + --> $DIR/mut-borrow-of-mut-ref.rs:17:12 | LL | h(&mut &mut b); | ^^^^^^ cannot borrow as mutable | note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:17:13 + --> $DIR/mut-borrow-of-mut-ref.rs:16:13 | LL | pub fn g(b: &mut i32) { | ^^^^^^^^ @@ -50,7 +44,7 @@ LL + h(&mut b); | error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:35:5 + --> $DIR/mut-borrow-of-mut-ref.rs:34:5 | LL | f.bar(); | ^^^^^^^ cannot borrow as mutable @@ -60,6 +54,6 @@ help: consider making the binding mutable LL | pub fn baz(mut f: &mut String) { | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/mutability-errors.rs b/src/test/ui/borrowck/mutability-errors.rs index 5be0df13761..82116425f06 100644 --- a/src/test/ui/borrowck/mutability-errors.rs +++ b/src/test/ui/borrowck/mutability-errors.rs @@ -50,9 +50,9 @@ fn ref_closure(mut x: (i32,)) { }); } -fn imm_local(x: (i32,)) { - &mut x; //~ ERROR - &mut x.0; //~ ERROR +fn imm_local(x: (i32,)) { //~ ERROR + &mut x; + &mut x.0; } fn imm_capture(x: (i32,)) { diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index dd29ae492d6..d7c602718f1 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -1,37 +1,46 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/mutability-errors.rs:9:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` LL | *x = (1,); | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `x.0`, which is behind a `&` reference --> $DIR/mutability-errors.rs:10:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -LL | *x = (1,); LL | x.0 = 1; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/mutability-errors.rs:11:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -... LL | &mut *x; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference --> $DIR/mutability-errors.rs:12:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -... LL | &mut x.0; | ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to data in a `&` reference --> $DIR/mutability-errors.rs:16:5 @@ -60,37 +69,46 @@ LL | &mut f().0; error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:23:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` LL | *x = (1,); | ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:24:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -LL | *x = (1,); LL | (*x).0 = 1; | ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer --> $DIR/mutability-errors.rs:25:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -... LL | &mut *x; | ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer --> $DIR/mutability-errors.rs:26:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -... LL | &mut (*x).0; | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to data in a `*const` pointer --> $DIR/mutability-errors.rs:30:5 @@ -227,21 +245,19 @@ LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/mutability-errors.rs:54:5 + --> $DIR/mutability-errors.rs:53:14 | LL | fn imm_local(x: (i32,)) { - | - help: consider changing this to be mutable: `mut x` -LL | &mut x; - | ^^^^^^ cannot borrow as mutable - -error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable - --> $DIR/mutability-errors.rs:55:5 - | -LL | fn imm_local(x: (i32,)) { - | - help: consider changing this to be mutable: `mut x` + | ^ not mutable LL | &mut x; + | ------ cannot borrow as mutable LL | &mut x.0; - | ^^^^^^^^ cannot borrow as mutable + | -------- cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm_local(mut x: (i32,)) { + | +++ error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/mutability-errors.rs:60:9 @@ -339,7 +355,7 @@ error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item LL | &mut X.0; | ^^^^^^^^ cannot borrow as mutable -error: aborting due to 38 previous errors +error: aborting due to 37 previous errors Some errors have detailed explanations: E0594, E0596. For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index a3885b5f5ca..81e5bc45d4d 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -11,11 +11,13 @@ LL | x.a = 1; error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 | -LL | let x: Foo; - | - help: consider changing this to be mutable: `mut x` -LL | x.a = 1; LL | x.b = 22; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: Foo; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index 49c81adad49..ba0457809ad 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_twice.rs:7:5 | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -LL | x = (22, 44); LL | x.0 = 1; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: (u32, u32); + | +++ error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields_twice.rs:12:5 diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr index 481d7e58529..95f36fc042c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -1,14 +1,16 @@ error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference --> $DIR/mut_ref.rs:12:13 | -LL | let ref_mref_x = &mref_x; - | ------- help: consider changing this to be a mutable reference: `&mut mref_x` -LL | LL | let c = || { | ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable LL | LL | **ref_mref_x = y; | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure + | +help: consider changing this to be a mutable reference + | +LL | let ref_mref_x = &mut mref_x; + | ~~~~~~~~~~~ error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference --> $DIR/mut_ref.rs:26:13 diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr index bf9e1febdbb..239f071ca92 100644 --- a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 | -LL | let callback = || { - | -------- help: consider changing this to be mutable: `mut callback` LL | &mut my_var; | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr index b67cec6a609..1ec279f03ef 100644 --- a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 | -LL | let callback = move || { - | -------- help: consider changing this to be mutable: `mut callback` LL | &mut my_var; | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr index 6e98549f6b8..22a62ce7350 100644 --- a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutation-in-closure.rs:6:5 | -LL | let callback = || { - | -------- help: consider changing this to be mutable: `mut callback` LL | my_var = true; | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr index edd55422a0b..a2222f8cc95 100644 --- a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 | -LL | let callback = move || { - | -------- help: consider changing this to be mutable: `mut callback` LL | my_var = true; | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-81700-mut-borrow.stderr b/src/test/ui/closures/issue-81700-mut-borrow.stderr index 3f564afff58..03b18c3f70c 100644 --- a/src/test/ui/closures/issue-81700-mut-borrow.stderr +++ b/src/test/ui/closures/issue-81700-mut-borrow.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `bar` as mutable, as it is not declared as mutable --> $DIR/issue-81700-mut-borrow.rs:3:5 | LL | let bar = || { foo(x); }; - | --- - calling `bar` requires mutable binding due to mutable borrow of `x` - | | - | help: consider changing this to be mutable: `mut bar` + | - calling `bar` requires mutable binding due to mutable borrow of `x` LL | bar(); | ^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut bar = || { foo(x); }; + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-82438-mut-without-upvar.stderr b/src/test/ui/closures/issue-82438-mut-without-upvar.stderr index 802284b2658..f0951b7d108 100644 --- a/src/test/ui/closures/issue-82438-mut-without-upvar.stderr +++ b/src/test/ui/closures/issue-82438-mut-without-upvar.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable --> $DIR/issue-82438-mut-without-upvar.rs:27:27 | -LL | let c = |a, b, c, d| {}; - | - help: consider changing this to be mutable: `mut c` -LL | LL | A.f(participant_name, &mut c); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut c = |a, b, c, d| {}; + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-84044-drop-non-mut.stderr b/src/test/ui/closures/issue-84044-drop-non-mut.stderr index c0bfad263f1..5335a056cd8 100644 --- a/src/test/ui/closures/issue-84044-drop-non-mut.stderr +++ b/src/test/ui/closures/issue-84044-drop-non-mut.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/issue-84044-drop-non-mut.rs:5:10 | -LL | let f = || {}; - | - help: consider changing this to be mutable: `mut f` LL | drop(&mut f); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || {}; + | +++ error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index a60f1c77a58..9f8ce3b6183 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/huge_multispan_highlight.rs:90:13 | -LL | let x = "foo"; - | - help: consider changing this to be mutable: `mut x` -... LL | let y = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = "foo"; + | +++ error: aborting due to previous error diff --git a/src/test/ui/command/command-argv0-debug.rs b/src/test/ui/command/command-argv0-debug.rs deleted file mode 100644 index 4aba1229f29..00000000000 --- a/src/test/ui/command/command-argv0-debug.rs +++ /dev/null @@ -1,21 +0,0 @@ -// run-pass - -// ignore-windows - this is a unix-specific test -// ignore-emscripten no processes -// ignore-sgx no processes -use std::os::unix::process::CommandExt; -use std::process::Command; - -fn main() { - let mut command = Command::new("some-boring-name"); - - assert_eq!(format!("{:?}", command), r#""some-boring-name""#); - - command.args(&["1", "2", "3"]); - - assert_eq!(format!("{:?}", command), r#""some-boring-name" "1" "2" "3""#); - - command.arg0("exciting-name"); - - assert_eq!(format!("{:?}", command), r#"["some-boring-name"] "exciting-name" "1" "2" "3""#); -} diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index f01d7f4710c..eb19d57ab05 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -6,6 +6,11 @@ LL | fn renew<'b: 'a>(self) -> &'b mut [T]; ... LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { | ^^ impl has extra requirement `'a: 'b` + | +help: copy the `where` clause predicates from the trait + | +LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'b: 'a { + | ~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index 4a3af65e904..1a471e18d9d 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -6,6 +6,12 @@ LL | fn foo(); ... LL | fn foo() where 'a: 'b { } | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - fn foo() where 'a: 'b { } +LL + fn foo() { } + | error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs new file mode 100644 index 00000000000..f797beda8e6 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs index a00a19e46d5..bd9c8483ec2 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-1 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs index 71cc0a12ea3..bd0f08f45b6 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-2 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs index 921687d4c3b..1226c2fbb46 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-3 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/crateresolve1.rs b/src/test/ui/crate-loading/crateresolve1.rs index f4795e9536a..f5477f244dd 100644 --- a/src/test/ui/crate-loading/crateresolve1.rs +++ b/src/test/ui/crate-loading/crateresolve1.rs @@ -9,7 +9,6 @@ // NOTE: This test is duplicated at `src/test/ui/error-codes/E0464.rs`. extern crate crateresolve1; -//~^ ERROR multiple matching crates for `crateresolve1` +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/crate-loading/crateresolve1.stderr b/src/test/ui/crate-loading/crateresolve1.stderr index 0d7538eafd8..7b840b52628 100644 --- a/src/test/ui/crate-loading/crateresolve1.stderr +++ b/src/test/ui/crate-loading/crateresolve1.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve1` +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found --> $DIR/crateresolve1.rs:11:1 | LL | extern crate crateresolve1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib error: aborting due to previous error diff --git a/src/test/ui/crate-loading/crateresolve2.rs b/src/test/ui/crate-loading/crateresolve2.rs index 5a4fee7ed6a..0774c0dfd32 100644 --- a/src/test/ui/crate-loading/crateresolve2.rs +++ b/src/test/ui/crate-loading/crateresolve2.rs @@ -8,7 +8,6 @@ // normalize-stderr-test: "\\\?\\" -> "" extern crate crateresolve2; -//~^ ERROR multiple matching crates for `crateresolve2` +//~^ ERROR multiple candidates for `rmeta` dependency `crateresolve2` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/crate-loading/crateresolve2.stderr b/src/test/ui/crate-loading/crateresolve2.stderr index afd3702de7f..a36f4f02265 100644 --- a/src/test/ui/crate-loading/crateresolve2.stderr +++ b/src/test/ui/crate-loading/crateresolve2.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve2` +error[E0464]: multiple candidates for `rmeta` dependency `crateresolve2` found --> $DIR/crateresolve2.rs:10:1 | LL | extern crate crateresolve2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 9562d94509e..1670da55957 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -1,26 +1,35 @@ error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable --> $DIR/issue-35937.rs:7:5 | -LL | let f = Foo { v: Vec::new() }; - | - help: consider changing this to be mutable: `mut f` LL | f.v.push("cat".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = Foo { v: Vec::new() }; + | +++ error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable --> $DIR/issue-35937.rs:16:5 | -LL | let s = S { x: 42 }; - | - help: consider changing this to be mutable: `mut s` LL | s.x += 1; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut s = S { x: 42 }; + | +++ error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable --> $DIR/issue-35937.rs:20:5 | -LL | fn bar(s: S) { - | - help: consider changing this to be mutable: `mut s` LL | s.x += 1; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn bar(mut s: S) { + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index dd193458b37..74fb1c2eca3 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-1.rs:17:9 | -LL | fn f(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.s.push('x'); | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index a2d162f08a1..d3339989361 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-4.rs:6:5 | -LL | fn f(x: usize, f: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>` LL | f.s.push('x'); | ^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: usize, f: &mut Foo<'_>) { + | ~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index 68180eaee03..8dc0512a945 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -1,94 +1,123 @@ error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable --> $DIR/issue-39544.rs:11:13 | -LL | let z = Z { x: X::Y }; - | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut z = Z { x: X::Y }; + | +++ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:16:17 | -LL | fn foo<'z>(&'z self) { - | -------- help: consider changing this to be a mutable reference: `&'z mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo<'z>(&'z mut self) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:20:17 | -LL | fn foo1(&self, other: &Z) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&mut self, other: &Z) { + | ~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:21:17 | -LL | fn foo1(&self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:25:17 | -LL | fn foo2<'a>(&'a self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&'a mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a mut self, other: &Z) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:26:17 | -LL | fn foo2<'a>(&'a self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:30:17 | -LL | fn foo3<'a>(self: &'a Self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&'a mut Self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a mut Self, other: &Z) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:31:17 | -LL | fn foo3<'a>(self: &'a Self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a Self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:35:17 | -LL | fn foo4(other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable --> $DIR/issue-39544.rs:41:13 | -LL | pub fn with_arg(z: Z, w: &Z) { - | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub fn with_arg(mut z: Z, w: &Z) { + | +++ error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:42:13 | -LL | pub fn with_arg(z: Z, w: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut z.x; LL | let _ = &mut w.x; | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn with_arg(z: Z, w: &mut Z) { + | ~~~~~~ error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference --> $DIR/issue-39544.rs:48:5 diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index 67703a1497f..aadd698891e 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference --> $DIR/issue-40823.rs:3:5 | -LL | let mut buf = &[1, 2, 3, 4]; - | ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]` LL | buf.iter_mut(); | ^^^^^^^^^^^^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let mut buf = &mut [1, 2, 3, 4]; + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/dyn-star/align.normal.stderr b/src/test/ui/dyn-star/align.normal.stderr index 983d7bf6e7e..53c2cbeac32 100644 --- a/src/test/ui/dyn-star/align.normal.stderr +++ b/src/test/ui/dyn-star/align.normal.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/align.over_aligned.stderr b/src/test/ui/dyn-star/align.over_aligned.stderr index 6b6fc55d805..62e28efab58 100644 --- a/src/test/ui/dyn-star/align.over_aligned.stderr +++ b/src/test/ui/dyn-star/align.over_aligned.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: `AlignedUsize` needs to be a pointer-sized type diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr index fdf74aa7efe..cb9c7815814 100644 --- a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr +++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr index 933c133831a..bcd014f8dc3 100644 --- a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr +++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/feature-gate-dyn_star.stderr b/src/test/ui/dyn-star/feature-gate-dyn_star.stderr index 2767e9478e2..c3449b6278b 100644 --- a/src/test/ui/dyn-star/feature-gate-dyn_star.stderr +++ b/src/test/ui/dyn-star/feature-gate-dyn_star.stderr @@ -4,7 +4,7 @@ error[E0658]: dyn* trait objects are unstable LL | pub fn dyn_star_parameter(_: &dyn* Send) { | ^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr index 687d7db0464..eb9c933055a 100644 --- a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr +++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr @@ -4,7 +4,7 @@ error[E0658]: dyn* trait objects are unstable LL | let dyn_i: dyn* Debug = i as dyn* Debug; | ^^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error[E0658]: dyn* trait objects are unstable @@ -13,7 +13,7 @@ error[E0658]: dyn* trait objects are unstable LL | let dyn_i: dyn* Debug = i as dyn* Debug; | ^^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error[E0606]: casting `usize` as `dyn* Debug` is invalid diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr index 2fc751b3b4a..c7f1a4b9ae1 100644 --- a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr +++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star, trait_upcasting)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types diff --git a/src/test/ui/dyn-star/return.stderr b/src/test/ui/dyn-star/return.stderr index e000351a68f..9c265682904 100644 --- a/src/test/ui/dyn-star/return.stderr +++ b/src/test/ui/dyn-star/return.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/upcast.stderr b/src/test/ui/dyn-star/upcast.stderr index 6a95f7754e6..74ccd6a1889 100644 --- a/src/test/ui/dyn-star/upcast.stderr +++ b/src/test/ui/dyn-star/upcast.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star, trait_upcasting)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: `dyn* Foo` needs to be a pointer-sized type diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 19439651394..289561bad8a 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -1,13 +1,13 @@ // compile-flags: -Z teach - trait SomeTrait { - fn foo(); //~ associated function `foo` has no `self` parameter + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} } - fn main() { - let trait_obj: &dyn SomeTrait = SomeTrait; - //~^ ERROR expected value, found trait `SomeTrait` - //~| ERROR E0038 + let trait_obj: &dyn SomeTrait = &S; let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 3b68abbb4a0..31bc6719a56 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -1,31 +1,3 @@ -error[E0423]: expected value, found trait `SomeTrait` - --> $DIR/E0033-teach.rs:8:37 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^ not a value - -error[E0038]: the trait `SomeTrait` cannot be made into an object - --> $DIR/E0033-teach.rs:8:20 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/E0033-teach.rs:4:8 - | -LL | trait SomeTrait { - | --------- this trait cannot be made into an object... -LL | fn foo(); - | ^^^ ...because associated function `foo` has no `self` parameter -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self); - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized; - | +++++++++++++++++ - error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033-teach.rs:12:9 | @@ -36,7 +8,6 @@ LL | let &invalid = trait_obj; You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0033, E0038, E0423. -For more information about an error, try `rustc --explain E0033`. +For more information about this error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index e5f0530f45f..bd6ec207223 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -1,11 +1,12 @@ trait SomeTrait { - fn foo(); //~ associated function `foo` has no `self` parameter + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} } - fn main() { - let trait_obj: &dyn SomeTrait = SomeTrait; - //~^ ERROR expected value, found trait `SomeTrait` - //~| ERROR E0038 + let trait_obj: &dyn SomeTrait = &S; let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index f0645107831..ab2e780ee62 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -1,38 +1,9 @@ -error[E0423]: expected value, found trait `SomeTrait` - --> $DIR/E0033.rs:6:37 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^ not a value - -error[E0038]: the trait `SomeTrait` cannot be made into an object - --> $DIR/E0033.rs:6:20 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/E0033.rs:2:8 - | -LL | trait SomeTrait { - | --------- this trait cannot be made into an object... -LL | fn foo(); - | ^^^ ...because associated function `foo` has no `self` parameter -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self); - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized; - | +++++++++++++++++ - error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033.rs:10:9 + --> $DIR/E0033.rs:11:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0033, E0038, E0423. -For more information about an error, try `rustc --explain E0033`. +For more information about this error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr index 3d615bd932f..51c4c92addf 100644 --- a/src/test/ui/error-codes/E0389.stderr +++ b/src/test/ui/error-codes/E0389.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/E0389.rs:8:5 | -LL | let fancy_ref = &(&mut fancy); - | ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)` LL | fancy_ref.num = 6; | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0464.rs b/src/test/ui/error-codes/E0464.rs index 969115a7d97..554f1ce72d9 100644 --- a/src/test/ui/error-codes/E0464.rs +++ b/src/test/ui/error-codes/E0464.rs @@ -9,7 +9,6 @@ // NOTE: This test is duplicated from `src/test/ui/crate-loading/crateresolve1.rs`. extern crate crateresolve1; -//~^ ERROR multiple matching crates for `crateresolve1` +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0464.stderr b/src/test/ui/error-codes/E0464.stderr index 3d950ddd28e..574270f94a6 100644 --- a/src/test/ui/error-codes/E0464.stderr +++ b/src/test/ui/error-codes/E0464.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve1` +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found --> $DIR/E0464.rs:11:1 | LL | extern crate crateresolve1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib + = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0519.rs b/src/test/ui/error-codes/E0519.rs new file mode 100644 index 00000000000..269ffd6320d --- /dev/null +++ b/src/test/ui/error-codes/E0519.rs @@ -0,0 +1,8 @@ +// no need to create a new aux file, we can use an existing. +// aux-build: crateresolve1-1.rs + +// set same metadata as `crateresolve1` +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +extern crate crateresolve1; //~ ERROR E0519 diff --git a/src/test/ui/error-codes/E0519.stderr b/src/test/ui/error-codes/E0519.stderr new file mode 100644 index 00000000000..e24fc4aaa70 --- /dev/null +++ b/src/test/ui/error-codes/E0519.stderr @@ -0,0 +1,9 @@ +error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `crateresolve1` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + --> $DIR/E0519.rs:8:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0519`. diff --git a/src/test/ui/error-codes/E0596.stderr b/src/test/ui/error-codes/E0596.stderr index 79bc258f1fa..3f9aebcc8ae 100644 --- a/src/test/ui/error-codes/E0596.stderr +++ b/src/test/ui/error-codes/E0596.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/E0596.rs:3:13 | -LL | let x = 1; - | - help: consider changing this to be mutable: `mut x` LL | let y = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs index a00a19e46d5..bd9c8483ec2 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-1 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs index 71cc0a12ea3..bd0f08f45b6 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-2 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs index 921687d4c3b..1226c2fbb46 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-3 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs index e4341e19687..fdec072b8a8 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs @@ -8,7 +8,6 @@ fn main() { let p = Some(45).and_then({ - //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>` |x| println!("doubling {}", x); Some(x * 2) //~^ ERROR: cannot find value `x` in this scope diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr index 2f9d10d70a2..e8b34121b5f 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -1,29 +1,9 @@ error[E0425]: cannot find value `x` in this scope - --> $DIR/ruby_style_closure.rs:13:14 + --> $DIR/ruby_style_closure.rs:12:14 | LL | Some(x * 2) | ^ not found in this scope -error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` - --> $DIR/ruby_style_closure.rs:10:31 - | -LL | let p = Some(45).and_then({ - | ______________________--------_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | |x| println!("doubling {}", x); -LL | | Some(x * 2) - | | ----------- this tail expression is of type `Option<_>` -LL | | -LL | | }); - | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` - | - = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` -note: required by a bound in `Option::<T>::and_then` - --> $SRC_DIR/core/src/option.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0425. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs index e44a84776bc..539c8fb27b3 100644 --- a/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs +++ b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs @@ -5,7 +5,8 @@ extern crate proc_macro; -use proc_macro::{Literal, Span, TokenStream, TokenTree}; +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; #[proc_macro] pub fn foo_with_input_span(input: TokenStream) -> TokenStream { @@ -26,3 +27,14 @@ pub fn err_with_input_span(input: TokenStream) -> TokenStream { TokenStream::from(TokenTree::Literal(lit)) } + +#[proc_macro] +pub fn respan_to_invalid_format_literal(input: TokenStream) -> TokenStream { + let mut s = Literal::string("{"); + s.set_span(input.into_iter().next().unwrap().span()); + TokenStream::from_iter([ + TokenTree::from(Ident::new("format", Span::call_site())), + TokenTree::from(Punct::new('!', Spacing::Alone)), + TokenTree::from(Group::new(Delimiter::Parenthesis, TokenTree::from(s).into())), + ]) +} diff --git a/src/test/ui/fmt/respanned-literal-issue-106191.rs b/src/test/ui/fmt/respanned-literal-issue-106191.rs new file mode 100644 index 00000000000..44642a10fc0 --- /dev/null +++ b/src/test/ui/fmt/respanned-literal-issue-106191.rs @@ -0,0 +1,10 @@ +// aux-build:format-string-proc-macro.rs + +extern crate format_string_proc_macro; + +fn main() { + format_string_proc_macro::respan_to_invalid_format_literal!("¡"); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + format_args!(r#concat!("¡ {")); + //~^ ERROR invalid format string: expected `'}'` but string was terminated +} diff --git a/src/test/ui/fmt/respanned-literal-issue-106191.stderr b/src/test/ui/fmt/respanned-literal-issue-106191.stderr new file mode 100644 index 00000000000..73a3af65a38 --- /dev/null +++ b/src/test/ui/fmt/respanned-literal-issue-106191.stderr @@ -0,0 +1,19 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/respanned-literal-issue-106191.rs:6:65 + | +LL | format_string_proc_macro::respan_to_invalid_format_literal!("¡"); + | ^^^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/respanned-literal-issue-106191.rs:8:18 + | +LL | format_args!(r#concat!("¡ {")); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr index 40bf7a3898a..6f430687e6d 100644 --- a/src/test/ui/function-pointer/unsized-ret.stderr +++ b/src/test/ui/function-pointer/unsized-ret.stderr @@ -23,7 +23,7 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&() | required by a bound introduced by this call | = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` - = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` + = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn Display + 'a)` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 | diff --git a/src/test/ui/functions-closures/fn-help-with-err.rs b/src/test/ui/functions-closures/fn-help-with-err.rs index 49a514a8b4e..612fe1b8419 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.rs +++ b/src/test/ui/functions-closures/fn-help-with-err.rs @@ -4,7 +4,6 @@ struct Foo; trait Bar { //~^ NOTE `Bar` defines an item `bar`, perhaps you need to implement it - //~| NOTE `Bar` defines an item `bar`, perhaps you need to implement it fn bar(&self) {} } @@ -15,9 +14,6 @@ fn main() { //~^ ERROR cannot find value `oops` in this scope //~| NOTE not found arc.bar(); - //~^ ERROR no method named `bar` - //~| NOTE method not found - //~| HELP items from traits can only be used if the trait is implemented and in scope let arc2 = std::sync::Arc::new(|| Foo); arc2.bar(); diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr index 463ac7684ec..83a2b1f58f9 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -1,27 +1,14 @@ error[E0425]: cannot find value `oops` in this scope - --> $DIR/fn-help-with-err.rs:14:35 + --> $DIR/fn-help-with-err.rs:13:35 | LL | let arc = std::sync::Arc::new(oops); | ^^^^ not found in this scope -error[E0599]: no method named `bar` found for struct `Arc<_>` in the current scope - --> $DIR/fn-help-with-err.rs:17:9 - | -LL | arc.bar(); - | ^^^ method not found in `Arc<_>` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `bar`, perhaps you need to implement it - --> $DIR/fn-help-with-err.rs:5:1 - | -LL | trait Bar { - | ^^^^^^^^^ - -error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope - --> $DIR/fn-help-with-err.rs:23:10 +error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope + --> $DIR/fn-help-with-err.rs:19:10 | LL | arc2.bar(); - | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>` + | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:18:36]>` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `bar`, perhaps you need to implement it @@ -34,7 +21,7 @@ help: use parentheses to call this closure LL | arc2().bar(); | ++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0425, E0599. For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index ed0628bbbc3..ebf35be581c 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -35,7 +35,7 @@ note: required because it's used within this generator | LL | || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])` +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])` --> $DIR/generator-print-verbose-1.rs:41:30 | LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> { diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 01165fcebaf..e45bdcf9213 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -15,7 +15,6 @@ impl<T> Foo for Fooy<T> { //~^ ERROR impl has stricter requirements than trait type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; //~^ ERROR impl has stricter requirements than trait - //~| ERROR lifetime bound not satisfied type C = String where Self: Copy; //~^ ERROR the trait bound `T: Copy` is not satisfied fn d() where Self: Copy {} diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 442d4f33690..3456b345cc2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -15,29 +15,14 @@ LL | type B<'a, 'b> where 'a: 'b; ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^ impl has extra requirement `'b: 'a` - -error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:16:22 | -LL | type B<'a, 'b> where 'a: 'b; - | -------------- definition of `B` from trait -... -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b` +help: copy the `where` clause predicates from the trait | -note: lifetime parameter instantiated with the lifetime `'a` as defined here - --> $DIR/impl_bounds.rs:16:12 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined here - --> $DIR/impl_bounds.rs:16:16 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'a: 'b; + | ~~~~~~~~~~~~ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:19:33 + --> $DIR/impl_bounds.rs:18:33 | LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` @@ -62,7 +47,7 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:21:24 + --> $DIR/impl_bounds.rs:20:24 | LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` @@ -86,7 +71,7 @@ help: consider restricting type parameter `T` LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0276, E0277, E0478. +Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 2d3f4a6af7e..b4b1bc7da7f 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -5,13 +5,17 @@ LL | type Fut<'a> where Self: 'a; | ------------ definition of `Fut` from trait ... LL | type Fut<'a> = impl Future<Output = ()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:13:14 | LL | type Fut<'a> = impl Future<Output = ()>; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type Fut<'a> = impl Future<Output = ()> where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-91883.stderr b/src/test/ui/generic-associated-types/issue-91883.stderr index 1cfc2aaf161..d5db962094c 100644 --- a/src/test/ui/generic-associated-types/issue-91883.stderr +++ b/src/test/ui/generic-associated-types/issue-91883.stderr @@ -5,7 +5,7 @@ LL | type Cursor<'tx>: Cursor<'tx> | ----------------------------- definition of `Cursor` from trait ... LL | type Cursor<'tx> = CursorImpl<'tx>; - | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` + | ^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'db` as defined here --> $DIR/issue-91883.rs:29:6 @@ -17,6 +17,10 @@ note: but lifetime parameter must outlive the lifetime `'tx` as defined here | LL | type Cursor<'tx> = CursorImpl<'tx>; | ^^^ +help: copy the `where` clause predicates from the trait + | +LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index cd7eed25421..ddc420a7b4e 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -5,13 +5,17 @@ LL | type TextureIter<'a>: Iterator<Item = &'a Texture> | -------------------------------------------------- definition of `TextureIter` from trait ... LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:20:22 | LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs new file mode 100644 index 00000000000..8caf5317693 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs @@ -0,0 +1,12 @@ +trait Foo { + type T<'a1, 'b1> + where + 'a1: 'b1; +} + +impl Foo for () { + type T<'a2, 'b2> = () where 'b2: 'a2; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr new file mode 100644 index 00000000000..91a03007640 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/mismatched-where-clause-regions.rs:8:38 + | +LL | type T<'a1, 'b1> + | ---------------- definition of `T` from trait +... +LL | type T<'a2, 'b2> = () where 'b2: 'a2; + | ^^^ impl has extra requirement `'b2: 'a2` + | +help: copy the `where` clause predicates from the trait + | +LL | type T<'a2, 'b2> = () where 'a2: 'b2; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index ffdba6676bf..8a71fc73a9d 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -6,6 +6,12 @@ LL | type Assoc<'a, 'b>; ... LL | type Assoc<'a, 'b> = () where 'a: 'b; | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - type Assoc<'a, 'b> = () where 'a: 'b; +LL + type Assoc<'a, 'b> = () ; + | error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs new file mode 100644 index 00000000000..4b096be591a --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs @@ -0,0 +1,20 @@ +// Test that Fn-family traits with lifetime parameters shouldn't compile and +// we suggest the usage of higher-rank trait bounds instead. + +fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +use std::ops::Fn as AliasedFn; +fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr new file mode 100644 index 00000000000..e8f6d63b5ab --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr @@ -0,0 +1,62 @@ +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:4:17 + | +LL | fn fa(_: impl Fn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +LL + fn fa(_: impl for<'a> Fn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:7:20 + | +LL | fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} + | ^^^^^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +LL + fn fb(_: impl for<'a, 'b> FnMut(&'a str, &'b str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:10:41 + | +LL | fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +LL + fn fc(_: impl std::fmt::Display + for<'a> FnOnce(&'a str) -> bool + std::fmt::Debug) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:14:24 + | +LL | fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +LL + fn fd(_: impl for<'a> AliasedFn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:17:27 + | +LL | fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} +LL + fn fe<F>(_: F) where F: for<'a> Fn(&'a str) -> bool {} + | + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index be9c643b2d8..63f4898f430 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -5,7 +5,6 @@ pub struct Lint {} impl Lint {} pub fn gather_all() -> impl Iterator<Item = Lint> { - //~^ ERROR type annotations needed lint_files().flat_map(|f| gather_from_file(&f)) } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index fc7200c75c2..0e86561aa27 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -1,22 +1,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/issue-72911.rs:12:33 + --> $DIR/issue-72911.rs:11:33 | LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> { | ^^^ use of undeclared crate or module `foo` error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/issue-72911.rs:17:41 + --> $DIR/issue-72911.rs:16:41 | LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> { | ^^^ use of undeclared crate or module `foo` -error[E0282]: type annotations needed - --> $DIR/issue-72911.rs:7:24 - | -LL | pub fn gather_all() -> impl Iterator<Item = Lint> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0433. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/issues/issue-13497-2.stderr b/src/test/ui/issues/issue-13497-2.stderr index 3abeadf9e4b..a365e24e27e 100644 --- a/src/test/ui/issues/issue-13497-2.stderr +++ b/src/test/ui/issues/issue-13497-2.stderr @@ -1,10 +1,7 @@ error[E0515]: cannot return value referencing local variable `rawLines` --> $DIR/issue-13497-2.rs:3:5 | -LL | rawLines - | ______^ - | | _____| - | || +LL | // rawLines LL | || .iter().map(|l| l.trim()).collect() | ||_______________-___________________________^ returns a value referencing data owned by the current function | |_______________| diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr index 72c65029746..04379f07ba0 100644 --- a/src/test/ui/issues/issue-21763.stderr +++ b/src/test/ui/issues/issue-21763.stderr @@ -7,7 +7,7 @@ LL | foo::<HashMap<Rc<()>, Rc<()>>>(); = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>` = note: required because it appears within the type `(Rc<()>, Rc<()>)` = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send` - = note: required because it appears within the type `hashbrown::map::HashMap<Rc<()>, Rc<()>, RandomState>` + = note: required because it appears within the type `HashMap<Rc<()>, Rc<()>, RandomState>` = note: required because it appears within the type `HashMap<Rc<()>, Rc<()>>` note: required by a bound in `foo` --> $DIR/issue-21763.rs:6:11 diff --git a/src/test/ui/issues/issue-36400.stderr b/src/test/ui/issues/issue-36400.stderr index 3b37578f3c4..5b753c69d5d 100644 --- a/src/test/ui/issues/issue-36400.stderr +++ b/src/test/ui/issues/issue-36400.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable --> $DIR/issue-36400.rs:5:7 | -LL | let x = Box::new(3); - | - help: consider changing this to be mutable: `mut x` LL | f(&mut *x); | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Box::new(3); + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51515.stderr b/src/test/ui/issues/issue-51515.stderr index 067bdef8b67..c4e61e71953 100644 --- a/src/test/ui/issues/issue-51515.stderr +++ b/src/test/ui/issues/issue-51515.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/issue-51515.rs:5:5 | -LL | let foo = &16; - | --- help: consider changing this to be a mutable reference: `&mut 16` -... LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let foo = &mut 16; + | ~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/issue-51515.rs:8:5 diff --git a/src/test/ui/issues/issue-61623.stderr b/src/test/ui/issues/issue-61623.stderr index f6546054233..5fcc338557c 100644 --- a/src/test/ui/issues/issue-61623.stderr +++ b/src/test/ui/issues/issue-61623.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x.1` as mutable, as it is behind a `&` reference --> $DIR/issue-61623.rs:6:19 | -LL | fn f3<'a>(x: &'a ((), &'a mut ())) { - | -------------------- help: consider changing this to be a mutable reference: `&'a mut ((), &'a mut ())` LL | f2(|| x.0, f1(x.1)) | ^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f3<'a>(x: &'a mut ((), &'a mut ())) { + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-67535.rs b/src/test/ui/issues/issue-67535.rs new file mode 100644 index 00000000000..24f50621310 --- /dev/null +++ b/src/test/ui/issues/issue-67535.rs @@ -0,0 +1,22 @@ +fn main() {} + +impl std::ops::AddAssign for () { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: ()) -> () { + () + } +} + +impl std::ops::AddAssign for [(); 1] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: [(); 1]) -> [(); 1] { + [()] + } +} + +impl std::ops::AddAssign for &[u8] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: &[u8]) -> &[u8] { + self + } +} diff --git a/src/test/ui/issues/issue-67535.stderr b/src/test/ui/issues/issue-67535.stderr new file mode 100644 index 00000000000..4d7a02a5096 --- /dev/null +++ b/src/test/ui/issues/issue-67535.stderr @@ -0,0 +1,39 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:3:1 + | +LL | impl std::ops::AddAssign for () { + | ^^^^^-------------------^^^^^-- + | | | | + | | | this is not defined in the current crate because tuples are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:10:1 + | +LL | impl std::ops::AddAssign for [(); 1] { + | ^^^^^-------------------^^^^^------- + | | | | + | | | this is not defined in the current crate because arrays are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:17:1 + | +LL | impl std::ops::AddAssign for &[u8] { + | ^^^^^-------------------^^^^^----- + | | | | + | | | this is not defined in the current crate because slices are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.rs b/src/test/ui/lexer/lex-bad-char-literals-6.rs index 4379b4fa6d7..1b498c0fbca 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.rs +++ b/src/test/ui/lexer/lex-bad-char-literals-6.rs @@ -7,10 +7,8 @@ fn main() { //~^ ERROR: character literal may only contain one codepoint if x == y {} - //~^ ERROR: can't compare `&str` with `char` if y == z {} // no error here if x == z {} - //~^ ERROR: can't compare `&str` with `char` let a: usize = ""; //~^ ERROR: mismatched types diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index ce41942467c..2fe30304a50 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -31,49 +31,14 @@ help: if you meant to write a `str` literal, use double quotes LL | let z = "ef"; | ~~~~ -error[E0277]: can't compare `&str` with `char` - --> $DIR/lex-bad-char-literals-6.rs:9:10 - | -LL | if x == y {} - | ^^ no implementation for `&str == char` - | - = help: the trait `PartialEq<char>` is not implemented for `&str` - = help: the following other types implement trait `PartialEq<Rhs>`: - <&'a str as PartialEq<OsString>> - <&'a str as PartialEq<String>> - <&'b str as PartialEq<Cow<'a, str>>> - <str as PartialEq<Cow<'a, str>>> - <str as PartialEq<OsStr>> - <str as PartialEq<OsString>> - <str as PartialEq<String>> - <str as PartialEq> - error[E0308]: mismatched types - --> $DIR/lex-bad-char-literals-6.rs:15:20 + --> $DIR/lex-bad-char-literals-6.rs:13:20 | LL | let a: usize = ""; | ----- ^^ expected `usize`, found `&str` | | | expected due to this -error[E0277]: can't compare `&str` with `char` - --> $DIR/lex-bad-char-literals-6.rs:12:10 - | -LL | if x == z {} - | ^^ no implementation for `&str == char` - | - = help: the trait `PartialEq<char>` is not implemented for `&str` - = help: the following other types implement trait `PartialEq<Rhs>`: - <&'a str as PartialEq<OsString>> - <&'a str as PartialEq<String>> - <&'b str as PartialEq<Cow<'a, str>>> - <str as PartialEq<Cow<'a, str>>> - <str as PartialEq<OsStr>> - <str as PartialEq<OsString>> - <str as PartialEq<String>> - <str as PartialEq> - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index a909c5fa823..cc2447b1877 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -16,10 +16,13 @@ LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 | -LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` LL | y.push(z); | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:fn(&u8, &u8), mut y: Vec<&u8>, z: &u8) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index d85ea6529f6..2ba5afa808d 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -16,10 +16,13 @@ LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) { error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 | -LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` LL | y.push(z); | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , mut y: Vec<&u8>, z: &u8) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr index 72118275774..47ab613bec2 100644 --- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr +++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr @@ -4,7 +4,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used LL | Box::from_raw(ptr); | ^^^^^^^^^^^^^^^^^^ | - = note: call `drop(from_raw(ptr))` if you intend to drop the `Box` + = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box` note: the lint level is defined here --> $DIR/must-use-box-from-raw.rs:5:9 | diff --git a/src/test/ui/macros/best-failure.rs b/src/test/ui/macros/best-failure.rs new file mode 100644 index 00000000000..bbdd465d5ec --- /dev/null +++ b/src/test/ui/macros/best-failure.rs @@ -0,0 +1,11 @@ +macro_rules! number { + (neg false, $self:ident) => { $self }; + ($signed:tt => $ty:ty;) => { + number!(neg $signed, $self); + //~^ ERROR no rules expected the token `$` + }; +} + +number! { false => u8; } + +fn main() {} diff --git a/src/test/ui/macros/best-failure.stderr b/src/test/ui/macros/best-failure.stderr new file mode 100644 index 00000000000..a52fc5e3da6 --- /dev/null +++ b/src/test/ui/macros/best-failure.stderr @@ -0,0 +1,21 @@ +error: no rules expected the token `$` + --> $DIR/best-failure.rs:4:30 + | +LL | macro_rules! number { + | ------------------- when calling this macro +... +LL | number!(neg $signed, $self); + | ^^^^^ no rules expected this token in macro call +... +LL | number! { false => u8; } + | ------------------------ in this macro invocation + | +note: while trying to match meta-variable `$self:ident` + --> $DIR/best-failure.rs:2:17 + | +LL | (neg false, $self:ident) => { $self }; + | ^^^^^^^^^^^ + = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr index ce3424a8b15..e57347b362d 100644 --- a/src/test/ui/macros/span-covering-argument-1.stderr +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -1,8 +1,6 @@ error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable --> $DIR/span-covering-argument-1.rs:5:14 | -LL | let $s = 0; - | -- help: consider changing this to be mutable: `mut foo` LL | *&mut $s = 0; | ^^^^^^^ cannot borrow as mutable ... @@ -10,6 +8,10 @@ LL | bad!(foo whatever); | ------------------ in this macro invocation | = note: this error originates in the macro `bad` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider changing this to be mutable + | +LL | let mut $s = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index bc0d4488162..5cd217df6fc 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -801,7 +801,7 @@ fn test_ty() { assert_eq!(stringify_ty!(*const T), "*const T"); assert_eq!(stringify_ty!(*mut T), "*mut T"); - // TyKind::Rptr + // TyKind::Ref assert_eq!(stringify_ty!(&T), "&T"); assert_eq!(stringify_ty!(&mut T), "&mut T"); assert_eq!(stringify_ty!(&'a T), "&'a T"); diff --git a/src/test/ui/match/single-line.rs b/src/test/ui/match/single-line.rs new file mode 100644 index 00000000000..0f69d089f9a --- /dev/null +++ b/src/test/ui/match/single-line.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = match Some(42) { Some(x) => x, None => "" }; //~ ERROR E0308 +} diff --git a/src/test/ui/match/single-line.stderr b/src/test/ui/match/single-line.stderr new file mode 100644 index 00000000000..ec3b76e3f4d --- /dev/null +++ b/src/test/ui/match/single-line.stderr @@ -0,0 +1,12 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/single-line.rs:2:52 + | +LL | let _ = match Some(42) { Some(x) => x, None => "" }; + | -------------- - ^^ expected integer, found `&str` + | | | + | | this is found to be of type `{integer}` + | `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/methods/issues/issue-105732.rs b/src/test/ui/methods/issues/issue-105732.rs index 98b7a8d0d04..d7005065813 100644 --- a/src/test/ui/methods/issues/issue-105732.rs +++ b/src/test/ui/methods/issues/issue-105732.rs @@ -6,7 +6,8 @@ auto trait Foo { trait Bar { fn f(&self) { - self.g(); //~ ERROR the method `g` exists for reference `&Self`, but its trait bounds were not satisfied + // issue #105788 + self.g(); //~ ERROR no method named `g` found for reference `&Self` in the current scope } } diff --git a/src/test/ui/methods/issues/issue-105732.stderr b/src/test/ui/methods/issues/issue-105732.stderr index fb2bdf47de7..7696642548d 100644 --- a/src/test/ui/methods/issues/issue-105732.stderr +++ b/src/test/ui/methods/issues/issue-105732.stderr @@ -6,21 +6,11 @@ LL | auto trait Foo { LL | fn g(&self); | ---^-------- help: remove these associated items -error[E0599]: the method `g` exists for reference `&Self`, but its trait bounds were not satisfied - --> $DIR/issue-105732.rs:9:14 +error[E0599]: no method named `g` found for reference `&Self` in the current scope + --> $DIR/issue-105732.rs:10:14 | LL | self.g(); - | ^ - | - = note: the following trait bounds were not satisfied: - `Self: Foo` - which is required by `&Self: Foo` - `&Self: Foo` - = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `g`, perhaps you need to add a supertrait for it: - | -LL | trait Bar: Foo { - | +++++ + | ^ help: there is a method with a similar name: `f` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs index 79cdc41959a..fbecaf9b971 100644 --- a/src/test/ui/methods/issues/issue-90315.rs +++ b/src/test/ui/methods/issues/issue-90315.rs @@ -69,8 +69,7 @@ fn main() { //~^ ERROR `usize` is not an iterator let _res: i32 = ..6.take(2).sum(); - //~^ can't call method `take` on ambiguous numeric type - //~| ERROR mismatched types [E0308] + //~^ ERROR can't call method `take` on ambiguous numeric type //~| HELP you must specify a concrete type for this numeric value // Won't suggest because `RangeTo` dest not implemented `take` } diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr index 8d7b32e025a..4d3c086ff6e 100644 --- a/src/test/ui/methods/issues/issue-90315.stderr +++ b/src/test/ui/methods/issues/issue-90315.stderr @@ -184,18 +184,7 @@ help: you must specify a concrete type for this numeric value, like `i32` LL | let _res: i32 = ..6_i32.take(2).sum(); | ~~~~~ -error[E0308]: mismatched types - --> $DIR/issue-90315.rs:71:21 - | -LL | let _res: i32 = ..6.take(2).sum(); - | --- ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo` - | | - | expected due to this - | - = note: expected type `i32` - found struct `RangeTo<_>` - -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors Some errors have detailed explanations: E0308, E0599, E0689. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mut/mut-suggestion.rs b/src/test/ui/mut/mut-suggestion.rs index 3104b20aca4..8c269d1e727 100644 --- a/src/test/ui/mut/mut-suggestion.rs +++ b/src/test/ui/mut/mut-suggestion.rs @@ -8,7 +8,7 @@ impl S { fn func(arg: S) { //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut arg + //~| SUGGESTION mut arg.mutate(); //~^ ERROR cannot borrow `arg` as mutable, as it is not declared as mutable } @@ -16,7 +16,7 @@ fn func(arg: S) { fn main() { let local = S; //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut local + //~| SUGGESTION mut local.mutate(); //~^ ERROR cannot borrow `local` as mutable, as it is not declared as mutable } diff --git a/src/test/ui/mut/mut-suggestion.stderr b/src/test/ui/mut/mut-suggestion.stderr index cba284550b9..d89c8b41304 100644 --- a/src/test/ui/mut/mut-suggestion.stderr +++ b/src/test/ui/mut/mut-suggestion.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/mut-suggestion.rs:12:5 | -LL | fn func(arg: S) { - | --- help: consider changing this to be mutable: `mut arg` -... LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable --> $DIR/mut-suggestion.rs:20:5 | -LL | let local = S; - | ----- help: consider changing this to be mutable: `mut local` -... LL | local.mutate(); | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut local = S; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/mut/mutable-class-fields-2.stderr b/src/test/ui/mut/mutable-class-fields-2.stderr index 5a4e31947f2..c53c6ea302c 100644 --- a/src/test/ui/mut/mutable-class-fields-2.stderr +++ b/src/test/ui/mut/mutable-class-fields-2.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference --> $DIR/mutable-class-fields-2.rs:9:5 | -LL | pub fn eat(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.how_hungry -= 5; | ^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | pub fn eat(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/mut/mutable-class-fields.stderr b/src/test/ui/mut/mutable-class-fields.stderr index 40a0dc9b29c..1d731be8a85 100644 --- a/src/test/ui/mut/mutable-class-fields.stderr +++ b/src/test/ui/mut/mutable-class-fields.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable --> $DIR/mutable-class-fields.rs:15:3 | -LL | let nyan : Cat = cat(52, 99); - | ---- help: consider changing this to be mutable: `mut nyan` LL | nyan.how_hungry = 0; | ^^^^^^^^^^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut nyan : Cat = cat(52, 99); + | +++ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr index a4ee7781753..c780451dfa9 100644 --- a/src/test/ui/nll/issue-47388.stderr +++ b/src/test/ui/nll/issue-47388.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/issue-47388.rs:8:5 | -LL | let fancy_ref = &(&mut fancy); - | ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)` LL | fancy_ref.num = 6; | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr index 63ca6ae5c28..27b1f8705ff 100644 --- a/src/test/ui/nll/issue-51191.stderr +++ b/src/test/ui/nll/issue-51191.stderr @@ -30,10 +30,13 @@ LL | (&mut self).bar(); error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable --> $DIR/issue-51191.rs:13:9 | -LL | fn imm(self) { - | ---- help: consider changing this to be mutable: `mut self` LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm(mut self) { + | +++ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable --> $DIR/issue-51191.rs:22:9 diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr index dcb6f9fec18..03d8acc8188 100644 --- a/src/test/ui/nll/issue-51244.stderr +++ b/src/test/ui/nll/issue-51244.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference --> $DIR/issue-51244.rs:3:5 | -LL | let ref my_ref @ _ = 0; - | ---------- help: consider changing this to be a mutable reference: `ref mut my_ref` LL | *my_ref = 0; | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut my_ref @ _ = 0; + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr index e85e63e52ec..31f40d8252e 100644 --- a/src/test/ui/nll/issue-57989.stderr +++ b/src/test/ui/nll/issue-57989.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-57989.rs:5:5 | -LL | fn f(x: &i32) { - | ---- help: consider changing this to be a mutable reference: `&mut i32` -LL | let g = &x; LL | *x = 0; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: &mut i32) { + | ~~~~~~~~ error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/issue-57989.rs:5:5 diff --git a/src/test/ui/object-safety/issue-106247.rs b/src/test/ui/object-safety/issue-106247.rs new file mode 100644 index 00000000000..64bf59e5d3a --- /dev/null +++ b/src/test/ui/object-safety/issue-106247.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(where_clauses_object_safety)] + +pub trait Trait { + fn method(&self) where Self: Sync; +} + +fn main() {} diff --git a/src/test/ui/parser/diff-markers/enum-2.rs b/src/test/ui/parser/diff-markers/enum-2.rs new file mode 100644 index 00000000000..76ea980fc62 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.rs @@ -0,0 +1,11 @@ +enum E { + Foo { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +||||||| + z: (), +======= + y: i8, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/enum-2.stderr b/src/test/ui/parser/diff-markers/enum-2.stderr new file mode 100644 index 00000000000..63da5c2a6e1 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.stderr @@ -0,0 +1,21 @@ +error: encountered diff marker + --> $DIR/enum-2.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ||||||| + | ------- +LL | z: (), +LL | ======= + | ------- +LL | y: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/enum.rs b/src/test/ui/parser/diff-markers/enum.rs new file mode 100644 index 00000000000..45df6e3251d --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.rs @@ -0,0 +1,7 @@ +enum E { +<<<<<<< HEAD //~ ERROR encountered diff marker + Foo(u8), +======= + Bar(i8), +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/enum.stderr b/src/test/ui/parser/diff-markers/enum.stderr new file mode 100644 index 00000000000..abbf3fb41e7 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/enum.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | Foo(u8), +LL | ======= + | ------- +LL | Bar(i8), +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/fn-arg.rs b/src/test/ui/parser/diff-markers/fn-arg.rs new file mode 100644 index 00000000000..86c355628ab --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.rs @@ -0,0 +1,16 @@ +trait T { + fn foo( +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch + ) {} +} + +struct S; +impl T for S {} + +fn main() { + S::foo(42); +} diff --git a/src/test/ui/parser/diff-markers/fn-arg.stderr b/src/test/ui/parser/diff-markers/fn-arg.stderr new file mode 100644 index 00000000000..933a206410e --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/fn-arg.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item-with-attr.rs b/src/test/ui/parser/diff-markers/item-with-attr.rs new file mode 100644 index 00000000000..985907c08b2 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.rs @@ -0,0 +1,10 @@ +#[attribute] +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item-with-attr.stderr b/src/test/ui/parser/diff-markers/item-with-attr.stderr new file mode 100644 index 00000000000..850e2368e55 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item-with-attr.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item.rs b/src/test/ui/parser/diff-markers/item.rs new file mode 100644 index 00000000000..4ed36b7b42b --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.rs @@ -0,0 +1,9 @@ +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item.stderr b/src/test/ui/parser/diff-markers/item.stderr new file mode 100644 index 00000000000..9ab3631a60e --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/statement.rs b/src/test/ui/parser/diff-markers/statement.rs new file mode 100644 index 00000000000..e55d16d3bbb --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.rs @@ -0,0 +1,15 @@ +trait T { + fn foo() {} + fn bar() {} +} + +struct S; +impl T for S {} + +fn main() { +<<<<<<< HEAD //~ ERROR encountered diff marker + S::foo(); +======= + S::bar(); +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/statement.stderr b/src/test/ui/parser/diff-markers/statement.stderr new file mode 100644 index 00000000000..7ca2495b829 --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/statement.rs:10:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | S::foo(); +LL | ======= + | ------- +LL | S::bar(); +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct-expr.rs b/src/test/ui/parser/diff-markers/struct-expr.rs new file mode 100644 index 00000000000..99d2fd662c6 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.rs @@ -0,0 +1,12 @@ +struct S { + x: u8, +} +fn main() { + let _ = S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: 42, +======= + x: 0, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/struct-expr.stderr b/src/test/ui/parser/diff-markers/struct-expr.stderr new file mode 100644 index 00000000000..d70476a9833 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct-expr.rs:6:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: 42, +LL | ======= + | ------- +LL | x: 0, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct.rs b/src/test/ui/parser/diff-markers/struct.rs new file mode 100644 index 00000000000..d26464d47bc --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.rs @@ -0,0 +1,7 @@ +struct S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/struct.stderr b/src/test/ui/parser/diff-markers/struct.stderr new file mode 100644 index 00000000000..cc0b3da664e --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/trait-item.rs b/src/test/ui/parser/diff-markers/trait-item.rs new file mode 100644 index 00000000000..3227c8212c9 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.rs @@ -0,0 +1,14 @@ +trait T { +<<<<<<< HEAD //~ ERROR encountered diff marker + fn foo() {} +======= + fn bar() {} +>>>>>>> branch +} + +struct S; +impl T for S {} + +fn main() { + S::foo(); +} diff --git a/src/test/ui/parser/diff-markers/trait-item.stderr b/src/test/ui/parser/diff-markers/trait-item.stderr new file mode 100644 index 00000000000..cdc19f8e076 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/trait-item.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/tuple-struct.rs b/src/test/ui/parser/diff-markers/tuple-struct.rs new file mode 100644 index 00000000000..7eec35c968d --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.rs @@ -0,0 +1,7 @@ +struct S( +<<<<<<< HEAD //~ ERROR encountered diff marker + u8, +======= + i8, +>>>>>>> branch +); diff --git a/src/test/ui/parser/diff-markers/tuple-struct.stderr b/src/test/ui/parser/diff-markers/tuple-struct.stderr new file mode 100644 index 00000000000..d673db89837 --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/tuple-struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | u8, +LL | ======= + | ------- +LL | i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/use-statement.rs b/src/test/ui/parser/diff-markers/use-statement.rs new file mode 100644 index 00000000000..6306243a514 --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.rs @@ -0,0 +1,9 @@ +use foo::{ +<<<<<<< HEAD //~ ERROR encountered diff marker + bar, +======= + baz, +>>>>>>> branch +}; + +fn main() {} diff --git a/src/test/ui/parser/diff-markers/use-statement.stderr b/src/test/ui/parser/diff-markers/use-statement.stderr new file mode 100644 index 00000000000..12e6f57dd50 --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/use-statement.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | bar, +LL | ======= + | ------- +LL | baz, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/intersection-patterns-1.fixed b/src/test/ui/parser/intersection-patterns-1.fixed new file mode 100644 index 00000000000..44773095b87 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-1.fixed @@ -0,0 +1,35 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +// run-rustfix + +#![allow(unused_variables)] + +fn main() { + let s: Option<u8> = None; + + match s { + y @ Some(x) => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION y @ Some(x) + _ => {} + } + + match 2 { + e @ 1..=5 => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION e @ 1..=5 + _ => {} + } +} diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns-1.rs index a6d27aab4f6..1036b9daf64 100644 --- a/src/test/ui/parser/intersection-patterns.rs +++ b/src/test/ui/parser/intersection-patterns-1.rs @@ -6,6 +6,10 @@ // to suggest either switching the order or note that intersection // patterns are not allowed. +// run-rustfix + +#![allow(unused_variables)] + fn main() { let s: Option<u8> = None; @@ -19,15 +23,6 @@ fn main() { _ => {} } - match s { - Some(x) @ Some(y) => {} - //~^ ERROR left-hand side of `@` must be a binding - //~| interpreted as a pattern, not a binding - //~| also a pattern - //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` - _ => {} - } - match 2 { 1 ..= 5 @ e => {} //~^ ERROR pattern on wrong side of `@` diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns-1.stderr index 9dc4c469a60..dc968656c91 100644 --- a/src/test/ui/parser/intersection-patterns.stderr +++ b/src/test/ui/parser/intersection-patterns-1.stderr @@ -1,5 +1,5 @@ error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:13:9 + --> $DIR/intersection-patterns-1.rs:17:9 | LL | Some(x) @ y => {} | -------^^^- @@ -8,19 +8,8 @@ LL | Some(x) @ y => {} | pattern on the left, should be on the right | help: switch the order: `y @ Some(x)` -error: left-hand side of `@` must be a binding - --> $DIR/intersection-patterns.rs:23:9 - | -LL | Some(x) @ Some(y) => {} - | -------^^^------- - | | | - | | also a pattern - | interpreted as a pattern, not a binding - | - = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` - error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:32:9 + --> $DIR/intersection-patterns-1.rs:27:9 | LL | 1 ..= 5 @ e => {} | -------^^^- @@ -29,5 +18,5 @@ LL | 1 ..= 5 @ e => {} | pattern on the left, should be on the right | help: switch the order: `e @ 1..=5` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/intersection-patterns-2.rs b/src/test/ui/parser/intersection-patterns-2.rs new file mode 100644 index 00000000000..408415e87ef --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-2.rs @@ -0,0 +1,20 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +fn main() { + let s: Option<u8> = None; + + match s { + Some(x) @ Some(y) => {} + //~^ ERROR left-hand side of `@` must be a binding + //~| interpreted as a pattern, not a binding + //~| also a pattern + //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` + _ => {} + } +} diff --git a/src/test/ui/parser/intersection-patterns-2.stderr b/src/test/ui/parser/intersection-patterns-2.stderr new file mode 100644 index 00000000000..f7e78814ca5 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-2.stderr @@ -0,0 +1,13 @@ +error: left-hand side of `@` must be a binding + --> $DIR/intersection-patterns-2.rs:13:9 + | +LL | Some(x) @ Some(y) => {} + | -------^^^------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs index fa037e5937d..e9e85339aff 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.rs +++ b/src/test/ui/parser/kw-in-trait-bounds.rs @@ -4,21 +4,13 @@ fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) //~^ ERROR expected identifier, found keyword `fn` //~| ERROR expected identifier, found keyword `fn` //~| ERROR expected identifier, found keyword `fn` -//~| ERROR cannot find trait `r#fn` in this scope -//~| ERROR cannot find trait `r#fn` in this scope -//~| ERROR cannot find trait `r#fn` in this scope -//~| HELP a trait with a similar name exists -//~| HELP a trait with a similar name exists -//~| HELP a trait with a similar name exists -//~| HELP escape `fn` to use it as an identifier -//~| HELP escape `fn` to use it as an identifier -//~| HELP escape `fn` to use it as an identifier +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait where G: fn(), //~^ ERROR expected identifier, found keyword `fn` - //~| ERROR cannot find trait `r#fn` in this scope - //~| HELP a trait with a similar name exists - //~| HELP escape `fn` to use it as an identifier + //~| HELP use `Fn` to refer to the trait {} fn _g<A: struct, B>(_: impl struct, _: &dyn struct) diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr index 79643660e8b..2d3aad4d6ba 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.stderr +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -2,48 +2,48 @@ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:10 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn()) - | ++ +LL | fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn()) + | ~~ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:27 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn()) - | ++ +LL | fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn()) + | ~~ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:41 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn()) - | ++ +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn()) + | ~~ error: expected identifier, found keyword `fn` - --> $DIR/kw-in-trait-bounds.rs:17:4 + --> $DIR/kw-in-trait-bounds.rs:11:4 | LL | G: fn(), - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | G: r#fn(), - | ++ +LL | G: Fn(), + | ~~ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:10 + --> $DIR/kw-in-trait-bounds.rs:16:10 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -54,7 +54,7 @@ LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:29 + --> $DIR/kw-in-trait-bounds.rs:16:29 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -65,7 +65,7 @@ LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:45 + --> $DIR/kw-in-trait-bounds.rs:16:45 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -76,7 +76,7 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:38:8 + --> $DIR/kw-in-trait-bounds.rs:30:8 | LL | B: struct, | ^^^^^^ expected identifier, found keyword @@ -86,44 +86,8 @@ help: escape `struct` to use it as an identifier LL | B: r#struct, | ++ -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:10 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:17:4 - | -LL | G: fn(), - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:27 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:41 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:10 + --> $DIR/kw-in-trait-bounds.rs:16:10 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -132,7 +96,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:38:8 + --> $DIR/kw-in-trait-bounds.rs:30:8 | LL | B: struct, | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -141,7 +105,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:29 + --> $DIR/kw-in-trait-bounds.rs:16:29 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -150,7 +114,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:45 + --> $DIR/kw-in-trait-bounds.rs:16:45 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -158,6 +122,6 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) LL | trait Struct {} | ------------ similarly named trait `Struct` defined here -error: aborting due to 16 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs new file mode 100644 index 00000000000..b6611e6273d --- /dev/null +++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs @@ -0,0 +1,12 @@ +fn foo(_: impl fn() -> i32) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn foo2<T: fn(i32)>(_: T) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn main() { + foo(|| ()); + //~^ mismatched types + foo2(|_: ()| {}); + //~^ type mismatch in closure arguments +} diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr new file mode 100644 index 00000000000..3681a796c53 --- /dev/null +++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr @@ -0,0 +1,48 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:1:16 + | +LL | fn foo(_: impl fn() -> i32) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo(_: impl Fn() -> i32) {} + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2<T: fn(i32)>(_: T) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo2<T: Fn(i32)>(_: T) {} + | ~~ + +error[E0308]: mismatched types + --> $DIR/recover-fn-trait-from-fn-kw.rs:8:12 + | +LL | foo(|| ()); + | ^^ expected `i32`, found `()` + +error[E0631]: type mismatch in closure arguments + --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5 + | +LL | foo2(|_: ()| {}); + | ^^^^ ------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(i32) -> _` + found closure signature `fn(()) -> _` +note: required by a bound in `foo2` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2<T: fn(i32)>(_: T) {} + | ^^^^^^^ required by this bound in `foo2` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr index 70beb5d4232..54118dc3677 100644 --- a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable --> $DIR/nested-binding-modes-mut.rs:4:5 | -LL | let mut is_mut @ not_mut = 42; - | ------- help: consider changing this to be mutable: `mut not_mut` -LL | &mut is_mut; LL | &mut not_mut; | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut is_mut @ mut not_mut = 42; + | +++ error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable --> $DIR/nested-binding-modes-mut.rs:9:5 | -LL | let not_mut @ mut is_mut = 42; - | ------- help: consider changing this to be mutable: `mut not_mut` -LL | &mut is_mut; LL | &mut not_mut; | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut not_mut @ mut is_mut = 42; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index bb7b818368b..1b93267b397 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -104,20 +104,24 @@ LL | *_x0 = U; error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:26:5 | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x0` -... LL | *_x0 = U; | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref mut _x0, _x1, ref _x2, ..) = tup; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:27:5 | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x2` -... LL | *_x2 = U; | ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref _x0, _x1, ref mut _x2, ..) = tup; + | ~~~~~~~~~~~ error[E0382]: use of moved value: `tup.1` --> $DIR/borrowck-move-ref-pattern.rs:28:10 diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.rs b/src/test/ui/repr/transparent-enum-too-many-variants.rs new file mode 100644 index 00000000000..0dd4b4e6846 --- /dev/null +++ b/src/test/ui/repr/transparent-enum-too-many-variants.rs @@ -0,0 +1,10 @@ +use std::mem::size_of; + +#[repr(transparent)] +enum Foo { //~ ERROR E0731 + A(u8), B(u8), +} + +fn main() { + println!("Foo: {}", size_of::<Foo>()); +} diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.stderr b/src/test/ui/repr/transparent-enum-too-many-variants.stderr new file mode 100644 index 00000000000..fb44757efaf --- /dev/null +++ b/src/test/ui/repr/transparent-enum-too-many-variants.stderr @@ -0,0 +1,11 @@ +error[E0731]: transparent enum needs exactly one variant, but has 2 + --> $DIR/transparent-enum-too-many-variants.rs:4:1 + | +LL | enum Foo { + | ^^^^^^^^ needs exactly one variant, but has 2 +LL | A(u8), B(u8), + | - - too many variants in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0731`. diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs index fefb84de729..28b3f76c9d5 100644 --- a/src/test/ui/rfc-2091-track-caller/call-chain.rs +++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs @@ -1,10 +1,14 @@ // run-pass +// revisions: default mir-opt +//[default] compile-flags: -Zinline-mir=no +//[mir-opt] compile-flags: -Zmir-opt-level=4 use std::panic::Location; struct Foo; impl Foo { + #[inline(always)] #[track_caller] fn check_loc(&self, line: u32, col: u32) -> &Self { let loc = Location::caller(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs new file mode 100644 index 00000000000..b5f19e40c03 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); +//~^ ERROR: the trait bound + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr new file mode 100644 index 00000000000..4470e287cc3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ------------------ ^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ^^^^^ + = note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}` +note: required by a bound in `need_const_closure` + --> $DIR/const-closure-trait-method-fail.rs:12:32 + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `need_const_closure` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs new file mode 100644 index 00000000000..3e6d1908848 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl const Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); + +fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed new file mode 100644 index 00000000000..8cdb08e81b9 --- /dev/null +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed @@ -0,0 +1,137 @@ +// edition:2018 +// aux-build:edition-lint-infer-outlives-macro.rs +// run-rustfix + +#![deny(explicit_outlives_requirements)] +#![allow(dead_code)] + +#[macro_use] +extern crate edition_lint_infer_outlives_macro; + +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. +macro_rules! make_foo { + ($a:tt) => { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { + foo: &$a &'b (), + } + } +} + +gimme_a! {make_foo!} + +struct Bar<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +struct BarWhere<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs index d7a832831c1..647906c2dc2 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs @@ -1,18 +1,22 @@ // edition:2018 // aux-build:edition-lint-infer-outlives-macro.rs - -// Test that the lint does not fire if the where predicate -// is from the local crate, but all the bounds are from an -// external macro. +// run-rustfix #![deny(explicit_outlives_requirements)] +#![allow(dead_code)] #[macro_use] extern crate edition_lint_infer_outlives_macro; +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. macro_rules! make_foo { ($a:tt) => { - struct Foo<$a, 'b> where 'b: $a { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { foo: &$a &'b (), } } @@ -25,4 +29,109 @@ struct Bar<'a, 'b: 'a> { bar: &'a &'b (), } +struct BarWhere<'a, 'b> where 'b: 'a { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b: 'a>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b: 'a>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr index 553b1cd976a..734ae687978 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr @@ -1,14 +1,110 @@ error: outlives requirements can be inferred - --> $DIR/edition-lint-infer-outlives-macro.rs:23:18 + --> $DIR/edition-lint-infer-outlives-macro.rs:27:18 | LL | struct Bar<'a, 'b: 'a> { | ^^^^ help: remove this bound | note: the lint level is defined here - --> $DIR/edition-lint-infer-outlives-macro.rs:8:9 + --> $DIR/edition-lint-infer-outlives-macro.rs:5:9 | LL | #![deny(explicit_outlives_requirements)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:32:24 + | +LL | struct BarWhere<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:41:30 + | +LL | struct Foo<'a, 'b: 'a>(&'a &'b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:43:44 + | +LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:45:61 + | +LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:55:30 + | +LL | struct Foo<'a, $b: 'a>(&'a &$b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:57:44 + | +LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:59:61 + | +LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:114:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:126:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:128:50 + | +LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:130:61 + | +LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: aborting due to 12 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index e4ec9f87576..570328fc211 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -1,18 +1,24 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24 | -LL | fn deref_mut_field1(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut x.y; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_field1(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10 | -LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize { - | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>` LL | &mut x.y | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_field1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19 @@ -27,18 +33,24 @@ LL | use_mut(_x); error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5 | -LL | fn assign_field1<'a>(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | x.y = 3; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_field1<'a>(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5 | -LL | fn assign_field2<'a>(x: &'a Own<Point>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>` LL | x.y = 3; | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_field2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5 @@ -53,34 +65,46 @@ LL | use_mut(_p); error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5 | -LL | fn deref_mut_method1(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | x.set(0, 0); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_method1(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 | -LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize { - | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>` LL | x.y_mut() | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_method1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 | -LL | fn assign_method1<'a>(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | *x.y_mut() = 3; | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_method1<'a>(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 | -LL | fn assign_method2<'a>(x: &'a Own<Point>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>` LL | *x.y_mut() = 3; | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_method2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 3ebfba7e4de..3fed7b3f4dc 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -1,34 +1,46 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25 | -LL | fn deref_mut1(x: Own<isize>) { - | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut *x; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut1(mut x: Own<isize>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11 | -LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>` LL | &mut **x | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut1<'a>(x: &'a mut Own<isize>) -> &'a mut isize { + | ~~~~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6 | -LL | fn assign1<'a>(x: Own<isize>) { - | - help: consider changing this to be mutable: `mut x` LL | *x = 3; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign1<'a>(mut x: Own<isize>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6 | -LL | fn assign2<'a>(x: &'a Own<isize>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>` LL | **x = 3; | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign2<'a>(x: &'a mut Own<isize>) { + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 6b43801b5e0..48b42bc7825 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -13,18 +13,24 @@ LL | f((Box::new(|| {}))) error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5 | -LL | fn test2<F>(f: &F) where F: FnMut() { - | -- help: consider changing this to be a mutable reference: `&mut F` LL | (*f)(); | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test2<F>(f: &mut F) where F: FnMut() { + | ~~~~~~ error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 | -LL | fn test4(f: &Test) { - | ----- help: consider changing this to be a mutable reference: `&mut Test<'_>` LL | f.f.call_mut(()) | ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test4(f: &mut Test<'_>) { + | ~~~~~~~~~~~~~ error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index 1864f5de108..2a842f5a2a9 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5 | -LL | fn b(x: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo` -LL | x.f(); LL | x.h(); | ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn b(x: &mut Foo) { + | ~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 1f5d8bd32bb..1df19deb12f 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-fn-in-const-b.rs:7:9 | -LL | fn broken(x: &Vec<String>) { - | ------------ help: consider changing this to be a mutable reference: `&mut Vec<String>` LL | x.push(format!("this is broken")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn broken(x: &mut Vec<String>) { + | ~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index cc43f6d0928..b6517e0b309 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-object-mutability.rs:8:5 | -LL | fn borrowed_receiver(x: &dyn Foo) { - | -------- help: consider changing this to be a mutable reference: `&mut dyn Foo` -LL | x.borrowed(); LL | x.borrowed_mut(); | ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrowed_receiver(x: &mut dyn Foo) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable --> $DIR/borrowck-object-mutability.rs:18:5 | -LL | fn owned_receiver(x: Box<dyn Foo>) { - | - help: consider changing this to be mutable: `mut x` -LL | x.borrowed(); LL | x.borrowed_mut(); | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn owned_receiver(mut x: Box<dyn Foo>) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 8a7c504f005..96ce4d5bc6c 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -1,26 +1,35 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:3:9 | -LL | fn foo(mut a: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("bar"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:8:5 | -LL | pub fn foo<'a>(mut a: &'a String) { - | ---------- help: consider changing this to be a mutable reference: `&'a mut String` LL | a.push_str("foo"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo<'a>(mut a: &'a mut String) { + | ~~~~~~~~~~~~~~ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:15:9 | -LL | pub fn foo(mut a: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("foo"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 15900bef7f6..7d9ff2dfb4d 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -41,8 +41,8 @@ ast-stats-1 - Wild 88 ( 1.2%) 1 ast-stats-1 - Ident 440 ( 5.9%) 5 ast-stats-1 PathSegment 720 ( 9.7%) 30 24 ast-stats-1 Ty 896 (12.1%) 14 64 -ast-stats-1 - Rptr 64 ( 0.9%) 1 ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.7%) 2 ast-stats-1 - Path 640 ( 8.6%) 10 ast-stats-1 Item 1_656 (22.3%) 9 184 @@ -100,8 +100,8 @@ ast-stats-2 - Lit 144 ( 1.8%) 2 ast-stats-2 - Block 216 ( 2.7%) 3 ast-stats-2 PathSegment 792 ( 9.8%) 33 24 ast-stats-2 Ty 896 (11.0%) 14 64 -ast-stats-2 - Rptr 64 ( 0.8%) 1 ast-stats-2 - Ptr 64 ( 0.8%) 1 +ast-stats-2 - Ref 64 ( 0.8%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2 ast-stats-2 - Path 640 ( 7.9%) 10 ast-stats-2 Item 2_024 (25.0%) 11 184 @@ -154,7 +154,7 @@ hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 -hir-stats - Rptr 48 ( 0.5%) 1 +hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - Path 64 ( 0.7%) 1 diff --git a/src/test/ui/suggestions/bad-hex-float-lit.rs b/src/test/ui/suggestions/bad-hex-float-lit.rs new file mode 100644 index 00000000000..cd6fdbde96c --- /dev/null +++ b/src/test/ui/suggestions/bad-hex-float-lit.rs @@ -0,0 +1,13 @@ +fn main() { + let _f: f32 = 0xAAf32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f32 = 0xAB_f32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f64 = 0xFF_f64; + //~^ ERROR mismatched types + //~| HELP rewrite this +} diff --git a/src/test/ui/suggestions/bad-hex-float-lit.stderr b/src/test/ui/suggestions/bad-hex-float-lit.stderr new file mode 100644 index 00000000000..bc09abb1a56 --- /dev/null +++ b/src/test/ui/suggestions/bad-hex-float-lit.stderr @@ -0,0 +1,48 @@ +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:2:19 + | +LL | let _f: f32 = 0xAAf32; + | --- ^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAA as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 170_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:6:19 + | +LL | let _f: f32 = 0xAB_f32; + | --- ^^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAB as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 171_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:10:19 + | +LL | let _f: f64 = 0xFF_f64; + | --- ^^^^^^^^ expected `f64`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f64 = 0xFF as f64; + | ~~~~~~~~~~~ +LL | let _f: f64 = 255_f64; + | ~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-104287.rs b/src/test/ui/suggestions/issue-104287.rs index b7601a548b9..e3fa22a8f66 100644 --- a/src/test/ui/suggestions/issue-104287.rs +++ b/src/test/ui/suggestions/issue-104287.rs @@ -1,9 +1,13 @@ // The purpose of this test is not to validate the output of the compiler. // Instead, it ensures the suggestion is generated without performing an arithmetic overflow. +struct S; +impl S { + fn foo(&self) {} +} fn main() { - let x = not_found; //~ ERROR cannot find value `not_found` in this scope - simd_gt::<()>(x); + let x = S; + foo::<()>(x); //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied - //~| ERROR cannot find function `simd_gt` in this scope + //~| ERROR cannot find function `foo` in this scope } diff --git a/src/test/ui/suggestions/issue-104287.stderr b/src/test/ui/suggestions/issue-104287.stderr index 79812a2985e..602a01828b2 100644 --- a/src/test/ui/suggestions/issue-104287.stderr +++ b/src/test/ui/suggestions/issue-104287.stderr @@ -1,30 +1,30 @@ -error[E0425]: cannot find value `not_found` in this scope - --> $DIR/issue-104287.rs:5:13 - | -LL | let x = not_found; - | ^^^^^^^^^ not found in this scope - error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/issue-104287.rs:6:5 + --> $DIR/issue-104287.rs:10:5 | -LL | simd_gt::<()>(x); - | ^^^^^^^------ help: remove these generics +LL | foo::<()>(x); + | ^^^------ help: remove these generics | | | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-104287.rs:6:8 + | +LL | fn foo(&self) {} + | ^^^ -error[E0425]: cannot find function `simd_gt` in this scope - --> $DIR/issue-104287.rs:6:5 +error[E0425]: cannot find function `foo` in this scope + --> $DIR/issue-104287.rs:10:5 | -LL | simd_gt::<()>(x); - | ^^^^^^^ not found in this scope +LL | foo::<()>(x); + | ^^^ not found in this scope | -help: use the `.` operator to call the method `SimdPartialOrd::simd_gt` on `[type error]` +help: use the `.` operator to call the method `foo` on `&S` | -LL - simd_gt::<()>(x); -LL + x.simd_gt(); +LL - foo::<()>(x); +LL + x.foo(); | -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0107, E0425. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/issue-68049-2.stderr b/src/test/ui/suggestions/issue-68049-2.stderr index 2f31193e4a4..de35aa5b186 100644 --- a/src/test/ui/suggestions/issue-68049-2.stderr +++ b/src/test/ui/suggestions/issue-68049-2.stderr @@ -1,20 +1,24 @@ error[E0594]: cannot assign to `*input`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:9:7 | -LL | fn example(&self, input: &i32); // should suggest here - | ---- help: consider changing that to be a mutable reference: `&mut i32` -... LL | *input = self.0; | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&self, input: &mut i32); // should suggest here + | ~~~~~~~~ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:17:5 | -LL | fn example(&self, input: &i32); // should suggest here - | ----- help: consider changing that to be a mutable reference: `&mut self` -... LL | self.0 += *input; | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&mut self, input: &i32); // should suggest here + | ~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-99240-2.stderr b/src/test/ui/suggestions/issue-99240-2.stderr index 260df85653b..a2b55978478 100644 --- a/src/test/ui/suggestions/issue-99240-2.stderr +++ b/src/test/ui/suggestions/issue-99240-2.stderr @@ -4,10 +4,7 @@ error[E0618]: expected function, found enum variant `Alias::Unit` LL | Unit, | ---- enum variant `Alias::Unit` defined here ... -LL | Alias:: - | ______^ - | | _____| - | || +LL | // Alias:: LL | || Unit(); | ||________^_- call expression requires function | |________| diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.rs b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs new file mode 100644 index 00000000000..ac662edafe6 --- /dev/null +++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs @@ -0,0 +1,30 @@ +fn as_ref() -> Option<Vec<u8>> { + None +} +struct Type { + option: Option<Vec<u8>> +} +trait Trait { + fn foo(&self) -> Vec<u8>; +} +impl Trait for Option<Vec<u8>> { + fn foo(&self) -> Vec<u8> { + vec![1, 2, 3] + } +} + +impl Type { + fn method(&self) -> Option<Vec<u8>> { + self.option..as_ref().map(|x| x) + //~^ ERROR E0308 + } + fn method2(&self) -> &u8 { + self.option..foo().get(0) + //~^ ERROR E0425 + //~| ERROR E0308 + } +} + +fn main() { + let _ = Type { option: None }.method(); +} diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr new file mode 100644 index 00000000000..c84f9467891 --- /dev/null +++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr @@ -0,0 +1,48 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/method-access-to-range-literal-typo.rs:22:22 + | +LL | self.option..foo().get(0) + | ^^^ not found in this scope + | +help: you might have meant to write `.` instead of `..` + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:18:9 + | +LL | fn method(&self) -> Option<Vec<u8>> { + | --------------- expected `Option<Vec<u8>>` because of return type +LL | self.option..as_ref().map(|x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range` + | + = note: expected enum `Option<_>` + found struct `std::ops::Range<Option<_>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..as_ref().map(|x| x) +LL + self.option.as_ref().map(|x| x) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:22:9 + | +LL | fn method2(&self) -> &u8 { + | --- expected `&u8` because of return type +LL | self.option..foo().get(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&u8`, found struct `Range` + | + = note: expected reference `&u8` + found struct `std::ops::Range<Option<Vec<u8>>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr index 9fd2658ec70..7973759bf5e 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.stderr +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -1,37 +1,46 @@ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:7:9 | -LL | fn zap(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` -... LL | self.0 = 32; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn zap(&mut self) { + | ~~~~~~~~~ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:16:5 | -LL | let ref foo = 16; - | ------- help: consider changing this to be a mutable reference: `ref mut foo` -... LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut foo = 16; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:21:9 | -LL | if let Some(ref bar) = Some(16) { - | ------- help: consider changing this to be a mutable reference: `ref mut bar` -... LL | *bar = 32; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | if let Some(ref mut bar) = Some(16) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*quo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:25:22 | LL | ref quo => { *quo = 32; }, - | ------- ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written - | | - | help: consider changing this to be a mutable reference: `ref mut quo` + | ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | ref mut quo => { *quo = 32; }, + | ~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr index ede3ebfa739..24bedb5297b 100644 --- a/src/test/ui/suggestions/unnamable-types.stderr +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const C: _ = || 42; | ^ not allowed in type signatures | -note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named +note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named --> $DIR/unnamable-types.rs:17:14 | LL | const C: _ = || 42; @@ -31,7 +31,7 @@ error: missing type for `const` item LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; | ^ | -note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named +note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named --> $DIR/unnamable-types.rs:23:11 | LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 7fb90581f8a..4b6915f7715 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -32,12 +32,7 @@ Thir { kind: Scope { region_scope: Node(2), lint_level: Explicit( - HirId { - owner: OwnerId { - def_id: DefId(0:3 ~ thir_tree[8f1d]::main), - }, - local_id: 2, - }, + HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2), ), value: e0, }, diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 41fc3600fcd..30cc76b2e1a 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -50,7 +50,7 @@ LL | is_send((8, TestType)); | required by a bound introduced by this call | = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` - = note: required because it appears within the type `({integer}, dummy1c::TestType)` + = note: required because it appears within the type `({integer}, TestType)` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | @@ -67,7 +67,7 @@ LL | is_send(Box::new(TestType)); | = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied = note: required for `Unique<dummy2::TestType>` to implement `Send` - = note: required because it appears within the type `Box<dummy2::TestType>` + = note: required because it appears within the type `Box<TestType>` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | @@ -87,13 +87,13 @@ LL | is_send(Box::new(Outer2(TestType))); | required by a bound introduced by this call | = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType` -note: required because it appears within the type `Outer2<dummy3::TestType>` +note: required because it appears within the type `Outer2<TestType>` --> $DIR/negated-auto-traits-error.rs:12:8 | LL | struct Outer2<T>(T); | ^^^^^^ = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send` - = note: required because it appears within the type `Box<Outer2<dummy3::TestType>>` + = note: required because it appears within the type `Box<Outer2<TestType>>` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr index aac119afda5..39b60c31197 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr @@ -1,18 +1,24 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6:5 | -LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | *t | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10:6 | -LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | {*t} | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn copy_reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs b/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs new file mode 100644 index 00000000000..1cd192b783c --- /dev/null +++ b/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs @@ -0,0 +1,8 @@ +struct Foo { + val: MissingType, + //~^ ERROR cannot find type `MissingType` in this scope +} + +fn main() { + Foo { val: Default::default() }; +} diff --git a/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr b/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr new file mode 100644 index 00000000000..76a2a5f99f2 --- /dev/null +++ b/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/nonexistent-field-not-ambiguous.rs:2:10 + | +LL | val: MissingType, + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.rs b/src/test/ui/typeck/quiet-type-err-let-binding.rs new file mode 100644 index 00000000000..a6eab536a6b --- /dev/null +++ b/src/test/ui/typeck/quiet-type-err-let-binding.rs @@ -0,0 +1,17 @@ +// fn foo() -> String { +// String::new() +// } + +fn test(s: &str) { + println!("{}", s); +} + +fn test2(s: String) { + println!("{}", s); +} + +fn main() { + let x = foo(); //~ERROR cannot find function `foo` in this scope + test(&x); + test2(x); // Does not complain about `x` being a `&str`. +} diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.stderr b/src/test/ui/typeck/quiet-type-err-let-binding.stderr new file mode 100644 index 00000000000..ad7f85e01ec --- /dev/null +++ b/src/test/ui/typeck/quiet-type-err-let-binding.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/quiet-type-err-let-binding.rs:14:13 + | +LL | let x = foo(); + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 22fedb22d66..b96c5271339 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -220,3 +220,11 @@ fn value() -> Option<&'static _> { const _: Option<_> = map(value); //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + +fn evens_squared(n: usize) -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + (1..n).filter(|x| x % 2 == 0).map(|x| x * x) +} + +const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index c57f71b8057..bc02547c65e 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -428,6 +428,27 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option<u8>` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:224:31 + | +LL | fn evens_squared(n: usize) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Iterator<Item = usize>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:229:10 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^ not allowed in type signatures + | +note: however, the inferred type `Map<Filter<Range<i32>, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:229:14 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:140:31 | @@ -636,7 +657,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 69 previous errors +error: aborting due to 71 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index a0ed56d4bcf..5c93ed6d7f7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -12,13 +12,16 @@ LL | tick1(); error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:19:5 | -LL | let tick2 = || { - | ----- help: consider changing this to be mutable: `mut tick2` LL | tick1(); | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` ... LL | tick2(); | ^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick2 = || { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index 27d23e3fa04..3f539c42d9b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 | LL | let tick = || counter += 1; - | ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter` - | | - | help: consider changing this to be mutable: `mut tick` + | ------- calling `tick` requires mutable binding due to mutable borrow of `counter` LL | tick(); | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = || counter += 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index c00f986c397..e3b19297b9c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 | LL | let tick = move || counter += 1; - | ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter` - | | - | help: consider changing this to be mutable: `mut tick` + | ------- calling `tick` requires mutable binding due to possible mutation of `counter` LL | tick(); | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = move || counter += 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/unsized-locals/suggest-borrow.rs b/src/test/ui/unsized-locals/suggest-borrow.rs new file mode 100644 index 00000000000..08694857993 --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let x: [u8] = vec!(1, 2, 3)[..]; //~ ERROR E0277 + let x: &[u8] = vec!(1, 2, 3)[..]; //~ ERROR E0308 + let x: [u8] = &vec!(1, 2, 3)[..]; //~ ERROR E0308 + //~^ ERROR E0277 + let x: &[u8] = &vec!(1, 2, 3)[..]; +} diff --git a/src/test/ui/unsized-locals/suggest-borrow.stderr b/src/test/ui/unsized-locals/suggest-borrow.stderr new file mode 100644 index 00000000000..08745eab28d --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.stderr @@ -0,0 +1,60 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:2:9 + | +LL | let x: [u8] = vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | + + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:3:20 + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | expected `&[u8]`, found slice `[{integer}]` + | | help: consider borrowing here: `&vec!(1, 2, 3)[..]` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:4:19 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let x: [u8] = &vec!(1, 2, 3)[..]; +LL + let x: [u8] = vec!(1, 2, 3)[..]; + | +help: alternatively, consider changing the type annotation + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:4:9 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr index da77026673d..ace5a87187b 100644 --- a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr +++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr @@ -27,6 +27,10 @@ LL | let _foo: [u8] = *foo; = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let _foo: &[u8] = *foo; + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr index 011f2b426c7..18ac1ea1875 100644 --- a/src/test/ui/unsized/unsized6.stderr +++ b/src/test/ui/unsized/unsized6.stderr @@ -14,6 +14,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) { LL + fn f1<W: ?Sized, X: ?Sized, Y, Z: ?Sized>(x: &X) { | +help: consider borrowing here + | +LL | let y: &Y; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 @@ -62,6 +66,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f2<X: ?Sized, Y: ?Sized>(x: &X) { LL + fn f2<X, Y: ?Sized>(x: &X) { | +help: consider borrowing here + | +LL | let y: &X; + | + error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 @@ -94,6 +102,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 @@ -144,6 +156,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 diff --git a/src/test/ui/writing-to-immutable-vec.stderr b/src/test/ui/writing-to-immutable-vec.stderr index a65765c86c8..286267c3834 100644 --- a/src/test/ui/writing-to-immutable-vec.stderr +++ b/src/test/ui/writing-to-immutable-vec.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/writing-to-immutable-vec.rs:3:5 | -LL | let v: Vec<isize> = vec![1, 2, 3]; - | - help: consider changing this to be mutable: `mut v` LL | v[1] = 4; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<isize> = vec![1, 2, 3]; + | +++ error: aborting due to previous error diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 903ee938d9d..02f3188f8be 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -4203,6 +4203,7 @@ Released 2018-09-13 [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const [`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs [`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons +[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_null_check [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any @@ -4460,6 +4461,7 @@ Released 2018-09-13 [`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch +[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence @@ -4545,6 +4547,7 @@ Released 2018-09-13 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count +[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive @@ -4590,6 +4593,7 @@ Released 2018-09-13 [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool [`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float +[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn [`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index e862f13e69f..c8e54d7b8e0 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv diag.span_suggestion( expr.span, - &format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), + format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), sugg, rustc_errors::Applicability::HasPlaceholders, ); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3cd7d1d7e72..2982460c9cf 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -161,6 +161,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::float_literal::LOSSY_FLOAT_LITERAL_INFO, crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO, crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO, + crate::fn_null_check::FN_NULL_CHECK_INFO, crate::format::USELESS_FORMAT_INFO, crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO, crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, @@ -494,6 +495,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO, crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO, crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO, + crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO, crate::precedence::PRECEDENCE_INFO, crate::ptr::CMP_NULL_INFO, crate::ptr::INVALID_NULL_PTR_USAGE_INFO, @@ -535,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, + crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO, crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO, @@ -568,6 +571,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO, crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO, crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO, + crate::transmute::TRANSMUTE_NULL_TO_FN_INFO, crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO, crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO, crate::transmute::TRANSMUTE_PTR_TO_REF_INFO, diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 7b43d8ccc67..f327c9a71b3 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -969,14 +969,14 @@ fn binding_ty_auto_deref_stability<'tcx>( precedence: i8, binder_args: &'tcx List<BoundVariableKind>, ) -> Position { - let TyKind::Rptr(_, ty) = &ty.kind else { + let TyKind::Ref(_, ty) = &ty.kind else { return Position::Other(precedence); }; let mut ty = ty; loop { break match ty.ty.kind { - TyKind::Rptr(_, ref ref_ty) => { + TyKind::Ref(_, ref ref_ty) => { ty = ref_ty; continue; }, @@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>( possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); } let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1; - // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is - // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of - // itself. See the comment in that method for an explanation as to why. - possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location) + // If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The + // reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible + // borrower of itself. See the comment in that method for an explanation as to why. + possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location) && used_exactly_once(mir, place.local).unwrap_or(false) } else { false diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 0ed30196475..f95b628e6c3 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -324,7 +324,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: let maybe_neg_sugg = |expr, hir_id| { let sugg = Sugg::hir(cx, expr, ".."); if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { - format!("-{sugg}") + format!("-{}", sugg.maybe_par()) } else { sugg.to_string() } diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs new file mode 100644 index 00000000000..91c8c340ce2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs @@ -0,0 +1,106 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for comparing a function pointer to null. + /// + /// ### Why is this bad? + /// Function pointers are assumed to not be null. + /// + /// ### Example + /// ```rust,ignore + /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ + /// + /// if (fn_ptr as *const ()).is_null() { ... } + /// ``` + /// Use instead: + /// ```rust,ignore + /// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */ + /// + /// if fn_ptr.is_none() { ... } + /// ``` + #[clippy::version = "1.67.0"] + pub FN_NULL_CHECK, + correctness, + "`fn()` type assumed to be nullable" +} +declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]); + +fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { + span_lint_and_help( + cx, + FN_NULL_CHECK, + expr.span, + "function pointer assumed to be nullable, even though it isn't", + None, + "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value", + ); +} + +fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind + && let TyKind::Ptr(_) = cast_ty.kind + { + cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn() + } else { + false + } +} + +impl<'tcx> LateLintPass<'tcx> for FnNullCheck { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + match expr.kind { + // Catching: + // (fn_ptr as *<const/mut> <ty>).is_null() + ExprKind::MethodCall(method_name, receiver, _, _) + if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) => + { + lint_expr(cx, expr); + }, + + ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { + let to_check: &Expr<'_>; + if is_fn_ptr_cast(cx, left) { + to_check = right; + } else if is_fn_ptr_cast(cx, right) { + to_check = left; + } else { + return; + } + + match to_check.kind { + // Catching: + // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>) + ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => { + lint_expr(cx, expr); + }, + + // Catching: + // (fn_ptr as *<const/mut> <ty>) == std::ptr::null() + ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => { + lint_expr(cx, expr); + }, + + // Catching: + // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr> + _ if matches!( + constant(cx, cx.typeck_results(), to_check), + Some((Constant::RawPtr(0), _)) + ) => + { + lint_expr(cx, expr); + }, + + _ => {}, + } + }, + _ => {}, + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 69f7c152fc4..043112bbc95 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -382,7 +382,7 @@ fn check_format_in_format_args( call_site, &format!("`format!` in `{name}!` args"), |diag| { - diag.help(&format!( + diag.help(format!( "combine the `format!(..)` arguments with the outer `{name}!(..)` call" )); diag.help("or consider changing `format!` to `format_args!`"); diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs index 91e6ffe6447..9dbce3f889b 100644 --- a/src/tools/clippy/clippy_lints/src/functions/mod.rs +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -63,23 +63,40 @@ declare_clippy_lint! { /// arguments but are not marked `unsafe`. /// /// ### Why is this bad? - /// The function should probably be marked `unsafe`, since - /// for an arbitrary raw pointer, there is no way of telling for sure if it is - /// valid. + /// The function should almost definitely be marked `unsafe`, since for an + /// arbitrary raw pointer, there is no way of telling for sure if it is valid. + /// + /// In general, this lint should **never be disabled** unless it is definitely a + /// false positive (please submit an issue if so) since it breaks Rust's + /// soundness guarantees, directly exposing API users to potentially dangerous + /// program behavior. This is also true for internal APIs, as it is easy to leak + /// unsoundness. + /// + /// ### Context + /// In Rust, an `unsafe {...}` block is used to indicate that the code in that + /// section has been verified in some way that the compiler can not. For a + /// function that accepts a raw pointer then accesses the pointer's data, this is + /// generally impossible as the incoming pointer could point anywhere, valid or + /// not. So, the signature should be marked `unsafe fn`: this indicates that the + /// function's caller must provide some verification that the arguments it sends + /// are valid (and then call the function within an `unsafe` block). /// /// ### Known problems /// * It does not check functions recursively so if the pointer is passed to a /// private non-`unsafe` function which does the dereferencing, the lint won't - /// trigger. + /// trigger (false negative). /// * It only checks for arguments whose type are raw pointers, not raw pointers /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or - /// `some_argument.get_raw_ptr()`). + /// `some_argument.get_raw_ptr()`) (false negative). /// /// ### Example /// ```rust,ignore /// pub fn foo(x: *const u8) { /// println!("{}", unsafe { *x }); /// } + /// + /// // this call "looks" safe but will segfault or worse! + /// // foo(invalid_ptr); /// ``` /// /// Use instead: @@ -87,6 +104,12 @@ declare_clippy_lint! { /// pub unsafe fn foo(x: *const u8) { /// println!("{}", unsafe { *x }); /// } + /// + /// // this would cause a compiler error for calling without `unsafe` + /// // foo(invalid_ptr); + /// + /// // sound call if the caller knows the pointer is valid + /// unsafe { foo(valid_ptr); } /// ``` #[clippy::version = "pre 1.29.0"] pub NOT_UNSAFE_PTR_ARG_DEREF, diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 76c83ab47d0..db637dfc068 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -34,12 +34,12 @@ declare_clippy_lint! { } pub struct LargeConstArrays { - maximum_allowed_size: u64, + maximum_allowed_size: u128, } impl LargeConstArrays { #[must_use] - pub fn new(maximum_allowed_size: u64) -> Self { + pub fn new(maximum_allowed_size: u128) -> Self { Self { maximum_allowed_size } } } @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind(); if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx); if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()); - if self.maximum_allowed_size < element_count * element_size; + if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size); then { let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index b18456ee523..b8d4abdbb78 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { ); diag.span_label( def.variants[variants_size[1].ind].span, - &if variants_size[1].fields_size.is_empty() { + if variants_size[1].fields_size.is_empty() { "the second-largest variant carries no data at all".to_owned() } else { format!( diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 5857d81ab1f..89ae83d48f5 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -24,12 +24,12 @@ declare_clippy_lint! { } pub struct LargeStackArrays { - maximum_allowed_size: u64, + maximum_allowed_size: u128, } impl LargeStackArrays { #[must_use] - pub fn new(maximum_allowed_size: u64) -> Self { + pub fn new(maximum_allowed_size: u128) -> Self { Self { maximum_allowed_size } } } @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && !cx.tcx.hir().parent_iter(expr.hir_id) .any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. }))) - && self.maximum_allowed_size < element_count * element_size { + && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) { span_lint_and_help( cx, LARGE_STACK_ARRAYS, diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index e88d1764a24..9eba4675629 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -361,7 +361,7 @@ fn check_for_is_empty<'tcx>( db.span_note(span, "`is_empty` defined here"); } if let Some(self_kind) = self_kind { - db.note(&output.expected_sig(self_kind)); + db.note(output.expected_sig(self_kind)); } }); } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 39850d59803..dcd8ca81ae8 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -125,6 +125,7 @@ mod explicit_write; mod fallible_impl_from; mod float_literal; mod floating_point_arithmetic; +mod fn_null_check; mod format; mod format_args; mod format_impl; @@ -234,6 +235,7 @@ mod partialeq_ne_impl; mod partialeq_to_none; mod pass_by_ref_or_value; mod pattern_type_mismatch; +mod permissions_set_readonly_false; mod precedence; mod ptr; mod ptr_offset_with_cast; @@ -263,6 +265,7 @@ mod shadow; mod single_char_lifetime_names; mod single_component_path_imports; mod size_of_in_element_count; +mod size_of_ref; mod slow_vector_initialization; mod std_instead_of_core; mod strings; @@ -334,7 +337,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf { Ok(Some(path)) => path, Ok(None) => return Conf::default(), Err(error) => { - sess.struct_err(&format!("error finding Clippy's configuration file: {error}")) + sess.struct_err(format!("error finding Clippy's configuration file: {error}")) .emit(); return Conf::default(); }, @@ -902,6 +905,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock)); + store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); + store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse)); + store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs index 14f22348132..1953ee8a717 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs @@ -77,7 +77,7 @@ pub(super) fn check<'tcx>( applicability, ); - diag.note(&format!( + diag.note(format!( "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" )); }, diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 075ecbe7ede..63212beaa63 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { let help = format!("make the function `async` and {ret_sugg}"); diag.span_suggestion( header_span, - &help, + help, format!("async {}{ret_snip}", &header_snip[..ret_pos]), Applicability::MachineApplicable ); @@ -152,7 +152,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) let input_lifetimes: Vec<LifetimeName> = inputs .iter() .filter_map(|ty| { - if let TyKind::Rptr(lt, _) = ty.kind { + if let TyKind::Ref(lt, _) = ty.kind { Some(lt.res) } else { None diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs index bb6d628af3b..f239736d38a 100644 --- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs @@ -35,6 +35,9 @@ declare_clippy_lint! { /// Some may consider panicking in these situations to be desirable, but it also may /// introduce panicking where there wasn't any before. /// + /// See also [the discussion in the + /// PR](https://github.com/rust-lang/rust-clippy/pull/9484#issuecomment-1278922613). + /// /// ### Examples /// ```rust /// # let (input, min, max) = (0, -2, 1); @@ -78,7 +81,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.66.0"] pub MANUAL_CLAMP, - complexity, + nursery, "using a clamp pattern instead of the clamp function" } impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]); diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index de166b9765f..c795c1d9a16 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { let test_span = expr.span.until(then.span); span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| { - diag.span_note(test_span, &format!("the {kind_word} was tested here")); + diag.span_note(test_span, format!("the {kind_word} was tested here")); multispan_sugg( diag, &format!("try using the `strip_{kind_word}` method"), diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs index d521a529e0d..f6bf0e7aa1a 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id}; -use rustc_hir::LangItem::OptionSome; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind}; use rustc_lint::LateContext; use rustc_span::{sym, SyntaxContext}; @@ -25,15 +25,13 @@ fn get_cond_expr<'tcx>( if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr); if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind; if let PatKind::Binding(_,target, ..) = pat.kind; - if let (then_visitor, else_visitor) - = (is_some_expr(cx, target, ctxt, then_expr), - is_some_expr(cx, target, ctxt, else_expr)); - if then_visitor != else_visitor; // check that one expr resolves to `Some(x)`, the other to `None` + if is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr) + || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr); // check that one expr resolves to `Some(x)`, the other to `None` then { return Some(SomeExpr { expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()), needs_unsafe_block: contains_unsafe_block(cx, expr), - needs_negated: !then_visitor // if the `then_expr` resolves to `None`, need to negate the cond + needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond }) } }; @@ -74,6 +72,13 @@ fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: false } +fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) { + return is_res_lang_ctor(cx, path_res(cx, inner_expr), OptionNone); + }; + false +} + // given the closure: `|<pattern>| <expr>` // returns `|&<pattern>| <expr>` fn add_ampersand_if_copy(body_str: String, has_copy_trait: bool) -> String { diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index 1bf8d4e96ad..c94a1f76330 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -31,19 +31,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e }; // Do we need to add ';' to suggestion ? - match match_body.kind { - ExprKind::Block(block, _) => { - // macro + expr_ty(body) == () - if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() { - snippet_body.push(';'); - } - }, - _ => { - // expr_ty(body) == () - if cx.typeck_results().expr_ty(match_body).is_unit() { - snippet_body.push(';'); - } - }, + if let ExprKind::Block(block, _) = match_body.kind { + // macro + expr_ty(body) == () + if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() { + snippet_body.push(';'); + } } let mut applicability = Applicability::MaybeIncorrect; diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs index 7f8d124838c..59de8c0384b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs @@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { let mut has_non_wild = false; for arm in arms { match peel_hir_pat_refs(arm.pat).0.kind { - PatKind::Wild => wildcard_span = Some(arm.pat.span), + PatKind::Wild if arm.guard.is_none() => wildcard_span = Some(arm.pat.span), PatKind::Binding(_, _, ident, None) => { wildcard_span = Some(arm.pat.span); wildcard_ident = Some(ident); diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index d8c821bc9ee..424482859ee 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -36,7 +36,7 @@ pub fn check( expr.span, &format!("calling `to_string` on `{arg_ty}`"), |diag| { - diag.help(&format!( + diag.help(format!( "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`" )); let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs index beb772100af..279175e20c3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs @@ -29,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr application = Applicability::Unspecified; diag.span_help( pat.span, - &format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), + format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 561e4336593..77be61b4793 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3986,7 +3986,7 @@ impl OutType { (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true, (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true, (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true, - (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), + (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 910ee14855e..4c6328481e4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); } - diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability); + diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); }); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 3c01ce1fecd..d00708e828e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -167,7 +167,7 @@ fn check_manual_split_once_indirect( }; diag.span_suggestion_verbose( local.span, - &format!("try `{r}split_once`"), + format!("try `{r}split_once`"), format!("let ({lhs}, {rhs}) = {self_snip}.{r}split_once({pat_snip}){unwrap};"), app, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 0e73459ad65..47e2e744112 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { diag.span_suggestion( span, - &format!("use `{simplify_using}(..)` instead"), + format!("use `{simplify_using}(..)` instead"), format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index bc90e131b7f..64d8333a093 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { return; } - if let hir::TyKind::Rptr( + if let hir::TyKind::Ref( _, hir::MutTy { ty: pty, @@ -94,7 +94,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { }, ) = ty.kind { - if let hir::TyKind::Rptr( + if let hir::TyKind::Ref( _, hir::MutTy { mutbl: hir::Mutability::Mut, diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index f2ffac85bf4..5457eeec4ea 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -124,7 +124,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl); } }, - TyKind::Rptr(lifetime, mut_ty) => { + TyKind::Ref(lifetime, mut_ty) => { if_chain! { if let TyKind::Path(None, path) = &mut_ty.ty.kind; if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind; diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 67debe7e08a..5a9387b34cc 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -284,7 +284,7 @@ fn check<'tcx>( diag.span_suggestion( assign.lhs_span, - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), let_snippet, Applicability::MachineApplicable, ); @@ -304,7 +304,7 @@ fn check<'tcx>( diag.span_suggestion_verbose( usage.stmt.span.shrink_to_lo(), - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), format!("{let_snippet} = "), applicability, ); @@ -335,7 +335,7 @@ fn check<'tcx>( diag.span_suggestion_verbose( usage.stmt.span.shrink_to_lo(), - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), format!("{let_snippet} = "), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index ae0a41db918..7376ab0c846 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -125,7 +125,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { if is_string { "string" } else { "byte string" } ), |diag| { - diag.help(&format!( + diag.help(format!( "octal escapes are not supported, `\\0` is always a null {}", if is_string { "character" } else { "byte" } )); @@ -139,7 +139,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { // suggestion 2: unambiguous null byte diag.span_suggestion( span, - &format!( + format!( "if the null {} is intended, disambiguate using", if is_string { "character" } else { "byte" } ), diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index ae805147f07..015f6c14e76 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -50,7 +50,7 @@ fn lint_misrefactored_assign_op( let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r)); diag.span_suggestion( expr.span, - &format!( + format!( "did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with", op.as_str() ), diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index f9fd3645668..75add4ee4aa 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -184,7 +184,7 @@ impl<'tcx> PassByRefOrValue { if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size - && let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind + && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind { if let Some(typeck) = cx.maybe_typeck_results() { // Don't lint if an unsafe pointer is created. diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs new file mode 100644 index 00000000000..e7095ec191f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::paths; +use clippy_utils::ty::match_type; +use rustc_ast::ast::LitKind; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`. + /// + /// ### Why is this bad? + /// On Unix platforms this results in the file being world writable, + /// equivalent to `chmod a+w <file>`. + /// ### Example + /// ```rust + /// use std::fs::File; + /// let f = File::create("foo.txt").unwrap(); + /// let metadata = f.metadata().unwrap(); + /// let mut permissions = metadata.permissions(); + /// permissions.set_readonly(false); + /// ``` + #[clippy::version = "1.66.0"] + pub PERMISSIONS_SET_READONLY_FALSE, + suspicious, + "Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`" +} +declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALSE]); + +impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind + && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS) + && path.ident.name == sym!(set_readonly) + && let ExprKind::Lit(lit) = &arg.kind + && LitKind::Bool(false) == lit.node + { + span_lint_and_then( + cx, + PERMISSIONS_SET_READONLY_FALSE, + expr.span, + "call to `set_readonly` with argument `false`", + |diag| { + diag.note("on Unix platforms this results in the file being world writable"); + diag.help("you can set the desired permissions using `PermissionsExt`. For more information, see\n\ + https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html"); + } + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index e395ff54cb1..26295304258 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -421,7 +421,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( if let ty::Ref(_, ty, mutability) = *ty.kind(); if let ty::Adt(adt, substs) = *ty.kind(); - if let TyKind::Rptr(lt, ref ty) = hir_ty.kind; + if let TyKind::Ref(lt, ref ty) = hir_ty.kind; if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind; // Check that the name as typed matches the actual name of the type. @@ -503,14 +503,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>( fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&'tcx Body<'_>>) { if let FnRetTy::Return(ty) = sig.decl.output - && let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) + && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty) { let out_region = cx.tcx.named_region(out.hir_id); let args: Option<Vec<_>> = sig .decl .inputs .iter() - .filter_map(get_rptr_lm) + .filter_map(get_ref_lm) .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region) .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span)) .collect(); @@ -704,8 +704,8 @@ fn matches_preds<'tcx>( }) } -fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> { - if let TyKind::Rptr(lt, ref m) = ty.kind { +fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> { + if let TyKind::Ref(lt, ref m) = ty.kind { Some((lt, m.mutbl, ty.span)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index c1677fb3da1..0e7c5cca724 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { // `res = clone(arg)` can be turned into `res = move arg;` // if `arg` is the only borrow of `cloned` at this point. - if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) { + if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) { continue; } @@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { // StorageDead(pred_arg); // res = to_path_buf(cloned); // ``` - if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) { + if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 41f991a967b..44bf824aa0e 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -59,7 +59,7 @@ impl RedundantStaticLifetimes { } }, // This is what we are looking for ! - TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { + TyKind::Ref(ref optional_lifetime, ref borrow_type) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { match borrow_type.ty.kind { diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index f21b3ea6c3b..448a32b77c0 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -39,7 +39,7 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { if_chain! { - if let TyKind::Rptr(_, ref mut_ty) = ty.kind; + if let TyKind::Ref(_, ref mut_ty) = ty.kind; if mut_ty.mutbl == Mutability::Not; if let TyKind::Path(ref qpath) = &mut_ty.ty.kind; let last = last_path_segment(qpath); @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { GenericArg::Type(inner_ty) => Some(inner_ty), _ => None, }); - if let TyKind::Rptr(_, ref inner_mut_ty) = inner_ty.kind; + if let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind; if inner_mut_ty.mutbl == Mutability::Not; then { diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 81143d7799e..d4d50660520 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -6,7 +6,7 @@ use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; @@ -207,6 +207,12 @@ fn check_final_expr<'tcx>( match &peeled_drop_expr.kind { // simple return is always "bad" ExprKind::Ret(ref inner) => { + // if desugar of `do yeet`, don't lint + if let Some(inner_expr) = inner + && let ExprKind::Call(path_expr, _) = inner_expr.kind + && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind { + return; + } if cx.tcx.hir().attrs(expr.hir_id).is_empty() { let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner)); if !borrows { diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index caab5851baf..17763128cd1 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { |diag| { diag.span_note( trait_method_span, - &format!("existing `{method_name}` defined here"), + format!("existing `{method_name}` defined here"), ); }, ); @@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { // iterate on trait_spans? diag.span_note( trait_spans[0], - &format!("existing `{method_name}` defined here"), + format!("existing `{method_name}` defined here"), ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs new file mode 100644 index 00000000000..3fcdb4288ce --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -0,0 +1,73 @@ +use clippy_utils::{diagnostics::span_lint_and_help, path_def_id, ty::peel_mid_ty_refs}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for calls to `std::mem::size_of_val()` where the argument is + /// a reference to a reference. + /// + /// ### Why is this bad? + /// + /// Calling `size_of_val()` with a reference to a reference as the argument + /// yields the size of the reference-type, not the size of the value behind + /// the reference. + /// + /// ### Example + /// ```rust + /// struct Foo { + /// buffer: [u8], + /// } + /// + /// impl Foo { + /// fn size(&self) -> usize { + /// // Note that `&self` as an argument is a `&&Foo`: Because `self` + /// // is already a reference, `&self` is a double-reference. + /// // The return value of `size_of_val()` therefor is the + /// // size of the reference-type, not the size of `self`. + /// std::mem::size_of_val(&self) + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct Foo { + /// buffer: [u8], + /// } + /// + /// impl Foo { + /// fn size(&self) -> usize { + /// // Correct + /// std::mem::size_of_val(self) + /// } + /// } + /// ``` + #[clippy::version = "1.67.0"] + pub SIZE_OF_REF, + suspicious, + "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended" +} +declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); + +impl LateLintPass<'_> for SizeOfRef { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let Some(def_id) = path_def_id(cx, path) + && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id) + && let arg_ty = cx.typeck_results().expr_ty(arg) + && peel_mid_ty_refs(arg_ty).1 > 1 + { + span_lint_and_help( + cx, + SIZE_OF_REF, + expr.span, + "argument to `std::mem::size_of_val()` is a reference to a reference", + None, + "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type", + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index c374529d1ea..17e9cc5f6b7 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -132,7 +132,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa applicability, ); if !is_xor_based { - diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?")); + diag.note(format!("or maybe you should use `{sugg}::mem::replace`?")); } }, ); @@ -214,7 +214,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { Applicability::MaybeIncorrect, ); diag.note( - &format!("or maybe you should use `{sugg}::mem::replace`?") + format!("or maybe you should use `{sugg}::mem::replace`?") ); } }); diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 83e651aba8e..691d759d773 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -3,6 +3,7 @@ mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_int_to_float; +mod transmute_null_to_fn; mod transmute_num_to_bytes; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; @@ -409,6 +410,34 @@ declare_clippy_lint! { "transmutes from a null pointer to a reference, which is undefined behavior" } +declare_clippy_lint! { + /// ### What it does + /// Checks for null function pointer creation through transmute. + /// + /// ### Why is this bad? + /// Creating a null function pointer is undefined behavior. + /// + /// More info: https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization + /// + /// ### Known problems + /// Not all cases can be detected at the moment of this writing. + /// For example, variables which hold a null pointer and are then fed to a `transmute` + /// call, aren't detectable yet. + /// + /// ### Example + /// ```rust + /// let null_fn: fn() = unsafe { std::mem::transmute( std::ptr::null::<()>() ) }; + /// ``` + /// Use instead: + /// ```rust + /// let null_fn: Option<fn()> = None; + /// ``` + #[clippy::version = "1.67.0"] + pub TRANSMUTE_NULL_TO_FN, + correctness, + "transmute results in a null function pointer, which is undefined behavior" +} + pub struct Transmute { msrv: Msrv, } @@ -428,6 +457,7 @@ impl_lint_pass!(Transmute => [ TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, TRANSMUTE_UNDEFINED_REPR, TRANSMUTING_NULL, + TRANSMUTE_NULL_TO_FN, ]); impl Transmute { #[must_use] @@ -461,6 +491,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmuting_null::check(cx, e, arg, to_ty) + | transmute_null_to_fn::check(cx, e, arg, to_ty) | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs new file mode 100644 index 00000000000..e75d7f6bf1d --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs @@ -0,0 +1,64 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; +use rustc_span::symbol::sym; + +use super::TRANSMUTE_NULL_TO_FN; + +fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { + span_lint_and_then( + cx, + TRANSMUTE_NULL_TO_FN, + expr.span, + "transmuting a known null pointer into a function pointer", + |diag| { + diag.span_label(expr.span, "this transmute results in undefined behavior"); + diag.help( + "try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value" + ); + }, + ); +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, to_ty: Ty<'tcx>) -> bool { + if !to_ty.is_fn() { + return false; + } + + match arg.kind { + // Catching: + // transmute over constants that resolve to `null`. + ExprKind::Path(ref _qpath) + if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) => + { + lint_expr(cx, expr); + true + }, + + // Catching: + // `std::mem::transmute(0 as *const i32)` + ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => { + lint_expr(cx, expr); + true + }, + + // Catching: + // `std::mem::transmute(std::ptr::null::<i32>())` + ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => { + lint_expr(cx, expr); + true + }, + + _ => { + // FIXME: + // Also catch transmutations of variables which are known nulls. + // To do this, MIR const propagation seems to be the better tool. + // Whenever MIR const prop routines are more developed, this will + // become available. As of this writing (25/03/19) it is not yet. + false + }, + } +} diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 3dde4eee671..54ac04df1c1 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -71,7 +71,7 @@ pub(super) fn check<'tcx>( /// Gets the type `Bar` in `…::transmute<Foo, &Bar>`. fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> { if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)? - && let TyKind::Rptr(_, ty) = &ty.kind + && let TyKind::Ref(_, ty) = &ty.kind { Some(ty.ty) } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 34642f4b122..af0242348ac 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -77,7 +77,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty.peel_refs() { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } }, ); @@ -91,7 +91,7 @@ pub(super) fn check<'tcx>( &format!("transmute to `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty.peel_refs() { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } }, ); @@ -119,16 +119,16 @@ pub(super) fn check<'tcx>( ), |diag| { if let Some(same_adt_did) = same_adt_did { - diag.note(&format!( + diag.note(format!( "two instances of the same generic type (`{}`) may have different layouts", cx.tcx.item_name(same_adt_did) )); } else { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } } }, @@ -146,7 +146,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } }, ); @@ -163,7 +163,7 @@ pub(super) fn check<'tcx>( &format!("transmute into `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 6b444922a7c..b79d4e915a2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"), |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let sugg = arg.as_ty(&to_ty.to_string()).to_string(); + let sugg = arg.as_ty(to_ty.to_string()).to_string(); diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); } }, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs index 19ce5ae72c2..1e407fc4138 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs @@ -18,8 +18,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching transmute over constants that resolve to `null`. let mut const_eval_context = constant_context(cx, cx.typeck_results()); if let ExprKind::Path(ref _qpath) = arg.kind && - let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg) && - x == 0 + let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg) { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); return true; diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index f919bbd5afc..871c3fadbba 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -61,7 +61,7 @@ pub(super) fn check<'tcx>( "transmute from an integer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified); + diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 20978e81dc5..c14f056a1f2 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -539,7 +539,7 @@ impl Types { QPath::LangItem(..) => {}, } }, - TyKind::Rptr(lt, ref mut_ty) => { + TyKind::Ref(lt, ref mut_ty) => { context.is_nested_call = true; if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { self.check_ty(cx, mut_ty.ty, context); diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index fae5385ffc8..f9b9a66b5fa 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ &format!("usage of `{outer_sym}<{generic_snippet}>`"), |diag| { diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability); - diag.note(&format!( + diag.note(format!( "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap" )); }, @@ -78,7 +78,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ format!("{outer_sym}<{generic_snippet}>"), applicability, ); - diag.note(&format!( + diag.note(format!( "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation" )); }, @@ -91,10 +91,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ hir_ty.span, &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), |diag| { - diag.note(&format!( + diag.note(format!( "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation" )); - diag.help(&format!( + diag.help(format!( "consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`" )); }, diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index 5ca4023aa5c..0aa50c99c16 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -44,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { let (add_score, sub_nest) = match ty.kind { // _, &x and *x have only small overhead; don't mess with nesting level - TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0), + TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0), // the "normal" components of a type: named types, arrays/tuples TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs index 0fa75f8f0a9..7f43b7841ff 100644 --- a/src/tools/clippy/clippy_lints/src/types/utils.rs +++ b/src/tools/clippy/clippy_lints/src/types/utils.rs @@ -13,7 +13,7 @@ pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) GenericArg::Type(ty) => Some(ty), _ => None, }); - if let TyKind::Rptr(..) = ty.kind; + if let TyKind::Ref(..) = ty.kind; then { return Some(ty.span); } diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index f6d3fb00f4e..ef9f740f704 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp if arg_snippets_without_empty_blocks.is_empty() { db.multipart_suggestion( - &format!("use {singular}unit literal{plural} instead"), + format!("use {singular}unit literal{plural} instead"), args_to_recover .iter() .map(|arg| (arg.span, "()".to_string())) @@ -142,7 +142,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp let it_or_them = if plural { "them" } else { "it" }; db.span_suggestion( expr.span, - &format!( + format!( "{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`" ), sugg, diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 3743d5d97a7..a95e7b61374 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::{snippet, snippet_with_macro_callsite}; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts}; -use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths}; +use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; +use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -81,16 +81,24 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter { - if let Some(parent_expr) = get_parent_expr(cx, e) { - if let ExprKind::MethodCall(parent_name, ..) = parent_expr.kind { - if parent_name.ident.name != sym::into_iter { - return; - } - } + if get_parent_expr(cx, e).is_some() && + let Some(id) = path_to_local(recv) && + let Node::Pat(pat) = cx.tcx.hir().get(id) && + let PatKind::Binding(ann, ..) = pat.kind && + ann != BindingAnnotation::MUT + { + // Do not remove .into_iter() applied to a non-mutable local variable used in + // a larger expression context as it would differ in mutability. + return; } + let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(recv); - if same_type_and_consts(a, b) { + + // If the types are identical then .into_iter() can be removed, unless the type + // implements Copy, in which case .into_iter() returns a copy of the receiver and + // cannot be safely omitted. + if same_type_and_consts(a, b) && !is_copy(cx, b) { let sugg = snippet(cx, recv.span, "<expr>").into_owned(); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 3e7d0028c0f..c1589c771c4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -333,7 +333,7 @@ define_Conf! { /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS. /// /// The maximum allowed size for arrays on the stack - (array_size_threshold: u64 = 512_000), + (array_size_threshold: u128 = 512_000), /// Lint: VEC_BOX. /// /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 786d9608c85..4c3b1b131fd 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -257,7 +257,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { } pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { - if let TyKind::Rptr( + if let TyKind::Ref( _, MutTy { ty: inner, diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 857abe77e21..929544cd69d 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -558,8 +558,8 @@ impl fmt::Display for ClippyConfiguration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { writeln!( f, - "* `{}`: `{}`: {} (defaults to `{}`)", - self.name, self.config_type, self.doc, self.default + "* `{}`: `{}`(defaults to `{}`): {}", + self.name, self.config_type, self.default, self.doc ) } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 6b321765bc0..df335038881 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -377,7 +377,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c // print!("\n"), write!(f, "\n") diag.multipart_suggestion( - &format!("use `{name}ln!` instead"), + format!("use `{name}ln!` instead"), vec![(name_span, format!("{name}ln")), (format_string_span, String::new())], Applicability::MachineApplicable, ); @@ -388,7 +388,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c let newline_span = format_string_span.with_lo(hi - BytePos(3)).with_hi(hi - BytePos(1)); diag.multipart_suggestion( - &format!("use `{name}ln!` instead"), + format!("use `{name}ln!` instead"), vec![(name_span, format!("{name}ln")), (newline_span, String::new())], Applicability::MachineApplicable, ); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 49e5f283db0..9d0263e93be 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -625,7 +625,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { (Slice(l), Slice(r)) => eq_ty(l, r), (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), - (Rptr(ll, l), Rptr(rl, r)) => { + (Ref(ll, l), Ref(rl, r)) => { both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, (BareFn(l), BareFn(r)) => { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 7a637d32bab..a67bd8d4600 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -620,12 +620,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( int.try_into().expect("invalid f64 bit representation"), ))), - ty::RawPtr(type_and_mut) => { - if let ty::Uint(_) = type_and_mut.ty.kind() { - return Some(Constant::RawPtr(int.assert_bits(int.size()))); - } - None - }, + ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), // FIXME: implement other conversions. _ => None, } diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 16b160b6fd2..812f6fe71a0 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -17,7 +17,7 @@ use std::env; fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { if let Some(lint) = lint.name_lower().strip_prefix("clippy::") { - diag.help(&format!( + diag.help(format!( "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}", &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { // extract just major + minor version and ignore patch versions diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 07fb6af91ba..2bbe1a19b62 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -430,7 +430,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl), (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), - (TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => { + (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), @@ -950,7 +950,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - TyKind::Rptr(lifetime, ref mut_ty) => { + TyKind::Ref(lifetime, ref mut_ty) => { self.hash_lifetime(lifetime); self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 43e2d1ec826..d863609b6a7 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2264,7 +2264,7 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) let mut count = 0; loop { match &ty.kind { - TyKind::Rptr(_, ref_ty) => { + TyKind::Ref(_, ref_ty) => { ty = ref_ty.ty; count += 1; }, diff --git a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs b/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs deleted file mode 100644 index d262b335d99..00000000000 --- a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs +++ /dev/null @@ -1,52 +0,0 @@ -use rustc_index::bit_set::BitSet; -use rustc_middle::mir; -use rustc_mir_dataflow::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis}; - -/// Determines liveness of each local purely based on `StorageLive`/`Dead`. -#[derive(Copy, Clone)] -pub(super) struct MaybeStorageLive; - -impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive { - type Domain = BitSet<mir::Local>; - const NAME: &'static str = "maybe_storage_live"; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - // bottom = dead - BitSet::new_empty(body.local_decls.len()) - } - - fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) { - for arg in body.args_iter() { - state.insert(arg); - } - } -} - -impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive { - type Idx = mir::Local; - - fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) { - match stmt.kind { - mir::StatementKind::StorageLive(l) => trans.gen(l), - mir::StatementKind::StorageDead(l) => trans.kill(l), - _ => (), - } - } - - fn terminator_effect( - &self, - _trans: &mut impl GenKill<Self::Idx>, - _terminator: &mir::Terminator<'tcx>, - _loc: mir::Location, - ) { - } - - fn call_return_effect( - &self, - _trans: &mut impl GenKill<Self::Idx>, - _block: mir::BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - // Nothing to do when a call returns successfully - } -} diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 818e603f665..26c0015e87e 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -5,8 +5,6 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::TyCtxt; -mod maybe_storage_live; - mod possible_borrower; pub use possible_borrower::PossibleBorrowerMap; diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 25717bf3d2f..395d46e7a2f 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -1,92 +1,137 @@ -use super::{ - maybe_storage_live::MaybeStorageLive, possible_origin::PossibleOriginVisitor, - transitive_relation::TransitiveRelation, -}; +use super::possible_origin::PossibleOriginVisitor; use crate::ty::is_copy; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::LateContext; -use rustc_middle::mir::{self, visit::Visitor as _, Mutability}; -use rustc_middle::ty::{self, visit::TypeVisitor}; -use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use rustc_middle::mir::{ + self, visit::Visitor as _, BasicBlock, Local, Location, Mutability, Statement, StatementKind, Terminator, +}; +use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt}; +use rustc_mir_dataflow::{ + fmt::DebugWithContext, impls::MaybeStorageLive, lattice::JoinSemiLattice, Analysis, AnalysisDomain, + CallReturnPlaces, ResultsCursor, +}; +use std::borrow::Cow; use std::ops::ControlFlow; /// Collects the possible borrowers of each local. /// For example, `b = &a; c = &a;` will make `b` and (transitively) `c` /// possible borrowers of `a`. #[allow(clippy::module_name_repetitions)] -struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { - possible_borrower: TransitiveRelation, +struct PossibleBorrowerAnalysis<'b, 'tcx> { + tcx: TyCtxt<'tcx>, body: &'b mir::Body<'tcx>, - cx: &'a LateContext<'tcx>, possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, } -impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> { - fn new( - cx: &'a LateContext<'tcx>, - body: &'b mir::Body<'tcx>, - possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, - ) -> Self { +#[derive(Clone, Debug, Eq, PartialEq)] +struct PossibleBorrowerState { + map: FxIndexMap<Local, BitSet<Local>>, + domain_size: usize, +} + +impl PossibleBorrowerState { + fn new(domain_size: usize) -> Self { Self { - possible_borrower: TransitiveRelation::default(), - cx, - body, - possible_origin, + map: FxIndexMap::default(), + domain_size, } } - fn into_map( - self, - cx: &'a LateContext<'tcx>, - maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>, - ) -> PossibleBorrowerMap<'b, 'tcx> { - let mut map = FxHashMap::default(); - for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { - if is_copy(cx, self.body.local_decls[row].ty) { - continue; - } + #[allow(clippy::similar_names)] + fn add(&mut self, borrowed: Local, borrower: Local) { + self.map + .entry(borrowed) + .or_insert(BitSet::new_empty(self.domain_size)) + .insert(borrower); + } +} - let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len()); - borrowers.remove(mir::Local::from_usize(0)); +impl<C> DebugWithContext<C> for PossibleBorrowerState { + fn fmt_with(&self, _ctxt: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + <_ as std::fmt::Debug>::fmt(self, f) + } + fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + unimplemented!() + } +} + +impl JoinSemiLattice for PossibleBorrowerState { + fn join(&mut self, other: &Self) -> bool { + let mut changed = false; + for (&borrowed, borrowers) in other.map.iter() { if !borrowers.is_empty() { - map.insert(row, borrowers); + changed |= self + .map + .entry(borrowed) + .or_insert(BitSet::new_empty(self.domain_size)) + .union(borrowers); } } + changed + } +} - let bs = BitSet::new_empty(self.body.local_decls.len()); - PossibleBorrowerMap { - map, - maybe_live, - bitset: (bs.clone(), bs), +impl<'b, 'tcx> AnalysisDomain<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> { + type Domain = PossibleBorrowerState; + + const NAME: &'static str = "possible_borrower"; + + fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { + PossibleBorrowerState::new(body.local_decls.len()) + } + + fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _entry_set: &mut Self::Domain) {} +} + +impl<'b, 'tcx> PossibleBorrowerAnalysis<'b, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + body: &'b mir::Body<'tcx>, + possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, + ) -> Self { + Self { + tcx, + body, + possible_origin, } } } -impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> { - fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) { - let lhs = place.local; - match rvalue { - mir::Rvalue::Ref(_, _, borrowed) => { - self.possible_borrower.add(borrowed.local, lhs); - }, - other => { - if ContainsRegion - .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty) - .is_continue() - { - return; - } - rvalue_locals(other, |rhs| { - if lhs != rhs { - self.possible_borrower.add(rhs, lhs); +impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> { + fn apply_call_return_effect( + &self, + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + } + + fn apply_statement_effect(&self, state: &mut Self::Domain, statement: &Statement<'tcx>, _location: Location) { + if let StatementKind::Assign(box (place, rvalue)) = &statement.kind { + let lhs = place.local; + match rvalue { + mir::Rvalue::Ref(_, _, borrowed) => { + state.add(borrowed.local, lhs); + }, + other => { + if ContainsRegion + .visit_ty(place.ty(&self.body.local_decls, self.tcx).ty) + .is_continue() + { + return; } - }); - }, + rvalue_locals(other, |rhs| { + if lhs != rhs { + state.add(rhs, lhs); + } + }); + }, + } } } - fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) { + fn apply_terminator_effect(&self, state: &mut Self::Domain, terminator: &Terminator<'tcx>, _location: Location) { if let mir::TerminatorKind::Call { args, destination: mir::Place { local: dest, .. }, @@ -126,10 +171,10 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, for y in mutable_variables { for x in &immutable_borrowers { - self.possible_borrower.add(*x, y); + state.add(*x, y); } for x in &mutable_borrowers { - self.possible_borrower.add(*x, y); + state.add(*x, y); } } } @@ -165,73 +210,98 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { } } -/// Result of `PossibleBorrowerVisitor`. +/// Result of `PossibleBorrowerAnalysis`. #[allow(clippy::module_name_repetitions)] pub struct PossibleBorrowerMap<'b, 'tcx> { - /// Mapping `Local -> its possible borrowers` - pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, - maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>, - // Caches to avoid allocation of `BitSet` on every query - pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>), + body: &'b mir::Body<'tcx>, + possible_borrower: ResultsCursor<'b, 'tcx, PossibleBorrowerAnalysis<'b, 'tcx>>, + maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'b>>, + pushed: BitSet<Local>, + stack: Vec<Local>, } -impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { - pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self { +impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { + pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self { let possible_origin = { let mut vis = PossibleOriginVisitor::new(mir); vis.visit_body(mir); vis.into_map(cx) }; - let maybe_storage_live_result = MaybeStorageLive + let possible_borrower = PossibleBorrowerAnalysis::new(cx.tcx, mir, possible_origin) .into_engine(cx.tcx, mir) - .pass_name("redundant_clone") + .pass_name("possible_borrower") .iterate_to_fixpoint() .into_results_cursor(mir); - let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin); - vis.visit_body(mir); - vis.into_map(cx, maybe_storage_live_result) - } - - /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. - pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { - self.bounded_borrowers(borrowers, borrowers, borrowed, at) + let maybe_live = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len()))) + .into_engine(cx.tcx, mir) + .pass_name("possible_borrower") + .iterate_to_fixpoint() + .into_results_cursor(mir); + PossibleBorrowerMap { + body: mir, + possible_borrower, + maybe_live, + pushed: BitSet::new_empty(mir.local_decls.len()), + stack: Vec::with_capacity(mir.local_decls.len()), + } } - /// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below` - /// but no more than `above`. - pub fn bounded_borrowers( + /// Returns true if the set of borrowers of `borrowed` living at `at` includes no more than + /// `borrowers`. + /// Notes: + /// 1. It would be nice if `PossibleBorrowerMap` could store `cx` so that `at_most_borrowers` + /// would not require it to be passed in. But a `PossibleBorrowerMap` is stored in `LintPass` + /// `Dereferencing`, which outlives any `LateContext`. + /// 2. In all current uses of `at_most_borrowers`, `borrowers` is a slice of at most two + /// elements. Thus, `borrowers.contains(...)` is effectively a constant-time operation. If + /// `at_most_borrowers`'s uses were to expand beyond this, its implementation might have to be + /// adjusted. + pub fn at_most_borrowers( &mut self, - below: &[mir::Local], - above: &[mir::Local], + cx: &LateContext<'tcx>, + borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location, ) -> bool { - self.maybe_live.seek_after_primary_effect(at); + if is_copy(cx, self.body.local_decls[borrowed].ty) { + return true; + } - self.bitset.0.clear(); - let maybe_live = &mut self.maybe_live; - if let Some(bitset) = self.map.get(&borrowed) { - for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) { - self.bitset.0.insert(b); + self.possible_borrower.seek_before_primary_effect(at); + self.maybe_live.seek_before_primary_effect(at); + + let possible_borrower = &self.possible_borrower.get().map; + let maybe_live = &self.maybe_live; + + self.pushed.clear(); + self.stack.clear(); + + if let Some(borrowers) = possible_borrower.get(&borrowed) { + for b in borrowers.iter() { + if self.pushed.insert(b) { + self.stack.push(b); + } } } else { - return false; + // Nothing borrows `borrowed` at `at`. + return true; } - self.bitset.1.clear(); - for b in below { - self.bitset.1.insert(*b); - } - - if !self.bitset.0.superset(&self.bitset.1) { - return false; - } + while let Some(borrower) = self.stack.pop() { + if maybe_live.contains(borrower) && !borrowers.contains(&borrower) { + return false; + } - for b in above { - self.bitset.0.remove(*b); + if let Some(borrowers) = possible_borrower.get(&borrower) { + for b in borrowers.iter() { + if self.pushed.insert(b) { + self.stack.push(b); + } + } + } } - self.bitset.0.is_empty() + true } pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index b66604f33db..e7879bb196e 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -185,7 +185,6 @@ impl<'a> Sugg<'a> { ) -> Self { use rustc_ast::ast::RangeLimits; - #[expect(clippy::match_wildcard_for_single_variants)] match expr.kind { _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), ast::ExprKind::AddrOf(..) @@ -813,9 +812,9 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let closure_body = cx.tcx.hir().body(body); // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`) // a type annotation is present if param `kind` is different from `TyKind::Infer` - let closure_arg_is_type_annotated_double_ref = if let TyKind::Rptr(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind + let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind { - matches!(ty.kind, TyKind::Rptr(_, MutTy { .. })) + matches!(ty.kind, TyKind::Ref(_, MutTy { .. })) } else { false }; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2773da70d78..c8d56a3be5c 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -496,7 +496,7 @@ pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bo /// Returns the base type for HIR references and pointers. pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { match ty.kind { - TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty), + TyKind::Ptr(ref mut_ty) | TyKind::Ref(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty), _ => ty, } } diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 8e21cef32ab..9399d422036 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-12-17" +channel = "nightly-2022-12-29" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index 92ba3592967..22ce1c6f647 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -3,8 +3,7 @@ error: an async construct yields a type which is itself awaitable | LL | let _h = async { | _____________________- -LL | | async { - | | _________^ +LL | |/ async { LL | || 3 LL | || } | ||_________^ awaitable value not awaited @@ -37,8 +36,7 @@ error: an async construct yields a type which is itself awaitable | LL | let _j = async || { | ________________________- -LL | | async { - | | _________^ +LL | |/ async { LL | || 3 LL | || } | ||_________^ awaitable value not awaited diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.rs b/src/tools/clippy/tests/ui/crashes/ice-10044.rs new file mode 100644 index 00000000000..65f38fe7118 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-10044.rs @@ -0,0 +1,3 @@ +fn main() { + [0; usize::MAX]; +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.stderr b/src/tools/clippy/tests/ui/crashes/ice-10044.stderr new file mode 100644 index 00000000000..731f8265ad6 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-10044.stderr @@ -0,0 +1,10 @@ +error: statement with no effect + --> $DIR/ice-10044.rs:2:5 + | +LL | [0; usize::MAX]; + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/floating_point_powi.fixed b/src/tools/clippy/tests/ui/floating_point_powi.fixed index 884d05fed71..8ffd4cc5137 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.fixed +++ b/src/tools/clippy/tests/ui/floating_point_powi.fixed @@ -14,6 +14,15 @@ fn main() { let _ = (y as f32).mul_add(y as f32, x); let _ = x.mul_add(x, y).sqrt(); let _ = y.mul_add(y, x).sqrt(); + + let _ = (x - 1.0).mul_add(x - 1.0, -y); + let _ = (x - 1.0).mul_add(x - 1.0, -y) + 3.0; + let _ = (x - 1.0).mul_add(x - 1.0, -(y + 3.0)); + let _ = (y + 1.0).mul_add(-(y + 1.0), x); + let _ = (3.0 * y).mul_add(-(3.0 * y), x); + let _ = (y + 1.0 + x).mul_add(-(y + 1.0 + x), x); + let _ = (y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x); + // Cases where the lint shouldn't be applied let _ = x.powi(2); let _ = x.powi(1 + 1); diff --git a/src/tools/clippy/tests/ui/floating_point_powi.rs b/src/tools/clippy/tests/ui/floating_point_powi.rs index e6a1c895371..9ae3455a134 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.rs +++ b/src/tools/clippy/tests/ui/floating_point_powi.rs @@ -14,6 +14,15 @@ fn main() { let _ = x + (y as f32).powi(2); let _ = (x.powi(2) + y).sqrt(); let _ = (x + y.powi(2)).sqrt(); + + let _ = (x - 1.0).powi(2) - y; + let _ = (x - 1.0).powi(2) - y + 3.0; + let _ = (x - 1.0).powi(2) - (y + 3.0); + let _ = x - (y + 1.0).powi(2); + let _ = x - (3.0 * y).powi(2); + let _ = x - (y + 1.0 + x).powi(2); + let _ = x - (y + 1.0 + 2.0).powi(2); + // Cases where the lint shouldn't be applied let _ = x.powi(2); let _ = x.powi(1 + 1); diff --git a/src/tools/clippy/tests/ui/floating_point_powi.stderr b/src/tools/clippy/tests/ui/floating_point_powi.stderr index 5df0de1fef2..fdf6d088052 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.stderr +++ b/src/tools/clippy/tests/ui/floating_point_powi.stderr @@ -42,5 +42,47 @@ error: multiply and add expressions can be calculated more efficiently and accur LL | let _ = (x + y.powi(2)).sqrt(); | ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` -error: aborting due to 7 previous errors +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:18:13 + | +LL | let _ = (x - 1.0).powi(2) - y; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:19:13 + | +LL | let _ = (x - 1.0).powi(2) - y + 3.0; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:20:13 + | +LL | let _ = (x - 1.0).powi(2) - (y + 3.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -(y + 3.0))` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:21:13 + | +LL | let _ = x - (y + 1.0).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0).mul_add(-(y + 1.0), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:22:13 + | +LL | let _ = x - (3.0 * y).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(3.0 * y).mul_add(-(3.0 * y), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:23:13 + | +LL | let _ = x - (y + 1.0 + x).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + x).mul_add(-(y + 1.0 + x), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:24:13 + | +LL | let _ = x - (y + 1.0 + 2.0).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x)` + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs new file mode 100644 index 00000000000..df5bc8420d5 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_null_check.rs @@ -0,0 +1,21 @@ +#![allow(unused)] +#![warn(clippy::fn_null_check)] +#![allow(clippy::cmp_null)] +#![allow(clippy::ptr_eq)] +#![allow(clippy::zero_ptr)] + +pub const ZPTR: *const () = 0 as *const _; +pub const NOT_ZPTR: *const () = 1 as *const _; + +fn main() { + let fn_ptr = main; + + if (fn_ptr as *mut ()).is_null() {} + if (fn_ptr as *const u8).is_null() {} + if (fn_ptr as *const ()) == std::ptr::null() {} + if (fn_ptr as *const ()) == (0 as *const ()) {} + if (fn_ptr as *const ()) == ZPTR {} + + // no lint + if (fn_ptr as *const ()) == NOT_ZPTR {} +} diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr new file mode 100644 index 00000000000..660dd323979 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_null_check.stderr @@ -0,0 +1,43 @@ +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:13:8 + | +LL | if (fn_ptr as *mut ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + = note: `-D clippy::fn-null-check` implied by `-D warnings` + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:14:8 + | +LL | if (fn_ptr as *const u8).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:15:8 + | +LL | if (fn_ptr as *const ()) == std::ptr::null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:16:8 + | +LL | if (fn_ptr as *const ()) == (0 as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:17:8 + | +LL | if (fn_ptr as *const ()) == ZPTR {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed index 3553291b87d..ef6780dc96d 100644 --- a/src/tools/clippy/tests/ui/manual_filter.fixed +++ b/src/tools/clippy/tests/ui/manual_filter.fixed @@ -116,4 +116,45 @@ fn main() { }, None => None, }; + + match Some(20) { + // Don't Lint, because `Some(3*x)` is not `None` + None => None, + Some(x) => { + if x > 0 { + Some(3 * x) + } else { + Some(x) + } + }, + }; + + // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088 + let result = if let Some(a) = maybe_some() { + if let Some(b) = maybe_some() { + Some(a + b) + } else { + Some(a) + } + } else { + None + }; + + let allowed_integers = vec![3, 4, 5, 6]; + // Don't lint, since there's a side effect in the else branch + match Some(21) { + Some(x) => { + if allowed_integers.contains(&x) { + Some(x) + } else { + println!("Invalid integer: {x:?}"); + None + } + }, + None => None, + }; +} + +fn maybe_some() -> Option<u32> { + Some(0) } diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs index aa9f90f752b..ea0ce83172b 100644 --- a/src/tools/clippy/tests/ui/manual_filter.rs +++ b/src/tools/clippy/tests/ui/manual_filter.rs @@ -240,4 +240,45 @@ fn main() { }, None => None, }; + + match Some(20) { + // Don't Lint, because `Some(3*x)` is not `None` + None => None, + Some(x) => { + if x > 0 { + Some(3 * x) + } else { + Some(x) + } + }, + }; + + // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088 + let result = if let Some(a) = maybe_some() { + if let Some(b) = maybe_some() { + Some(a + b) + } else { + Some(a) + } + } else { + None + }; + + let allowed_integers = vec![3, 4, 5, 6]; + // Don't lint, since there's a side effect in the else branch + match Some(21) { + Some(x) => { + if allowed_integers.contains(&x) { + Some(x) + } else { + println!("Invalid integer: {x:?}"); + None + } + }, + None => None, + }; +} + +fn maybe_some() -> Option<u32> { + Some(0) } diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed index e5ae3cf3e50..8f25fea678f 100644 --- a/src/tools/clippy/tests/ui/manual_retain.fixed +++ b/src/tools/clippy/tests/ui/manual_retain.fixed @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_retain)] -#![allow(unused)] +#![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::BinaryHeap; diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs index 1021f15edd1..e6b3995a689 100644 --- a/src/tools/clippy/tests/ui/manual_retain.rs +++ b/src/tools/clippy/tests/ui/manual_retain.rs @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_retain)] -#![allow(unused)] +#![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::BinaryHeap; diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed index a6e315e4773..6cfb6661a03 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.fixed +++ b/src/tools/clippy/tests/ui/match_single_binding.fixed @@ -133,3 +133,16 @@ fn issue_9575() { println!("Needs curlies"); }; } + +#[allow(dead_code)] +fn issue_9725(r: Option<u32>) { + let x = r; + match x { + Some(_) => { + println!("Some"); + }, + None => { + println!("None"); + }, + }; +} diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs index cecbd703e56..f188aeb5f2f 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.rs +++ b/src/tools/clippy/tests/ui/match_single_binding.rs @@ -148,3 +148,17 @@ fn issue_9575() { _ => println!("Needs curlies"), }; } + +#[allow(dead_code)] +fn issue_9725(r: Option<u32>) { + match r { + x => match x { + Some(_) => { + println!("Some"); + }, + None => { + println!("None"); + }, + }, + }; +} diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr index 2b9ec7ee702..e960d64ad2b 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.stderr +++ b/src/tools/clippy/tests/ui/match_single_binding.stderr @@ -213,5 +213,30 @@ LL + println!("Needs curlies"); LL ~ }; | -error: aborting due to 14 previous errors +error: this match could be written as a `let` statement + --> $DIR/match_single_binding.rs:154:5 + | +LL | / match r { +LL | | x => match x { +LL | | Some(_) => { +LL | | println!("Some"); +... | +LL | | }, +LL | | }; + | |_____^ + | +help: consider using a `let` statement + | +LL ~ let x = r; +LL + match x { +LL + Some(_) => { +LL + println!("Some"); +LL + }, +LL + None => { +LL + println!("None"); +LL + }, +LL ~ }; + | + +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed index e675c183ea7..fc252cdd352 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed @@ -132,3 +132,25 @@ fn main() { } } } + +mod issue9993 { + enum Foo { + A(bool), + B, + } + + fn test() { + let _ = match Foo::A(true) { + _ if false => 0, + Foo::A(true) => 1, + Foo::A(false) => 2, + Foo::B => 3, + }; + + let _ = match Foo::B { + _ if false => 0, + Foo::A(_) => 1, + Foo::B => 2, + }; + } +} diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs index 38c3ffc00c7..9a5c849e6ec 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs @@ -132,3 +132,25 @@ fn main() { } } } + +mod issue9993 { + enum Foo { + A(bool), + B, + } + + fn test() { + let _ = match Foo::A(true) { + _ if false => 0, + Foo::A(true) => 1, + Foo::A(false) => 2, + Foo::B => 3, + }; + + let _ = match Foo::B { + _ if false => 0, + Foo::A(_) => 1, + _ => 2, + }; + } +} diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr index 34538dea8e5..6fa313dc911 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr @@ -48,5 +48,11 @@ error: wildcard matches only a single variant and will also match any future add LL | _ => (), | ^ help: try this: `Color::Blue` -error: aborting due to 8 previous errors +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:153:13 + | +LL | _ => 2, + | ^ help: try this: `Foo::B` + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index 4cb7f6b687f..31e1cb6c3d7 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![feature(lint_reasons)] +#![feature(custom_inner_attributes, lint_reasons, rustc_private)] #![allow( unused, clippy::uninlined_format_args, @@ -491,3 +491,14 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +extern crate rustc_lint; +extern crate rustc_span; + +#[allow(dead_code)] +mod span_lint { + use rustc_lint::{LateContext, Lint, LintContext}; + fn foo(cx: &LateContext<'_>, lint: &'static Lint) { + cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(String::new())); + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 9a01190ed8d..55c2738fcf2 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -1,5 +1,5 @@ // run-rustfix -#![feature(lint_reasons)] +#![feature(custom_inner_attributes, lint_reasons, rustc_private)] #![allow( unused, clippy::uninlined_format_args, @@ -491,3 +491,14 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +extern crate rustc_lint; +extern crate rustc_span; + +#[allow(dead_code)] +mod span_lint { + use rustc_lint::{LateContext, Lint, LintContext}; + fn foo(cx: &LateContext<'_>, lint: &'static Lint) { + cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new())); + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index d26c317124b..98a48d68317 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -216,5 +216,11 @@ error: the borrowed expression implements the required traits LL | foo(&a); | ^^ help: change this to: `a` -error: aborting due to 36 previous errors +error: the borrowed expression implements the required traits + --> $DIR/needless_borrow.rs:502:85 + | +LL | cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new())); + | ^^^^^^^^^^^^^^ help: change this to: `String::new()` + +error: aborting due to 37 previous errors diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index 4386aaec49e..d451be1f389 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,6 +1,7 @@ // run-rustfix #![feature(lint_reasons)] +#![feature(yeet_expr)] #![allow(unused)] #![allow( clippy::if_same_then_else, @@ -272,4 +273,8 @@ mod issue9416 { } } +fn issue9947() -> Result<(), String> { + do yeet "hello"; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index 666dc54b76b..e1a1bea2c0b 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,6 +1,7 @@ // run-rustfix #![feature(lint_reasons)] +#![feature(yeet_expr)] #![allow(unused)] #![allow( clippy::if_same_then_else, @@ -282,4 +283,8 @@ mod issue9416 { } } +fn issue9947() -> Result<(), String> { + do yeet "hello"; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index a8b5d86cd55..ca2253e6586 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> $DIR/needless_return.rs:26:5 + --> $DIR/needless_return.rs:27:5 | LL | return true; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:30:5 + --> $DIR/needless_return.rs:31:5 | LL | return true; | ^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:35:9 + --> $DIR/needless_return.rs:36:9 | LL | return true; | ^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:37:9 + --> $DIR/needless_return.rs:38:9 | LL | return false; | ^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:43:17 + --> $DIR/needless_return.rs:44:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | true => return false, = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:45:13 + --> $DIR/needless_return.rs:46:13 | LL | return true; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:52:9 + --> $DIR/needless_return.rs:53:9 | LL | return true; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:54:16 + --> $DIR/needless_return.rs:55:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = || return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:58:5 + --> $DIR/needless_return.rs:59:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | return the_answer!(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:61:21 + --> $DIR/needless_return.rs:62:21 | LL | fn test_void_fun() { | _____________________^ @@ -82,7 +82,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:66:11 + --> $DIR/needless_return.rs:67:11 | LL | if b { | ___________^ @@ -92,7 +92,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:68:13 + --> $DIR/needless_return.rs:69:13 | LL | } else { | _____________^ @@ -102,7 +102,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:76:14 + --> $DIR/needless_return.rs:77:14 | LL | _ => return, | ^^^^^^ @@ -110,7 +110,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:84:24 + --> $DIR/needless_return.rs:85:24 | LL | let _ = 42; | ________________________^ @@ -120,7 +120,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:87:14 + --> $DIR/needless_return.rs:88:14 | LL | _ => return, | ^^^^^^ @@ -128,7 +128,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:100:9 + --> $DIR/needless_return.rs:101:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | return String::from("test"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:102:9 + --> $DIR/needless_return.rs:103:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | return String::new(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:124:32 + --> $DIR/needless_return.rs:125:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -152,7 +152,7 @@ LL | bar.unwrap_or_else(|_| return) = help: replace `return` with an empty block error: unneeded `return` statement - --> $DIR/needless_return.rs:128:21 + --> $DIR/needless_return.rs:129:21 | LL | let _ = || { | _____________________^ @@ -162,7 +162,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:131:20 + --> $DIR/needless_return.rs:132:20 | LL | let _ = || return; | ^^^^^^ @@ -170,7 +170,7 @@ LL | let _ = || return; = help: replace `return` with an empty block error: unneeded `return` statement - --> $DIR/needless_return.rs:137:32 + --> $DIR/needless_return.rs:138:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | res.unwrap_or_else(|_| return Foo) = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:146:5 + --> $DIR/needless_return.rs:147:5 | LL | return true; | ^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:150:5 + --> $DIR/needless_return.rs:151:5 | LL | return true; | ^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:155:9 + --> $DIR/needless_return.rs:156:9 | LL | return true; | ^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:157:9 + --> $DIR/needless_return.rs:158:9 | LL | return false; | ^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:163:17 + --> $DIR/needless_return.rs:164:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | true => return false, = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:165:13 + --> $DIR/needless_return.rs:166:13 | LL | return true; | ^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:172:9 + --> $DIR/needless_return.rs:173:9 | LL | return true; | ^^^^^^^^^^^ @@ -234,7 +234,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:174:16 + --> $DIR/needless_return.rs:175:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -242,7 +242,7 @@ LL | let _ = || return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:178:5 + --> $DIR/needless_return.rs:179:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL | return the_answer!(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:181:33 + --> $DIR/needless_return.rs:182:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -260,7 +260,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:186:11 + --> $DIR/needless_return.rs:187:11 | LL | if b { | ___________^ @@ -270,7 +270,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:188:13 + --> $DIR/needless_return.rs:189:13 | LL | } else { | _____________^ @@ -280,7 +280,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:196:14 + --> $DIR/needless_return.rs:197:14 | LL | _ => return, | ^^^^^^ @@ -288,7 +288,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:209:9 + --> $DIR/needless_return.rs:210:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -296,7 +296,7 @@ LL | return String::from("test"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:211:9 + --> $DIR/needless_return.rs:212:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -304,7 +304,7 @@ LL | return String::new(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:227:5 + --> $DIR/needless_return.rs:228:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +312,7 @@ LL | return format!("Hello {}", "world!"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:238:9 + --> $DIR/needless_return.rs:239:9 | LL | return true; | ^^^^^^^^^^^ @@ -320,7 +320,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:240:9 + --> $DIR/needless_return.rs:241:9 | LL | return false; | ^^^^^^^^^^^^ @@ -328,7 +328,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:247:13 + --> $DIR/needless_return.rs:248:13 | LL | return 10; | ^^^^^^^^^ @@ -336,7 +336,7 @@ LL | return 10; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:250:13 + --> $DIR/needless_return.rs:251:13 | LL | return 100; | ^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | return 100; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:258:9 + --> $DIR/needless_return.rs:259:9 | LL | return 0; | ^^^^^^^^ @@ -352,7 +352,7 @@ LL | return 0; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:265:13 + --> $DIR/needless_return.rs:266:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -360,7 +360,7 @@ LL | return *(x as *const isize); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:267:13 + --> $DIR/needless_return.rs:268:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL | return !*(x as *const isize); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:274:20 + --> $DIR/needless_return.rs:275:20 | LL | let _ = 42; | ____________________^ @@ -379,7 +379,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:281:20 + --> $DIR/needless_return.rs:282:20 | LL | let _ = 42; return; | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs new file mode 100644 index 00000000000..28c00d10094 --- /dev/null +++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs @@ -0,0 +1,29 @@ +#![allow(unused)] +#![warn(clippy::permissions_set_readonly_false)] + +use std::fs::File; + +struct A; + +impl A { + pub fn set_readonly(&mut self, b: bool) {} +} + +fn set_readonly(b: bool) {} + +fn main() { + let f = File::create("foo.txt").unwrap(); + let metadata = f.metadata().unwrap(); + let mut permissions = metadata.permissions(); + // lint here + permissions.set_readonly(false); + // no lint + permissions.set_readonly(true); + + let mut a = A; + // no lint here - a is not of type std::fs::Permissions + a.set_readonly(false); + + // no lint here - plain function + set_readonly(false); +} diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr new file mode 100644 index 00000000000..e7a8ee6cb19 --- /dev/null +++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr @@ -0,0 +1,13 @@ +error: call to `set_readonly` with argument `false` + --> $DIR/permissions_set_readonly_false.rs:19:5 + | +LL | permissions.set_readonly(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: on Unix platforms this results in the file being world writable + = help: you can set the desired permissions using `PermissionsExt`. For more information, see + https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html + = note: `-D clippy::permissions-set-readonly-false` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 00b42745093..a157b6a6f9a 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -239,3 +239,9 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +#[allow(unused, clippy::manual_retain)] +fn possible_borrower_improvements() { + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').collect(); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index f899127db8d..430672e8b8d 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -239,3 +239,9 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +#[allow(unused, clippy::manual_retain)] +fn possible_borrower_improvements() { + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').to_owned().collect(); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index 782590034d0..1bacc2c76af 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -179,5 +179,17 @@ note: this value is dropped without further use LL | foo(&x.clone(), move || { | ^ -error: aborting due to 15 previous errors +error: redundant clone + --> $DIR/redundant_clone.rs:246:40 + | +LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + | ^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:246:9 + | +LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr index 2e1eb8eb180..d0e534f6356 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr @@ -19,10 +19,7 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_unfixable.rs:29:5 | -LL | x.field.map(|value| { - | ______^ - | | _____| - | || +LL | // x.field.map(|value| { LL | || do_nothing(value); LL | || do_nothing(value) LL | || }); diff --git a/src/tools/clippy/tests/ui/size_of_ref.rs b/src/tools/clippy/tests/ui/size_of_ref.rs new file mode 100644 index 00000000000..1e83ab82907 --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_ref.rs @@ -0,0 +1,27 @@ +#![allow(unused)] +#![warn(clippy::size_of_ref)] + +use std::mem::size_of_val; + +fn main() { + let x = 5; + let y = &x; + + size_of_val(&x); // no lint + size_of_val(y); // no lint + + size_of_val(&&x); + size_of_val(&y); +} + +struct S { + field: u32, + data: Vec<u8>, +} + +impl S { + /// Get size of object including `self`, in bytes. + pub fn size(&self) -> usize { + std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) + } +} diff --git a/src/tools/clippy/tests/ui/size_of_ref.stderr b/src/tools/clippy/tests/ui/size_of_ref.stderr new file mode 100644 index 00000000000..d4c13ac3290 --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_ref.stderr @@ -0,0 +1,27 @@ +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:13:5 + | +LL | size_of_val(&&x); + | ^^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = note: `-D clippy::size-of-ref` implied by `-D warnings` + +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:14:5 + | +LL | size_of_val(&y); + | ^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:25:9 + | +LL | std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs new file mode 100644 index 00000000000..b3ea3d9039e --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] +#![warn(clippy::transmute_null_to_fn)] +#![allow(clippy::zero_ptr)] + +// Easy to lint because these only span one line. +fn one_liners() { + unsafe { + let _: fn() = std::mem::transmute(0 as *const ()); + let _: fn() = std::mem::transmute(std::ptr::null::<()>()); + } +} + +pub const ZPTR: *const usize = 0 as *const _; +pub const NOT_ZPTR: *const usize = 1 as *const _; + +fn transmute_const() { + unsafe { + // Should raise a lint. + let _: fn() = std::mem::transmute(ZPTR); + // Should NOT raise a lint. + let _: fn() = std::mem::transmute(NOT_ZPTR); + } +} + +fn main() { + one_liners(); + transmute_const(); +} diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr new file mode 100644 index 00000000000..f0c65497d75 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr @@ -0,0 +1,27 @@ +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:8:23 + | +LL | let _: fn() = std::mem::transmute(0 as *const ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + = note: `-D clippy::transmute-null-to-fn` implied by `-D warnings` + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:9:23 + | +LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:19:23 + | +LL | let _: fn() = std::mem::transmute(ZPTR); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed index 70ff08f3655..94b206d8e58 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.fixed +++ b/src/tools/clippy/tests/ui/useless_conversion.fixed @@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } -fn test_issue_5833() -> Result<(), ()> { +fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let lines = text.lines(); if Some("ok") == lines.into_iter().next() {} +} - Ok(()) +fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator_2() { + let text = "foo\r\nbar\n\nbaz\n"; + if Some("ok") == text.lines().next() {} +} + +#[allow(const_item_mutation)] +fn lint_into_iter_on_const_implementing_iterator() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let _ = NUMBERS.next(); +} + +fn lint_into_iter_on_const_implementing_iterator_2() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let mut n = NUMBERS; + n.next(); +} + +#[derive(Clone, Copy)] +struct CopiableCounter { + counter: u32, +} + +impl Iterator for CopiableCounter { + type Item = u32; + + fn next(&mut self) -> Option<Self::Item> { + self.counter = self.counter.wrapping_add(1); + Some(self.counter) + } +} + +fn dont_lint_into_iter_on_copy_iter() { + let mut c = CopiableCounter { counter: 0 }; + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.next(), Some(1)); + assert_eq!(c.next(), Some(2)); +} + +fn dont_lint_into_iter_on_static_copy_iter() { + static mut C: CopiableCounter = CopiableCounter { counter: 0 }; + unsafe { + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.next(), Some(1)); + assert_eq!(C.next(), Some(2)); + } } fn main() { @@ -46,7 +105,15 @@ fn main() { test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); - test_issue_5833().unwrap(); + + dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_expr_implementing_iterator(); + lint_into_iter_on_expr_implementing_iterator_2(); + lint_into_iter_on_const_implementing_iterator(); + lint_into_iter_on_const_implementing_iterator_2(); + dont_lint_into_iter_on_copy_iter(); + dont_lint_into_iter_on_static_copy_iter(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs index f2444a8f436..c7ae927941b 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.rs +++ b/src/tools/clippy/tests/ui/useless_conversion.rs @@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } -fn test_issue_5833() -> Result<(), ()> { +fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let lines = text.lines(); if Some("ok") == lines.into_iter().next() {} +} - Ok(()) +fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.into_iter().next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines().into_iter(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator_2() { + let text = "foo\r\nbar\n\nbaz\n"; + if Some("ok") == text.lines().into_iter().next() {} +} + +#[allow(const_item_mutation)] +fn lint_into_iter_on_const_implementing_iterator() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let _ = NUMBERS.into_iter().next(); +} + +fn lint_into_iter_on_const_implementing_iterator_2() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let mut n = NUMBERS.into_iter(); + n.next(); +} + +#[derive(Clone, Copy)] +struct CopiableCounter { + counter: u32, +} + +impl Iterator for CopiableCounter { + type Item = u32; + + fn next(&mut self) -> Option<Self::Item> { + self.counter = self.counter.wrapping_add(1); + Some(self.counter) + } +} + +fn dont_lint_into_iter_on_copy_iter() { + let mut c = CopiableCounter { counter: 0 }; + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.next(), Some(1)); + assert_eq!(c.next(), Some(2)); +} + +fn dont_lint_into_iter_on_static_copy_iter() { + static mut C: CopiableCounter = CopiableCounter { counter: 0 }; + unsafe { + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.next(), Some(1)); + assert_eq!(C.next(), Some(2)); + } } fn main() { @@ -46,7 +105,15 @@ fn main() { test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); - test_issue_5833().unwrap(); + + dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_expr_implementing_iterator(); + lint_into_iter_on_expr_implementing_iterator_2(); + lint_into_iter_on_const_implementing_iterator(); + lint_into_iter_on_const_implementing_iterator_2(); + dont_lint_into_iter_on_copy_iter(); + dont_lint_into_iter_on_static_copy_iter(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index 65ee3807fa9..be067c6843a 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -22,71 +22,101 @@ error: useless conversion to the same type: `i32` LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:45:22 + | +LL | if Some("ok") == lines.into_iter().next() {} + | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines` + +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:50:21 + | +LL | let mut lines = text.lines().into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` + +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:56:22 + | +LL | if Some("ok") == text.lines().into_iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` + +error: useless conversion to the same type: `std::ops::Range<i32>` + --> $DIR/useless_conversion.rs:62:13 + | +LL | let _ = NUMBERS.into_iter().next(); + | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` + +error: useless conversion to the same type: `std::ops::Range<i32>` + --> $DIR/useless_conversion.rs:67:17 + | +LL | let mut n = NUMBERS.into_iter(); + | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` + error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:61:21 + --> $DIR/useless_conversion.rs:128:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:62:21 + --> $DIR/useless_conversion.rs:129:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:63:13 + --> $DIR/useless_conversion.rs:130:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:64:13 + --> $DIR/useless_conversion.rs:131:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> $DIR/useless_conversion.rs:65:13 + --> $DIR/useless_conversion.rs:132:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter<i32>` - --> $DIR/useless_conversion.rs:66:13 + --> $DIR/useless_conversion.rs:133:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:67:21 + --> $DIR/useless_conversion.rs:134:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> $DIR/useless_conversion.rs:72:13 + --> $DIR/useless_conversion.rs:139:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> $DIR/useless_conversion.rs:78:23 + --> $DIR/useless_conversion.rs:145:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> $DIR/useless_conversion.rs:80:13 + --> $DIR/useless_conversion.rs:147:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>` - --> $DIR/useless_conversion.rs:82:13 + --> $DIR/useless_conversion.rs:149:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` -error: aborting due to 14 previous errors +error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index ef55f1c31a8..0baec6f0b64 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -5,7 +5,6 @@ // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint // no longer detects some of the cases starting with Rust 2018. -// FIXME: We should likely add another edition 2021 test case for this lint #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs index b8128514206..db591d56ab4 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports.rs @@ -5,7 +5,6 @@ // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint // no longer detects some of the cases starting with Rust 2018. -// FIXME: We should likely add another edition 2021 test case for this lint #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index 626c1754fc8..6b469cdfc44 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -1,5 +1,5 @@ error: usage of wildcard import - --> $DIR/wildcard_imports.rs:16:5 + --> $DIR/wildcard_imports.rs:15:5 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` @@ -7,85 +7,85 @@ LL | use crate::fn_mod::*; = note: `-D clippy::wildcard-imports` implied by `-D warnings` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:17:5 + --> $DIR/wildcard_imports.rs:16:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:18:5 + --> $DIR/wildcard_imports.rs:17:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:20:5 + --> $DIR/wildcard_imports.rs:19:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:24:5 + --> $DIR/wildcard_imports.rs:23:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:25:5 + --> $DIR/wildcard_imports.rs:24:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:96:13 + --> $DIR/wildcard_imports.rs:95:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:102:75 + --> $DIR/wildcard_imports.rs:101:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:103:13 + --> $DIR/wildcard_imports.rs:102:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:114:20 + --> $DIR/wildcard_imports.rs:113:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:114:30 + --> $DIR/wildcard_imports.rs:113:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:121:13 + --> $DIR/wildcard_imports.rs:120:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:150:9 + --> $DIR/wildcard_imports.rs:149:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:159:9 + --> $DIR/wildcard_imports.rs:158:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:160:9 + --> $DIR/wildcard_imports.rs:159:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:171:13 + --> $DIR/wildcard_imports.rs:170:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:206:17 + --> $DIR/wildcard_imports.rs:205:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:214:13 + --> $DIR/wildcard_imports.rs:213:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:223:17 + --> $DIR/wildcard_imports.rs:222:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:232:13 + --> $DIR/wildcard_imports.rs:231:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:240:13 + --> $DIR/wildcard_imports.rs:239:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed new file mode 100644 index 00000000000..6d534a10edc --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -0,0 +1,240 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::foo; +use crate::mod_mod::inner_mod; +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::struct_mod::{A, inner_struct_mod}; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::{ExternA, extern_foo}; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::foo; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + use wildcard_imports_helper::{ExternA, extern_foo}; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::inner_foo, inner2::inner_bar}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test::exported; + use crate:: fn_mod::foo; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr new file mode 100644 index 00000000000..acca9f651b4 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:13:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:14:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:16:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:19:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:21:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:91:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:97:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:98:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:116:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:145:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:154:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:155:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:166:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:201:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:209:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:218:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:227:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:235:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed new file mode 100644 index 00000000000..6d534a10edc --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -0,0 +1,240 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::foo; +use crate::mod_mod::inner_mod; +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::struct_mod::{A, inner_struct_mod}; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::{ExternA, extern_foo}; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::foo; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + use wildcard_imports_helper::{ExternA, extern_foo}; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::inner_foo, inner2::inner_bar}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test::exported; + use crate:: fn_mod::foo; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr new file mode 100644 index 00000000000..acca9f651b4 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:13:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:14:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:16:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:19:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:21:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:91:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:97:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:98:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:116:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:145:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:154:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:155:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:166:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:201:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:209:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:218:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:227:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:235:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs new file mode 100644 index 00000000000..b5ed58e6813 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs @@ -0,0 +1,241 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::*; +use crate::mod_mod::*; +use crate::multi_fn_mod::*; +use crate::struct_mod::*; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::*; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::*; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::*; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + use wildcard_imports_helper::*; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::*, inner2::*}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::*; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::*; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test:: * ; + use crate:: fn_mod:: + *; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::*; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::*; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::*; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::*; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr new file mode 100644 index 00000000000..92f6d31530f --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:9:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:10:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:11:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:12:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:17:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:87:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:93:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:94:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:105:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:105:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:112:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:141:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:150:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:151:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:162:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:197:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:205:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:214:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:223:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:231:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index e15f5fe3ccc..291d02d67bd 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -5,7 +5,7 @@ use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding, - TypeBindingKind, Typedef, Union, Variant, WherePredicate, + TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, }; use crate::{item_kind::Kind, Error, ErrorKind}; @@ -140,24 +140,24 @@ impl<'a> Validator<'a> { } fn check_variant(&mut self, x: &'a Variant, id: &'a Id) { - match x { - Variant::Plain(discr) => { - if let Some(discr) = discr { - if let (Err(_), Err(_)) = - (discr.value.parse::<i128>(), discr.value.parse::<u128>()) - { - self.fail( - id, - ErrorKind::Custom(format!( - "Failed to parse discriminant value `{}`", - discr.value - )), - ); - } - } + let Variant { kind, discriminant } = x; + + if let Some(discr) = discriminant { + if let (Err(_), Err(_)) = (discr.value.parse::<i128>(), discr.value.parse::<u128>()) { + self.fail( + id, + ErrorKind::Custom(format!( + "Failed to parse discriminant value `{}`", + discr.value + )), + ); } - Variant::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), - Variant::Struct { fields, fields_stripped: _ } => { + } + + match kind { + VariantKind::Plain => {} + VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), + VariantKind::Struct { fields, fields_stripped: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 876d49257ca..d17bb9533b4 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -45,9 +45,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -66,9 +66,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bstr" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" +checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" dependencies = [ "memchr", "once_cell", @@ -96,22 +96,23 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36" +checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", + "thiserror", ] [[package]] name = "cc" -version = "1.0.73" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cfg-if" @@ -169,12 +170,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", - "once_cell", ] [[package]] @@ -185,9 +185,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "env_logger" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -228,9 +228,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "hermit-abi" @@ -264,9 +264,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "lazy_static" @@ -276,9 +276,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.133" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libffi" @@ -301,9 +301,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", @@ -359,9 +359,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] @@ -389,18 +389,18 @@ dependencies = [ [[package]] name = "object" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "owo-colors" @@ -421,9 +421,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if", "instant", @@ -450,24 +450,24 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.45" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -513,9 +513,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -530,9 +530,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "scopeguard" @@ -584,27 +584,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.145" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.145" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -613,9 +613,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -633,15 +633,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.101" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -672,6 +672,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "thread_local" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -682,9 +702,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", @@ -693,9 +713,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -713,9 +733,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" dependencies = [ "sharded-slab", "thread_local", @@ -744,9 +764,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "valuable" diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 3e5d388668b..37926db0166 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.65" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] name = "bitflags" @@ -48,15 +48,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36" +checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", + "thiserror", ] [[package]] @@ -96,9 +97,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -116,30 +117,30 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "libc" -version = "0.2.133" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "proc-macro2" -version = "1.0.45" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -175,9 +176,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c4b4625eeb148cccf82d5e9b90ad7fab3b11a0204cf75cc7fa04981a0fdffd" +checksum = "d65b1271cdac365b71b59570ea35d945dea2dd2cc47eba3d33b4bd1e0190ac6d" dependencies = [ "anyhow", "rustc_version", @@ -207,33 +208,33 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "semver" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.145" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.145" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -242,9 +243,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -253,9 +254,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.101" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -278,18 +279,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -298,9 +299,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "wasi" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index ce8457469e7..2197160bc9d 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -18,7 +18,7 @@ directories = "4" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.15.0" -rustc-build-sysroot = "0.4" +rustc-build-sysroot = "0.4.1" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 2bffff47722..e51bfa3798f 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -236,22 +236,36 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { is_bin || is_test } - fn out_filename(prefix: &str, suffix: &str) -> PathBuf { - if let Some(out_dir) = get_arg_flag_value("--out-dir") { - let mut path = PathBuf::from(out_dir); - path.push(format!( - "{}{}{}{}", - prefix, - get_arg_flag_value("--crate-name").unwrap(), - // This is technically a `-C` flag but the prefix seems unique enough... - // (and cargo passes this before the filename so it should be unique) - get_arg_flag_value("extra-filename").unwrap_or_default(), - suffix, - )); - path + fn out_filenames() -> Vec<PathBuf> { + if let Some(out_file) = get_arg_flag_value("-o") { + // `-o` has precedence over `--out-dir`. + vec![PathBuf::from(out_file)] } else { - let out_file = get_arg_flag_value("-o").unwrap(); - PathBuf::from(out_file) + let out_dir = get_arg_flag_value("--out-dir").unwrap_or_default(); + let path = PathBuf::from(out_dir); + // Ask rustc for the filename (since that is target-dependent). + let mut rustc = miri_for_host(); // sysroot doesn't matter for this so we just use the host + rustc.arg("--print").arg("file-names"); + for flag in ["--crate-name", "--crate-type", "--target"] { + for val in get_arg_flag_values(flag) { + rustc.arg(flag).arg(val); + } + } + // This is technically passed as `-C extra-filename=...`, but the prefix seems unique + // enough... (and cargo passes this before the filename so it should be unique) + if let Some(extra) = get_arg_flag_value("extra-filename") { + rustc.arg("-C").arg(format!("extra-filename={extra}")); + } + rustc.arg("-"); + + let output = rustc.output().expect("cannot run rustc to determine file name"); + assert!( + output.status.success(), + "rustc failed when determining file name:\n{output:?}" + ); + let output = + String::from_utf8(output.stdout).expect("rustc returned non-UTF-8 filename"); + output.lines().filter(|l| !l.is_empty()).map(|l| path.join(l)).collect() } } @@ -267,24 +281,28 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV"); let store_json = |info: CrateRunInfo| { - // Create a stub .d file to stop Cargo from "rebuilding" the crate: - // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693 - // As we store a JSON file instead of building the crate here, an empty file is fine. - let dep_info_name = out_filename("", ".d"); - if verbose > 0 { - eprintln!("[cargo-miri rustc] writing stub dep-info to `{}`", dep_info_name.display()); + if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") { + // Create a stub .d file to stop Cargo from "rebuilding" the crate: + // https://github.com/rust-lang/miri/issues/1724#issuecomment-787115693 + // As we store a JSON file instead of building the crate here, an empty file is fine. + let dep_info_name = format!( + "{}/{}{}.d", + get_arg_flag_value("--out-dir").unwrap(), + get_arg_flag_value("--crate-name").unwrap(), + get_arg_flag_value("extra-filename").unwrap_or_default(), + ); + if verbose > 0 { + eprintln!("[cargo-miri rustc] writing stub dep-info to `{dep_info_name}`"); + } + File::create(dep_info_name).expect("failed to create fake .d file"); } - File::create(dep_info_name).expect("failed to create fake .d file"); - let filename = out_filename("", ""); - if verbose > 0 { - eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display()); + for filename in out_filenames() { + if verbose > 0 { + eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display()); + } + info.store(&filename); } - info.store(&filename); - // For Windows and WASM, do the same thing again with `.exe`/`.wasm` appended to the filename. - // (Need to do this here as cargo moves that "binary" to a different place before running it.) - info.store(&out_filename("", ".exe")); - info.store(&out_filename("", ".wasm")); }; let runnable_crate = !info_query && is_runnable_crate(); @@ -323,11 +341,14 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { // Alter the `-o` parameter so that it does not overwrite the JSON file we stored above. let mut args = env.args; + let mut out_filename = None; for i in 0..args.len() { if args[i] == "-o" { + out_filename = Some(args[i + 1].clone()); args[i + 1].push_str(".miri"); } } + let out_filename = out_filename.expect("rustdoc must pass `-o`"); cmd.args(&args); cmd.env("MIRI_BE_RUSTC", "target"); @@ -340,7 +361,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { eprintln!("[cargo-miri rustc inside rustdoc] going to run:\n{cmd:?}"); } - exec_with_pipe(cmd, &env.stdin, format!("{}.stdin", out_filename("", "").display())); + exec_with_pipe(cmd, &env.stdin, format!("{out_filename}.stdin")); } return; @@ -422,15 +443,12 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { // Create a stub .rlib file if "link" was requested by cargo. // This is necessary to prevent cargo from doing rebuilds all the time. if emit_link_hack { - // Some platforms prepend "lib", some do not... let's just create both files. - File::create(out_filename("lib", ".rlib")).expect("failed to create fake .rlib file"); - File::create(out_filename("", ".rlib")).expect("failed to create fake .rlib file"); - // Just in case this is a cdylib or staticlib, also create those fake files. - File::create(out_filename("lib", ".so")).expect("failed to create fake .so file"); - File::create(out_filename("lib", ".a")).expect("failed to create fake .a file"); - File::create(out_filename("lib", ".dylib")).expect("failed to create fake .dylib file"); - File::create(out_filename("", ".dll")).expect("failed to create fake .dll file"); - File::create(out_filename("", ".lib")).expect("failed to create fake .lib file"); + for filename in out_filenames() { + if verbose > 0 { + eprintln!("[cargo-miri rustc] creating fake lib file at `{}`", filename.display()); + } + File::create(filename).expect("failed to create fake lib file"); + } } debug_cmd("[cargo-miri rustc]", verbose, &cmd); diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index a696546954f..2e4f0a71013 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -137,9 +137,11 @@ pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta .rustflags(rustflags) .cargo(cargo_cmd) .build_from_source(&rust_src) - .unwrap_or_else(|_| { - if only_setup { - show_error!("failed to build sysroot, see error details above") + .unwrap_or_else(|err| { + if print_sysroot { + show_error!("failed to build sysroot") + } else if only_setup { + show_error!("failed to build sysroot: {err:?}") } else { show_error!( "failed to build sysroot; run `cargo miri setup` to see the error details" diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index e455b482338..b35f7370d68 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -108,8 +108,9 @@ case $HOST_TARGET in MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic - MIRI_TEST_TARGET=wasm32-wasi MIRI_NO_STD=1 run_tests_minimal no_std # supports std but miri doesn't support it + MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture + MIRI_TEST_TARGET=tests/avr.json MIRI_NO_STD=1 run_tests_minimal no_std # JSON target file ;; x86_64-apple-darwin) MIRI_TEST_TARGET=mips64-unknown-linux-gnuabi64 run_tests # big-endian architecture diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 4321bdf9aae..c792a27ab4c 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -47,7 +47,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let min_align = match this.tcx.sess.target.arch.as_ref() { "x86" | "arm" | "mips" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8, "x86_64" | "aarch64" | "mips64" | "s390x" | "sparc64" => 16, - arch => bug!("Unsupported target architecture: {}", arch), + arch => bug!("unsupported target architecture for malloc: `{}`", arch), }; // Windows always aligns, even small allocations. // Source: <https://support.microsoft.com/en-us/help/286470/how-to-use-pageheap-exe-in-windows-xp-windows-2000-and-windows-server> @@ -320,7 +320,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(Some(body)); } - this.handle_unsupported(format!("can't call foreign function: {link_name}"))?; + this.handle_unsupported(format!( + "can't call foreign function `{link_name}` on OS `{os}`", + os = this.tcx.sess.target.os, + ))?; return Ok(None); } } @@ -336,9 +339,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> { let this = self.eval_context_mut(); - let allocator_kind = if let Some(allocator_kind) = this.tcx.allocator_kind(()) { - allocator_kind - } else { + let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator return Ok(EmulateByNameResult::NotSupported); }; @@ -420,9 +421,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| { - err_machine_stop!(TerminationInfo::Abort( - format!("pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}") - )) + err_machine_stop!(TerminationInfo::Abort(format!( + "pointer passed to miri_get_alloc_id must not be dangling, got {ptr:?}" + ))) })?; this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; } @@ -438,7 +439,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr = this.read_pointer(ptr)?; let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?; if offset != Size::ZERO { - throw_unsup_format!("pointer passed to miri_static_root must point to beginning of an allocated block"); + throw_unsup_format!( + "pointer passed to miri_static_root must point to beginning of an allocated block" + ); } this.machine.static_roots.push(alloc_id); } @@ -453,7 +456,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We read this as a plain OsStr and write it as a path, which will convert it to the target. let path = this.read_os_str_from_c_str(ptr)?.to_owned(); - let (success, needed_size) = this.write_path_to_c_str(Path::new(&path), out, out_size)?; + let (success, needed_size) = + this.write_path_to_c_str(Path::new(&path), out, out_size)?; // Return value: 0 on success, otherwise the size it would have needed. this.write_int(if success { 0 } else { needed_size }, dest)?; } @@ -505,11 +509,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_pointer(res, dest)?; } "calloc" => { - let [items, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let [items, len] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let items = this.read_machine_usize(items)?; let len = this.read_machine_usize(len)?; - let size = - items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?; + let size = items + .checked_mul(len) + .ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?; let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?; this.write_pointer(res, dest)?; } @@ -519,7 +525,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.free(ptr, MiriMemoryKind::C)?; } "realloc" => { - let [old_ptr, new_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let [old_ptr, new_size] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_ptr = this.read_pointer(old_ptr)?; let new_size = this.read_machine_usize(new_size)?; let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?; @@ -551,11 +558,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; match link_name.as_str() { - "__rust_alloc" => return this.emulate_allocator(Symbol::intern("__rg_alloc"), default), + "__rust_alloc" => + return this.emulate_allocator(Symbol::intern("__rg_alloc"), default), "miri_alloc" => { default(this)?; return Ok(EmulateByNameResult::NeedsJumping); - }, + } _ => unreachable!(), } } @@ -574,7 +582,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { )?; // We just allocated this, the access is definitely in-bounds. - this.write_bytes_ptr(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap(); + this.write_bytes_ptr( + ptr.into(), + iter::repeat(0u8).take(usize::try_from(size).unwrap()), + ) + .unwrap(); this.write_pointer(ptr, dest) }); } @@ -600,7 +612,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; match link_name.as_str() { - "__rust_dealloc" => return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default), + "__rust_dealloc" => + return this.emulate_allocator(Symbol::intern("__rg_dealloc"), default), "miri_dealloc" => { default(this)?; return Ok(EmulateByNameResult::NeedsJumping); @@ -609,7 +622,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } "__rust_realloc" => { - let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?; + let [ptr, old_size, align, new_size] = + this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let old_size = this.read_machine_usize(old_size)?; let align = this.read_machine_usize(align)?; @@ -633,7 +647,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // C memory handling functions "memcmp" => { - let [left, right, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let [left, right, n] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let left = this.read_pointer(left)?; let right = this.read_pointer(right)?; let n = Size::from_bytes(this.read_machine_usize(n)?); @@ -653,7 +668,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(Scalar::from_i32(result), dest)?; } "memrchr" => { - let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let [ptr, val, num] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_machine_usize(num)?; @@ -676,7 +692,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } "memchr" => { - let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let [ptr, val, num] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_machine_usize(num)?; @@ -699,7 +716,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ptr = this.read_pointer(ptr)?; let n = this.read_c_str(ptr)?.len(); - this.write_scalar(Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), dest)?; + this.write_scalar( + Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), + dest, + )?; } // math functions (note that there are also intrinsics for some other functions) @@ -835,7 +855,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let a = this.read_scalar(a)?.to_u64()?; let b = this.read_scalar(b)?.to_u64()?; - #[allow(clippy::integer_arithmetic)] // adding two u64 and a u8 cannot wrap in a u128 + #[allow(clippy::integer_arithmetic)] + // adding two u64 and a u8 cannot wrap in a u128 let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b); #[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64 let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>()); @@ -845,7 +866,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let sum_field = this.place_field(dest, 1)?; this.write_scalar(Scalar::from_u64(sum), &sum_field)?; } - "llvm.x86.sse2.pause" if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => { + "llvm.x86.sse2.pause" + if this.tcx.sess.target.arch == "x86" || this.tcx.sess.target.arch == "x86_64" => + { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.yield_active_thread(); } @@ -853,7 +876,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; match arg { - 15 => { // SY ("full system scope") + // SY ("full system scope") + 15 => { this.yield_active_thread(); } _ => { @@ -863,11 +887,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } // Platform-specific shims - _ => match this.tcx.sess.target.os.as_ref() { - target if target_os_is_unix(target) => return shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "windows" => return shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - target => throw_unsup_format!("the target `{}` is not supported", target), - } + _ => + return match this.tcx.sess.target.os.as_ref() { + target_os if target_os_is_unix(target_os) => + shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + this, link_name, abi, args, dest, + ), + "windows" => + shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_by_name( + this, link_name, abi, args, dest, + ), + _ => Ok(EmulateByNameResult::NotSupported), + }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs index 7768772338a..ca31efa486c 100644 --- a/src/tools/miri/src/shims/tls.rs +++ b/src/tools/miri/src/shims/tls.rs @@ -257,16 +257,11 @@ impl TlsDtorsState { // And move to the final state. self.0 = Done; } - "wasi" | "none" => { - // No OS, no TLS dtors. + _ => { + // No TLS dtor support. // FIXME: should we do something on wasi? self.0 = Done; } - os => { - throw_unsup_format!( - "the TLS machinery does not know how to handle OS `{os}`" - ); - } } } PthreadDtors(state) => { diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 7f43afb7820..d018a7ea252 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -596,13 +596,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Platform-specific shims _ => { let target_os = &*this.tcx.sess.target.os; - match target_os { - "android" => return shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "freebsd" => return shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "linux" => return shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - "macos" => return shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), - _ => panic!("unsupported Unix OS {target_os}"), - } + return match target_os { + "android" => shims::unix::android::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + "freebsd" => shims::unix::freebsd::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + "linux" => shims::unix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + "macos" => shims::unix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest), + _ => Ok(EmulateByNameResult::NotSupported), + }; } }; diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock index 2c53c482bf9..af38ceb1d4c 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.lock +++ b/src/tools/miri/test-cargo-miri/Cargo.lock @@ -83,27 +83,27 @@ version = "0.1.0" [[package]] name = "proc-macro2" -version = "1.0.44" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "serde_derive" -version = "1.0.145" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.101" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -130,6 +130,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index c728e7c0778..bf7f0411bed 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -50,18 +50,18 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "lock_api" @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ "hermit-abi", "libc", @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", @@ -170,18 +170,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -269,9 +269,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" dependencies = [ "autocfg", "bytes", @@ -284,14 +284,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", @@ -300,9 +300,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "wasi" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 3a80e8c9644..1df35bbbe2f 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -9,13 +9,15 @@ edition = "2021" [dependencies] # all dependencies (and their transitive ones) listed here can be used in `tests/`. -tokio = { version = "1.0", features = ["full"] } libc = "0.2" -page_size = "0.5" num_cpus = "1.10.1" getrandom_1 = { package = "getrandom", version = "0.1" } getrandom = { version = "0.2" } rand = { version = "0.8", features = ["small_rng"] } +[target.'cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))'.dependencies] +page_size = "0.5" +tokio = { version = "1.0", features = ["full"] } + [workspace] diff --git a/src/tools/miri/tests/avr.json b/src/tools/miri/tests/avr.json new file mode 100644 index 00000000000..1e00b0f57ef --- /dev/null +++ b/src/tools/miri/tests/avr.json @@ -0,0 +1,25 @@ +{ + "arch": "avr", + "cpu": "atmega328p", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "env": "", + "executables": true, + "linker": "avr-gcc", + "linker-flavor": "gcc", + "linker-is-gnu": true, + "llvm-target": "avr-unknown-unknown", + "os": "unknown", + "position-independent-executables": false, + "exe-suffix": ".elf", + "eh-frame-header": false, + "pre-link-args": { + "gcc": ["-mmcu=atmega328p"] + }, + "late-link-args": { + "gcc": ["-lgcc"] + }, + "target-c-int-width": "16", + "target-endian": "little", + "target-pointer-width": "16", + "vendor": "unknown" +} diff --git a/src/tools/miri/tests/extern-so/fail/function_not_in_so.rs b/src/tools/miri/tests/extern-so/fail/function_not_in_so.rs index 3aaeb632cad..3540c75b73a 100644 --- a/src/tools/miri/tests/extern-so/fail/function_not_in_so.rs +++ b/src/tools/miri/tests/extern-so/fail/function_not_in_so.rs @@ -1,5 +1,6 @@ //@only-target-linux //@only-on-host +//@normalize-stderr-test: "OS `.*`" -> "$$OS" extern "C" { fn foo(); @@ -7,6 +8,6 @@ extern "C" { fn main() { unsafe { - foo(); //~ ERROR: unsupported operation: can't call foreign function: foo + foo(); //~ ERROR: unsupported operation: can't call foreign function `foo` } } diff --git a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr index f649f0ae43e..e9bc3220471 100644 --- a/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr +++ b/src/tools/miri/tests/extern-so/fail/function_not_in_so.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: can't call foreign function: foo +error: unsupported operation: can't call foreign function `foo` on $OS --> $DIR/function_not_in_so.rs:LL:CC | LL | foo(); - | ^^^^^ can't call foreign function: foo + | ^^^^^ can't call foreign function `foo` on $OS | = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.rs b/src/tools/miri/tests/fail/alloc/no_global_allocator.rs index fb0e7986bb5..624ad1bda58 100644 --- a/src/tools/miri/tests/fail/alloc/no_global_allocator.rs +++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.rs @@ -1,3 +1,4 @@ +//@normalize-stderr-test: "OS `.*`" -> "$$OS" // Make sure we pretend the allocation symbols don't exist when there is no allocator #![feature(lang_items, start)] @@ -10,7 +11,7 @@ extern "Rust" { #[start] fn start(_: isize, _: *const *const u8) -> isize { unsafe { - __rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function: __rust_alloc + __rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function `__rust_alloc` } 0 diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr index ea70970ae0f..fe6a22fadc9 100644 --- a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr +++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: can't call foreign function: __rust_alloc +error: unsupported operation: can't call foreign function `__rust_alloc` on $OS --> $DIR/no_global_allocator.rs:LL:CC | LL | __rust_alloc(1, 1); - | ^^^^^^^^^^^^^^^^^^ can't call foreign function: __rust_alloc + | ^^^^^^^^^^^^^^^^^^ can't call foreign function `__rust_alloc` on $OS | = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/unsupported_foreign_function.rs b/src/tools/miri/tests/fail/unsupported_foreign_function.rs index dfd099e734b..44f032fbabe 100644 --- a/src/tools/miri/tests/fail/unsupported_foreign_function.rs +++ b/src/tools/miri/tests/fail/unsupported_foreign_function.rs @@ -1,9 +1,11 @@ +//@normalize-stderr-test: "OS `.*`" -> "$$OS" + fn main() { extern "Rust" { fn foo(); } unsafe { - foo(); //~ ERROR: unsupported operation: can't call foreign function: foo + foo(); //~ ERROR: unsupported operation: can't call foreign function `foo` } } diff --git a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr index fde5fb78ac0..519f6d182d7 100644 --- a/src/tools/miri/tests/fail/unsupported_foreign_function.stderr +++ b/src/tools/miri/tests/fail/unsupported_foreign_function.stderr @@ -1,8 +1,8 @@ -error: unsupported operation: can't call foreign function: foo +error: unsupported operation: can't call foreign function `foo` on $OS --> $DIR/unsupported_foreign_function.rs:LL:CC | LL | foo(); - | ^^^^^ can't call foreign function: foo + | ^^^^^ can't call foreign function `foo` on $OS | = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/fail/unsupported_signal.rs b/src/tools/miri/tests/fail/unsupported_incomplete_function.rs index d50041ffbd9..6ef842c9ccb 100644 --- a/src/tools/miri/tests/fail/unsupported_signal.rs +++ b/src/tools/miri/tests/fail/unsupported_incomplete_function.rs @@ -1,10 +1,11 @@ //! `signal()` is special on Linux and macOS that it's only supported within libstd. //! The implementation is not complete enough to permit user code to call it. //@ignore-target-windows: No libc on Windows +//@normalize-stderr-test: "OS `.*`" -> "$$OS" fn main() { unsafe { libc::signal(libc::SIGPIPE, libc::SIG_IGN); - //~^ ERROR: unsupported operation: can't call foreign function: signal + //~^ ERROR: unsupported operation: can't call foreign function `signal` } } diff --git a/src/tools/miri/tests/fail/unsupported_signal.stderr b/src/tools/miri/tests/fail/unsupported_incomplete_function.stderr index d22ecbc11ff..ec2bba61172 100644 --- a/src/tools/miri/tests/fail/unsupported_signal.stderr +++ b/src/tools/miri/tests/fail/unsupported_incomplete_function.stderr @@ -1,12 +1,12 @@ -error: unsupported operation: can't call foreign function: signal - --> $DIR/unsupported_signal.rs:LL:CC +error: unsupported operation: can't call foreign function `signal` on $OS + --> $DIR/unsupported_incomplete_function.rs:LL:CC | LL | libc::signal(libc::SIGPIPE, libc::SIG_IGN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function: signal + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function `signal` on $OS | = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support = note: BACKTRACE: - = note: inside `main` at $DIR/unsupported_signal.rs:LL:CC + = note: inside `main` at $DIR/unsupported_incomplete_function.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.rs b/src/tools/miri/tests/panic/unsupported_foreign_function.rs index a78646528fb..b8301c50772 100644 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.rs +++ b/src/tools/miri/tests/panic/unsupported_foreign_function.rs @@ -1,4 +1,5 @@ //@compile-flags: -Zmiri-panic-on-unsupported +//@normalize-stderr-test: "OS `.*`" -> "$$OS" fn main() { extern "Rust" { diff --git a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr index 9af3e48655f..a49dbdae58a 100644 --- a/src/tools/miri/tests/panic/unsupported_foreign_function.stderr +++ b/src/tools/miri/tests/panic/unsupported_foreign_function.stderr @@ -1,2 +1,2 @@ -thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function: foo', $DIR/unsupported_foreign_function.rs:LL:CC +thread 'main' panicked at 'unsupported Miri functionality: can't call foreign function `foo` on $OS', $DIR/unsupported_foreign_function.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/tools/rust-installer b/src/tools/rust-installer -Subproject 300b5ec61ef38855a07e6bb4955a37aa1c414c0 +Subproject 5b2eee7eed72b4894909c5eecbf014ea0b5ad99 diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index d5177a2057b..c1991e8d2c8 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -688,7 +688,7 @@ impl Rewrite for ast::Ty { rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } - ast::TyKind::Rptr(ref lifetime, ref mt) => { + ast::TyKind::Ref(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); @@ -1059,7 +1059,7 @@ pub(crate) fn can_be_overflowed_type( ) -> bool { match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + ast::TyKind::Ref(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { can_be_overflowed_type(context, &*mutty.ty, len) } _ => false, diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 97d038da702..fff83a1d097 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -11,6 +11,7 @@ miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" walkdir = "2" ignore = "0.4.18" +termcolor = "1.1.3" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 49fc2ceb3a2..3f060e437ac 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -11,8 +11,8 @@ use regex::Regex; // A few of those error codes can't be tested but all the others can and *should* be tested! const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0519", "E0523", "E0554", "E0640", - "E0717", "E0729", "E0789", + "E0313", "E0461", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", + "E0789", ]; // Some error codes don't have any tests apparently... @@ -80,15 +80,6 @@ fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { ignore_found } -macro_rules! some_or_continue { - ($e:expr) => { - match $e { - Some(e) => e, - None => continue, - } - }; -} - fn extract_error_codes( f: &str, error_codes: &mut HashMap<String, ErrorCodeStatus>, @@ -122,10 +113,16 @@ fn extract_error_codes( Some((file_name, _)) => file_name, }, }; - let path = some_or_continue!(path.parent()) + + let Some(parent) = path.parent() else { + continue; + }; + + let path = parent .join(md_file_name) .canonicalize() .expect("failed to canonicalize error explanation file path"); + match read_to_string(&path) { Ok(content) => { let has_test = check_if_error_code_is_test_in_explanation(&content, &err_code); @@ -215,8 +212,6 @@ pub fn check(paths: &[&Path], bad: &mut bool) { // * #[error = "E0111"] let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); - println!("Checking which error codes lack tests..."); - for path in paths { walk(path, &mut filter_dirs, &mut |entry, contents| { let file_name = entry.file_name(); @@ -245,20 +240,15 @@ pub fn check(paths: &[&Path], bad: &mut bool) { }); } if found_explanations == 0 { - eprintln!("No error code explanation was tested!"); - *bad = true; + tidy_error!(bad, "No error code explanation was tested!"); } if found_tests == 0 { - eprintln!("No error code was found in compilation errors!"); - *bad = true; + tidy_error!(bad, "No error code was found in compilation errors!"); } if explanations.is_empty() { - eprintln!("No error code explanation was found!"); - *bad = true; + tidy_error!(bad, "No error code explanation was found!"); } if errors.is_empty() { - println!("Found {} error codes", error_codes.len()); - for (err_code, error_status) in &error_codes { if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { errors.push(format!("Error code {err_code} needs to have at least one UI test!")); @@ -310,11 +300,6 @@ pub fn check(paths: &[&Path], bad: &mut bool) { } errors.sort(); for err in &errors { - eprintln!("{err}"); - } - println!("Found {} error(s) in error codes", errors.len()); - if !errors.is_empty() { - *bad = true; + tidy_error!(bad, "{err}"); } - println!("Done!"); } diff --git a/src/tools/tidy/src/features/version/tests.rs b/src/tools/tidy/src/features/version/tests.rs index 31224fdf1ea..7701dce2df1 100644 --- a/src/tools/tidy/src/features/version/tests.rs +++ b/src/tools/tidy/src/features/version/tests.rs @@ -12,8 +12,8 @@ fn test_try_from_invalid_version() { #[test] fn test_try_from_single() { - assert_eq!("1.32.0".parse(), Ok(Version { parts: [1, 32, 0] })); - assert_eq!("1.0.0".parse(), Ok(Version { parts: [1, 0, 0] })); + assert_eq!("1.32.0".parse(), Ok(Version::Explicit { parts: [1, 32, 0] })); + assert_eq!("1.0.0".parse(), Ok(Version::Explicit { parts: [1, 0, 0] })); } #[test] diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 698e4850bea..ce7e7ac5cd4 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,6 +3,10 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. +use std::fmt::Display; + +use termcolor::WriteColor; + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The expression that failed @@ -26,18 +30,27 @@ macro_rules! t { } macro_rules! tidy_error { - ($bad:expr, $fmt:expr) => ({ - *$bad = true; - eprint!("tidy error: "); - eprintln!($fmt); - }); - ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ - *$bad = true; - eprint!("tidy error: "); - eprintln!($fmt, $($arg)*); + ($bad:expr, $($fmt:tt)*) => ({ + $crate::tidy_error($bad, format_args!($($fmt)*)).expect("failed to output error"); }); } +fn tidy_error(bad: &mut bool, args: impl Display) -> std::io::Result<()> { + use std::io::Write; + use termcolor::{Color, ColorChoice, ColorSpec, StandardStream}; + + *bad = true; + + let mut stderr = StandardStream::stdout(ColorChoice::Auto); + stderr.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + + write!(&mut stderr, "tidy error")?; + stderr.set_color(&ColorSpec::new())?; + + writeln!(&mut stderr, ": {args}")?; + Ok(()) +} + pub mod alphabetical; pub mod bins; pub mod debug_artifacts; diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index f746bdeffd7..070e72437be 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 939; -const ISSUES_ENTRY_LIMIT: usize = 2020; +const ISSUES_ENTRY_LIMIT: usize = 2050; fn check_entries(path: &Path, bad: &mut bool) { for dir in Walk::new(&path.join("test/ui")) { diff --git a/triagebot.toml b/triagebot.toml index 22f09396efc..0da9fcddad8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -496,7 +496,6 @@ infra-ci = [ rustdoc = [ "@jsha", "@GuillaumeGomez", - "@CraftSpider", "@notriddle", ] docs = [ diff --git a/x.ps1 b/x.ps1 index 81b98919f43..f324a4676c8 100755 --- a/x.ps1 +++ b/x.ps1 @@ -14,6 +14,12 @@ function Get-Application($app) { return Get-Command $app -ErrorAction SilentlyContinue -CommandType Application } +function Invoke-Application($application, $arguments) { + $process = Start-Process -NoNewWindow -PassThru $application $arguments + $process.WaitForExit() + Exit $process.ExitCode +} + foreach ($python in "py", "python3", "python", "python2") { # NOTE: this only tests that the command exists in PATH, not that it's actually # executable. The latter is not possible in a portable way, see @@ -23,16 +29,14 @@ foreach ($python in "py", "python3", "python", "python2") { # Use python3, not python2 $xpy_args = @("-3") + $xpy_args } - $process = Start-Process -NoNewWindow -Wait -PassThru $python $xpy_args - Exit $process.ExitCode + Invoke-Application $python $xpy_args } } $found = (Get-Application "python*" | Where-Object {$_.name -match '^python[2-3]\.[0-9]+(\.exe)?$'}) if (($null -ne $found) -and ($found.Length -ge 1)) { $python = $found[0] - $process = Start-Process -NoNewWindow -Wait -PassThru $python $xpy_args - Exit $process.ExitCode + Invoke-Application $python $xpy_args } Write-Error "${PSCommandPath}: error: did not find python installed" |
