Skip to content

Commit 1b93d71

Browse files
committed
Fix ICE in EXPL_IMPL_CLONE_ON_COPY
1 parent 6a624fe commit 1b93d71

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

src/derive.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use rustc::lint::*;
2+
use rustc::middle::ty::TypeVariants;
23
use rustc::middle::ty::fast_reject::simplify_type;
34
use rustc::middle::ty;
45
use rustc_front::hir::*;
56
use syntax::ast::{Attribute, MetaItemKind};
67
use syntax::codemap::Span;
78
use utils::{CLONE_TRAIT_PATH, HASH_PATH};
89
use utils::{match_path, span_lint_and_then};
9-
use rustc::middle::ty::TypeVariants;
1010

1111
/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq`
1212
/// explicitly.
@@ -73,14 +73,14 @@ impl LateLintPass for Derive {
7373
let ast_ty_to_ty_cache = cx.tcx.ast_ty_to_ty_cache.borrow();
7474

7575
if_let_chain! {[
76-
let ItemImpl(_, _, _, Some(ref trait_ref), ref ast_ty, _) = item.node,
76+
let ItemImpl(_, _, ref ast_generics, Some(ref trait_ref), ref ast_ty, _) = item.node,
7777
let Some(&ty) = ast_ty_to_ty_cache.get(&ast_ty.id)
7878
], {
7979
if item.attrs.iter().any(is_automatically_derived) {
8080
check_hash_peq(cx, item.span, trait_ref, ty);
8181
}
82-
else {
83-
check_copy_clone(cx, item.span, trait_ref, ty);
82+
else if !ast_generics.is_lt_parameterized() {
83+
check_copy_clone(cx, item, trait_ref, ty);
8484
}
8585
}}
8686
}
@@ -127,11 +127,13 @@ fn check_hash_peq(cx: &LateContext, span: Span, trait_ref: &TraitRef, ty: ty::Ty
127127
}
128128

129129
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
130-
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
130+
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>,
131+
item: &Item,
132+
trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
131133
if match_path(&trait_ref.path, &CLONE_TRAIT_PATH) {
132-
let parameter_environment = cx.tcx.empty_parameter_environment();
134+
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
133135

134-
if ty.moves_by_default(&parameter_environment, span) {
136+
if ty.moves_by_default(&parameter_environment, item.span) {
135137
return; // ty is not Copy
136138
}
137139

@@ -160,10 +162,10 @@ fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref:
160162

161163
span_lint_and_then(cx,
162164
DERIVE_HASH_NOT_EQ,
163-
span,
165+
item.span,
164166
"you are implementing `Clone` explicitly on a `Copy` type",
165167
|db| {
166-
db.span_note(span, "consider deriving `Clone` or removing `Copy`");
168+
db.span_note(item.span, "consider deriving `Clone` or removing `Copy`");
167169
});
168170
}
169171
}

tests/ice-666.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(plugin)]
2+
#![plugin(clippy)]
3+
4+
pub struct Lt<'a> {
5+
_foo: &'a u8,
6+
}
7+
8+
impl<'a> Copy for Lt<'a> {}
9+
impl<'a> Clone for Lt<'a> {
10+
fn clone(&self) -> Lt<'a> {
11+
unimplemented!();
12+
}
13+
}
14+
15+
pub struct Ty<A> {
16+
_foo: A,
17+
}
18+
19+
impl<A: Copy> Copy for Ty<A> {}
20+
impl<A> Clone for Ty<A> {
21+
fn clone(&self) -> Ty<A> {
22+
unimplemented!();
23+
}
24+
}

0 commit comments

Comments
 (0)