diff --git a/.github/ISSUE_TEMPLATE/tracking_issue_future.md b/.github/ISSUE_TEMPLATE/tracking_issue_future.md new file mode 100644 index 0000000000000..f04a458d8a5aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tracking_issue_future.md @@ -0,0 +1,54 @@ +--- +name: Future Incompatibility Tracking Issue +about: A tracking issue for a future-incompatible lint +title: Tracking Issue for future-incompatibility lint XXX +labels: C-tracking-issue C-future-incompatibility T-compiler A-lints +--- + + +This is the **tracking issue** for the `YOUR_LINT_NAME_HERE` future-compatibility warning and other related errors. The goal of this page is describe why this change was made and how you can fix code that is affected by it. It also provides a place to ask questions or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our [breaking change policy guidelines][guidelines]. + +[guidelines]: https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html + +### What is the warning for? + +*Describe the conditions that trigger the warning.* + +### Why was this change made? + +*Explain why this change was made. If there is additional context, like an MCP, link it here.* + +### Example + +```rust +// Include an example here. +``` + +### Recommendations + +*Give some recommendations on how a user can avoid the lint.* + +### When will this warning become a hard error? + +*If known, describe the future plans. For example, how long you anticipate this being a warning, or if there are other factors that will influence the anticipated closure.* + +### Steps + +- [ ] Implement the lint +- [ ] Raise lint level to deny +- [ ] Make lint report in dependencies +- [ ] Switch to a hard error + +### Implementation history + + diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 732795535087e..06103fe1c91bc 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -680,6 +680,18 @@ pub(crate) enum SuggestBoxing { hir_typeck_suggest_boxing_when_appropriate, applicability = "machine-applicable" )] + ExprFieldShorthand { + #[suggestion_part(code = "{ident}: Box::new(")] + start: Span, + #[suggestion_part(code = ")")] + end: Span, + ident: Ident, + }, + #[note(hir_typeck_suggest_boxing_note)] + #[multipart_suggestion( + hir_typeck_suggest_boxing_when_appropriate, + applicability = "machine-applicable" + )] Other { #[suggestion_part(code = "Box::new(")] start: Span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 91eb1989864ff..251801f479efb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -585,6 +585,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { errors::SuggestBoxing::AsyncBody } + _ if let Node::ExprField(expr_field) = self.tcx.parent_hir_node(hir_id) + && expr_field.is_shorthand => + { + errors::SuggestBoxing::ExprFieldShorthand { + start: span.shrink_to_lo(), + end: span.shrink_to_hi(), + ident: expr_field.ident, + } + } _ => errors::SuggestBoxing::Other { start: span.shrink_to_lo(), end: span.shrink_to_hi(), diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index a8bbc89dbded5..956671fc66ed2 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -105,16 +105,26 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { } fn assign(&mut self, span: Span, nid: HirId, ty_opt: Option>) -> Ty<'tcx> { + // We evaluate expressions twice occasionally in diagnostics for better + // type information or because it needs type information out-of-order. + // In order to not ICE and not lead to knock-on ambiguity errors, if we + // try to re-assign a type to a local, then just take out the previous + // type and delay a bug. + if let Some(&local) = self.fcx.locals.borrow_mut().get(&nid) { + self.fcx.dcx().span_delayed_bug(span, "evaluated expression more than once"); + return local; + } + match ty_opt { None => { // Infer the variable's type. let var_ty = self.fcx.next_ty_var(span); - assert_eq!(self.fcx.locals.borrow_mut().insert(nid, var_ty), None); + self.fcx.locals.borrow_mut().insert(nid, var_ty); var_ty } Some(typ) => { // Take type that the user specified. - assert_eq!(self.fcx.locals.borrow_mut().insert(nid, typ), None); + self.fcx.locals.borrow_mut().insert(nid, typ); typ } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3a95447308a90..efae6250b0720 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -280,6 +280,8 @@ symbols! { IoSeek, IoWrite, IpAddr, + Ipv4Addr, + Ipv6Addr, IrTyKind, Is, Item, diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index d0be82adb6b16..63a479ed8dd4e 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -391,7 +391,7 @@ impl MaybeUninit { /// For your convenience, this also returns a mutable reference to the /// (now safely initialized) contents of `self`. /// - /// As the content is stored inside a `MaybeUninit`, the destructor is not + /// As the content is stored inside a `ManuallyDrop`, the destructor is not /// run for the inner data if the MaybeUninit leaves scope without a call to /// [`assume_init`], [`assume_init_drop`], or similar. Code that receives /// the mutable reference returned by this function needs to keep this in diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 2f027be692860..aaa68e8d7d1ad 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -68,6 +68,7 @@ pub enum IpAddr { /// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal /// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex /// ``` +#[rustc_diagnostic_item = "Ipv4Addr"] #[derive(Copy, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv4Addr { @@ -160,6 +161,7 @@ impl Hash for Ipv4Addr { /// assert_eq!("::1".parse(), Ok(localhost)); /// assert_eq!(localhost.is_loopback(), true); /// ``` +#[rustc_diagnostic_item = "Ipv6Addr"] #[derive(Copy, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Ipv6Addr { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 05ab1b6eddefb..ff63b8c62d3a0 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -579,9 +579,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustix" -version = "1.0.2" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", diff --git a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md index 8e6725c54efac..55436261fdefa 100644 --- a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md +++ b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md @@ -80,41 +80,11 @@ approachable and practical; it may make sense to direct users to an RFC or some other issue for the full details. The issue also serves as a place where users can comment with questions or other concerns. -A template for these breaking-change tracking issues can be found below. An -example of how such an issue should look can be [found +A template for these breaking-change tracking issues can be found +[here][template]. An example of how such an issue should look can be [found here][breaking-change-issue]. -The issue should be tagged with (at least) `B-unstable` and `T-compiler`. - -### Tracking issue template - -This is a template to use for tracking issues: - -``` -This is the **summary issue** for the `YOUR_LINT_NAME_HERE` -future-compatibility warning and other related errors. The goal of -this page is describe why this change was made and how you can fix -code that is affected by it. It also provides a place to ask questions -or register a complaint if you feel the change should not be made. For -more information on the policy around future-compatibility warnings, -see our [breaking change policy guidelines][guidelines]. - -[guidelines]: LINK_TO_THIS_RFC - -#### What is the warning for? - -*Describe the conditions that trigger the warning and how they can be -fixed. Also explain why the change was made.** - -#### When will this warning become a hard error? - -At the beginning of each 6-week release cycle, the Rust compiler team -will review the set of outstanding future compatibility warnings and -nominate some of them for **Final Comment Period**. Toward the end of -the cycle, we will review any comments and make a final determination -whether to convert the warning into a hard error or remove it -entirely. -``` +[template]: https://github.com/rust-lang/rust/issues/new?template=tracking_issue_future.md ### Issuing future compatibility warnings diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3c87bcb205fc6..75f24adb70fa5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2609,18 +2609,19 @@ impl<'test> TestCx<'test> { (expected, actual) }; - // Write the actual output to a file in build/ - let test_name = self.config.compare_mode.as_ref().map_or("", |m| m.to_str()); + // Write the actual output to a file in build directory. let actual_path = self .output_base_name() .with_extra_extension(self.revision.unwrap_or("")) - .with_extra_extension(test_name) + .with_extra_extension( + self.config.compare_mode.as_ref().map(|cm| cm.to_str()).unwrap_or(""), + ) .with_extra_extension(stream); if let Err(err) = fs::write(&actual_path, &actual) { - self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",)); + self.fatal(&format!("failed to write {stream} to `{actual_path}`: {err}",)); } - println!("Saved the actual {stream} to {actual_path:?}"); + println!("Saved the actual {stream} to `{actual_path}`"); if !self.config.bless { if expected.is_empty() { @@ -2646,13 +2647,16 @@ impl<'test> TestCx<'test> { if !actual.is_empty() { if let Err(err) = fs::write(&expected_path, &actual) { - self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}")); + self.fatal(&format!("failed to write {stream} to `{expected_path}`: {err}")); } - println!("Blessing the {stream} of {test_name} in {expected_path:?}"); + println!( + "Blessing the {stream} of `{test_name}` as `{expected_path}`", + test_name = self.testpaths.file + ); } } - println!("\nThe actual {0} differed from the expected {0}.", stream); + println!("\nThe actual {stream} differed from the expected {stream}"); if self.config.bless { CompareOutcome::Blessed } else { CompareOutcome::Differed } } diff --git a/tests/ui/box/suggest-box-for-expr-field-issue-139631.rs b/tests/ui/box/suggest-box-for-expr-field-issue-139631.rs new file mode 100644 index 0000000000000..8d040da1ef7cc --- /dev/null +++ b/tests/ui/box/suggest-box-for-expr-field-issue-139631.rs @@ -0,0 +1,14 @@ +struct X { + a: Box, +} + +struct Y { + y: Box, +} + +fn main() { + let a = 8; + let v2 = X { a }; //~ ERROR mismatched types [E0308] + let v3 = Y { y: a }; //~ ERROR mismatched types [E0308] + let v4 = Y { a }; //~ ERROR struct `Y` has no field named `a` [E0560] +} diff --git a/tests/ui/box/suggest-box-for-expr-field-issue-139631.stderr b/tests/ui/box/suggest-box-for-expr-field-issue-139631.stderr new file mode 100644 index 0000000000000..01bd0523a162d --- /dev/null +++ b/tests/ui/box/suggest-box-for-expr-field-issue-139631.stderr @@ -0,0 +1,44 @@ +error[E0308]: mismatched types + --> $DIR/suggest-box-for-expr-field-issue-139631.rs:11:18 + | +LL | let v2 = X { a }; + | ^ expected `Box`, found integer + | + = note: expected struct `Box` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | let v2 = X { a: Box::new(a) }; + | ++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/suggest-box-for-expr-field-issue-139631.rs:12:21 + | +LL | let v3 = Y { y: a }; + | ^ expected `Box`, found integer + | + = note: expected struct `Box` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | let v3 = Y { y: Box::new(a) }; + | +++++++++ + + +error[E0560]: struct `Y` has no field named `a` + --> $DIR/suggest-box-for-expr-field-issue-139631.rs:13:18 + | +LL | let v4 = Y { a }; + | ^ unknown field + | +help: a field with a similar name exists + | +LL - let v4 = Y { a }; +LL + let v4 = Y { y }; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/typeck/gather-locals-twice.rs b/tests/ui/typeck/gather-locals-twice.rs new file mode 100644 index 0000000000000..e9351146f4564 --- /dev/null +++ b/tests/ui/typeck/gather-locals-twice.rs @@ -0,0 +1,7 @@ +// Regression test for . + +fn main() { + () += { let x; }; + //~^ ERROR binary assignment operation `+=` cannot be applied to type `()` + //~| ERROR invalid left-hand side of assignment +} diff --git a/tests/ui/typeck/gather-locals-twice.stderr b/tests/ui/typeck/gather-locals-twice.stderr new file mode 100644 index 0000000000000..7598ef8e7ea4c --- /dev/null +++ b/tests/ui/typeck/gather-locals-twice.stderr @@ -0,0 +1,20 @@ +error[E0368]: binary assignment operation `+=` cannot be applied to type `()` + --> $DIR/gather-locals-twice.rs:4:5 + | +LL | () += { let x; }; + | --^^^^^^^^^^^^^^ + | | + | cannot use `+=` on type `()` + +error[E0067]: invalid left-hand side of assignment + --> $DIR/gather-locals-twice.rs:4:8 + | +LL | () += { let x; }; + | -- ^^ + | | + | cannot assign to this expression + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0067, E0368. +For more information about an error, try `rustc --explain E0067`.