diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4f726f3ed38..0933e90f8ba 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -952,7 +952,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } unimplemented_traits.entry(p.trait_ref.def_id).or_insert(( - predicate.kind().rebind(p.trait_ref), + predicate.kind().rebind(p), Obligation { cause: cause.clone(), param_env: self.param_env, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 824c25db07d..26b0faca258 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { notes, parent_label, append_const_msg, - } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file); + } = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file); let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id()); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index c3100c48b0a..cd41ab9fa6c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::LintDiagnostic; use rustc_middle::bug; use rustc_middle::ty::print::PrintTraitRefExt as _; -use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt}; +use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; use rustc_span::Span; @@ -108,14 +108,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn on_unimplemented_note( &self, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, obligation: &PredicateObligation<'tcx>, long_ty_file: &mut Option, ) -> OnUnimplementedNote { + if trait_pred.polarity() != ty::PredicatePolarity::Positive { + return OnUnimplementedNote::default(); + } + let (def_id, args) = self - .impl_similar_to(trait_ref, obligation) - .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args)); - let trait_ref = trait_ref.skip_binder(); + .impl_similar_to(trait_pred.to_poly_trait_ref(), obligation) + .unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args)); + let trait_pred = trait_pred.skip_binder(); let mut flags = vec![]; // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs, @@ -144,13 +148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { flags.push((sym::cause, Some("MainFunctionType".to_string()))); } - flags.push((sym::Trait, Some(trait_ref.print_trait_sugared().to_string()))); + flags.push((sym::Trait, Some(trait_pred.trait_ref.print_trait_sugared().to_string()))); // Add all types without trimmed paths or visible paths, ensuring they end up with // their "canonical" def path. ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({ let generics = self.tcx.generics_of(def_id); - let self_ty = trait_ref.self_ty(); + let self_ty = trait_pred.self_ty(); // This is also included through the generics list as `Self`, // but the parser won't allow you to use it flags.push((sym::_Self, Some(self_ty.to_string()))); @@ -266,7 +270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { })); if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) { - command.evaluate(self.tcx, trait_ref, &flags, long_ty_file) + command.evaluate(self.tcx, trait_pred.trait_ref, &flags, long_ty_file) } else { OnUnimplementedNote::default() } diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.rs b/tests/ui/traits/negative-bounds/on-unimplemented.rs new file mode 100644 index 00000000000..34582590861 --- /dev/null +++ b/tests/ui/traits/negative-bounds/on-unimplemented.rs @@ -0,0 +1,12 @@ +#![feature(negative_bounds)] + +#[diagnostic::on_unimplemented(message = "this ain't fooing")] +trait Foo {} +struct NotFoo; + +fn hello() -> impl !Foo { + //~^ ERROR the trait bound `NotFoo: !Foo` is not satisfied + NotFoo +} + +fn main() {} diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.stderr b/tests/ui/traits/negative-bounds/on-unimplemented.stderr new file mode 100644 index 00000000000..07483e788e5 --- /dev/null +++ b/tests/ui/traits/negative-bounds/on-unimplemented.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `NotFoo: !Foo` is not satisfied + --> $DIR/on-unimplemented.rs:7:15 + | +LL | fn hello() -> impl !Foo { + | ^^^^^^^^^ the trait bound `NotFoo: !Foo` is not satisfied +LL | +LL | NotFoo + | ------ return type was inferred to be `NotFoo` here + | +help: this trait has no implementations, consider adding one + --> $DIR/on-unimplemented.rs:4:1 + | +LL | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.