From aa884da1e7e1f7d08a3c66ca25a824a907f43258 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Feb 2025 04:22:50 +0000 Subject: [PATCH] Delay bug when method confirmation cannot upcast object pick of self --- .../rustc_hir_typeck/src/method/confirm.rs | 24 ++++++++++++------- tests/ui/self/invalid-self-dyn-receiver.rs | 20 ++++++++++++++++ .../ui/self/invalid-self-dyn-receiver.stderr | 12 ++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 tests/ui/self/invalid-self-dyn-receiver.rs create mode 100644 tests/ui/self/invalid-self-dyn-receiver.stderr diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 5c1c38aeb9534..dadebc6eff4de 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -673,17 +673,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id); // must be exactly one trait ref or we'd get an ambig error etc - let [upcast_trait_ref] = upcast_trait_refs.as_slice() else { - span_bug!( + if let &[upcast_trait_ref] = upcast_trait_refs.as_slice() { + upcast_trait_ref + } else { + self.dcx().span_delayed_bug( self.span, - "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`", - source_trait_ref, - target_trait_def_id, - upcast_trait_refs - ) - }; + format!( + "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`", + source_trait_ref, target_trait_def_id, upcast_trait_refs + ), + ); - *upcast_trait_ref + ty::Binder::dummy(ty::TraitRef::new_from_args( + self.tcx, + target_trait_def_id, + ty::GenericArgs::extend_with_error(self.tcx, target_trait_def_id, &[]), + )) + } } fn instantiate_binder_with_fresh_vars(&self, value: ty::Binder<'tcx, T>) -> T diff --git a/tests/ui/self/invalid-self-dyn-receiver.rs b/tests/ui/self/invalid-self-dyn-receiver.rs new file mode 100644 index 0000000000000..a989b331b5e0b --- /dev/null +++ b/tests/ui/self/invalid-self-dyn-receiver.rs @@ -0,0 +1,20 @@ +// Makes sure we don't ICE when encountering a receiver that is *ostensibly* dyn safe, +// because it satisfies `&dyn Bar: DispatchFromDyn<&dyn Bar>`, but is not a valid receiver +// in wfcheck. + +#![feature(arbitrary_self_types)] + +use std::ops::Deref; + +trait Foo: Deref { + fn method(self: &dyn Bar) {} + //~^ ERROR invalid `self` parameter type: `&dyn Bar` +} + +trait Bar {} + +fn test(x: &dyn Foo) { + x.method(); +} + +fn main() {} diff --git a/tests/ui/self/invalid-self-dyn-receiver.stderr b/tests/ui/self/invalid-self-dyn-receiver.stderr new file mode 100644 index 0000000000000..f77f5686ad282 --- /dev/null +++ b/tests/ui/self/invalid-self-dyn-receiver.stderr @@ -0,0 +1,12 @@ +error[E0307]: invalid `self` parameter type: `&dyn Bar` + --> $DIR/invalid-self-dyn-receiver.rs:10:22 + | +LL | fn method(self: &dyn Bar) {} + | ^^^^^^^^ + | + = note: type of `self` must be `Self` or some type implementing `Receiver` + = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0307`.