Skip to content

Commit 6fc3d3a

Browse files
committed
Avoid autoderef coercions leaking if they don't apply
1 parent 187e6ba commit 6fc3d3a

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

crates/hir_ty/src/infer/coerce.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ impl<'a> InferenceContext<'a> {
259259
// details of coercion errors though, so I think it's useful to leave
260260
// the structure like it is.
261261

262+
let snapshot = self.table.snapshot();
263+
262264
let mut autoderef = Autoderef::new(&mut self.table, from_ty.clone());
263265
let mut first_error = None;
264266
let mut found = None;
@@ -315,6 +317,7 @@ impl<'a> InferenceContext<'a> {
315317
let InferOk { value: ty, goals } = match found {
316318
Some(d) => d,
317319
None => {
320+
self.table.rollback_to(snapshot);
318321
let err = first_error.expect("coerce_borrowed_pointer had no error");
319322
return Err(err);
320323
}

crates/hir_ty/src/tests/coercion.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,45 @@ fn test() {
242242
);
243243
}
244244

245+
#[test]
246+
fn coerce_autoderef_implication_1() {
247+
check_no_mismatches(
248+
r"
249+
//- minicore: deref
250+
struct Foo<T>;
251+
impl core::ops::Deref for Foo<u32> { type Target = (); }
252+
253+
fn takes_ref_foo<T>(x: &Foo<T>) {}
254+
fn test() {
255+
let foo = Foo;
256+
//^^^ type: Foo<{unknown}>
257+
takes_ref_foo(&foo);
258+
259+
let foo = Foo;
260+
//^^^ type: Foo<u32>
261+
let _: &() = &foo;
262+
}",
263+
);
264+
}
265+
266+
#[test]
267+
fn coerce_autoderef_implication_2() {
268+
check(
269+
r"
270+
//- minicore: deref
271+
struct Foo<T>;
272+
impl core::ops::Deref for Foo<u32> { type Target = (); }
273+
274+
fn takes_ref_foo<T>(x: &Foo<T>) {}
275+
fn test() {
276+
let foo = Foo;
277+
//^^^ type: Foo<{unknown}>
278+
let _: &u32 = &Foo;
279+
//^^^^ expected &u32, got &Foo<{unknown}>
280+
}",
281+
);
282+
}
283+
245284
#[test]
246285
fn closure_return_coerce() {
247286
check_no_mismatches(

0 commit comments

Comments
 (0)