From b47bf81f5ba90c631c6f47a09fdea404a44b66c0 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Tue, 26 Apr 2022 18:24:43 +0000 Subject: [PATCH] Special case inference around `AsRef>` to support existing code without reverting #95098 #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 #96074. --- .../src/traits/select/mod.rs | 19 ++++++++++++++++++- .../ui/inference/vec-from-array-ref-impl.rs | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/inference/vec-from-array-ref-impl.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e69bf6eca90ef..e1578ab8fe90a 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1767,7 +1767,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { !needs_infer } Some(_) => true, - None => false, + None => { + if let Some(other) = tcx.impl_trait_ref(other_def) + && let Some(victim) = tcx.impl_trait_ref(victim_def) + && tcx.is_diagnostic_item(sym::AsRef, other.def_id) + && tcx.is_diagnostic_item(sym::AsRef, victim.def_id) + && other.substs.len() > 1 + && victim.substs.len() > 1 + && let ty::Slice(other) = other.substs.type_at(1).kind() + && let ty::Adt(def, substs) = victim.substs.type_at(1).kind() + && tcx.is_diagnostic_item(sym::Vec, def.did()) + { + // If this is an `AsRef` implementation that can go either way for + // `AsRef<[T]>` or `AsRef`, prefer the former. + other == &substs.type_at(0) + } else { + false + } + } } } else { false diff --git a/src/test/ui/inference/vec-from-array-ref-impl.rs b/src/test/ui/inference/vec-from-array-ref-impl.rs new file mode 100644 index 0000000000000..58588f0eacd59 --- /dev/null +++ b/src/test/ui/inference/vec-from-array-ref-impl.rs @@ -0,0 +1,14 @@ +// check-pass + +#[derive(Clone)] +struct Constraint; + +fn constraints(constraints: C) +where C: Into> +{ + let _: Vec = constraints.into(); +} + +fn main() { + constraints(vec![Constraint].as_ref()); +}