Don't lose binders when printing trait bound suggestion
This commit is contained in:
parent
ed937594d3
commit
b2b34351de
3 changed files with 48 additions and 16 deletions
|
@ -676,7 +676,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||||
has_custom_message: bool,
|
has_custom_message: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let span = obligation.cause.span;
|
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());
|
never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
|
||||||
|
|
||||||
let param_env = obligation.param_env;
|
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 = trait_ref.self_ty();
|
||||||
let found_ty_str = found_ty.to_string();
|
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, &[]);
|
let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);
|
||||||
|
|
||||||
// Try to apply the original trait binding obligation by borrowing.
|
// Try to apply the original trait binding obligation by borrowing.
|
||||||
let mut try_borrowing = |new_imm_trait_ref: ty::TraitRef<'tcx>,
|
let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||||
new_mut_trait_ref: ty::TraitRef<'tcx>,
|
new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||||
expected_trait_ref: ty::TraitRef<'tcx>,
|
expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||||
blacklist: &[DefId]|
|
blacklist: &[DefId]|
|
||||||
-> bool {
|
-> bool {
|
||||||
if blacklist.contains(&expected_trait_ref.def_id) {
|
if blacklist.contains(&expected_trait_ref.def_id()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
|
let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
param_env,
|
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(
|
let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
param_env,
|
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 {
|
if imm_result || mut_result {
|
||||||
|
@ -806,19 +806,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
|
if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
|
||||||
let expected_trait_ref = obligation.parent_trait_ref.skip_binder();
|
let expected_trait_ref = obligation.parent_trait_ref;
|
||||||
let new_imm_trait_ref =
|
let new_imm_trait_ref = poly_trait_ref
|
||||||
ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
|
.rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs));
|
||||||
let new_mut_trait_ref =
|
let new_mut_trait_ref = poly_trait_ref
|
||||||
ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs);
|
.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, &[]);
|
return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]);
|
||||||
} else if let ObligationCauseCode::BindingObligation(_, _)
|
} else if let ObligationCauseCode::BindingObligation(_, _)
|
||||||
| ObligationCauseCode::ItemObligation(_) = &*code
|
| ObligationCauseCode::ItemObligation(_) = &*code
|
||||||
{
|
{
|
||||||
return try_borrowing(
|
return try_borrowing(
|
||||||
ty::TraitRef::new(trait_ref.def_id, imm_substs),
|
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)),
|
||||||
ty::TraitRef::new(trait_ref.def_id, mut_substs),
|
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)),
|
||||||
trait_ref,
|
*poly_trait_ref,
|
||||||
&never_suggest_borrow[..],
|
&never_suggest_borrow[..],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
9
src/test/ui/suggestions/issue-89333.rs
Normal file
9
src/test/ui/suggestions/issue-89333.rs
Normal file
|
@ -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<T>(arg: &impl Fn() -> T) where for<'a> &'a T: Default {}
|
23
src/test/ui/suggestions/issue-89333.stderr
Normal file
23
src/test/ui/suggestions/issue-89333.stderr
Normal file
|
@ -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<T>(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`.
|
Loading…
Reference in a new issue