From 17aff1d774b11ef68c122c995b1d2b238ff5fb04 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 18 May 2018 22:56:25 +0200 Subject: [PATCH] Fix cargo late bound region mismatch ICE --- clippy_lints/src/utils/mod.rs | 6 +++++- tests/run-pass/ice-2774.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/run-pass/ice-2774.rs diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 4a30b134a69c..a49464b021a7 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -8,7 +8,7 @@ use rustc::hir::map::Node; use rustc::lint::{LateContext, Level, Lint, LintContext}; use rustc::session::Session; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; +use rustc::ty::{self, Binder, Ty, TyCtxt, layout::{self, IntegerExt}, subst::Kind}; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; @@ -869,10 +869,14 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'t } /// Check if two types are the same. +/// +/// This discards any lifetime annotations, too. // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for // <'b> Foo<'b>` but // not for type parameters. pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + let a = cx.tcx.erase_late_bound_regions(&Binder::bind(a)); + let b = cx.tcx.erase_late_bound_regions(&Binder::bind(b)); cx.tcx .infer_ctxt() .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) diff --git a/tests/run-pass/ice-2774.rs b/tests/run-pass/ice-2774.rs new file mode 100644 index 000000000000..c6d9bb4a276e --- /dev/null +++ b/tests/run-pass/ice-2774.rs @@ -0,0 +1,31 @@ +use std::collections::HashSet; + +// See https://github.com/rust-lang-nursery/rust-clippy/issues/2774 + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Bar { + foo: Foo, +} + +#[derive(Eq, PartialEq, Debug, Hash)] +pub struct Foo {} + +#[allow(implicit_hasher)] +// This should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) { + let mut foos = HashSet::new(); + foos.extend( + bars.iter().map(|b| &b.foo) + ); +} + +#[allow(implicit_hasher)] +// Also this should not cause a 'cannot relate bound region' ICE +pub fn add_barfoos_to_foos2(bars: &HashSet<&Bar>) { + let mut foos = HashSet::new(); + foos.extend( + bars.iter().map(|b| &b.foo) + ); +} + +fn main() {}