Skip to content

Commit b47bf81

Browse files
committedApr 26, 2022
Special case inference around AsRef<Vec<T>> to support existing code without reverting rust-lang#95098
rust-lang#95098 introduces new `From` impls for `Vec`, which can break existing code that relies on inference when calling `.as_ref()`. This change explicitly carves out a bias in the inference machinery to keep existing code compiling, while still maintaining the new `From` impls. Reported in rust-lang#96074.
1 parent 3d237ab commit b47bf81

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed
 

‎compiler/rustc_trait_selection/src/traits/select/mod.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17671767
!needs_infer
17681768
}
17691769
Some(_) => true,
1770-
None => false,
1770+
None => {
1771+
if let Some(other) = tcx.impl_trait_ref(other_def)
1772+
&& let Some(victim) = tcx.impl_trait_ref(victim_def)
1773+
&& tcx.is_diagnostic_item(sym::AsRef, other.def_id)
1774+
&& tcx.is_diagnostic_item(sym::AsRef, victim.def_id)
1775+
&& other.substs.len() > 1
1776+
&& victim.substs.len() > 1
1777+
&& let ty::Slice(other) = other.substs.type_at(1).kind()
1778+
&& let ty::Adt(def, substs) = victim.substs.type_at(1).kind()
1779+
&& tcx.is_diagnostic_item(sym::Vec, def.did())
1780+
{
1781+
// If this is an `AsRef` implementation that can go either way for
1782+
// `AsRef<[T]>` or `AsRef<Vec[T]>`, prefer the former.
1783+
other == &substs.type_at(0)
1784+
} else {
1785+
false
1786+
}
1787+
}
17711788
}
17721789
} else {
17731790
false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
#[derive(Clone)]
4+
struct Constraint;
5+
6+
fn constraints<C>(constraints: C)
7+
where C: Into<Vec<Constraint>>
8+
{
9+
let _: Vec<Constraint> = constraints.into();
10+
}
11+
12+
fn main() {
13+
constraints(vec![Constraint].as_ref());
14+
}

0 commit comments

Comments
 (0)
Please sign in to comment.