diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 8ed0ac98e1e..16a77315bd5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -18,6 +18,7 @@ use metadata::csearch::{each_impl, get_impl_trait}; use metadata::csearch; +use middle::region; use middle::subst::{mod, Subst}; use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId}; use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type}; @@ -26,8 +27,6 @@ use middle::ty::{ty_param, Polytype, ty_ptr}; use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup}; use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open}; use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn}; -use middle::ty::{ty_closure}; -use middle::subst::Subst; use middle::ty; use CrateCtxt; use middle::infer::combine::Combine; @@ -472,6 +471,17 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { impl_did.node); let self_type = self_type.ty.subst(tcx, ¶m_env.free_substs); + // the self-type may have late-bound regions bound in the + // impl; liberate them. + let item_scope = region::CodeExtent::from_node_id(impl_did.node); + let self_type = + ty::liberate_late_bound_regions(tcx, + item_scope, + &ty::bind(self_type)).value; + + debug!("can_type_implement_copy(self_type={})", + self_type.repr(tcx)); + match ty::can_type_implement_copy(tcx, self_type, ¶m_env) { Ok(()) => {} Err(ty::FieldDoesNotImplementCopy(name)) => { diff --git a/src/test/run-pass/hrtb-opt-in-copy.rs b/src/test/run-pass/hrtb-opt-in-copy.rs new file mode 100644 index 00000000000..b6bba363e72 --- /dev/null +++ b/src/test/run-pass/hrtb-opt-in-copy.rs @@ -0,0 +1,38 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we handle binder levels correctly when checking whether a +// type can implement `Copy`. In particular, we had a bug where we failed to +// liberate the late-bound regions from the impl, and thus wound up +// searching for an impl of `for<'tcx> Foo<&'tcx T>`. The impl that +// exists however is `impl Copy for Foo` and the current rules +// did not consider that a match (something I would like to revise in +// a later PR). + +#![allow(dead_code)] + +use std::kinds::marker; + +#[deriving(Copy)] +struct Foo { x: T } + +type Ty<'tcx> = &'tcx TyS<'tcx>; + +enum TyS<'tcx> { + Boop(marker::InvariantLifetime<'tcx>) +} + +enum Bar<'tcx> { + Baz(Foo>) +} + +impl<'tcx> Copy for Bar<'tcx> { } + +fn main() { }