From f4a9d29c50de93c3320867a4f63c9e36eee43d3b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 17 Oct 2023 15:12:21 +1100 Subject: [PATCH 01/11] Remove `rustc_symbol_mangling/messages.ftl`. It contains a single message that (a) doesn't contain any natural language, and (b) is only used in tests. --- Cargo.lock | 2 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_symbol_mangling/Cargo.toml | 2 - compiler/rustc_symbol_mangling/messages.ftl | 1 - compiler/rustc_symbol_mangling/src/errors.rs | 40 +++++++++++++------- compiler/rustc_symbol_mangling/src/lib.rs | 4 -- 6 files changed, 26 insertions(+), 24 deletions(-) delete mode 100644 compiler/rustc_symbol_mangling/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 5cfb7feb6f5..11f30b41079 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4543,9 +4543,7 @@ dependencies = [ "rustc-demangle", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", - "rustc_macros", "rustc_middle", "rustc_session", "rustc_span", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5bb7c41677c..f768fd5ef19 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -137,7 +137,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_query_system::DEFAULT_LOCALE_RESOURCE, rustc_resolve::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE, - rustc_symbol_mangling::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, rustc_ty_utils::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 052ef8bb94c..d53bc5b6a8e 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -15,9 +15,7 @@ twox-hash = "1.6.3" rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } rustc_hir = { path = "../rustc_hir" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_target = { path = "../rustc_target" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_session = { path = "../rustc_session" } -rustc_macros = { path = "../rustc_macros" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_symbol_mangling/messages.ftl b/compiler/rustc_symbol_mangling/messages.ftl deleted file mode 100644 index b7d48280f46..00000000000 --- a/compiler/rustc_symbol_mangling/messages.ftl +++ /dev/null @@ -1 +0,0 @@ -symbol_mangling_test_output = {$kind}({$content}) diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index f4d0751f753..2e081e55531 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -1,18 +1,32 @@ //! Errors emitted by symbol_mangling. -use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; -use rustc_macros::Diagnostic; +use rustc_errors::{ErrorGuaranteed, IntoDiagnostic}; use rustc_span::Span; +use std::fmt; -#[derive(Diagnostic)] -#[diag(symbol_mangling_test_output)] pub struct TestOutput { - #[primary_span] pub span: Span, pub kind: Kind, pub content: String, } +// This diagnostic doesn't need translation because (a) it doesn't contain any +// natural language, and (b) it's only used in tests. So we construct it +// manually and avoid the fluent machinery. +impl IntoDiagnostic<'_> for TestOutput { + fn into_diagnostic( + self, + handler: &'_ rustc_errors::Handler, + ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { + let TestOutput { span, kind, content } = self; + + #[allow(rustc::untranslatable_diagnostic)] + let mut diag = handler.struct_err(format!("{kind}({content})")); + diag.set_span(span); + diag + } +} + pub enum Kind { SymbolName, Demangling, @@ -20,15 +34,13 @@ pub enum Kind { DefPath, } -impl IntoDiagnosticArg for Kind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - let kind = match self { - Kind::SymbolName => "symbol-name", - Kind::Demangling => "demangling", - Kind::DemanglingAlt => "demangling-alt", - Kind::DefPath => "def-path", +impl fmt::Display for Kind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Kind::SymbolName => write!(f, "symbol-name"), + Kind::Demangling => write!(f, "demangling"), + Kind::DemanglingAlt => write!(f, "demangling-alt"), + Kind::DefPath => write!(f, "def-path"), } - .into(); - DiagnosticArgValue::Str(kind) } } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 6ade2d777c7..90cd0479cb2 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -103,8 +103,6 @@ extern crate rustc_middle; #[macro_use] extern crate tracing; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -121,8 +119,6 @@ pub mod errors; pub mod test; pub mod typeid; -fluent_messages! { "../messages.ftl" } - /// This function computes the symbol name for the given `instance` and the /// given instantiating crate. That is, if you know that instance X is /// instantiated in crate Y, this is the symbol name this instance would have. From 041f0313cf39f1be4fbceebf3186fe5254e7be78 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 26 Oct 2023 11:11:36 +0000 Subject: [PATCH 02/11] Properly restore snapshot when failing to recover parsing ternary --- compiler/rustc_parse/src/parser/diagnostics.rs | 6 ++---- tests/ui/parser/ternary_operator.rs | 7 +++++++ tests/ui/parser/ternary_operator.stderr | 16 +++++++++++----- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 9f8361a4b1e..64db7d9809e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1454,13 +1454,11 @@ impl<'a> Parser<'a> { } Err(err) => { err.cancel(); - self.restore_snapshot(snapshot); } }; } - } else { - self.restore_snapshot(snapshot); - }; + } + self.restore_snapshot(snapshot); false } diff --git a/tests/ui/parser/ternary_operator.rs b/tests/ui/parser/ternary_operator.rs index 23d537e77f7..03cf86f6da4 100644 --- a/tests/ui/parser/ternary_operator.rs +++ b/tests/ui/parser/ternary_operator.rs @@ -49,6 +49,13 @@ fn c() { //~ NOTE this function should return `Result` or `Option` to accept `?` //~| NOTE in this expansion of desugaring of operator `?` } +fn bad() { + // regression test for #117208 + v ? return; + //~^ ERROR expected one of + //~| NOTE expected one of +} + fn main() { //~ NOTE this function should return `Result` or `Option` to accept `?` let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; //~^ ERROR Rust has no ternary operator diff --git a/tests/ui/parser/ternary_operator.stderr b/tests/ui/parser/ternary_operator.stderr index af9565bbead..61d3c35eb97 100644 --- a/tests/ui/parser/ternary_operator.stderr +++ b/tests/ui/parser/ternary_operator.stderr @@ -22,8 +22,14 @@ LL | let x = 5 > 2 ? f32::MAX : f32::MIN; | = help: use an `if-else` expression instead +error: expected one of `.`, `;`, `?`, `}`, or an operator, found keyword `return` + --> $DIR/ternary_operator.rs:54:9 + | +LL | v ? return; + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` - --> $DIR/ternary_operator.rs:53:37 + --> $DIR/ternary_operator.rs:60:37 | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^ expected one of `.`, `;`, `?`, `else`, or an operator @@ -31,7 +37,7 @@ LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; = note: type ascription syntax has been removed, see issue #101728 error: Rust has no ternary operator - --> $DIR/ternary_operator.rs:53:19 + --> $DIR/ternary_operator.rs:60:19 | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -93,7 +99,7 @@ LL | let x = 5 > 2 ? f32::MAX : f32::MIN; = help: the trait `FromResidual<_>` is not implemented for `()` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/ternary_operator.rs:53:17 + --> $DIR/ternary_operator.rs:60:17 | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^^^ the `?` operator cannot be applied to type `{integer}` @@ -101,7 +107,7 @@ LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; = help: the trait `Try` is not implemented for `{integer}` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/ternary_operator.rs:53:19 + --> $DIR/ternary_operator.rs:60:19 | LL | fn main() { | --------- this function should return `Result` or `Option` to accept `?` @@ -110,6 +116,6 @@ LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | = help: the trait `FromResidual<_>` is not implemented for `()` -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0277`. From 3bbc70a5f72a8e54e50d981c01d748d3d9087b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 26 Oct 2023 18:33:03 +0000 Subject: [PATCH 03/11] Restrict param constraint suggestion When encountering an associated item with a type param that could be constrained, do not look at the parent item if the type param comes from the associated item. Fix #117209. --- .../infer/error_reporting/note_and_explain.rs | 11 +++++--- ...on-for-type-param-of-current-assoc-item.rs | 28 +++++++++++++++++++ ...or-type-param-of-current-assoc-item.stderr | 18 ++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs create mode 100644 tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 00289f9bfb4..799e41650b6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -364,12 +364,11 @@ impl Trait for X { }; // Get the `DefId` for the type parameter corresponding to `A` in `::Foo`. // This will also work for `impl Trait`. - let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() { - let generics = tcx.generics_of(body_owner_def_id); - generics.type_param(param_ty, tcx).def_id - } else { + let ty::Param(param_ty) = proj_ty.self_ty().kind() else { return false; }; + let generics = tcx.generics_of(body_owner_def_id); + let def_id = generics.type_param(param_ty, tcx).def_id; let Some(def_id) = def_id.as_local() else { return false; }; @@ -390,6 +389,10 @@ impl Trait for X { return true; } } + if (param_ty.index as usize) >= generics.parent_count { + // The param comes from the current item, do not look at the parent. (#117209) + return false; + } // If associated item, look to constrain the params of the trait/impl. let hir_id = match item { hir::Node::ImplItem(item) => item.hir_id(), diff --git a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs new file mode 100644 index 00000000000..c1047d85645 --- /dev/null +++ b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs @@ -0,0 +1,28 @@ +use std::collections::HashMap; +use std::hash::Hash; + +trait LowT: Identify {} + +trait Identify { + type Id: Clone + Hash + PartialEq + Eq; + fn identify(&self) -> Self::Id; +} + +struct MapStore +where + L: LowT + Identify, +{ + lows: HashMap, +} + +impl MapStore +where + L: LowT + Identify, + I: Clone + Hash + PartialEq + Eq, +{ + fn remove_low(&mut self, low: &impl LowT) { + let _low = self.lows.remove(low.identify()).unwrap(); //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr new file mode 100644 index 00000000000..78bf93c32d5 --- /dev/null +++ b/tests/ui/associated-type-bounds/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/do-not-look-at-parent-item-in-suggestion-for-type-param-of-current-assoc-item.rs:24:37 + | +LL | let _low = self.lows.remove(low.identify()).unwrap(); + | ------ ^^^^^^^^^^^^^^ expected `&I`, found associated type + | | + | arguments to this method are incorrect + | + = note: expected reference `&I` + found associated type `::Id` + = help: consider constraining the associated type `::Id` to `&I` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +note: method defined here + --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 84c9c4aca7665e40986392845406a1b7524da07f Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Thu, 26 Oct 2023 21:43:43 +0200 Subject: [PATCH 04/11] NVPTX: Allow PassMode::Direct for ptx kernels for now --- compiler/rustc_codegen_llvm/src/abi.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 9e834b83df4..6bface44a63 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -362,8 +362,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { // currently use this mode so we have to allow it -- but we absolutely // shouldn't let any more targets do that. // (Also see .) + // + // The unstable api `PtxKernel` also uses Direct for now. + // It needs to switch to something else before stabilization can happen. + // (Tracking issue abi_ptx: https://github.com/rust-lang/rust/issues/38788) assert!( - matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64"), + matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") + || self.conv == Conv::PtxKernel, "`PassMode::Direct` for aggregates only allowed on wasm targets\nProblematic type: {:#?}", arg.layout, ); From 4d33876778011f7273ab3ebdbdbc35928832332b Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Fri, 27 Oct 2023 00:47:52 +0200 Subject: [PATCH 05/11] Documentation and error message improvements related to PassMode::Direct assert Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> --- compiler/rustc_codegen_llvm/src/abi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 6bface44a63..7d742ac732c 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -363,13 +363,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { // shouldn't let any more targets do that. // (Also see .) // - // The unstable api `PtxKernel` also uses Direct for now. + // The unstable abi `PtxKernel` also uses Direct for now. // It needs to switch to something else before stabilization can happen. // (Tracking issue abi_ptx: https://github.com/rust-lang/rust/issues/38788) assert!( matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") || self.conv == Conv::PtxKernel, - "`PassMode::Direct` for aggregates only allowed on wasm targets\nProblematic type: {:#?}", + "`PassMode::Direct` for aggregates only allowed on wasm and `extern \"ptx-kernel\"` fns\nProblematic type: {:#?}", arg.layout, ); } From e81a5c65d9b254e625b96dfc756f1695ee1824ed Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 26 Oct 2023 11:35:11 +0000 Subject: [PATCH 06/11] Recover ternary expression as error --- .../rustc_parse/src/parser/diagnostics.rs | 20 +++-- tests/ui/parser/ternary_operator.rs | 54 +----------- tests/ui/parser/ternary_operator.stderr | 87 ++----------------- 3 files changed, 22 insertions(+), 139 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 64db7d9809e..7b5bb319ed8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -504,8 +504,10 @@ impl<'a> Parser<'a> { // Special-case "expected `;`" errors if expected.contains(&TokenType::Token(token::Semi)) { - if self.prev_token == token::Question && self.maybe_recover_from_ternary_operator() { - return Ok(true); + // If the user is trying to write a ternary expression, recover it and + // return an Err to prevent a cascade of irrelevant diagnostics + if self.prev_token == token::Question && let Err(e) = self.maybe_recover_from_ternary_operator() { + return Err(e); } if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP { @@ -1428,10 +1430,10 @@ impl<'a> Parser<'a> { /// Rust has no ternary operator (`cond ? then : else`). Parse it and try /// to recover from it if `then` and `else` are valid expressions. Returns - /// whether it was a ternary operator. - pub(super) fn maybe_recover_from_ternary_operator(&mut self) -> bool { + /// an err if this appears to be a ternary expression. + pub(super) fn maybe_recover_from_ternary_operator(&mut self) -> PResult<'a, ()> { if self.prev_token != token::Question { - return false; + return PResult::Ok(()); } let lo = self.prev_token.span.lo(); @@ -1449,8 +1451,9 @@ impl<'a> Parser<'a> { if self.eat_noexpect(&token::Colon) { match self.parse_expr() { Ok(_) => { - self.sess.emit_err(TernaryOperator { span: self.token.span.with_lo(lo) }); - return true; + return Err(self + .sess + .create_err(TernaryOperator { span: self.token.span.with_lo(lo) })); } Err(err) => { err.cancel(); @@ -1459,8 +1462,7 @@ impl<'a> Parser<'a> { } } self.restore_snapshot(snapshot); - - false + Ok(()) } pub(super) fn maybe_recover_from_bad_type_plus(&mut self, ty: &Ty) -> PResult<'a, ()> { diff --git a/tests/ui/parser/ternary_operator.rs b/tests/ui/parser/ternary_operator.rs index 03cf86f6da4..c8810781b3d 100644 --- a/tests/ui/parser/ternary_operator.rs +++ b/tests/ui/parser/ternary_operator.rs @@ -1,76 +1,30 @@ -// A good chunk of these errors aren't shown to the user, but are still -// required in the test for it to pass. - -fn a() { //~ NOTE this function should return `Result` or `Option` to accept `?` +fn a() { let x = 5 > 2 ? true : false; //~^ ERROR Rust has no ternary operator //~| HELP use an `if-else` expression instead - //~| ERROR the `?` operator can only be applied to values that implement `Try` [E0277] - //~| HELP the trait `Try` is not implemented for `{integer}` - //~| ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) [E0277] - //~| HELP the trait `FromResidual<_>` is not implemented for `()` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE the `?` operator cannot be applied to type `{integer}` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE cannot use the `?` operator in a function that returns `()` - //~| NOTE in this expansion of desugaring of operator `?` } -fn b() { //~ NOTE this function should return `Result` or `Option` to accept `?` +fn b() { let x = 5 > 2 ? { true } : { false }; //~^ ERROR Rust has no ternary operator //~| HELP use an `if-else` expression instead - //~| ERROR the `?` operator can only be applied to values that implement `Try` [E0277] - //~| HELP the trait `Try` is not implemented for `{integer}` - //~| ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) [E0277] - //~| HELP the trait `FromResidual<_>` is not implemented for `()` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE the `?` operator cannot be applied to type `{integer}` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE cannot use the `?` operator in a function that returns `()` - //~| NOTE in this expansion of desugaring of operator `?` } -fn c() { //~ NOTE this function should return `Result` or `Option` to accept `?` +fn c() { let x = 5 > 2 ? f32::MAX : f32::MIN; //~^ ERROR Rust has no ternary operator //~| HELP use an `if-else` expression instead - //~| ERROR the `?` operator can only be applied to values that implement `Try` [E0277] - //~| HELP the trait `Try` is not implemented for `{integer}` - //~| ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) [E0277] - //~| HELP the trait `FromResidual<_>` is not implemented for `()` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE the `?` operator cannot be applied to type `{integer}` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE cannot use the `?` operator in a function that returns `()` - //~| NOTE in this expansion of desugaring of operator `?` } fn bad() { // regression test for #117208 v ? return; //~^ ERROR expected one of - //~| NOTE expected one of } -fn main() { //~ NOTE this function should return `Result` or `Option` to accept `?` +fn main() { let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; //~^ ERROR Rust has no ternary operator //~| HELP use an `if-else` expression instead //~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `:` - //~| NOTE expected one of `.`, `;`, `?`, `else`, or an operator - //~| ERROR the `?` operator can only be applied to values that implement `Try` [E0277] - //~| HELP the trait `Try` is not implemented for `{integer}` - //~| ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) [E0277] - //~| HELP the trait `FromResidual<_>` is not implemented for `()` - //~| NOTE type ascription syntax has been removed, see issue #101728 - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE the `?` operator cannot be applied to type `{integer}` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE cannot use the `?` operator in a function that returns `()` - //~| NOTE in this expansion of desugaring of operator `?` } diff --git a/tests/ui/parser/ternary_operator.stderr b/tests/ui/parser/ternary_operator.stderr index 61d3c35eb97..6635e1672f7 100644 --- a/tests/ui/parser/ternary_operator.stderr +++ b/tests/ui/parser/ternary_operator.stderr @@ -1,5 +1,5 @@ error: Rust has no ternary operator - --> $DIR/ternary_operator.rs:5:19 + --> $DIR/ternary_operator.rs:2:19 | LL | let x = 5 > 2 ? true : false; | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let x = 5 > 2 ? true : false; = help: use an `if-else` expression instead error: Rust has no ternary operator - --> $DIR/ternary_operator.rs:21:19 + --> $DIR/ternary_operator.rs:8:19 | LL | let x = 5 > 2 ? { true } : { false }; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | let x = 5 > 2 ? { true } : { false }; = help: use an `if-else` expression instead error: Rust has no ternary operator - --> $DIR/ternary_operator.rs:37:19 + --> $DIR/ternary_operator.rs:14:19 | LL | let x = 5 > 2 ? f32::MAX : f32::MIN; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -23,13 +23,13 @@ LL | let x = 5 > 2 ? f32::MAX : f32::MIN; = help: use an `if-else` expression instead error: expected one of `.`, `;`, `?`, `}`, or an operator, found keyword `return` - --> $DIR/ternary_operator.rs:54:9 + --> $DIR/ternary_operator.rs:21:9 | LL | v ? return; | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` - --> $DIR/ternary_operator.rs:60:37 + --> $DIR/ternary_operator.rs:26:37 | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^ expected one of `.`, `;`, `?`, `else`, or an operator @@ -37,85 +37,12 @@ LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; = note: type ascription syntax has been removed, see issue #101728 error: Rust has no ternary operator - --> $DIR/ternary_operator.rs:60:19 + --> $DIR/ternary_operator.rs:26:19 | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use an `if-else` expression instead -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/ternary_operator.rs:5:17 - | -LL | let x = 5 > 2 ? true : false; - | ^^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` +error: aborting due to 6 previous errors -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/ternary_operator.rs:5:19 - | -LL | fn a() { - | ------ this function should return `Result` or `Option` to accept `?` -LL | let x = 5 > 2 ? true : false; - | ^ cannot use the `?` operator in a function that returns `()` - | - = help: the trait `FromResidual<_>` is not implemented for `()` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/ternary_operator.rs:21:17 - | -LL | let x = 5 > 2 ? { true } : { false }; - | ^^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/ternary_operator.rs:21:19 - | -LL | fn b() { - | ------ this function should return `Result` or `Option` to accept `?` -LL | let x = 5 > 2 ? { true } : { false }; - | ^ cannot use the `?` operator in a function that returns `()` - | - = help: the trait `FromResidual<_>` is not implemented for `()` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/ternary_operator.rs:37:17 - | -LL | let x = 5 > 2 ? f32::MAX : f32::MIN; - | ^^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/ternary_operator.rs:37:19 - | -LL | fn c() { - | ------ this function should return `Result` or `Option` to accept `?` -LL | let x = 5 > 2 ? f32::MAX : f32::MIN; - | ^ cannot use the `?` operator in a function that returns `()` - | - = help: the trait `FromResidual<_>` is not implemented for `()` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/ternary_operator.rs:60:17 - | -LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; - | ^^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) - --> $DIR/ternary_operator.rs:60:19 - | -LL | fn main() { - | --------- this function should return `Result` or `Option` to accept `?` -LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; - | ^ cannot use the `?` operator in a function that returns `()` - | - = help: the trait `FromResidual<_>` is not implemented for `()` - -error: aborting due to 14 previous errors - -For more information about this error, try `rustc --explain E0277`. From 72d5f4b1dce3e2ae15ced8f97a567fd64face5e1 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Fri, 27 Oct 2023 04:30:49 -0400 Subject: [PATCH 07/11] Hide internal methods from documentation --- library/std/src/io/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index bca5d859b66..aa9a2482d2d 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -317,6 +317,7 @@ pub use self::stdio::set_output_capture; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; #[unstable(feature = "print_internals", issue = "none")] +#[doc(hidden)] pub use self::stdio::{_eprint, _print}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::{ From bb45c812e0b8e45a704b768a6a2080f6f794667b Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Fri, 27 Oct 2023 11:38:07 +0200 Subject: [PATCH 08/11] Link to correct issue in PassMode::Direct ptx-kernel exception --- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 7d742ac732c..6e3a4cae2f6 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -365,7 +365,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { // // The unstable abi `PtxKernel` also uses Direct for now. // It needs to switch to something else before stabilization can happen. - // (Tracking issue abi_ptx: https://github.com/rust-lang/rust/issues/38788) + // (See issue: https://github.com/rust-lang/rust/issues/117271) assert!( matches!(&*cx.tcx.sess.target.arch, "wasm32" | "wasm64") || self.conv == Conv::PtxKernel, From ccb36a688d2b67e8df05142a0f525882dae19709 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 27 Oct 2023 15:14:25 +0200 Subject: [PATCH 09/11] std::thread: add SAFETY comment --- library/std/src/thread/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 68ea486933a..4097eb5549e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -546,6 +546,8 @@ impl Builder { } let main = Box::new(main); + // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the + // lifetime change is justified. #[cfg(bootstrap)] let main = unsafe { mem::transmute::, Box>(main) }; From b915fc86ca1b567c1355febf2c440bad6e66c573 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 27 Oct 2023 18:20:19 +0300 Subject: [PATCH 10/11] fix miri target information for Test step Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 831a86940fb..9980a3f3d38 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -629,7 +629,7 @@ impl Step for Miri { SourceType::InTree, &[], ); - let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "miri", host, host); + let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "miri", host, target); cargo.add_rustc_lib_path(builder, compiler); From 7449478c2f6fd2d72c12a51d8562f1e6108facab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 26 Oct 2023 19:56:46 +0000 Subject: [PATCH 11/11] Account for type param from other item in `note_and_explain` Fix #89868. --- .../infer/error_reporting/note_and_explain.rs | 104 ++++++++++-------- compiler/rustc_middle/src/ty/generics.rs | 28 +++++ .../do-not-ice-on-note_and_explain.rs | 7 ++ .../do-not-ice-on-note_and_explain.stderr | 79 +++++++++++++ 4 files changed, 175 insertions(+), 43 deletions(-) create mode 100644 tests/ui/malformed/do-not-ice-on-note_and_explain.rs create mode 100644 tests/ui/malformed/do-not-ice-on-note_and_explain.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 799e41650b6..a8ae43d5297 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -54,13 +54,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } (ty::Param(expected), ty::Param(found)) => { let generics = tcx.generics_of(body_owner_def_id); - let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id); - if !sp.contains(e_span) { - diag.span_label(e_span, "expected type parameter"); + if let Some(param) = generics.opt_type_param(expected, tcx) { + let e_span = tcx.def_span(param.def_id); + if !sp.contains(e_span) { + diag.span_label(e_span, "expected type parameter"); + } } - let f_span = tcx.def_span(generics.type_param(found, tcx).def_id); - if !sp.contains(f_span) { - diag.span_label(f_span, "found type parameter"); + if let Some(param) = generics.opt_type_param(found, tcx) { + let f_span = tcx.def_span(param.def_id); + if !sp.contains(f_span) { + diag.span_label(f_span, "found type parameter"); + } } diag.note( "a type parameter was expected, but a different one was found; \ @@ -83,23 +87,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { | (ty::Alias(ty::Projection, proj), ty::Param(p)) if !tcx.is_impl_trait_in_trait(proj.def_id) => { - let p_def_id = tcx.generics_of(body_owner_def_id).type_param(p, tcx).def_id; - let p_span = tcx.def_span(p_def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); - } - let hir = tcx.hir(); + let parent = tcx.generics_of(body_owner_def_id) + .opt_type_param(p, tcx) + .and_then(|param| { + let p_def_id = param.def_id; + let p_span = tcx.def_span(p_def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label( + p_span, + format!("{expected}this type parameter"), + ); + } + p_def_id.as_local().and_then(|id| { + let local_id = tcx.hir().local_def_id_to_hir_id(id); + let generics = tcx.hir().find_parent(local_id)?.generics()?; + Some((id, generics)) + }) + }); let mut note = true; - let parent = p_def_id.as_local().and_then(|id| { - let local_id = hir.local_def_id_to_hir_id(id); - let generics = tcx.hir().find_parent(local_id)?.generics()?; - Some((id, generics)) - }); if let Some((local_id, generics)) = parent { // Synthesize the associated type restriction `Add`. // FIXME: extract this logic for use in other diagnostics. @@ -172,14 +182,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..)) | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); - let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); + if let Some(param) = generics.opt_type_param(p, tcx) { + let p_span = tcx.def_span(param.def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); + } } diag.help("type parameters must be constrained to match other types"); if tcx.sess.teach(&diag.get_code().unwrap()) { @@ -217,9 +229,11 @@ impl Trait for X { } (ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => { let generics = tcx.generics_of(body_owner_def_id); - let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); - if !sp.contains(p_span) { - diag.span_label(p_span, "expected this type parameter"); + if let Some(param) = generics.opt_type_param(p, tcx) { + let p_span = tcx.def_span(param.def_id); + if !sp.contains(p_span) { + diag.span_label(p_span, "expected this type parameter"); + } } diag.help(format!( "every closure has a distinct type and so could not always match the \ @@ -228,14 +242,16 @@ impl Trait for X { } (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); - let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); + if let Some(param) = generics.opt_type_param(p, tcx) { + let p_span = tcx.def_span(param.def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); + } } } (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) @@ -368,8 +384,10 @@ impl Trait for X { return false; }; let generics = tcx.generics_of(body_owner_def_id); - let def_id = generics.type_param(param_ty, tcx).def_id; - let Some(def_id) = def_id.as_local() else { + let Some(param) = generics.opt_type_param(param_ty, tcx) else { + return false; + }; + let Some(def_id) = param.def_id.as_local() else { return false; }; diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 44e88d3e230..888ee1d237a 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -237,6 +237,20 @@ impl<'tcx> Generics { } } + /// Returns the `GenericParamDef` with the given index if available. + pub fn opt_param_at( + &'tcx self, + param_index: usize, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx GenericParamDef> { + if let Some(index) = param_index.checked_sub(self.parent_count) { + self.params.get(index) + } else { + tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) + .opt_param_at(param_index, tcx) + } + } + pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] { if let Some(index) = param_index.checked_sub(self.parent_count) { &self.params[..index] @@ -268,6 +282,20 @@ impl<'tcx> Generics { } } + /// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this + /// `Generics`. + pub fn opt_type_param( + &'tcx self, + param: &ParamTy, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx GenericParamDef> { + let param = self.opt_param_at(param.index as usize, tcx)?; + match param.kind { + GenericParamDefKind::Type { .. } => Some(param), + _ => None, + } + } + /// Returns the `GenericParamDef` associated with this `ParamConst`. pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.rs b/tests/ui/malformed/do-not-ice-on-note_and_explain.rs new file mode 100644 index 00000000000..e65276fb738 --- /dev/null +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.rs @@ -0,0 +1,7 @@ +struct A(B); +implA{fn d(){fn d(){Self(1)}}} +//~^ ERROR the size for values of type `B` cannot be known at compilation time +//~| ERROR the size for values of type `B` cannot be known at compilation time +//~| ERROR mismatched types +//~| ERROR mismatched types +//~| ERROR `main` function not found in crate diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr new file mode 100644 index 00000000000..27b86145e90 --- /dev/null +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr @@ -0,0 +1,79 @@ +error[E0601]: `main` function not found in crate `do_not_ice_on_note_and_explain` + --> $DIR/do-not-ice-on-note_and_explain.rs:2:37 + | +LL | implA{fn d(){fn d(){Self(1)}}} + | ^ consider adding a `main` function to `$DIR/do-not-ice-on-note_and_explain.rs` + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/do-not-ice-on-note_and_explain.rs:2:32 + | +LL | implA{fn d(){fn d(){Self(1)}}} + | - ---- ^ doesn't have a size known at compile-time + | | | + | | required by a bound introduced by this call + | this type parameter needs to be `Sized` + | +note: required by a bound in `A` + --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 + | +LL | struct A(B); + | ^ required by this bound in `A` + +error[E0308]: mismatched types + --> $DIR/do-not-ice-on-note_and_explain.rs:2:32 + | +LL | implA{fn d(){fn d(){Self(1)}}} + | ---- ^ expected type parameter `B`, found integer + | | + | arguments to this function are incorrect + | + = note: expected type parameter `B` + found type `{integer}` +note: tuple struct defined here + --> $DIR/do-not-ice-on-note_and_explain.rs:1:8 + | +LL | struct A(B); + | ^ + +error[E0308]: mismatched types + --> $DIR/do-not-ice-on-note_and_explain.rs:2:27 + | +LL | implA{fn d(){fn d(){Self(1)}}} + | ^^^^^^^ expected `()`, found `A` + | + = note: expected unit type `()` + found struct `A` +help: consider using a semicolon here + | +LL | implA{fn d(){fn d(){Self(1);}}} + | + +help: try adding a return type + | +LL | implA{fn d(){fn d() -> A{Self(1)}}} + | +++++++ + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/do-not-ice-on-note_and_explain.rs:2:27 + | +LL | implA{fn d(){fn d(){Self(1)}}} + | - ^^^^^^^ doesn't have a size known at compile-time + | | + | this type parameter needs to be `Sized` + | +note: required by a bound in `A` + --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 + | +LL | struct A(B); + | ^ required by this bound in `A` +help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box` + --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 + | +LL | struct A(B); + | ^ - ...if indirection were used here: `Box` + | | + | this could be changed to `B: ?Sized`... + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0308, E0601. +For more information about an error, try `rustc --explain E0277`.