Skip to content

report_similar_impl_candidates seems to not put things in a canonical order #53302

Closed
@scottmcm

Description

@scottmcm

I hit the following UI test failure in travis today:

 	   |         ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32`
 	   |
 	   = help: the following implementations were found:
+	             <i32 as std::convert::From<u8>>
 	             <i32 as std::convert::From<i8>>
-	             <i32 as std::convert::From<bool>>
 	             <i32 as std::convert::From<u16>>
 	             <i32 as std::convert::From<i16>>
-	             <i32 as std::convert::From<u8>>
+	             <i32 as std::convert::From<bool>>
 	   = note: required by `std::convert::From::from`

https://travis-ci.org/rust-lang/rust/jobs/415272826#L1942-L1958

Despite being fully-up-to-date against master and that passing locally.

Perhaps the order is deterministic normally, but different for me because I built --incremental?

I figured it was worth filing, at least, as I can't see any obvious sort in the relevant code:

fn find_similar_impl_candidates(&self,
trait_ref: ty::PolyTraitRef<'tcx>)
-> Vec<ty::TraitRef<'tcx>>
{
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true);
let mut impl_candidates = Vec::new();
match simp {
Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx,
imp.self_ty(),
true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return;
}
}
impl_candidates.push(imp);
}),
None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
impl_candidates.push(
self.tcx.impl_trait_ref(def_id).unwrap());
})
};
impl_candidates
}
fn report_similar_impl_candidates(&self,
impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder)
{
if impl_candidates.is_empty() {
return;
}
let end = if impl_candidates.len() <= 5 {
impl_candidates.len()
} else {
4
};
let normalize = |candidate| self.tcx.global_tcx().infer_ctxt().enter(|ref infcx| {
let normalized = infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
.normalize(candidate)
.ok();
match normalized {
Some(normalized) => format!("\n {:?}", normalized.value),
None => format!("\n {:?}", candidate),
}
});
err.help(&format!("the following implementations were found:{}{}",
&impl_candidates[0..end].iter().map(normalize).collect::<String>(),
if impl_candidates.len() > 5 {
format!("\nand {} others", impl_candidates.len() - 4)
} else {
"".to_owned()
}
));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions