Avoid autoderef coercions leaking if they don't apply

This commit is contained in:
Florian Diebold 2022-02-25 15:46:02 +01:00
parent 187e6bacac
commit 6fc3d3aa4c
2 changed files with 42 additions and 0 deletions

View File

@ -259,6 +259,8 @@ impl<'a> InferenceContext<'a> {
// details of coercion errors though, so I think it's useful to leave
// the structure like it is.
let snapshot = self.table.snapshot();
let mut autoderef = Autoderef::new(&mut self.table, from_ty.clone());
let mut first_error = None;
let mut found = None;
@ -315,6 +317,7 @@ impl<'a> InferenceContext<'a> {
let InferOk { value: ty, goals } = match found {
Some(d) => d,
None => {
self.table.rollback_to(snapshot);
let err = first_error.expect("coerce_borrowed_pointer had no error");
return Err(err);
}

View File

@ -242,6 +242,45 @@ fn test() {
);
}
#[test]
fn coerce_autoderef_implication_1() {
check_no_mismatches(
r"
//- minicore: deref
struct Foo<T>;
impl core::ops::Deref for Foo<u32> { type Target = (); }
fn takes_ref_foo<T>(x: &Foo<T>) {}
fn test() {
let foo = Foo;
//^^^ type: Foo<{unknown}>
takes_ref_foo(&foo);
let foo = Foo;
//^^^ type: Foo<u32>
let _: &() = &foo;
}",
);
}
#[test]
fn coerce_autoderef_implication_2() {
check(
r"
//- minicore: deref
struct Foo<T>;
impl core::ops::Deref for Foo<u32> { type Target = (); }
fn takes_ref_foo<T>(x: &Foo<T>) {}
fn test() {
let foo = Foo;
//^^^ type: Foo<{unknown}>
let _: &u32 = &Foo;
//^^^^ expected &u32, got &Foo<{unknown}>
}",
);
}
#[test]
fn closure_return_coerce() {
check_no_mismatches(