From c2cc90402b6a896c3273a57e506d6c02a1ec6038 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 7 Mar 2024 20:01:28 -0700 Subject: [PATCH 1/9] diagnostics: suggest `Clone` bounds when noop `clone()` --- .../src/traits/error_reporting/suggestions.rs | 60 +++++++++++++++---- tests/ui/suggestions/clone-bounds-121524.rs | 19 ++++++ .../ui/suggestions/clone-bounds-121524.stderr | 19 ++++++ 3 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 tests/ui/suggestions/clone-bounds-121524.rs create mode 100644 tests/ui/suggestions/clone-bounds-121524.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1241227a5af39..0dc59a4578a94 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -987,10 +987,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { else { return false; }; - let arg_node = self.tcx.hir_node(*arg_hir_id); - let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { - return false; - }; let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); let has_clone = |ty| { @@ -998,6 +994,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .must_apply_modulo_regions() }; + let existing_clone_call = match self.tcx.hir_node(*arg_hir_id) { + // It's just a variable. Propose cloning it. + Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) => None, + // It's already a call to `clone()`. We might be able to suggest + // adding a `+ Clone` bound, though. + Node::Expr(Expr { + kind: + hir::ExprKind::MethodCall( + hir::PathSegment { ident, .. }, + _receiver, + &[], + call_span, + ), + hir_id, + .. + }) if ident.name == sym::clone + && !call_span.from_expansion() + && !has_clone(*inner_ty) => + { + // We only care about method calls corresponding to the real `Clone` trait. + let Some(typeck_results) = self.typeck_results.as_ref() else { return false }; + let Some((DefKind::AssocFn, did)) = typeck_results.type_dependent_def(*hir_id) + else { + return false; + }; + if self.tcx.trait_of_item(did) != Some(clone_trait) { + return false; + } + Some(ident.span) + } + _ => return false, + }; + let new_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), @@ -1015,12 +1044,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { None, ); } - err.span_suggestion_verbose( - obligation.cause.span.shrink_to_hi(), - "consider using clone here", - ".clone()".to_string(), - Applicability::MaybeIncorrect, - ); + if let Some(existing_clone_call) = existing_clone_call { + err.span_note( + existing_clone_call, + format!( + "this `clone()` copies the reference, \ + which does not do anything, \ + because `{inner_ty}` does not implement `Clone`" + ), + ); + } else { + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, + ); + } return true; } false diff --git a/tests/ui/suggestions/clone-bounds-121524.rs b/tests/ui/suggestions/clone-bounds-121524.rs new file mode 100644 index 0000000000000..8cd60b452de09 --- /dev/null +++ b/tests/ui/suggestions/clone-bounds-121524.rs @@ -0,0 +1,19 @@ +#[derive(Clone)] +struct ThingThatDoesAThing; + +trait DoesAThing {} + +impl DoesAThing for ThingThatDoesAThing {} + +fn clones_impl_ref_inline(thing: &impl DoesAThing) { + //~^ HELP consider further restricting this bound + drops_impl_owned(thing.clone()); //~ ERROR E0277 + //~^ NOTE copies the reference + //~| NOTE the trait `DoesAThing` is not implemented for `&impl DoesAThing` +} + +fn drops_impl_owned(_thing: impl DoesAThing) { } + +fn main() { + clones_impl_ref_inline(&ThingThatDoesAThing); +} diff --git a/tests/ui/suggestions/clone-bounds-121524.stderr b/tests/ui/suggestions/clone-bounds-121524.stderr new file mode 100644 index 0000000000000..6d60508a4a14c --- /dev/null +++ b/tests/ui/suggestions/clone-bounds-121524.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `&impl DoesAThing: DoesAThing` is not satisfied + --> $DIR/clone-bounds-121524.rs:10:22 + | +LL | drops_impl_owned(thing.clone()); + | ^^^^^^^^^^^^^ the trait `DoesAThing` is not implemented for `&impl DoesAThing` + | +note: this `clone()` copies the reference, which does not do anything, because `impl DoesAThing` does not implement `Clone` + --> $DIR/clone-bounds-121524.rs:10:28 + | +LL | drops_impl_owned(thing.clone()); + | ^^^^^ +help: consider further restricting this bound + | +LL | fn clones_impl_ref_inline(thing: &impl DoesAThing + Clone) { + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 2a9d1ed538546483702622a22132f75e24f34ab9 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 17 Oct 2023 16:18:59 -0700 Subject: [PATCH 2/9] Add `-Z external-sanitizer-runtime` This adds the unstable `-Z external-sanitizer-runtime` flag that will prevent rustc from emitting linker paths for the in-tree LLVM sanitizer runtime library. --- compiler/rustc_codegen_ssa/src/back/link.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e70cc9b621616..a37663b59724a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1206,6 +1206,7 @@ fn add_sanitizer_libraries( // Everywhere else the runtimes are currently distributed as static // libraries which should be linked to executables only. let needs_runtime = !sess.target.is_like_android + && !sess.opts.unstable_opts.external_clangrt && match crate_type { CrateType::Executable => true, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2f018fbaa8679..bf7f047af5bdc 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1645,6 +1645,8 @@ options! { "emit the bc module with thin LTO info (default: yes)"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), + external_clangrt: bool = (false, parse_bool, [UNTRACKED], + "rely on user specified linker commands to find clangrt"), extra_const_ub_checks: bool = (false, parse_bool, [TRACKED], "turns on more checks to detect const UB, which can be slow (default: no)"), #[rustc_lint_opt_deny_field_access("use `Session::fewer_names` instead of this field")] From bf2858a05f510b8a0317d25d7dc587afbd16acfc Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Wed, 13 Mar 2024 11:13:25 -0700 Subject: [PATCH 3/9] Split a complex conditional into separate statements --- compiler/rustc_codegen_ssa/src/back/link.rs | 36 +++++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a37663b59724a..0491b3a26953f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1201,21 +1201,29 @@ fn add_sanitizer_libraries( crate_type: CrateType, linker: &mut dyn Linker, ) { - // On macOS and Windows using MSVC the runtimes are distributed as dylibs - // which should be linked to both executables and dynamic libraries. - // Everywhere else the runtimes are currently distributed as static - // libraries which should be linked to executables only. - let needs_runtime = !sess.target.is_like_android - && !sess.opts.unstable_opts.external_clangrt - && match crate_type { - CrateType::Executable => true, - CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { - sess.target.is_like_osx || sess.target.is_like_msvc - } - CrateType::Rlib | CrateType::Staticlib => false, - }; + if sess.target.is_like_android { + // Sanitizer runtime libraries are provided dynamically on Android + // targets. + return; + } - if !needs_runtime { + if sess.opts.unstable_opts.external_clangrt { + // Linking against in-tree sanitizer runtimes is disabled via + // `-Z external-clangrt` + return; + } + + // On macOS the runtimes are distributed as dylibs which should be linked to + // both executables and dynamic shared objects. On most other platforms the + // runtimes are currently distributed as static libraries which should be + // linked to executables only. + if matches!(crate_type, CrateType::Rlib | CrateType::Staticlib) { + return; + } + + if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) + && (sess.target.is_like_osx || sess.target.is_like_msvc) + { return; } From f46aceaaf75e6072e4e7227d71bcbf0119201212 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Thu, 14 Mar 2024 11:06:39 -0700 Subject: [PATCH 4/9] Restore correct version of comment and fix logic bug --- compiler/rustc_codegen_ssa/src/back/link.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 0491b3a26953f..8d01832c678d4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1213,16 +1213,16 @@ fn add_sanitizer_libraries( return; } - // On macOS the runtimes are distributed as dylibs which should be linked to - // both executables and dynamic shared objects. On most other platforms the - // runtimes are currently distributed as static libraries which should be - // linked to executables only. if matches!(crate_type, CrateType::Rlib | CrateType::Staticlib) { return; } + // On macOS and Windows using MSVC the runtimes are distributed as dylibs + // which should be linked to both executables and dynamic libraries. + // Everywhere else the runtimes are currently distributed as static + // libraries which should be linked to executables only. if matches!(crate_type, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) - && (sess.target.is_like_osx || sess.target.is_like_msvc) + && !(sess.target.is_like_osx || sess.target.is_like_msvc) { return; } From 87ced1561ff66f7e19c8e564f9d85383543c8999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 14 Mar 2024 19:37:41 +0000 Subject: [PATCH 5/9] Pass the correct DefId when suggesting writing the aliased Self type out --- compiler/rustc_hir_typeck/src/demand.rs | 2 +- .../ice-self-mismatch-const-generics.rs | 25 +++++++++++++ .../ice-self-mismatch-const-generics.stderr | 37 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/ui/typeck/ice-self-mismatch-const-generics.rs create mode 100644 tests/ui/typeck/ice-self-mismatch-const-generics.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 71da655434032..67ff412651c20 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1071,7 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( *span, "use the type name directly", - self.tcx.value_path_str_with_args(*alias_to, e_args), + self.tcx.value_path_str_with_args(e_def.did(), e_args), Applicability::MaybeIncorrect, ); } diff --git a/tests/ui/typeck/ice-self-mismatch-const-generics.rs b/tests/ui/typeck/ice-self-mismatch-const-generics.rs new file mode 100644 index 0000000000000..43f435ba4cf16 --- /dev/null +++ b/tests/ui/typeck/ice-self-mismatch-const-generics.rs @@ -0,0 +1,25 @@ +// Checks that the following does not ICE when constructing type mismatch diagnostic involving +// `Self` and const generics. +// Issue: + +pub struct GenericStruct { + thing: T, +} + +impl GenericStruct<0, T> { + pub fn new(thing: T) -> GenericStruct<1, T> { + Self { thing } + //~^ ERROR mismatched types + } +} + +pub struct GenericStruct2(T); + +impl GenericStruct2<0, T> { + pub fn new(thing: T) -> GenericStruct2<1, T> { + Self { 0: thing } + //~^ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/typeck/ice-self-mismatch-const-generics.stderr b/tests/ui/typeck/ice-self-mismatch-const-generics.stderr new file mode 100644 index 0000000000000..c502ea4565f68 --- /dev/null +++ b/tests/ui/typeck/ice-self-mismatch-const-generics.stderr @@ -0,0 +1,37 @@ +error[E0308]: mismatched types + --> $DIR/ice-self-mismatch-const-generics.rs:11:9 + | +LL | impl GenericStruct<0, T> { + | ------------------- this is the type of the `Self` literal +LL | pub fn new(thing: T) -> GenericStruct<1, T> { + | ------------------- expected `GenericStruct<1, T>` because of return type +LL | Self { thing } + | ^^^^^^^^^^^^^^ expected `1`, found `0` + | + = note: expected struct `GenericStruct<_, 1>` + found struct `GenericStruct<_, 0>` +help: use the type name directly + | +LL | GenericStruct::<1, T> { thing } + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/ice-self-mismatch-const-generics.rs:20:9 + | +LL | impl GenericStruct2<0, T> { + | -------------------- this is the type of the `Self` literal +LL | pub fn new(thing: T) -> GenericStruct2<1, T> { + | -------------------- expected `GenericStruct2<1, T>` because of return type +LL | Self { 0: thing } + | ^^^^^^^^^^^^^^^^^ expected `1`, found `0` + | + = note: expected struct `GenericStruct2<_, 1>` + found struct `GenericStruct2<_, 0>` +help: use the type name directly + | +LL | GenericStruct2::<1, T> { 0: thing } + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 48f2f0d725e6d484af24e4666992cc66b6a31ebd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 Mar 2024 08:09:21 +0100 Subject: [PATCH 6/9] preserve span when evaluating mir::ConstOperand --- .../src/dataflow_const_prop.rs | 4 +- .../rustc_mir_transform/src/jump_threading.rs | 3 +- compiler/rustc_monomorphize/src/collector.rs | 7 ++- compiler/rustc_smir/src/rustc_smir/builder.rs | 2 +- .../ui/consts/assoc_const_generic_impl.stderr | 6 +++ .../index-out-of-bounds-never-type.stderr | 6 +++ .../const-eval/issue-50814-2.mir-opt.stderr | 46 +++++++++++++++++++ .../const-eval/issue-50814-2.normal.stderr | 14 ++++++ tests/ui/consts/const-eval/issue-50814.stderr | 14 ++++++ tests/ui/consts/const-eval/issue-85155.stderr | 8 ++++ .../collect-in-called-fn.noopt.stderr | 6 +++ .../collect-in-called-fn.opt.stderr | 6 +++ .../collect-in-dead-drop.noopt.stderr | 6 +++ .../collect-in-dead-fn.noopt.stderr | 6 +++ .../collect-in-dead-move.noopt.stderr | 6 +++ .../collect-in-dead-vtable.noopt.stderr | 6 +++ .../post_monomorphization_error_backtrace.rs | 3 ++ ...st_monomorphization_error_backtrace.stderr | 18 +++++++- .../const-expr-generic-err.stderr | 20 ++++++++ tests/ui/inline-const/required-const.stderr | 6 +++ .../ui/simd/const-err-trumps-simd-err.stderr | 6 +++ 21 files changed, 192 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index c3e932fe18726..f456196b2822d 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -393,7 +393,9 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Operand::Constant(box constant) => { - if let Ok(constant) = self.ecx.eval_mir_constant(&constant.const_, None, None) { + if let Ok(constant) = + self.ecx.eval_mir_constant(&constant.const_, Some(constant.span), None) + { self.assign_constant(state, place, constant, &[]); } } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index ad8f21ffbdaa1..6629face94041 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -416,7 +416,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?; + let constant = + self.ecx.eval_mir_constant(&constant.const_, Some(constant.span), None).ok()?; self.process_constant(bb, lhs, constant, state); } // Transfer the conditions on the copied rhs. diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2465f9fbfa8b0..cd9eb4916ce5d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -828,14 +828,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // a codegen-time error). rustc stops after collection if there was an error, so this // ensures codegen never has to worry about failing consts. // (codegen relies on this and ICEs will happen if this is violated.) - let val = match const_.eval(self.tcx, param_env, None) { + let val = match const_.eval(self.tcx, param_env, Some(constant.span)) { Ok(v) => v, - Err(ErrorHandled::Reported(..)) => return, Err(ErrorHandled::TooGeneric(..)) => span_bug!( self.body.source_info(location).span, "collection encountered polymorphic constant: {:?}", const_ ), + Err(err @ ErrorHandled::Reported(..)) => { + err.emit_note(self.tcx); + return; + } }; collect_const_value(self.tcx, val, self.output); MirVisitor::visit_ty(self, const_.ty(), TyContext::Location(location)); diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index 039bdec4c78a6..a13262cdcc494 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -56,7 +56,7 @@ impl<'tcx> MutVisitor<'tcx> for BodyBuilder<'tcx> { fn visit_constant(&mut self, constant: &mut mir::ConstOperand<'tcx>, location: mir::Location) { let const_ = self.monomorphize(constant.const_); - let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), None) { + let val = match const_.eval(self.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) { Ok(v) => v, Err(mir::interpret::ErrorHandled::Reported(..)) => return, Err(mir::interpret::ErrorHandled::TooGeneric(..)) => { diff --git a/tests/ui/consts/assoc_const_generic_impl.stderr b/tests/ui/consts/assoc_const_generic_impl.stderr index d826972ce9f5a..4521950839670 100644 --- a/tests/ui/consts/assoc_const_generic_impl.stderr +++ b/tests/ui/consts/assoc_const_generic_impl.stderr @@ -4,6 +4,12 @@ error[E0080]: evaluation of `::I_AM_ZERO_SIZED` failed LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4 +note: erroneous constant encountered + --> $DIR/assoc_const_generic_impl.rs:11:9 + | +LL | Self::I_AM_ZERO_SIZED; + | ^^^^^^^^^^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn ::requires_zero_size` --> $DIR/assoc_const_generic_impl.rs:18:5 | diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr index 4e7ef52f674af..7facb2d1a5ca2 100644 --- a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.stderr @@ -4,6 +4,12 @@ error[E0080]: evaluation of `PrintName::<()>::VOID` failed LL | const VOID: ! = { let x = 0 * std::mem::size_of::(); [][x] }; | ^^^^^ index out of bounds: the length is 0 but the index is 0 +note: erroneous constant encountered + --> $DIR/index-out-of-bounds-never-type.rs:16:13 + | +LL | let _ = PrintName::::VOID; + | ^^^^^^^^^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn f::<()>` --> $DIR/index-out-of-bounds-never-type.rs:20:5 | diff --git a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr index 7e764ca72390d..2de68d3fee9e0 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.mir-opt.stderr @@ -10,6 +10,52 @@ note: erroneous constant encountered LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:5 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:5 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:5 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:5 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:6 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:6 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr index f552c8fde5bce..4a7dfb1930443 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.normal.stderr +++ b/tests/ui/consts/const-eval/issue-50814-2.normal.stderr @@ -10,6 +10,20 @@ note: erroneous constant encountered LL | & as Foo>::BAR | ^^^^^^^^^^^^^^^^^^^^^ +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:5 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-50814-2.rs:20:6 + | +LL | & as Foo>::BAR + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: the above error was encountered while instantiating `fn foo::<()>` --> $DIR/issue-50814-2.rs:32:22 | diff --git a/tests/ui/consts/const-eval/issue-50814.stderr b/tests/ui/consts/const-eval/issue-50814.stderr index 8d01816140152..fe0e25b820f58 100644 --- a/tests/ui/consts/const-eval/issue-50814.stderr +++ b/tests/ui/consts/const-eval/issue-50814.stderr @@ -26,6 +26,20 @@ LL | &Sum::::MAX | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +note: erroneous constant encountered + --> $DIR/issue-50814.rs:21:5 + | +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/issue-50814.rs:21:6 + | +LL | &Sum::::MAX + | ^^^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: the above error was encountered while instantiating `fn foo::` --> $DIR/issue-50814.rs:26:5 | diff --git a/tests/ui/consts/const-eval/issue-85155.stderr b/tests/ui/consts/const-eval/issue-85155.stderr index a88e959a8a659..99836a3fac6d5 100644 --- a/tests/ui/consts/const-eval/issue-85155.stderr +++ b/tests/ui/consts/const-eval/issue-85155.stderr @@ -4,6 +4,14 @@ error[E0080]: evaluation of `post_monomorphization_error::ValidateConstImm::<2, LL | let _ = 1 / ((IMM >= MIN && IMM <= MAX) as usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to divide `1_usize` by zero +note: erroneous constant encountered + --> $DIR/auxiliary/post_monomorphization_error.rs:19:5 + | +LL | static_assert_imm1!(IMM1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `static_assert_imm1` (in Nightly builds, run with -Z macro-backtrace for more info) + note: the above error was encountered while instantiating `fn post_monomorphization_error::stdarch_intrinsic::<2>` --> $DIR/issue-85155.rs:19:5 | diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr b/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr index c7ff1328917fc..14a4cb0217f93 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-called-fn.rs:18:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn called::` --> $DIR/collect-in-called-fn.rs:23:5 | diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr b/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr index c7ff1328917fc..14a4cb0217f93 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-called-fn.rs:18:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn called::` --> $DIR/collect-in-called-fn.rs:23:5 | diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr index b7010e787633b..0bf231d09f174 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-dead-drop.rs:19:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn as std::ops::Drop>::drop` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr index 2162c35c83702..8bb99efe8e48d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-dead-fn.rs:22:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn not_called::` --> $DIR/collect-in-dead-fn.rs:29:9 | diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr index 8c853127e044c..5b1df78b23265 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-dead-move.rs:19:17 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn as std::ops::Drop>::drop` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr index 6fd82777bd364..56b6989b441ed 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr @@ -6,6 +6,12 @@ LL | const C: () = panic!(); | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/collect-in-dead-vtable.rs:26:21 + | +LL | let _ = Fail::::C; + | ^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn as MyTrait>::not_called` --> $DIR/collect-in-dead-vtable.rs:35:40 | diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.rs b/tests/ui/generics/post_monomorphization_error_backtrace.rs index 56155ae2bd5f5..2c18f2b233add 100644 --- a/tests/ui/generics/post_monomorphization_error_backtrace.rs +++ b/tests/ui/generics/post_monomorphization_error_backtrace.rs @@ -12,6 +12,9 @@ fn assert_zst() { //~| NOTE: the evaluated program panicked } F::::V; + //~^NOTE: erroneous constant + //~|NOTE: erroneous constant + //~|NOTE: duplicate } fn foo() { diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.stderr b/tests/ui/generics/post_monomorphization_error_backtrace.stderr index 0d707d83d2660..8a57979bca7d4 100644 --- a/tests/ui/generics/post_monomorphization_error_backtrace.stderr +++ b/tests/ui/generics/post_monomorphization_error_backtrace.stderr @@ -6,8 +6,14 @@ LL | const V: () = assert!(std::mem::size_of::() == 0); | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/post_monomorphization_error_backtrace.rs:14:5 + | +LL | F::::V; + | ^^^^^^^^^ + note: the above error was encountered while instantiating `fn assert_zst::` - --> $DIR/post_monomorphization_error_backtrace.rs:18:5 + --> $DIR/post_monomorphization_error_backtrace.rs:21:5 | LL | assert_zst::() | ^^^^^^^^^^^^^^^^^ @@ -20,8 +26,16 @@ LL | const V: () = assert!(std::mem::size_of::() == 0); | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/post_monomorphization_error_backtrace.rs:14:5 + | +LL | F::::V; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: the above error was encountered while instantiating `fn assert_zst::` - --> $DIR/post_monomorphization_error_backtrace.rs:18:5 + --> $DIR/post_monomorphization_error_backtrace.rs:21:5 | LL | assert_zst::() | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index fc0b6cc445164..7331c7f18e976 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -6,6 +6,12 @@ LL | const { assert!(std::mem::size_of::() == 0); } | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/const-expr-generic-err.rs:5:5 + | +LL | const { assert!(std::mem::size_of::() == 0); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn foo::` --> $DIR/const-expr-generic-err.rs:13:5 | @@ -18,6 +24,20 @@ error[E0080]: evaluation of `bar::<0>::{constant#0}` failed LL | const { N - 1 } | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow +note: erroneous constant encountered + --> $DIR/const-expr-generic-err.rs:9:5 + | +LL | const { N - 1 } + | ^^^^^^^^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/const-expr-generic-err.rs:9:5 + | +LL | const { N - 1 } + | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + note: the above error was encountered while instantiating `fn bar::<0>` --> $DIR/const-expr-generic-err.rs:14:5 | diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr index cd86020184dda..2a13d18547c54 100644 --- a/tests/ui/inline-const/required-const.stderr +++ b/tests/ui/inline-const/required-const.stderr @@ -6,6 +6,12 @@ LL | const { panic!() } | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/required-const.rs:7:9 + | +LL | const { panic!() } + | ^^^^^^^^^^^^^^^^^^ + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index 6e6aba8b6f186..1e46667cf4e2a 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -6,6 +6,12 @@ LL | const { assert!(LANE < 4); } // the error should be here... | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) +note: erroneous constant encountered + --> $DIR/const-err-trumps-simd-err.rs:16:5 + | +LL | const { assert!(LANE < 4); } // the error should be here... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + note: the above error was encountered while instantiating `fn get_elem::<4>` --> $DIR/const-err-trumps-simd-err.rs:23:5 | From 571f945713468f24e4f937d48828d1d8155911f2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 14 Mar 2024 20:30:57 -0400 Subject: [PATCH 7/9] Ensure RPITITs are created before def-id freezing --- compiler/rustc_hir_analysis/src/collect.rs | 2 ++ .../ensure-rpitits-are-created-before-freezing.rs | 13 +++++++++++++ ...nsure-rpitits-are-created-before-freezing.stderr | 9 +++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.rs create mode 100644 tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 10922d534792a..5cd6862786b46 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -595,12 +595,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure().type_of(def_id); tcx.ensure().impl_trait_header(def_id); tcx.ensure().predicates_of(def_id); + tcx.ensure().associated_items(def_id); } hir::ItemKind::Trait(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().trait_def(def_id); tcx.at(it.span).super_predicates_of(def_id); tcx.ensure().predicates_of(def_id); + tcx.ensure().associated_items(def_id); } hir::ItemKind::TraitAlias(..) => { tcx.ensure().generics_of(def_id); diff --git a/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.rs b/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.rs new file mode 100644 index 0000000000000..35a6acca52c7d --- /dev/null +++ b/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.rs @@ -0,0 +1,13 @@ +trait Iterable { + type Item; + fn iter(&self) -> impl Sized; +} + +// `ty::Error` in a trait ref will silence any missing item errors, but will also +// prevent the `associated_items` query from being called before def ids are frozen. +impl Iterable for Missing { +//~^ ERROR cannot find type `Missing` in this scope + fn iter(&self) -> Self::Item {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.stderr b/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.stderr new file mode 100644 index 0000000000000..c172787e6ef21 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/ensure-rpitits-are-created-before-freezing.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/ensure-rpitits-are-created-before-freezing.rs:8:19 + | +LL | impl Iterable for Missing { + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. From cac0b121b6ab5a3a2f34cd458d755bda503e619b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 15 Mar 2024 12:33:32 +1100 Subject: [PATCH 8/9] Docs for `thir::ExprKind::Use` and `thir::ExprKind::Let` --- compiler/rustc_middle/src/thir.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 74b47d8b04e6b..96a61883cc14f 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -321,9 +321,13 @@ pub enum ExprKind<'tcx> { Cast { source: ExprId, }, + /// Forces its contents to be treated as a value expression, not a place + /// expression. This is inserted in some places where an operation would + /// otherwise be erased completely (e.g. some no-op casts), but we still + /// need to ensure that its operand is treated as a value and not a place. Use { source: ExprId, - }, // Use a lexpr to get a vexpr. + }, /// A coercion from `!` to any type. NeverToAny { source: ExprId, @@ -338,6 +342,13 @@ pub enum ExprKind<'tcx> { Loop { body: ExprId, }, + /// Special expression representing the `let` part of an `if let` or similar construct + /// (including `if let` guards in match arms, and let-chains formed by `&&`). + /// + /// This isn't considered a real expression in surface Rust syntax, so it can + /// only appear in specific situations, such as within the condition of an `if`. + /// + /// (Not to be confused with [`StmtKind::Let`], which is a normal `let` statement.) Let { expr: ExprId, pat: Box>, From 5beda81b71509175f1661361a56eb8306b730639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 15 Mar 2024 02:19:29 +0100 Subject: [PATCH 9/9] Clean up AstConv --- .../rustc_hir_analysis/src/astconv/errors.rs | 114 +++++++++++- .../src/astconv/generics.rs | 12 +- .../rustc_hir_analysis/src/astconv/lint.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 176 ++---------------- .../src/astconv/object_safety.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 3 +- compiler/rustc_hir_analysis/src/lib.rs | 37 +--- compiler/rustc_hir_typeck/src/closure.rs | 4 +- 8 files changed, 142 insertions(+), 208 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 6caba6ff23e52..37fbf45235a86 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -22,7 +22,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_trait_selection::traits::object_safety_violations_for_assoc_item; -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using /// the type parameter's name as a placeholder. pub(crate) fn complain_about_missing_type_params( @@ -349,6 +349,118 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) } + pub(super) fn report_ambiguous_associated_type( + &self, + span: Span, + types: &[String], + traits: &[String], + name: Symbol, + ) -> ErrorGuaranteed { + let mut err = + struct_span_code_err!(self.tcx().dcx(), span, E0223, "ambiguous associated type"); + if self + .tcx() + .resolutions(()) + .confused_type_with_std_module + .keys() + .any(|full_span| full_span.contains(span)) + { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "you are looking for the module in `std`, not the primitive type", + "std::", + Applicability::MachineApplicable, + ); + } else { + let mut types = types.to_vec(); + types.sort(); + let mut traits = traits.to_vec(); + traits.sort(); + match (&types[..], &traits[..]) { + ([], []) => { + err.span_suggestion_verbose( + span, + format!( + "if there were a type named `Type` that implements a trait named \ + `Trait` with associated type `{name}`, you could use the \ + fully-qualified path", + ), + format!("::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], [trait_str]) => { + err.span_suggestion_verbose( + span, + format!( + "if there were a type named `Example` that implemented `{trait_str}`, \ + you could use the fully-qualified path", + ), + format!("::{name}"), + Applicability::HasPlaceholders, + ); + } + ([], traits) => { + err.span_suggestions( + span, + format!( + "if there were a type named `Example` that implemented one of the \ + traits with associated type `{name}`, you could use the \ + fully-qualified path", + ), + traits + .iter() + .map(|trait_str| format!("::{name}")) + .collect::>(), + Applicability::HasPlaceholders, + ); + } + ([type_str], []) => { + err.span_suggestion_verbose( + span, + format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for `{type_str}`, you could use the fully-qualified path", + ), + format!("<{type_str} as Example>::{name}"), + Applicability::HasPlaceholders, + ); + } + (types, []) => { + err.span_suggestions( + span, + format!( + "if there were a trait named `Example` with associated type `{name}` \ + implemented for one of the types, you could use the fully-qualified \ + path", + ), + types + .into_iter() + .map(|type_str| format!("<{type_str} as Example>::{name}")), + Applicability::HasPlaceholders, + ); + } + (types, traits) => { + let mut suggestions = vec![]; + for type_str in types { + for trait_str in traits { + suggestions.push(format!("<{type_str} as {trait_str}>::{name}")); + } + } + err.span_suggestions( + span, + "use fully-qualified syntax", + suggestions, + Applicability::MachineApplicable, + ); + } + } + } + let reported = err.emit(); + self.set_tainted_by_errors(reported); + reported + } + pub(crate) fn complain_about_ambiguous_inherent_assoc_type( &self, name: Ident, diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 63afa4f7e82d2..428eea2f686e9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -409,15 +409,12 @@ pub fn check_generic_arg_count_for_call( seg: &hir::PathSegment<'_>, is_method_call: IsMethodCall, ) -> GenericArgCountResult { - let empty_args = hir::GenericArgs::none(); - let gen_args = seg.args.unwrap_or(&empty_args); let gen_pos = match is_method_call { IsMethodCall::Yes => GenericArgPosition::MethodCall, IsMethodCall::No => GenericArgPosition::Value, }; let has_self = generics.parent.is_none() && generics.has_self; - - check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args) + check_generic_arg_count(tcx, def_id, seg, generics, gen_pos, has_self) } /// Checks that the correct number of generic arguments have been provided. @@ -428,11 +425,10 @@ pub(crate) fn check_generic_arg_count( def_id: DefId, seg: &hir::PathSegment<'_>, gen_params: &ty::Generics, - gen_args: &hir::GenericArgs<'_>, gen_pos: GenericArgPosition, has_self: bool, - infer_args: bool, ) -> GenericArgCountResult { + let gen_args = seg.args(); let default_counts = gen_params.own_defaults(); let param_counts = gen_params.own_counts(); @@ -453,7 +449,7 @@ pub(crate) fn check_generic_arg_count( .count(); let named_const_param_count = param_counts.consts - synth_const_param_count; let infer_lifetimes = - (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params(); + (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params(); if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() @@ -586,7 +582,7 @@ pub(crate) fn check_generic_arg_count( }; let args_correct = { - let expected_min = if infer_args { + let expected_min = if seg.infer_args { 0 } else { param_counts.consts + named_type_param_count diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index fb5f3426cea6a..b421a33ba294b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -8,7 +8,7 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa use super::AstConv; -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { /// Make sure that we are in the condition to suggest the blanket implementation. pub(super) fn maybe_lint_blanket_trait_impl( &self, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 25df76359a88e..401dd76a9f914 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -214,7 +214,7 @@ pub trait CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> { ) -> ty::GenericArg<'tcx>; } -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { #[instrument(level = "debug", skip(self), ret)] pub fn ast_region_to_region( &self, @@ -284,8 +284,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id, &[], item_segment, - item_segment.args(), - item_segment.infer_args, None, ty::BoundConstness::NotConst, ); @@ -330,14 +328,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// type itself: `['a]`. The returned `GenericArgsRef` concatenates these two /// lists: `[Vec, u8, 'a]`. #[instrument(level = "debug", skip(self, span), ret)] - fn create_args_for_ast_path<'a>( + fn create_args_for_ast_path( &self, span: Span, def_id: DefId, parent_args: &[ty::GenericArg<'tcx>], - seg: &hir::PathSegment<'_>, - generic_args: &'a hir::GenericArgs<'tcx>, - infer_args: bool, + segment: &hir::PathSegment<'tcx>, self_ty: Option>, constness: ty::BoundConstness, ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { @@ -365,12 +361,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut arg_count = check_generic_arg_count( tcx, def_id, - seg, + segment, generics, - generic_args, GenericArgPosition::Type, self_ty.is_some(), - infer_args, ); if let Err(err) = &arg_count.correct @@ -388,7 +382,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } struct InstantiationsForAstPathCtxt<'a, 'tcx> { - astconv: &'a (dyn AstConv<'tcx> + 'a), + astconv: &'a dyn AstConv<'tcx>, def_id: DefId, generic_args: &'a GenericArgs<'tcx>, span: Span, @@ -547,9 +541,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { astconv: self, def_id, span, - generic_args, + generic_args: segment.args(), inferred_params: vec![], - infer_args, + infer_args: segment.infer_args, }; if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness && generics.has_self @@ -592,8 +586,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_def_id, parent_args, item_segment, - item_segment.args(), - item_segment.infer_args, None, ty::BoundConstness::NotConst, ); @@ -661,7 +653,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) -> GenericArgCountResult { let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); let trait_segment = trait_ref.path.segments.last().unwrap(); - let args = trait_segment.args(); self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false); @@ -671,8 +662,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id, &[], trait_segment, - args, - trait_segment.infer_args, Some(self_ty), constness, ); @@ -690,7 +679,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); let mut dup_bindings = FxIndexMap::default(); - for binding in args.bindings { + for binding in trait_segment.args().bindings { // Don't register additional associated type bounds for negative bounds, // since we should have emitten an error for them earlier, and they will // not be well-formed! @@ -729,12 +718,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // FIXME(effects) move all host param things in astconv to hir lowering constness: ty::BoundConstness, ) -> ty::TraitRef<'tcx> { - let (generic_args, _) = self.create_args_for_ast_trait_ref( + self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); + + let (generic_args, _) = self.create_args_for_ast_path( span, trait_def_id, - self_ty, + &[], trait_segment, - is_impl, + Some(self_ty), constness, ); if let Some(b) = trait_segment.args().bindings.first() { @@ -743,30 +734,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::TraitRef::new(self.tcx(), trait_def_id, generic_args) } - #[instrument(level = "debug", skip(self, span))] - fn create_args_for_ast_trait_ref<'a>( - &self, - span: Span, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - trait_segment: &'a hir::PathSegment<'tcx>, - is_impl: bool, - constness: ty::BoundConstness, - ) -> (GenericArgsRef<'tcx>, GenericArgCountResult) { - self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl); - - self.create_args_for_ast_path( - span, - trait_def_id, - &[], - trait_segment, - trait_segment.args(), - trait_segment.infer_args, - Some(self_ty), - constness, - ) - } - fn trait_defines_associated_item_named( &self, trait_def_id: DefId, @@ -801,115 +768,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - fn report_ambiguous_associated_type( - &self, - span: Span, - types: &[String], - traits: &[String], - name: Symbol, - ) -> ErrorGuaranteed { - let mut err = - struct_span_code_err!(self.tcx().dcx(), span, E0223, "ambiguous associated type"); - if self - .tcx() - .resolutions(()) - .confused_type_with_std_module - .keys() - .any(|full_span| full_span.contains(span)) - { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "you are looking for the module in `std`, not the primitive type", - "std::", - Applicability::MachineApplicable, - ); - } else { - let mut types = types.to_vec(); - types.sort(); - let mut traits = traits.to_vec(); - traits.sort(); - match (&types[..], &traits[..]) { - ([], []) => { - err.span_suggestion_verbose( - span, - format!( - "if there were a type named `Type` that implements a trait named \ - `Trait` with associated type `{name}`, you could use the \ - fully-qualified path", - ), - format!("::{name}"), - Applicability::HasPlaceholders, - ); - } - ([], [trait_str]) => { - err.span_suggestion_verbose( - span, - format!( - "if there were a type named `Example` that implemented `{trait_str}`, \ - you could use the fully-qualified path", - ), - format!("::{name}"), - Applicability::HasPlaceholders, - ); - } - ([], traits) => { - err.span_suggestions( - span, - format!( - "if there were a type named `Example` that implemented one of the \ - traits with associated type `{name}`, you could use the \ - fully-qualified path", - ), - traits.iter().map(|trait_str| format!("::{name}")), - Applicability::HasPlaceholders, - ); - } - ([type_str], []) => { - err.span_suggestion_verbose( - span, - format!( - "if there were a trait named `Example` with associated type `{name}` \ - implemented for `{type_str}`, you could use the fully-qualified path", - ), - format!("<{type_str} as Example>::{name}"), - Applicability::HasPlaceholders, - ); - } - (types, []) => { - err.span_suggestions( - span, - format!( - "if there were a trait named `Example` with associated type `{name}` \ - implemented for one of the types, you could use the fully-qualified \ - path", - ), - types - .into_iter() - .map(|type_str| format!("<{type_str} as Example>::{name}")), - Applicability::HasPlaceholders, - ); - } - (types, traits) => { - let mut suggestions = vec![]; - for type_str in types { - for trait_str in traits { - suggestions.push(format!("<{type_str} as {trait_str}>::{name}")); - } - } - err.span_suggestions( - span, - "use fully-qualified syntax", - suggestions, - Applicability::MachineApplicable, - ); - } - } - } - let reported = err.emit(); - self.set_tainted_by_errors(reported); - reported - } - // Search for a bound on a type parameter which includes the associated item // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter // This function will fail if there are no suitable bounds or there is @@ -2471,8 +2329,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def_id, &[], &hir::PathSegment::invalid(), - &GenericArgs::none(), - true, None, ty::BoundConstness::NotConst, ); @@ -2552,9 +2408,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ty_of_arg(&self, ty: &hir::Ty<'tcx>, expected_ty: Option>) -> Ty<'tcx> { match ty.kind { - hir::TyKind::Infer if expected_ty.is_some() => { - self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span); - expected_ty.unwrap() + hir::TyKind::Infer if let Some(expected_ty) = expected_ty => { + self.record_ty(ty.hir_id, expected_ty, ty.span); + expected_ty } _ => self.ast_ty_to_ty(ty), } diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index b9543c7a29b2a..d97728c33035d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -17,7 +17,7 @@ use smallvec::{smallvec, SmallVec}; use super::AstConv; -impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { +impl<'tcx> dyn AstConv<'tcx> + '_ { pub(super) fn conv_object_ty_poly_trait_ref( &self, span: Span, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 598dba922d0c4..fd86f2dd1b16c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -108,8 +108,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .unwrap() .0 .def_id; - let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>; - let ty = item_ctxt.ast_ty_to_ty(hir_ty); + let ty = ItemCtxt::new(tcx, item_def_id).to_ty(hir_ty); // Iterate through the generics of the projection to find the one that corresponds to // the def_id that this query was called with. We filter to only type and const args here diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index b1b36ade50801..e5307f57a2f4d 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -99,19 +99,16 @@ pub mod structured_errors; mod variance; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_middle::middle; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::util; use rustc_session::parse::feature_err; -use rustc_span::{symbol::sym, Span, DUMMY_SP}; +use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; -use astconv::{AstConv, OnlySelfBounds}; -use bounds::Bounds; -use rustc_hir::def::DefKind; - rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { @@ -200,31 +197,5 @@ pub fn hir_ty_to_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id); - let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id); - item_cx.astconv().ast_ty_to_ty(hir_ty) -} - -pub fn hir_trait_to_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - hir_trait: &hir::TraitRef<'tcx>, - self_ty: Ty<'tcx>, -) -> Bounds<'tcx> { - // In case there are any projections, etc., find the "environment" - // def-ID that will be used to determine the traits/predicates in - // scope. This is derived from the enclosing item-like thing. - let env_def_id = tcx.hir().get_parent_item(hir_trait.hir_ref_id); - let item_cx = self::collect::ItemCtxt::new(tcx, env_def_id.def_id); - let mut bounds = Bounds::default(); - let _ = &item_cx.astconv().instantiate_poly_trait_ref( - hir_trait, - DUMMY_SP, - ty::BoundConstness::NotConst, - ty::ImplPolarity::Positive, - self_ty, - &mut bounds, - true, - OnlySelfBounds(false), - ); - - bounds + collect::ItemCtxt::new(tcx, env_def_id.def_id).to_ty(hir_ty) } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index c17af666eb9fe..4bea4bb3e8262 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -780,7 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl: &hir::FnDecl<'tcx>, closure_kind: hir::ClosureKind, ) -> ty::PolyFnSig<'tcx> { - let astconv: &dyn AstConv<'_> = self; + let astconv = self.astconv(); trace!("decl = {:#?}", decl); debug!(?closure_kind); @@ -985,7 +985,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl: &hir::FnDecl<'tcx>, guar: ErrorGuaranteed, ) -> ty::PolyFnSig<'tcx> { - let astconv: &dyn AstConv<'_> = self; + let astconv = self.astconv(); let err_ty = Ty::new_error(self.tcx, guar); let supplied_arguments = decl.inputs.iter().map(|a| {