From 6d2bd541e0066ba8ea429fb2e25a1d080e2e2d99 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 17 Jul 2022 10:56:12 -0700 Subject: [PATCH 01/14] use body's param-env when checking if type needs drop --- .../rustc_mir_build/src/check_unsafety.rs | 4 ++-- .../rustc_mir_transform/src/check_unsafety.rs | 7 ++----- src/test/ui/union/issue-99375.rs | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/union/issue-99375.rs diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 89f60902cf9d2..1f0d0ce04aaa3 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -431,9 +431,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { let lhs = &self.thir[lhs]; if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() { if let Some((assigned_ty, assignment_span)) = self.assignment_info { - if assigned_ty.needs_drop(self.tcx, self.tcx.param_env(adt_def.did())) { + if assigned_ty.needs_drop(self.tcx, self.param_env) { // This would be unsafe, but should be outright impossible since we reject such unions. - self.tcx.sess.delay_span_bug(assignment_span, "union fields that need dropping should be impossible"); + self.tcx.sess.delay_span_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}")); } } else { self.requires_unsafe(expr.span, AccessToUnionField); diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index ded1f0462cb01..a2ad96cfc16d2 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -219,14 +219,11 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { // We have to check the actual type of the assignment, as that determines if the // old value is being dropped. let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty; - if assigned_ty.needs_drop( - self.tcx, - self.tcx.param_env(base_ty.ty_adt_def().unwrap().did()), - ) { + if assigned_ty.needs_drop(self.tcx, self.param_env) { // This would be unsafe, but should be outright impossible since we reject such unions. self.tcx.sess.delay_span_bug( self.source_info.span, - "union fields that need dropping should be impossible", + format!("union fields that need dropping should be impossible: {assigned_ty}") ); } } else { diff --git a/src/test/ui/union/issue-99375.rs b/src/test/ui/union/issue-99375.rs new file mode 100644 index 0000000000000..175018a7d71a7 --- /dev/null +++ b/src/test/ui/union/issue-99375.rs @@ -0,0 +1,21 @@ +// check-pass + +union URes { + uninit: (), + init: R, +} + +struct Params { + function: F, + result: URes, +} + +unsafe extern "C" fn do_call(params: *mut Params) +where + R: Copy, + F: Fn() -> R, +{ + (*params).result.init = ((*params).function)(); +} + +fn main() {} From a22934bea1d02870cda58eb6297ff9332fcc2104 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 18 Jul 2022 14:25:34 +0900 Subject: [PATCH 02/14] avoid `Symbol` to `&str` conversions --- compiler/rustc_ast_lowering/src/asm.rs | 4 ++-- compiler/rustc_ast_passes/src/feature_gate.rs | 4 ++-- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- .../nice_region_error/different_lifetimes.rs | 2 +- compiler/rustc_passes/src/entry.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 21 ++++++++++++------- compiler/rustc_resolve/src/macros.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/error_reporting/mod.rs | 4 ++-- compiler/rustc_typeck/src/check/_match.rs | 2 +- compiler/rustc_typeck/src/check/op.rs | 3 +-- 12 files changed, 28 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 0e395d7033586..cd77dbca3c440 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -145,7 +145,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { InlineAsmRegOrRegClass::Reg(s) => { asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register `{}`: {}", s.as_str(), e); + let msg = format!("invalid register `{}`: {}", s, e); sess.struct_span_err(*op_sp, &msg).emit(); asm::InlineAsmReg::Err }) @@ -156,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { InlineAsmRegOrRegClass::RegClass(s) => { asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| { - let msg = format!("invalid register class `{}`: {}", s.as_str(), e); + let msg = format!("invalid register class `{}`: {}", s, e); sess.struct_span_err(*op_sp, &msg).emit(); asm::InlineAsmRegClass::Err }) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index fd2dd6cf6c7f1..d6b0ac158df9f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -62,9 +62,9 @@ impl<'a> PostExpansionVisitor<'a> { let ast::StrLit { symbol_unescaped, span, .. } = abi; if let ast::Const::Yes(_) = constness { - match symbol_unescaped.as_str() { + match symbol_unescaped { // Stable - "Rust" | "C" => {} + sym::Rust | sym::C => {} abi => gate_feature_post!( &self, const_extern_fn, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 5186aee57fb12..80fd9726fc780 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -55,7 +55,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' // The initial byte `4` instructs GDB that the following pretty printer // is defined inline as opposed to in a standalone file. section_contents.extend_from_slice(b"\x04"); - let vis_name = format!("pretty-printer-{}-{}\n", crate_name.as_str(), index); + let vis_name = format!("pretty-printer-{}-{}\n", crate_name, index); section_contents.extend_from_slice(vis_name.as_bytes()); section_contents.extend_from_slice(&visualizer.src); diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs index b744594ddb7e6..9a2ab3e32248b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -228,7 +228,7 @@ pub fn suggest_adding_lifetime_params<'tcx>( if is_impl { sugg.push_str(" and update trait if needed"); } - err.multipart_suggestion(sugg.as_str(), suggestions, Applicability::MaybeIncorrect); + err.multipart_suggestion(sugg, suggestions, Applicability::MaybeIncorrect); true } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 1add91fc9c531..7381019a62016 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -77,7 +77,7 @@ fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol) .sess .struct_span_err( attr.span, - &format!("`{}` attribute can only be used on functions", sym.as_str()), + &format!("`{}` attribute can only be used on functions", sym), ) .emit(); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 18ffe9528f565..cc3c74d4276ff 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1630,7 +1630,7 @@ impl<'a> Resolver<'a> { "{}{} `{}` defined here", prefix, suggestion.res.descr(), - suggestion.candidate.as_str(), + suggestion.candidate, ), ); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 03cb1cfcfc9ef..c82fd07035e03 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -80,7 +80,7 @@ impl ForLifetimeSpanType { } } - pub(crate) fn suggestion(&self, sugg: &str) -> String { + pub(crate) fn suggestion(&self, sugg: impl std::fmt::Display) -> String { match self { Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg), Self::BoundTail | Self::TypeTail => format!(", {}", sugg), @@ -2311,8 +2311,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { let suggest_existing = |err: &mut Diagnostic, - name: &str, - formatters: Vec String>>>| { + name: Symbol, + formatters: Vec String>>>| { if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) = self.missing_named_lifetime_spots.iter().rev().next() { @@ -2332,7 +2332,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { // If all single char lifetime names are present, we wrap around and double the chars. let lt_name = (1..) .flat_map(a_to_z_repeat_n) - .find(|lt| !lifetime_names.contains(&Symbol::intern(<))) + .map(|lt| Symbol::intern(<)) + .find(|lt| !lifetime_names.contains(lt)) .unwrap(); let msg = format!( "consider making the {} lifetime-generic with a new `{}` lifetime", @@ -2359,7 +2360,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { introduce_suggestion.push((*for_span, for_sugg)); for ((span, _), formatter) in spans_with_counts.iter().zip(formatters.iter()) { if let Some(formatter) = formatter { - introduce_suggestion.push((*span, formatter(<_name))); + introduce_suggestion.push((*span, formatter(lt_name))); } } err.multipart_suggestion_verbose( @@ -2582,7 +2583,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { let lifetime_names: Vec<_> = lifetime_names.iter().collect(); match &lifetime_names[..] { [name] => { - let mut suggs: Vec String>>> = Vec::new(); + let mut suggs: Vec String>>> = Vec::new(); for (snippet, (_, count)) in snippets.iter().zip(spans_with_counts.iter().copied()) { suggs.push(match snippet.as_deref() { @@ -2590,7 +2591,11 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { Some("'_") => Some(Box::new(|n| n.to_string())), Some("") => Some(Box::new(move |n| format!("{}, ", n).repeat(count))), Some("<") => Some(Box::new(move |n| { - std::iter::repeat(n).take(count).collect::>().join(", ") + std::iter::repeat(n) + .take(count) + .map(|n| n.to_string()) + .collect::>() + .join(", ") })), Some(snippet) if !snippet.ends_with('>') => Some(Box::new(move |name| { format!( @@ -2605,7 +2610,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { _ => None, }); } - suggest_existing(err, name.as_str(), suggs); + suggest_existing(err, **name, suggs); } [] => { let mut suggs = Vec::new(); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 4210560f5312b..54dd15270a136 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -325,7 +325,7 @@ impl<'a> ResolverExpand for Resolver<'a> { UNUSED_MACROS, node_id, ident.span, - &format!("unused macro definition: `{}`", ident.as_str()), + &format!("unused macro definition: `{}`", ident.name), ); } for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() { @@ -341,7 +341,7 @@ impl<'a> ResolverExpand for Resolver<'a> { &format!( "{} rule of macro `{}` is never used", crate::diagnostics::ordinalize(arm_i + 1), - ident.as_str() + ident.name ), ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9b6967621f1dc..5e26809142d7c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -257,6 +257,7 @@ symbols! { Result, Return, Right, + Rust, RustcDecodable, RustcEncodable, Send, 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 aa1c91362891b..5dcd6e585e891 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -474,7 +474,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(ref s) = label { // If it has a custom `#[rustc_on_unimplemented]` // error message, let's display it as the label! - err.span_label(span, s.as_str()); + err.span_label(span, s); if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { // When the self type is a type param We don't need to "the trait // `std::marker::Sized` is not implemented for `T`" as we will point @@ -531,7 +531,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let enclosing_scope_span = tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body)); - err.span_label(enclosing_scope_span, s.as_str()); + err.span_label(enclosing_scope_span, s); } self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index deaadf0e5c84a..09808ce0dda85 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -259,7 +259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &cause, &mut |err| { if let Some((span, msg)) = &ret_reason { - err.span_label(*span, msg.as_str()); + err.span_label(*span, msg); } else if let ExprKind::Block(block, _) = &then_expr.kind && let Some(expr) = &block.expr { diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 42893789957f4..b054d94aa334e 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -395,8 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false, ), }; - let mut err = - struct_span_err!(self.tcx.sess, op.span, E0369, "{}", message.as_str()); + let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}"); if !lhs_expr.span.eq(&rhs_expr.span) { self.add_type_neq_err_label( &mut err, From 454313fe83dc27df2508cbd82e6f2a2221d7f8d3 Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts <2467194+yoshuawuyts@users.noreply.github.com> Date: Mon, 18 Jul 2022 16:04:52 +0200 Subject: [PATCH 03/14] stabilize `core::task::ready!` --- library/core/src/task/mod.rs | 2 +- library/core/src/task/ready.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 71a67a2793a46..c5f89b9a2c608 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -11,7 +11,7 @@ mod wake; pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; -#[unstable(feature = "ready_macro", issue = "70922")] +#[stable(feature = "ready_macro", since = "1.64.0")] pub use ready::ready; #[unstable(feature = "poll_ready", issue = "89780")] pub use ready::Ready; diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 174ca67546033..b1daf545fbe7b 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -13,8 +13,6 @@ use core::task::Poll; /// # Examples /// /// ``` -/// #![feature(ready_macro)] -/// /// use std::task::{ready, Context, Poll}; /// use std::future::{self, Future}; /// use std::pin::Pin; @@ -34,7 +32,6 @@ use core::task::Poll; /// The `ready!` call expands to: /// /// ``` -/// # #![feature(ready_macro)] /// # use std::task::{Context, Poll}; /// # use std::future::{self, Future}; /// # use std::pin::Pin; @@ -53,7 +50,7 @@ use core::task::Poll; /// # Poll::Ready(()) /// # } /// ``` -#[unstable(feature = "ready_macro", issue = "70922")] +#[stable(feature = "ready_macro", since = "1.64.0")] #[rustc_macro_transparency = "semitransparent"] pub macro ready($e:expr) { match $e { From 37c21d6fc714748bb41bb1b9a53152632849a3f3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 18 Jul 2022 21:55:47 +0400 Subject: [PATCH 04/14] Do not suggest "wrapping the expression in `std::num::NonZeroU64`" --- compiler/rustc_typeck/src/check/demand.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 740261cfe743b..867570b42dac2 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -19,6 +19,7 @@ use rustc_span::{BytePos, Span}; use super::method::probe; use std::iter; +use std::ops::Bound; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn emit_coerce_suggestions( @@ -347,6 +348,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // Avoid suggesting wrapping in `NonZeroU64` and alike + if self.tcx.layout_scalar_valid_range(expected_adt.did()) + != (Bound::Unbounded, Bound::Unbounded) + { + return; + } + let compatible_variants: Vec = expected_adt .variants() .iter() From c0569f2aa7311d295cb273f66fbe365f2b5ad893 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 18 Jul 2022 15:22:01 -0400 Subject: [PATCH 05/14] Revert "Stabilize $$ in Rust 1.63.0" This reverts commit 9edaa76adce4de737db54194eb13d6c298827b37. --- compiler/rustc_expand/src/mbe/quoted.rs | 2 + .../rfc-3086-metavar-expr/allowed-features.rs | 12 ----- ...quired-features.rs => required-feature.rs} | 12 +++++ ...eatures.stderr => required-feature.stderr} | 50 ++++++++++++++++--- 4 files changed, 57 insertions(+), 19 deletions(-) delete mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs rename src/test/ui/macros/rfc-3086-metavar-expr/{required-features.rs => required-feature.rs} (65%) rename src/test/ui/macros/rfc-3086-metavar-expr/{required-features.stderr => required-feature.stderr} (52%) diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index d4b8563a03666..707cb73f097f8 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -234,6 +234,8 @@ fn parse_tree( sess, &Token { kind: token::Dollar, span }, ); + } else { + maybe_emit_macro_metavar_expr_feature(features, sess, span); } TokenTree::token(token::Dollar, span) } diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs b/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs deleted file mode 100644 index c248c46f52cd3..0000000000000 --- a/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs +++ /dev/null @@ -1,12 +0,0 @@ -// check-pass - -macro_rules! dollar_dollar { - () => { - macro_rules! bar { - ( $$( $$any:tt )* ) => { $$( $$any )* }; - } - }; -} - -fn main() { -} diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs similarity index 65% rename from src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs rename to src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs index cce3e578aeafe..b4fef11f1e29a 100644 --- a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -5,6 +5,18 @@ macro_rules! count { }; } +macro_rules! dollar_dollar { + () => { + macro_rules! bar { + ( $$( $$any:tt )* ) => { $$( $$any )* }; + //~^ ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + //~| ERROR meta-variable expressions are unstable + } + }; +} + macro_rules! index { ( $( $e:stmt ),* ) => { $( ${ignore(e)} ${index()} )* diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr similarity index 52% rename from src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr rename to src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr index 5efd3b10442d1..ecf598b104d05 100644 --- a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr +++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -1,5 +1,5 @@ error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:3:10 + --> $DIR/required-feature.rs:3:10 | LL | ${ count(e) } | ^^^^^^^^^^^^ @@ -8,7 +8,43 @@ LL | ${ count(e) } = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:10:13 + --> $DIR/required-feature.rs:11:16 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:20 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:39 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:11:43 + | +LL | ( $$( $$any:tt )* ) => { $$( $$any )* }; + | ^ + | + = note: see issue #83527 for more information + = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable + +error[E0658]: meta-variable expressions are unstable + --> $DIR/required-feature.rs:22:13 | LL | $( ${ignore(e)} ${index()} )* | ^^^^^^^^^^^ @@ -17,7 +53,7 @@ LL | $( ${ignore(e)} ${index()} )* = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:10:26 + --> $DIR/required-feature.rs:22:26 | LL | $( ${ignore(e)} ${index()} )* | ^^^^^^^^^ @@ -26,7 +62,7 @@ LL | $( ${ignore(e)} ${index()} )* = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:18:19 + --> $DIR/required-feature.rs:30:19 | LL | 0 $( + 1 ${ignore(i)} )* | ^^^^^^^^^^^ @@ -35,7 +71,7 @@ LL | 0 $( + 1 ${ignore(i)} )* = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:25:13 + --> $DIR/required-feature.rs:37:13 | LL | $( ${ignore(e)} ${length()} )* | ^^^^^^^^^^^ @@ -44,7 +80,7 @@ LL | $( ${ignore(e)} ${length()} )* = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable error[E0658]: meta-variable expressions are unstable - --> $DIR/required-features.rs:25:26 + --> $DIR/required-feature.rs:37:26 | LL | $( ${ignore(e)} ${length()} )* | ^^^^^^^^^^ @@ -52,6 +88,6 @@ LL | $( ${ignore(e)} ${length()} )* = note: see issue #83527 for more information = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable -error: aborting due to 6 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0658`. From 7163e7ff6542b200971a783dc2a720a0ff676e70 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 19 Jul 2022 00:11:21 +0400 Subject: [PATCH 06/14] Suggest a fix for `NonZero*` <- `*` coercion error --- compiler/rustc_span/src/symbol.rs | 10 ++++ compiler/rustc_typeck/src/check/demand.rs | 54 +++++++++++++++++++ library/core/src/num/nonzero.rs | 1 + .../non_zero_assigned_something.rs | 9 ++++ .../non_zero_assigned_something.stderr | 31 +++++++++++ 5 files changed, 105 insertions(+) create mode 100644 src/test/ui/mismatched_types/non_zero_assigned_something.rs create mode 100644 src/test/ui/mismatched_types/non_zero_assigned_something.stderr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d5e65c0b4420a..6ddcfbb05dc70 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -223,6 +223,16 @@ symbols! { LintPass, Mutex, N, + NonZeroI128, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI8, + NonZeroU128, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU8, None, Ok, Option, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 867570b42dac2..31da5cfe7fa66 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.annotate_expected_due_to_let_ty(err, expr, error); self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr); self.suggest_compatible_variants(err, expr, expected, expr_ty); + self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty); if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) { return; } @@ -418,6 +419,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn suggest_non_zero_new_unwrap( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + expected: Ty<'tcx>, + expr_ty: Ty<'tcx>, + ) { + let tcx = self.tcx; + let (adt, unwrap) = match expected.kind() { + // In case Option is wanted, but * is provided, suggest calling new + ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => { + // Unwrap option + let Some(fst) = substs.first() else { return }; + let ty::Adt(adt, _) = fst.expect_ty().kind() else { return }; + + (adt, "") + } + // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types + ty::Adt(adt, _) => (adt, ".unwrap()"), + _ => return, + }; + + let map = [ + (sym::NonZeroU8, tcx.types.u8), + (sym::NonZeroU16, tcx.types.u16), + (sym::NonZeroU32, tcx.types.u32), + (sym::NonZeroU64, tcx.types.u64), + (sym::NonZeroU128, tcx.types.u128), + (sym::NonZeroI8, tcx.types.i8), + (sym::NonZeroI16, tcx.types.i16), + (sym::NonZeroI32, tcx.types.i32), + (sym::NonZeroI64, tcx.types.i64), + (sym::NonZeroI128, tcx.types.i128), + ]; + + let Some((s, _)) = map + .iter() + .find(|&&(s, _)| self.tcx.is_diagnostic_item(s, adt.did())) + .filter(|&&(_, t)| { self.can_coerce(expr_ty, t) }) + else { return }; + + let path = self.tcx.def_path_str(adt.non_enum_variant().def_id); + + err.multipart_suggestion( + format!("consider calling `{s}::new`"), + vec![ + (expr.span.shrink_to_lo(), format!("{path}::new(")), + (expr.span.shrink_to_hi(), format!("){unwrap}")), + ], + Applicability::MaybeIncorrect, + ); + } + pub fn get_conversion_methods( &self, span: Span, diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 92d03b724b40e..4de0a0cf564c5 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -39,6 +39,7 @@ macro_rules! nonzero_integers { #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] + #[rustc_diagnostic_item = stringify!($Ty)] pub struct $Ty($Int); impl $Ty { diff --git a/src/test/ui/mismatched_types/non_zero_assigned_something.rs b/src/test/ui/mismatched_types/non_zero_assigned_something.rs new file mode 100644 index 0000000000000..d2adbe01c1828 --- /dev/null +++ b/src/test/ui/mismatched_types/non_zero_assigned_something.rs @@ -0,0 +1,9 @@ +fn main() { + let _: std::num::NonZeroU64 = 1; + //~^ ERROR mismatched types + //~| HELP consider calling `NonZeroU64::new` + + let _: Option = 1; + //~^ ERROR mismatched types + //~| HELP consider calling `NonZeroU64::new` +} diff --git a/src/test/ui/mismatched_types/non_zero_assigned_something.stderr b/src/test/ui/mismatched_types/non_zero_assigned_something.stderr new file mode 100644 index 0000000000000..d4b2c902f9b2e --- /dev/null +++ b/src/test/ui/mismatched_types/non_zero_assigned_something.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/non_zero_assigned_something.rs:2:35 + | +LL | let _: std::num::NonZeroU64 = 1; + | -------------------- ^ expected struct `NonZeroU64`, found integer + | | + | expected due to this + | +help: consider calling `NonZeroU64::new` + | +LL | let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap(); + | ++++++++++++++++ ++++++++++ + +error[E0308]: mismatched types + --> $DIR/non_zero_assigned_something.rs:6:43 + | +LL | let _: Option = 1; + | ---------------------------- ^ expected enum `Option`, found integer + | | + | expected due to this + | + = note: expected enum `Option` + found type `{integer}` +help: consider calling `NonZeroU64::new` + | +LL | let _: Option = NonZeroU64::new(1); + | ++++++++++++++++ + + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From da2752e00f0139fb13282b2bd97aa0f8c665aee9 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 19 Jul 2022 01:16:25 +0400 Subject: [PATCH 07/14] check accessibility before suggesting wrapping expressions --- compiler/rustc_typeck/src/check/demand.rs | 18 +++--- .../wrap-suggestion-privacy.rs | 24 ++++++++ .../wrap-suggestion-privacy.stderr | 59 +++++++++++++++++++ 3 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/mismatched_types/wrap-suggestion-privacy.rs create mode 100644 src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 31da5cfe7fa66..30d7cc2e5fc6a 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -19,7 +19,6 @@ use rustc_span::{BytePos, Span}; use super::method::probe; use std::iter; -use std::ops::Bound; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn emit_coerce_suggestions( @@ -349,13 +348,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - // Avoid suggesting wrapping in `NonZeroU64` and alike - if self.tcx.layout_scalar_valid_range(expected_adt.did()) - != (Bound::Unbounded, Bound::Unbounded) - { - return; - } - let compatible_variants: Vec = expected_adt .variants() .iter() @@ -364,6 +356,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .filter_map(|variant| { let sole_field = &variant.fields[0]; + + if !sole_field.did.is_local() + && !sole_field.vis.is_accessible_from( + self.tcx.parent_module(expr.hir_id).to_def_id(), + self.tcx, + ) + { + return None; + } + let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { let variant_path = diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs new file mode 100644 index 0000000000000..63cb1a1299147 --- /dev/null +++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs @@ -0,0 +1,24 @@ +mod inner { + pub struct Wrapper(T); +} + +fn needs_wrapper(t: inner::Wrapper) {} +fn needs_wrapping(t: std::num::Wrapping) {} +fn needs_ready(t: std::future::Ready) {} + +fn main() { + // Suggest wrapping expression because type is local + // and its privacy can be easily changed + needs_wrapper(0); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `inner::Wrapper` + + // Suggest wrapping expression because field is accessible + needs_wrapping(0); + //~^ ERROR mismatched types + //~| HELP try wrapping the expression in `std::num::Wrapping` + + // Do not suggest wrapping expression + needs_ready(Some(0)); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr new file mode 100644 index 0000000000000..536638632dec2 --- /dev/null +++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:12:19 + | +LL | needs_wrapper(0); + | ------------- ^ expected struct `Wrapper`, found integer + | | + | arguments to this function are incorrect + | + = note: expected struct `Wrapper` + found type `{integer}` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:5:4 + | +LL | fn needs_wrapper(t: inner::Wrapper) {} + | ^^^^^^^^^^^^^ ---------------------- +help: try wrapping the expression in `inner::Wrapper` + | +LL | needs_wrapper(inner::Wrapper(0)); + | +++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:17:20 + | +LL | needs_wrapping(0); + | -------------- ^ expected struct `Wrapping`, found integer + | | + | arguments to this function are incorrect + | + = note: expected struct `Wrapping` + found type `{integer}` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:6:4 + | +LL | fn needs_wrapping(t: std::num::Wrapping) {} + | ^^^^^^^^^^^^^^ -------------------------- +help: try wrapping the expression in `std::num::Wrapping` + | +LL | needs_wrapping(std::num::Wrapping(0)); + | +++++++++++++++++++ + + +error[E0308]: mismatched types + --> $DIR/wrap-suggestion-privacy.rs:22:17 + | +LL | needs_ready(Some(0)); + | ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option` + | | + | arguments to this function are incorrect + | + = note: expected struct `std::future::Ready` + found enum `Option<{integer}>` +note: function defined here + --> $DIR/wrap-suggestion-privacy.rs:7:4 + | +LL | fn needs_ready(t: std::future::Ready) {} + | ^^^^^^^^^^^ -------------------------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 821e9d56ae14a27048e1e60a4fd75376a0839829 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 18 Jul 2022 14:41:10 -0700 Subject: [PATCH 08/14] Update mdbook --- Cargo.lock | 45 +++++++-------------------------------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a0bff2ee4def..db8e3d5adbb9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -634,7 +634,7 @@ version = "3.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9" dependencies = [ - "heck 0.4.0", + "heck", "proc-macro-error", "proc-macro2", "quote", @@ -1202,17 +1202,14 @@ checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f" [[package]] name = "elasticlunr-rs" -version = "2.3.9" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35622eb004c8f0c5e7e2032815f3314a93df0db30a1ce5c94e62c1ecc81e22b9" +checksum = "e6dae5cac90640734ee881bc5f21b6e5123f4e5235e52428db114abffc2391d6" dependencies = [ - "lazy_static", "regex", "serde", "serde_derive", "serde_json", - "strum", - "strum_macros", ] [[package]] @@ -1735,15 +1732,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.0" @@ -2360,9 +2348,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d" +checksum = "13cdad8057b09a519c6c63e6d7c93ea854f5d7fbfe284df864d5e1140d215a2d" dependencies = [ "ammonia", "anyhow", @@ -2370,7 +2358,7 @@ dependencies = [ "clap", "clap_complete", "elasticlunr-rs", - "env_logger 0.7.1", + "env_logger 0.9.0", "handlebars", "lazy_static", "log", @@ -2379,7 +2367,6 @@ dependencies = [ "pulldown-cmark", "regex", "serde", - "serde_derive", "serde_json", "shlex", "tempfile", @@ -3335,7 +3322,7 @@ dependencies = [ "difference", "env_logger 0.9.0", "futures 0.3.19", - "heck 0.4.0", + "heck", "home", "itertools", "jsonrpc-core", @@ -5134,24 +5121,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b" - -[[package]] -name = "strum_macros" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" -dependencies = [ - "heck 0.3.1", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "syn" version = "1.0.91" From 2edad7d77c91145b594ac80c3dc7906998b7674a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 19 Jul 2022 02:15:56 +0400 Subject: [PATCH 09/14] Apply suggestions from the review - Use `expr.hir_id.owner` instead of `self.tcx.parent_module(expr.hir_id)` - Use `.type_at()` instead of `.first()` + `.expect_ty()` - Use single `.find()` with `&&` condition Co-authored-by: Michael Goulet --- compiler/rustc_typeck/src/check/demand.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 30d7cc2e5fc6a..e5f8b6b5f1e8d 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -358,10 +358,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sole_field = &variant.fields[0]; if !sole_field.did.is_local() - && !sole_field.vis.is_accessible_from( - self.tcx.parent_module(expr.hir_id).to_def_id(), - self.tcx, - ) + && !sole_field + .vis + .is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx) { return None; } @@ -433,8 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // In case Option is wanted, but * is provided, suggest calling new ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => { // Unwrap option - let Some(fst) = substs.first() else { return }; - let ty::Adt(adt, _) = fst.expect_ty().kind() else { return }; + let ty::Adt(adt, _) = substs.type_at(0).kind() else { return }; (adt, "") } @@ -458,8 +456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some((s, _)) = map .iter() - .find(|&&(s, _)| self.tcx.is_diagnostic_item(s, adt.did())) - .filter(|&&(_, t)| { self.can_coerce(expr_ty, t) }) + .find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t)) else { return }; let path = self.tcx.def_path_str(adt.non_enum_variant().def_id); From 5bd88dfa8a0b5d5bcdd84d21e2f465719ce8c328 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 19 Jul 2022 02:33:36 +0400 Subject: [PATCH 10/14] Add a note about privacy to wrapping suggestion --- compiler/rustc_typeck/src/check/demand.rs | 28 +++++++++++-------- .../wrap-suggestion-privacy.stderr | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e5f8b6b5f1e8d..a2d8765289c55 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let compatible_variants: Vec = expected_adt + let compatible_variants: Vec<(String, Option)> = expected_adt .variants() .iter() .filter(|variant| { @@ -357,14 +357,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .filter_map(|variant| { let sole_field = &variant.fields[0]; - if !sole_field.did.is_local() - && !sole_field - .vis - .is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx) - { + let field_is_local = sole_field.did.is_local(); + let field_is_accessible = + sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx); + + if !field_is_local && !field_is_accessible { return None; } + let note_about_variant_field_privacy = (field_is_local && !field_is_accessible) + .then(|| format!(" (its field is private, but it's local to this crate and its privacy can be changed)")); + let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { let variant_path = @@ -373,9 +376,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(path) = variant_path.strip_prefix("std::prelude::") && let Some((_, path)) = path.split_once("::") { - return Some(path.to_string()); + return Some((path.to_string(), note_about_variant_field_privacy)); } - Some(variant_path) + Some((variant_path, note_about_variant_field_privacy)) } else { None } @@ -389,10 +392,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &compatible_variants[..] { [] => { /* No variants to format */ } - [variant] => { + [(variant, note)] => { // Just a single matching variant. err.multipart_suggestion_verbose( - &format!("try wrapping the expression in `{variant}`"), + &format!( + "try wrapping the expression in `{variant}`{note}", + note = note.as_deref().unwrap_or("") + ), vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), (expr.span.shrink_to_hi(), ")".to_string()), @@ -407,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "try wrapping the expression in a variant of `{}`", self.tcx.def_path_str(expected_adt.did()) ), - compatible_variants.into_iter().map(|variant| { + compatible_variants.into_iter().map(|(variant, _)| { vec![ (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), (expr.span.shrink_to_hi(), ")".to_string()), diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr index 536638632dec2..e8eb8d263ec79 100644 --- a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr +++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr @@ -13,7 +13,7 @@ note: function defined here | LL | fn needs_wrapper(t: inner::Wrapper) {} | ^^^^^^^^^^^^^ ---------------------- -help: try wrapping the expression in `inner::Wrapper` +help: try wrapping the expression in `inner::Wrapper` (its field is private, but it's local to this crate and its privacy can be changed) | LL | needs_wrapper(inner::Wrapper(0)); | +++++++++++++++ + From 959c215001378f770b2a5faa058f591d2d5f9081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 19 Jul 2022 10:16:45 +0300 Subject: [PATCH 11/14] :arrow_up: rust-analyzer --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 5342f47f42766..897a7ec4b826f 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 5342f47f4276641ddb5f0a5e08fb307742d6cdc4 +Subproject commit 897a7ec4b826f85ec1626870e734490701138097 From 1cbacc0c8aa3c4d99a073108d4ec7a535ff79102 Mon Sep 17 00:00:00 2001 From: aticu <15schnic@gmail.com> Date: Sun, 12 Jun 2022 17:46:57 +0200 Subject: [PATCH 12/14] Add E0790 as more specific variant of E0283 --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0283.md | 41 +++------ .../src/error_codes/E0790.md | 51 ++++++++++ compiler/rustc_middle/src/ty/trait_def.rs | 4 + .../src/traits/error_reporting/mod.rs | 92 +++++++++++++++++++ src/test/ui/associated-consts/issue-63496.rs | 4 +- .../ui/associated-consts/issue-63496.stderr | 28 +++--- src/test/ui/associated-item/issue-48027.rs | 2 +- .../ui/associated-item/issue-48027.stderr | 14 +-- .../associated-types-unconstrained.rs | 2 +- .../associated-types-unconstrained.stderr | 11 ++- src/test/ui/error-codes/E0283.rs | 2 +- src/test/ui/error-codes/E0283.stderr | 15 ++- src/test/ui/error-codes/E0790.rs | 53 +++++++++++ src/test/ui/error-codes/E0790.stderr | 73 +++++++++++++++ src/test/ui/issues/issue-54954.rs | 2 +- src/test/ui/issues/issue-54954.stderr | 16 ++-- src/test/ui/issues/issue-58022.rs | 2 +- src/test/ui/issues/issue-58022.stderr | 17 ++-- .../traits/static-method-generic-inference.rs | 2 +- .../static-method-generic-inference.stderr | 14 ++- 21 files changed, 354 insertions(+), 92 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0790.md create mode 100644 src/test/ui/error-codes/E0790.rs create mode 100644 src/test/ui/error-codes/E0790.stderr diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 977318b85895e..97766b8368ab6 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -492,6 +492,7 @@ E0785: include_str!("./error_codes/E0785.md"), E0786: include_str!("./error_codes/E0786.md"), E0787: include_str!("./error_codes/E0787.md"), E0788: include_str!("./error_codes/E0788.md"), +E0790: include_str!("./error_codes/E0790.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md index 6885f9a486d3d..e5a3179aabf05 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0283.md +++ b/compiler/rustc_error_codes/src/error_codes/E0283.md @@ -3,48 +3,31 @@ An implementation cannot be chosen unambiguously because of lack of information. Erroneous code example: ```compile_fail,E0283 -trait Generator { - fn create() -> u32; -} - -struct Impl; - -impl Generator for Impl { - fn create() -> u32 { 1 } -} +struct Foo; -struct AnotherImpl; - -impl Generator for AnotherImpl { - fn create() -> u32 { 2 } +impl Into for Foo { + fn into(self) -> u32 { 1 } } fn main() { - let cont: u32 = Generator::create(); - // error, impossible to choose one of Generator trait implementation - // Should it be Impl or AnotherImpl, maybe something else? + let foo = Foo; + let bar: u32 = foo.into() * 1u32; } ``` This error can be solved by adding type annotations that provide the missing -information to the compiler. In this case, the solution is to use a concrete -type: +information to the compiler. In this case, the solution is to specify the +fully-qualified method: ``` -trait Generator { - fn create() -> u32; -} +struct Foo; -struct AnotherImpl; - -impl Generator for AnotherImpl { - fn create() -> u32 { 2 } +impl Into for Foo { + fn into(self) -> u32 { 1 } } fn main() { - let gen1 = AnotherImpl::create(); - - // if there are multiple methods with same name (different traits) - let gen2 = ::create(); + let foo = Foo; + let bar: u32 = >::into(foo) * 1u32; } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md new file mode 100644 index 0000000000000..93d9636626d44 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0790.md @@ -0,0 +1,51 @@ +You need to specify a specific implementation of the trait in order to call the +method. + +Erroneous code example: + +```compile_fail,E0790 +trait Generator { + fn create() -> u32; +} + +struct Impl; + +impl Generator for Impl { + fn create() -> u32 { 1 } +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let cont: u32 = Generator::create(); + // error, impossible to choose one of Generator trait implementation + // Should it be Impl or AnotherImpl, maybe something else? +} +``` + +This error can be solved by adding type annotations that provide the missing +information to the compiler. In this case, the solution is to use a concrete +type: + +``` +trait Generator { + fn create() -> u32; +} + +struct AnotherImpl; + +impl Generator for AnotherImpl { + fn create() -> u32 { 2 } +} + +fn main() { + let gen1 = AnotherImpl::create(); + + // if there are multiple methods with same name (different traits) + let gen2 = ::create(); +} +``` diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 826c16dda4aa7..541dace5cc2bb 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -74,6 +74,10 @@ impl TraitImpls { pub fn blanket_impls(&self) -> &[DefId] { self.blanket_impls.as_slice() } + + pub fn non_blanket_impls(&self) -> &FxIndexMap> { + &self.non_blanket_impls + } } impl<'tcx> TraitDef { 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 8a679ca005f3d..585159e309f69 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2104,6 +2104,98 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { ); } } + + if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) = + (body_id, subst.map(|subst| subst.unpack())) + { + struct FindExprBySpan<'hir> { + span: Span, + result: Option<&'hir hir::Expr<'hir>>, + } + + impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if self.span == ex.span { + self.result = Some(ex); + } else { + hir::intravisit::walk_expr(self, ex); + } + } + } + + let mut expr_finder = FindExprBySpan { span, result: None }; + + expr_finder.visit_expr(&self.tcx.hir().body(body_id).value); + + if let Some(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. } + ) = expr_finder.result + && let [ + .., + trait_path_segment @ hir::PathSegment { + res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)), + .. + }, + hir::PathSegment { + ident: assoc_item_name, + res: Some(rustc_hir::def::Res::Def(_, item_id)), + .. + } + ] = path.segments + && data.trait_ref.def_id == *trait_id + && self.tcx.trait_of_item(item_id) == Some(*trait_id) + && !self.is_tainted_by_errors() + { + let (verb, noun) = match self.tcx.associated_item(item_id).kind { + ty::AssocKind::Const => ("refer to the", "constant"), + ty::AssocKind::Fn => ("call", "function"), + ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here + }; + + // Replace the more general E0283 with a more specific error + err.cancel(); + err = self.tcx.sess.struct_span_err_with_code( + span, + &format!( + "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type", + ), + rustc_errors::error_code!(E0790), + ); + + if let Some(local_def_id) = data.trait_ref.def_id.as_local() + && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id) + && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) { + err.span_label(method_ref.span, format!("`{}::{}` defined here", trait_name, assoc_item_name)); + } + + err.span_label(span, format!("cannot {verb} associated {noun} of trait")); + + let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id); + + if trait_impls.blanket_impls().is_empty() + && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next() + && let Some(impl_def_id) = impl_ty.def() { + let message = if trait_impls.non_blanket_impls().len() == 1 { + "use the fully-qualified path to the only available implementation".to_string() + } else { + format!( + "use a fully-qualified path to a specific available implementation ({} found)", + trait_impls.non_blanket_impls().len() + ) + }; + + err.multipart_suggestion( + message, + vec![ + (trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())), + (trait_path_segment.ident.span.shrink_to_hi(), format!(">")) + ], + Applicability::MaybeIncorrect + ); + } + } + }; + err } diff --git a/src/test/ui/associated-consts/issue-63496.rs b/src/test/ui/associated-consts/issue-63496.rs index f9f663af5e265..67ef4e74cf2e0 100644 --- a/src/test/ui/associated-consts/issue-63496.rs +++ b/src/test/ui/associated-consts/issue-63496.rs @@ -2,8 +2,8 @@ trait A { const C: usize; fn f() -> ([u8; A::C], [u8; A::C]); - //~^ ERROR: type annotations needed - //~| ERROR: type annotations needed + //~^ ERROR: E0790 + //~| ERROR: E0790 } fn main() {} diff --git a/src/test/ui/associated-consts/issue-63496.stderr b/src/test/ui/associated-consts/issue-63496.stderr index db39fd762c307..f2a4e01adea43 100644 --- a/src/test/ui/associated-consts/issue-63496.stderr +++ b/src/test/ui/associated-consts/issue-63496.stderr @@ -1,27 +1,21 @@ -error[E0283]: type annotations needed +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type --> $DIR/issue-63496.rs:4:21 | +LL | const C: usize; + | --------------- `A::C` defined here +LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ - | | - | cannot infer type - | help: use the fully qualified path to an implementation: `::C` - | - = note: cannot satisfy `_: A` - = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + | ^^^^ cannot refer to the associated constant of trait -error[E0283]: type annotations needed +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type --> $DIR/issue-63496.rs:4:33 | +LL | const C: usize; + | --------------- `A::C` defined here +LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ - | | - | cannot infer type - | help: use the fully qualified path to an implementation: `::C` - | - = note: cannot satisfy `_: A` - = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + | ^^^^ cannot refer to the associated constant of trait error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0790`. diff --git a/src/test/ui/associated-item/issue-48027.rs b/src/test/ui/associated-item/issue-48027.rs index c9b4ccd3e8a99..d2b51184c999a 100644 --- a/src/test/ui/associated-item/issue-48027.rs +++ b/src/test/ui/associated-item/issue-48027.rs @@ -1,6 +1,6 @@ trait Bar { const X: usize; - fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed + fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790 } impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 5487af1a835d8..45ea419336b2c 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -13,19 +13,15 @@ LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait -error[E0283]: type annotations needed +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type --> $DIR/issue-48027.rs:3:32 | +LL | const X: usize; + | --------------- `Bar::X` defined here LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ - | | - | cannot infer type - | help: use the fully qualified path to an implementation: `::X` - | - = note: cannot satisfy `_: Bar` - = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + | ^^^^^^ cannot refer to the associated constant of trait error: aborting due to 2 previous errors -Some errors have detailed explanations: E0038, E0283. +Some errors have detailed explanations: E0038, E0790. For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/associated-types/associated-types-unconstrained.rs b/src/test/ui/associated-types/associated-types-unconstrained.rs index b97d4af184f92..2fb27bf3cd1eb 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.rs +++ b/src/test/ui/associated-types/associated-types-unconstrained.rs @@ -12,5 +12,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::bar(); - //~^ ERROR type annotations needed + //~^ ERROR E0790 } diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 60ec23cf655ab..e51a8f3bd1a3a 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,11 +1,12 @@ -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/associated-types-unconstrained.rs:14:20 | +LL | fn bar() -> isize; + | ------------------ `Foo::bar` defined here +... LL | let x: isize = Foo::bar(); - | ^^^^^^^^ cannot infer type - | - = note: cannot satisfy `_: Foo` + | ^^^^^^^^ cannot call associated function of trait error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0790`. diff --git a/src/test/ui/error-codes/E0283.rs b/src/test/ui/error-codes/E0283.rs index 4d7c2f2396d75..0643af4b7e8c6 100644 --- a/src/test/ui/error-codes/E0283.rs +++ b/src/test/ui/error-codes/E0283.rs @@ -27,7 +27,7 @@ impl Generator for AnotherImpl { } fn main() { - let cont: u32 = Generator::create(); //~ ERROR E0283 + let cont: u32 = Generator::create(); //~ ERROR E0790 } fn buzz() { diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index a107160d11a35..90a28874ead8c 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,10 +1,16 @@ -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/E0283.rs:30:21 | +LL | fn create() -> u32; + | ------------------- `Generator::create` defined here +... LL | let cont: u32 = Generator::create(); - | ^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use a fully-qualified path to a specific available implementation (2 found) | - = note: cannot satisfy `_: Generator` +LL | let cont: u32 = <::Impl as Generator>::create(); + | ++++++++++ + error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 @@ -27,4 +33,5 @@ LL | let bar = >::into(foo_impl) * 1u32; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0283`. +Some errors have detailed explanations: E0283, E0790. +For more information about an error, try `rustc --explain E0283`. diff --git a/src/test/ui/error-codes/E0790.rs b/src/test/ui/error-codes/E0790.rs new file mode 100644 index 0000000000000..d99006d2df734 --- /dev/null +++ b/src/test/ui/error-codes/E0790.rs @@ -0,0 +1,53 @@ +mod inner { + pub trait MyTrait { + const MY_ASSOC_CONST: (); + + fn my_fn(); + } + + pub struct MyStruct; + + impl MyTrait for MyStruct { + const MY_ASSOC_CONST: () = (); + + fn my_fn() {} + } + + fn call() { + MyTrait::my_fn(); //~ ERROR E0790 + } + + fn use_const() { + let _ = MyTrait::MY_ASSOC_CONST; //~ ERROR E0790 + } +} + +fn call_inner() { + inner::MyTrait::my_fn(); //~ ERROR E0790 +} + +fn use_const_inner() { + let _ = inner::MyTrait::MY_ASSOC_CONST; //~ ERROR E0790 +} + +trait MyTrait2 { + fn my_fn(); +} + +struct Impl1; + +impl MyTrait2 for Impl1 { + fn my_fn() {} +} + +struct Impl2; + +impl MyTrait2 for Impl2 { + fn my_fn() {} +} + +fn call_multiple_impls() { + MyTrait2::my_fn(); //~ ERROR E0790 +} + +fn main() {} diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr new file mode 100644 index 0000000000000..6e173a9682a0c --- /dev/null +++ b/src/test/ui/error-codes/E0790.stderr @@ -0,0 +1,73 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:17:9 + | +LL | fn my_fn(); + | ----------- `MyTrait::my_fn` defined here +... +LL | MyTrait::my_fn(); + | ^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <::inner::MyStruct as MyTrait>::my_fn(); + | +++++++++++++++++++++ + + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:21:17 + | +LL | const MY_ASSOC_CONST: (); + | ------------------------- `MyTrait::MY_ASSOC_CONST` defined here +... +LL | let _ = MyTrait::MY_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _ = <::inner::MyStruct as MyTrait>::MY_ASSOC_CONST; + | +++++++++++++++++++++ + + +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:26:5 + | +LL | fn my_fn(); + | ----------- `MyTrait::my_fn` defined here +... +LL | inner::MyTrait::my_fn(); + | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | inner::<::inner::MyStruct as MyTrait>::my_fn(); + | +++++++++++++++++++++ + + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:30:13 + | +LL | const MY_ASSOC_CONST: (); + | ------------------------- `MyTrait::MY_ASSOC_CONST` defined here +... +LL | let _ = inner::MyTrait::MY_ASSOC_CONST; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let _ = inner::<::inner::MyStruct as MyTrait>::MY_ASSOC_CONST; + | +++++++++++++++++++++ + + +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/E0790.rs:50:5 + | +LL | fn my_fn(); + | ----------- `MyTrait2::my_fn` defined here +... +LL | MyTrait2::my_fn(); + | ^^^^^^^^^^^^^^^ cannot call associated function of trait + | +help: use a fully-qualified path to a specific available implementation (2 found) + | +LL | <::Impl1 as MyTrait2>::my_fn(); + | +++++++++++ + + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0790`. diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs index ddd3914154147..d4e1df2277094 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/issues/issue-54954.rs @@ -1,5 +1,5 @@ const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); -//~^ ERROR type annotations needed +//~^ ERROR E0790 trait Tt { const fn const_val() -> usize { diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 6e8d3cac9a7e4..668985c2b5914 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -4,13 +4,17 @@ error[E0379]: functions in traits cannot be declared const LL | const fn const_val() -> usize { | ^^^^^ functions in traits cannot be const -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/issue-54954.rs:1:24 | -LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - | - = note: cannot satisfy `_: Tt` +LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait +... +LL | / const fn const_val() -> usize { +LL | | +LL | | core::mem::size_of::() +LL | | } + | |_____- `Tt::const_val` defined here error[E0080]: evaluation of constant value failed --> $DIR/issue-54954.rs:11:15 @@ -26,5 +30,5 @@ LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { error: aborting due to 4 previous errors -Some errors have detailed explanations: E0080, E0283, E0379. +Some errors have detailed explanations: E0080, E0379, E0790. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs index e4b9b3b53a69e..2a8a1eaa6d3a3 100644 --- a/src/test/ui/issues/issue-58022.rs +++ b/src/test/ui/issues/issue-58022.rs @@ -2,7 +2,7 @@ pub trait Foo: Sized { const SIZE: usize; fn new(slice: &[u8; Foo::SIZE]) -> Self; - //~^ ERROR: type annotations needed + //~^ ERROR: E0790 } pub struct Bar(T); diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index 0128b70e21643..6d24209ad3c7e 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -4,19 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo LL | Foo(Box::new(*slice)) | ^^^ not a function, tuple struct or tuple variant -error[E0283]: type annotations needed +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type --> $DIR/issue-58022.rs:4:25 | +LL | const SIZE: usize; + | ------------------ `Foo::SIZE` defined here +LL | LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ - | | - | cannot infer type - | help: use the fully qualified path to an implementation: `::SIZE` - | - = note: cannot satisfy `_: Foo` - = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + | ^^^^^^^^^ cannot refer to the associated constant of trait error: aborting due to 2 previous errors -Some errors have detailed explanations: E0283, E0423. -For more information about an error, try `rustc --explain E0283`. +Some errors have detailed explanations: E0423, E0790. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/traits/static-method-generic-inference.rs b/src/test/ui/traits/static-method-generic-inference.rs index 759416d1901db..f4e94c4f7867c 100644 --- a/src/test/ui/traits/static-method-generic-inference.rs +++ b/src/test/ui/traits/static-method-generic-inference.rs @@ -22,7 +22,7 @@ mod base { pub fn foo() { let _f: base::Foo = base::HasNew::new(); - //~^ ERROR type annotations needed + //~^ ERROR E0790 } fn main() { } diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr index 1a0bcf00a673a..f1b8f23ecc7db 100644 --- a/src/test/ui/traits/static-method-generic-inference.stderr +++ b/src/test/ui/traits/static-method-generic-inference.stderr @@ -1,11 +1,17 @@ -error[E0283]: type annotations needed +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/static-method-generic-inference.rs:24:25 | +LL | fn new() -> T; + | -------------- `HasNew::new` defined here +... LL | let _f: base::Foo = base::HasNew::new(); - | ^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | - = note: cannot satisfy `_: HasNew` +help: use the fully-qualified path to the only available implementation + | +LL | let _f: base::Foo = base::<::base::Foo as HasNew>::new(); + | +++++++++++++++ + error: aborting due to previous error -For more information about this error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0790`. From 38ea23558eca629d668208e368dfa711b8229192 Mon Sep 17 00:00:00 2001 From: aticu <15schnic@gmail.com> Date: Mon, 13 Jun 2022 09:32:54 +0200 Subject: [PATCH 13/14] Don't use main; improve example --- .../rustc_error_codes/src/error_codes/E0283.md | 14 +++++--------- .../rustc_error_codes/src/error_codes/E0790.md | 16 ++++++---------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md index e5a3179aabf05..79d2c8204f956 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0283.md +++ b/compiler/rustc_error_codes/src/error_codes/E0283.md @@ -9,15 +9,13 @@ impl Into for Foo { fn into(self) -> u32 { 1 } } -fn main() { - let foo = Foo; - let bar: u32 = foo.into() * 1u32; -} +let foo = Foo; +let bar: u32 = foo.into() * 1u32; ``` This error can be solved by adding type annotations that provide the missing information to the compiler. In this case, the solution is to specify the -fully-qualified method: +trait's type parameter: ``` struct Foo; @@ -26,8 +24,6 @@ impl Into for Foo { fn into(self) -> u32 { 1 } } -fn main() { - let foo = Foo; - let bar: u32 = >::into(foo) * 1u32; -} +let foo = Foo; +let bar: u32 = Into::::into(foo) * 1u32; ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md index 93d9636626d44..2aee9dfbdbd94 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0790.md +++ b/compiler/rustc_error_codes/src/error_codes/E0790.md @@ -20,11 +20,9 @@ impl Generator for AnotherImpl { fn create() -> u32 { 2 } } -fn main() { - let cont: u32 = Generator::create(); - // error, impossible to choose one of Generator trait implementation - // Should it be Impl or AnotherImpl, maybe something else? -} +let cont: u32 = Generator::create(); +// error, impossible to choose one of Generator trait implementation +// Should it be Impl or AnotherImpl, maybe something else? ``` This error can be solved by adding type annotations that provide the missing @@ -42,10 +40,8 @@ impl Generator for AnotherImpl { fn create() -> u32 { 2 } } -fn main() { - let gen1 = AnotherImpl::create(); +let gen1 = AnotherImpl::create(); - // if there are multiple methods with same name (different traits) - let gen2 = ::create(); -} +// if there are multiple methods with same name (different traits) +let gen2 = ::create(); ``` From e2ecb68a0eeee6db4d8f605374e656822186f8b4 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Tue, 19 Jul 2022 17:00:51 +0800 Subject: [PATCH 14/14] use `par_for_each_in` in `par_body_owners` and `collect_crate_mono_items` --- compiler/rustc_data_structures/src/sync.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 +--- compiler/rustc_monomorphize/src/collector.rs | 4 ++-- src/test/ui/privacy/privacy2.stderr | 8 +++++++- src/test/ui/privacy/privacy3.stderr | 8 +++++++- src/test/ui/type_length_limit.stderr | 11 ++++++++++- 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index cf0940df9e487..52952a7932dbc 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -146,7 +146,7 @@ cfg_if! { t.into_iter() } - pub fn par_for_each_in(t: T, for_each: impl Fn(T::Item) + Sync + Send) { + pub fn par_for_each_in(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) { // We catch panics here ensuring that all the loop iterations execute. // This makes behavior consistent with the parallel compiler. let mut panic = None; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3a59b2069b3b7..0001e1aa53efc 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -491,9 +491,7 @@ impl<'hir> Map<'hir> { } pub fn par_body_owners(self, f: F) { - use rustc_data_structures::sync::{par_iter, ParallelIterator}; - - par_iter(&self.tcx.hir_crate_items(()).body_owners[..]).for_each(|&def_id| f(def_id)); + par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); } pub fn ty_param_owner(self, def_id: LocalDefId) -> LocalDefId { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index d9fa4d65b3a9a..e3cfb034e40ad 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -180,7 +180,7 @@ //! regardless of whether it is actually needed or not. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator}; +use rustc_data_structures::sync::{par_for_each_in, MTLock, MTRef}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; @@ -346,7 +346,7 @@ pub fn collect_crate_mono_items( let inlining_map: MTRef<'_, _> = &mut inlining_map; tcx.sess.time("monomorphization_collector_graph_walk", || { - par_iter(roots).for_each(|root| { + par_for_each_in(roots, |root| { let mut recursion_depths = DefIdMap::default(); collect_items_rec( tcx, diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr index c2a33ce1f59b3..882f314655d83 100644 --- a/src/test/ui/privacy/privacy2.stderr +++ b/src/test/ui/privacy/privacy2.stderr @@ -23,7 +23,13 @@ LL | pub fn foo() {} error: requires `sized` lang_item -error: aborting due to 3 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr index 22c1e48b07d94..42ce456d962a1 100644 --- a/src/test/ui/privacy/privacy3.stderr +++ b/src/test/ui/privacy/privacy3.stderr @@ -6,6 +6,12 @@ LL | use bar::gpriv; error: requires `sized` lang_item -error: aborting due to 2 previous errors +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: requires `sized` lang_item + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index a2ddffff997d8..1508b84c1b6e7 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -7,5 +7,14 @@ LL | pub fn drop(_x: T) {} = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate -error: aborting due to previous error +error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)` + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + | +LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' + = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + +error: aborting due to 2 previous errors