diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index c022fb55a16f7..09ef84f7cbb84 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -344,20 +344,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { err.span_help(source_info.span, "try removing `&mut` here"); } - } else if decl.mutability == Mutability::Not - && !matches!( + } else if decl.mutability == Mutability::Not { + if matches!( decl.local_info, Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( hir::ImplicitSelfKind::MutRef - )))) - ) - { - err.span_suggestion_verbose( - decl.source_info.span.shrink_to_lo(), - "consider making the binding mutable", - "mut ", - Applicability::MachineApplicable, - ); + ),))) + ) { + err.note( + "as `Self` may be unsized, this call attempts to take `&mut &mut self`", + ); + err.note("however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably"); + } else { + err.span_suggestion_verbose( + decl.source_info.span.shrink_to_lo(), + "consider making the binding mutable", + "mut ", + Applicability::MachineApplicable, + ); + }; } } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 3fba2cf57494d..76d5da19399ed 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -579,8 +579,7 @@ E0791: include_str!("./error_codes/E0791.md"), // E0300, // unexpanded macro // E0304, // expected signed integer constant // E0305, // expected constant - E0313, // lifetime of borrowed pointer outlives lifetime of captured - // variable +// E0313, // removed: found unreachable // E0314, // closure outlives stack frame // E0315, // cannot invoke closure outside of its lifetime // E0319, // trait impls for defaulted traits allowed just for structs/enums diff --git a/compiler/rustc_error_codes/src/error_codes/E0015.md b/compiler/rustc_error_codes/src/error_codes/E0015.md index 021a0219d13e2..ac78f66adada0 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0015.md +++ b/compiler/rustc_error_codes/src/error_codes/E0015.md @@ -1,5 +1,4 @@ -A constant item was initialized with something that is not a constant -expression. +A non-`const` function was called in a `const` context. Erroneous code example: @@ -8,26 +7,20 @@ fn create_some() -> Option { Some(1) } -const FOO: Option = create_some(); // error! +// error: cannot call non-const fn `create_some` in constants +const FOO: Option = create_some(); ``` -The only functions that can be called in static or constant expressions are -`const` functions, and struct/enum constructors. +All functions used in a `const` context (constant or static expression) must +be marked `const`. To fix this error, you can declare `create_some` as a constant function: ``` -const fn create_some() -> Option { // declared as a const function +// declared as a `const` function: +const fn create_some() -> Option { Some(1) } -const FOO: Option = create_some(); // ok! - -// These are also working: -struct Bar { - x: u8, -} - -const OTHER_FOO: Option = Some(1); -const BAR: Bar = Bar {x: 1}; +const FOO: Option = create_some(); // no error! ``` diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0f191c21a0a63..f15cf5e3ef948 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1379,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // If we've reached our target type with just removing `&`, then just print now. - if steps == 0 { + if steps == 0 && !remove.trim().is_empty() { return Some(( prefix_span, format!("consider removing the `{}`", remove.trim()), @@ -1438,6 +1438,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (prefix_span, format!("{}{}", prefix, "*".repeat(steps))) }; + if suggestion.trim().is_empty() { + return None; + } return Some(( span, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0644c7ada10fb..b02e7d73c51f8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! Error Reporting Code for the inference engine //! //! Because of the way inference, and in particular region inference, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index d91ef882bc4b8..7bb79d7bda8dd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -25,16 +25,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { 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); @@ -162,33 +152,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); 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, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b17a465eb3831..bc8bbd4be6ae1 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -409,9 +409,6 @@ pub enum SubregionOrigin<'tcx> { /// Creating a pointer `b` to contents of another reference Reborrow(Span), - /// Creating a pointer `b` to contents of an upvar - ReborrowUpvar(Span, ty::UpvarId), - /// Data with type `Ty<'tcx>` was borrowed DataBorrowed(Ty<'tcx>, Span), @@ -1954,7 +1951,6 @@ impl<'tcx> SubregionOrigin<'tcx> { RelateParamBound(a, ..) => a, RelateRegionParamBound(a) => a, Reborrow(a) => a, - ReborrowUpvar(a, _) => a, DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 0017baa66abe0..451e4936bc50e 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -636,6 +636,7 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); + /// buf.push_back(6); /// assert_eq!(buf.get(1), Some(&4)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -661,10 +662,11 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); + /// buf.push_back(6); + /// assert_eq!(buf[1], 4); /// if let Some(elem) = buf.get_mut(1) { /// *elem = 7; /// } - /// /// assert_eq!(buf[1], 7); /// ``` #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 3f8acc8505ff1..ced445a1f440a 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1026,7 +1026,6 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// ### Basic usage /// /// ```rust -/// #![feature(pin_macro)] /// # use core::marker::PhantomPinned as Foo; /// use core::pin::{pin, Pin}; /// @@ -1044,7 +1043,6 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// ### Manually polling a `Future` (without `Unpin` bounds) /// /// ```rust -/// #![feature(pin_macro)] /// use std::{ /// future::Future, /// pin::pin, @@ -1083,7 +1081,7 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// ### With `Generator`s /// /// ```rust -/// #![feature(generators, generator_trait, pin_macro)] +/// #![feature(generators, generator_trait)] /// use core::{ /// ops::{Generator, GeneratorState}, /// pin::pin, @@ -1126,7 +1124,6 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// The following, for instance, fails to compile: /// /// ```rust,compile_fail -/// #![feature(pin_macro)] /// use core::pin::{pin, Pin}; /// # use core::{marker::PhantomPinned as Foo, mem::drop as stuff}; /// @@ -1168,7 +1165,7 @@ impl DispatchFromDyn> for Pin

where P: DispatchFromDyn {} /// constructor. /// /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin -#[unstable(feature = "pin_macro", issue = "93178")] +#[stable(feature = "pin_macro", since = "CURRENT_RUSTC_VERSION")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(unsafe_pin_internals)] pub macro pin($value:expr $(,)?) { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c910cb65c55de..42a26ae1675c1 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -48,7 +48,6 @@ #![feature(is_sorted)] #![feature(layout_for_ptr)] #![feature(pattern)] -#![feature(pin_macro)] #![feature(sort_internals)] #![feature(slice_take)] #![feature(slice_from_ptr_range)] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 19d8f1edaf4c9..82d68369312f9 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -271,7 +271,7 @@ pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP; /// The primary separator of path components for the current platform. /// /// For example, `/` on Unix and `\` on Windows. -#[unstable(feature = "main_separator_str", issue = "94071")] +#[stable(feature = "main_separator_str", since = "CURRENT_RUSTC_VERSION")] pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index cd360cbef9654..ca4feac6fac70 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -351,7 +351,7 @@ pub fn interactive_path() -> io::Result { Ok(template) } -// install a git hook to automatically run tidy --bless, if they want +// install a git hook to automatically run tidy, if they want fn install_git_hook_maybe(config: &Config) -> io::Result<()> { let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| { assert!(output.status.success(), "failed to run `git`"); @@ -367,7 +367,7 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> { println!(); println!( "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality. -If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before +If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before pushing your code to ensure your code is up to par. If you decide later that this behavior is undesirable, simply delete the `pre-push` file from .git/hooks." ); diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh index 2a3086338b4bf..7a846d44ad6a8 100755 --- a/src/etc/pre-push.sh +++ b/src/etc/pre-push.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Call `tidy --bless` before git push +# Call `tidy` before git push # Copy this script to .git/hooks to activate, # and remove it from .git/hooks to deactivate. # diff --git a/src/test/ui/borrowck/issue-93078.rs b/src/test/ui/borrowck/issue-93078.rs new file mode 100644 index 0000000000000..2e608c5db3e1d --- /dev/null +++ b/src/test/ui/borrowck/issue-93078.rs @@ -0,0 +1,15 @@ +trait Modify { + fn modify(&mut self) ; +} + +impl Modify for T { + fn modify(&mut self) {} +} + +trait Foo { + fn mute(&mut self) { + self.modify(); //~ ERROR cannot borrow `self` as mutable + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-93078.stderr b/src/test/ui/borrowck/issue-93078.stderr new file mode 100644 index 0000000000000..771a652a1739c --- /dev/null +++ b/src/test/ui/borrowck/issue-93078.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-93078.rs:11:9 + | +LL | self.modify(); + | ^^^^^^^^^^^^^ cannot borrow as mutable + | + = note: as `Self` may be unsized, this call attempts to take `&mut &mut self` + = note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/error-codes/E0013.rs b/src/test/ui/error-codes/E0013.rs new file mode 100644 index 0000000000000..9b3982a785b7f --- /dev/null +++ b/src/test/ui/error-codes/E0013.rs @@ -0,0 +1,4 @@ +static X: i32 = 42; +const Y: i32 = X; //~ ERROR constants cannot refer to statics [E0013] + +fn main() {} diff --git a/src/test/ui/error-codes/E0013.stderr b/src/test/ui/error-codes/E0013.stderr new file mode 100644 index 0000000000000..dc22053a63895 --- /dev/null +++ b/src/test/ui/error-codes/E0013.stderr @@ -0,0 +1,11 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/E0013.rs:2:16 + | +LL | const Y: i32 = X; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0013`. diff --git a/src/test/ui/error-codes/E0015.rs b/src/test/ui/error-codes/E0015.rs new file mode 100644 index 0000000000000..b0211358d8166 --- /dev/null +++ b/src/test/ui/error-codes/E0015.rs @@ -0,0 +1,8 @@ +fn create_some() -> Option { + Some(1) +} + +const FOO: Option = create_some(); +//~^ ERROR cannot call non-const fn `create_some` in constants [E0015] + +fn main() {} diff --git a/src/test/ui/error-codes/E0015.stderr b/src/test/ui/error-codes/E0015.stderr new file mode 100644 index 0000000000000..ec1ce47b2ce78 --- /dev/null +++ b/src/test/ui/error-codes/E0015.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `create_some` in constants + --> $DIR/E0015.rs:5:25 + | +LL | const FOO: Option = create_some(); + | ^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/pin-macro/cant_access_internals.rs b/src/test/ui/pin-macro/cant_access_internals.rs index 120d08894f8f7..5826a18b5718b 100644 --- a/src/test/ui/pin-macro/cant_access_internals.rs +++ b/src/test/ui/pin-macro/cant_access_internals.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(pin_macro)] use core::{ marker::PhantomPinned, diff --git a/src/test/ui/pin-macro/cant_access_internals.stderr b/src/test/ui/pin-macro/cant_access_internals.stderr index 060c9c48c21c8..d43027657f046 100644 --- a/src/test/ui/pin-macro/cant_access_internals.stderr +++ b/src/test/ui/pin-macro/cant_access_internals.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'unsafe_pin_internals' - --> $DIR/cant_access_internals.rs:12:15 + --> $DIR/cant_access_internals.rs:11:15 | LL | mem::take(phantom_pinned.pointer); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs index ca2b6cf759376..59774bc753dc9 100644 --- a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs +++ b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(pin_macro)] use core::{ convert::identity, diff --git a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr index fc1be052fb791..4ecc6370d3caa 100644 --- a/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr +++ b/src/test/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/lifetime_errors_on_promotion_misusage.rs:12:35 + --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35 | LL | let phantom_pinned = identity(pin!(PhantomPinned)); | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -13,7 +13,7 @@ LL | stuff(phantom_pinned) = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0716]: temporary value dropped while borrowed - --> $DIR/lifetime_errors_on_promotion_misusage.rs:19:30 + --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30 | LL | let phantom_pinned = { | -------------- borrow later stored here diff --git a/src/test/ui/type/closure-with-wrong-borrows.rs b/src/test/ui/type/closure-with-wrong-borrows.rs new file mode 100644 index 0000000000000..5f6a78351a247 --- /dev/null +++ b/src/test/ui/type/closure-with-wrong-borrows.rs @@ -0,0 +1,10 @@ +struct S<'a>(&'a str); + +fn f(inner: fn(&str, &S)) { +} + +#[allow(unreachable_code)] +fn main() { + let inner: fn(_, _) = unimplemented!(); + f(inner); //~ ERROR mismatched types +} diff --git a/src/test/ui/type/closure-with-wrong-borrows.stderr b/src/test/ui/type/closure-with-wrong-borrows.stderr new file mode 100644 index 0000000000000..7370bc7646765 --- /dev/null +++ b/src/test/ui/type/closure-with-wrong-borrows.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/closure-with-wrong-borrows.rs:9:7 + | +LL | f(inner); + | - ^^^^^ one type is more general than the other + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `for<'a, 'b, 'c> fn(&'a str, &'b S<'c>)` + found fn pointer `fn(_, _)` +note: function defined here + --> $DIR/closure-with-wrong-borrows.rs:3:4 + | +LL | fn f(inner: fn(&str, &S)) { + | ^ ------------------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index f1b9c1acbaec0..c6f55410e4437 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -3,14 +3,17 @@ use std::hash::Hash; 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, VariantKind, WherePredicate, + GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, + OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, + Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, }; use serde_json::Value; use crate::{item_kind::Kind, json_find, Error, ErrorKind}; +// This is a rustc implementation detail that we rely on here +const LOCAL_CRATE_ID: u32 = 0; + /// The Validator walks over the JSON tree, and ensures it is well formed. /// It is made of several parts. /// @@ -53,12 +56,19 @@ impl<'a> Validator<'a> { } pub fn check_crate(&mut self) { + // Graph traverse the index let root = &self.krate.root; self.add_mod_id(root); while let Some(id) = set_remove(&mut self.todo) { self.seen_ids.insert(id); self.check_item(id); } + + let root_crate_id = self.krate.index[root].crate_id; + assert_eq!(root_crate_id, LOCAL_CRATE_ID, "LOCAL_CRATE_ID is wrong"); + for (id, item_info) in &self.krate.paths { + self.check_item_info(id, item_info); + } } fn check_item(&mut self, id: &'a Id) { @@ -364,6 +374,19 @@ impl<'a> Validator<'a> { fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } + fn check_item_info(&mut self, id: &Id, item_info: &ItemSummary) { + // FIXME: Their should be a better way to determine if an item is local, rather than relying on `LOCAL_CRATE_ID`, + // which encodes rustc implementation details. + if item_info.crate_id == LOCAL_CRATE_ID && !self.krate.index.contains_key(id) { + self.errs.push(Error { + id: id.clone(), + kind: ErrorKind::Custom( + "Id for local item in `paths` but not in `index`".to_owned(), + ), + }) + } + } + fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) { if let Some(kind) = self.kind_of(id) { if valid(kind) { diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index 37b826153efb1..1ef41ff123abf 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use rustdoc_json_types::{Crate, Item, Visibility}; +use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION}; use crate::json_find::SelectorPart; @@ -64,3 +64,101 @@ fn errors_on_missing_links() { }], ); } + +// Test we would catch +// https://github.com/rust-lang/rust/issues/104064#issuecomment-1368589718 +#[test] +fn errors_on_local_in_paths_and_not_index() { + let krate = Crate { + root: id("0:0:1572"), + crate_version: None, + includes_private: false, + index: HashMap::from_iter([ + ( + id("0:0:1572"), + Item { + id: id("0:0:1572"), + crate_id: 0, + name: Some("microcore".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Module(Module { + is_crate: true, + items: vec![id("0:1:717")], + is_stripped: false, + }), + }, + ), + ( + id("0:1:717"), + Item { + id: id("0:1:717"), + crate_id: 0, + name: Some("i32".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::default(), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }), + }, + ), + ]), + paths: HashMap::from_iter([( + id("0:1:1571"), + ItemSummary { + crate_id: 0, + path: vec!["microcore".to_owned(), "i32".to_owned()], + kind: ItemKind::Primitive, + }, + )]), + external_crates: HashMap::default(), + format_version: rustdoc_json_types::FORMAT_VERSION, + }; + + check( + &krate, + &[Error { + id: id("0:1:1571"), + kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()), + }], + ); +} + +#[test] +#[should_panic = "LOCAL_CRATE_ID is wrong"] +fn checks_local_crate_id_is_correct() { + let krate = Crate { + root: id("root"), + crate_version: None, + includes_private: false, + index: HashMap::from_iter([( + id("root"), + Item { + id: id("root"), + crate_id: LOCAL_CRATE_ID.wrapping_add(1), + name: Some("irrelavent".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::default(), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Module(Module { + is_crate: true, + items: vec![], + is_stripped: false, + }), + }, + )]), + paths: HashMap::default(), + external_crates: HashMap::default(), + format_version: FORMAT_VERSION, + }; + check(&krate, &[]); +} diff --git a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs index 7576ba78f607d..fe4078f77107b 100644 --- a/src/tools/miri/tests/pass/issues/issue-miri-2068.rs +++ b/src/tools/miri/tests/pass/issues/issue-miri-2068.rs @@ -1,5 +1,3 @@ -#![feature(pin_macro)] - use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index fdc9d78990590..8d70335a9e7b9 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -15,8 +15,6 @@ //! //! 4. We check that the error code is actually emitted by the compiler. //! - This is done by searching `compiler/` with a regex. -//! -//! This tidy check was merged and refactored from two others. See #PR_NUM for information about linting changes that occurred during this refactor. use std::{ffi::OsStr, fs, path::Path}; @@ -33,8 +31,8 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"]; // Error codes that don't yet have a UI test. This list will eventually be removed. const IGNORE_UI_TEST_CHECK: &[&str] = &[ - "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", - "E0729", "E0789", + "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", + "E0789", ]; macro_rules! verbose_print { @@ -57,7 +55,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose); // Stage 3: check list has UI tests - check_error_codes_tests(root_path, &error_codes, &mut errors, verbose); + check_error_codes_tests(root_path, &error_codes, &mut errors, verbose, &no_longer_emitted); // Stage 4: check list is emitted by compiler check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose); @@ -174,8 +172,9 @@ fn check_error_codes_docs( return; } - let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = + let (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) = check_explanation_has_doctest(&contents, &err_code); + if emit_ignore_warning { verbose_print!( verbose, @@ -183,13 +182,11 @@ fn check_error_codes_docs( `IGNORE_DOCTEST_CHECK` constant instead." ); } - if emit_no_longer_warning { + + if no_longer_emitted { no_longer_emitted_codes.push(err_code.to_owned()); - verbose_print!( - verbose, - "warning: Error code `{err_code}` is no longer emitted and should be removed entirely." - ); } + if !found_code_example { verbose_print!( verbose, @@ -226,7 +223,7 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo let mut found_proper_doctest = false; let mut emit_ignore_warning = false; - let mut emit_no_longer_warning = false; + let mut no_longer_emitted = false; for line in explanation.lines() { let line = line.trim(); @@ -246,13 +243,13 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo } else if line .starts_with("#### Note: this error code is no longer emitted by the compiler") { - emit_no_longer_warning = true; + no_longer_emitted = true; found_code_example = true; found_proper_doctest = true; } } - (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) + (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) } // Stage 3: Checks that each error code has a UI test in the correct directory @@ -261,6 +258,7 @@ fn check_error_codes_tests( error_codes: &[String], errors: &mut Vec, verbose: bool, + no_longer_emitted: &[String], ) { let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH)); @@ -295,6 +293,11 @@ fn check_error_codes_tests( } }; + if no_longer_emitted.contains(code) { + // UI tests *can't* contain error codes that are no longer emitted. + continue; + } + let mut found_code = false; for line in file.lines() {