From b2b34351de8a7b18888ff549c7d6dbe7698f734c Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 28 Sep 2021 20:12:46 -0400 Subject: [PATCH] Don't lose binders when printing trait bound suggestion --- .../src/traits/error_reporting/suggestions.rs | 32 +++++++++---------- src/test/ui/suggestions/issue-89333.rs | 9 ++++++ src/test/ui/suggestions/issue-89333.stderr | 23 +++++++++++++ 3 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/suggestions/issue-89333.rs create mode 100644 src/test/ui/suggestions/issue-89333.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 325126483b9..c74667643c4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -676,7 +676,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, + poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, has_custom_message: bool, ) -> bool { let span = obligation.cause.span; @@ -705,7 +705,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap()); let param_env = obligation.param_env; - let trait_ref = trait_ref.skip_binder(); + let trait_ref = poly_trait_ref.skip_binder(); let found_ty = trait_ref.self_ty(); let found_ty_str = found_ty.to_string(); @@ -715,25 +715,25 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]); // Try to apply the original trait binding obligation by borrowing. - let mut try_borrowing = |new_imm_trait_ref: ty::TraitRef<'tcx>, - new_mut_trait_ref: ty::TraitRef<'tcx>, - expected_trait_ref: ty::TraitRef<'tcx>, + let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, blacklist: &[DefId]| -> bool { - if blacklist.contains(&expected_trait_ref.def_id) { + if blacklist.contains(&expected_trait_ref.def_id()) { return false; } let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new( ObligationCause::dummy(), param_env, - ty::Binder::dummy(new_imm_trait_ref).without_const().to_predicate(self.tcx), + new_imm_trait_ref.without_const().to_predicate(self.tcx), )); let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new( ObligationCause::dummy(), param_env, - ty::Binder::dummy(new_mut_trait_ref).without_const().to_predicate(self.tcx), + new_mut_trait_ref.without_const().to_predicate(self.tcx), )); if imm_result || mut_result { @@ -806,19 +806,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code { - let expected_trait_ref = obligation.parent_trait_ref.skip_binder(); - let new_imm_trait_ref = - ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs); - let new_mut_trait_ref = - ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs); + let expected_trait_ref = obligation.parent_trait_ref; + let new_imm_trait_ref = poly_trait_ref + .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs)); + let new_mut_trait_ref = poly_trait_ref + .rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs)); return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]); } else if let ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ItemObligation(_) = &*code { return try_borrowing( - ty::TraitRef::new(trait_ref.def_id, imm_substs), - ty::TraitRef::new(trait_ref.def_id, mut_substs), - trait_ref, + poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)), + poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)), + *poly_trait_ref, &never_suggest_borrow[..], ); } else { diff --git a/src/test/ui/suggestions/issue-89333.rs b/src/test/ui/suggestions/issue-89333.rs new file mode 100644 index 00000000000..a7bb524c421 --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.rs @@ -0,0 +1,9 @@ +// check-fail +// Ensure we don't error when emitting trait bound not satisfied when self type +// has late bound var + +fn main() { + test(&|| 0); //~ ERROR the trait bound +} + +fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Default {} diff --git a/src/test/ui/suggestions/issue-89333.stderr b/src/test/ui/suggestions/issue-89333.stderr new file mode 100644 index 00000000000..6518114dcdc --- /dev/null +++ b/src/test/ui/suggestions/issue-89333.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `for<'a> &'a {integer}: Default` is not satisfied + --> $DIR/issue-89333.rs:6:10 + | +LL | test(&|| 0); + | ---- ^^^^^ the trait `for<'a> Default` is not implemented for `&'a {integer}` + | | + | required by a bound introduced by this call + | + = help: the following implementations were found: + <&CStr as Default> + <&OsStr as Default> + <&[T] as Default> + <&mut [T] as Default> + and 217 others +note: required by a bound in `test` + --> $DIR/issue-89333.rs:9:55 + | +LL | fn test(arg: &impl Fn() -> T) where for<'a> &'a T: Default {} + | ^^^^^^^ required by this bound in `test` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.