Skip to content

Commit

Permalink
Fix a bug in the opt-in-copy work: it was failing to liberate the reg…
Browse files Browse the repository at this point in the history
…ions bound in the impl before searching for `Copy` implements for all fields, leading to problems in the "copyability check". Basically the copyability check would wind up looking for an impl of `for<'tcx> Foo<&'tcx T>`. The impl that exists however is `impl<T> Copy for Foo<T>` and the current rules do not consider that a match (something I would like to revise in a later PR).
  • Loading branch information
nikomatsakis committed Dec 19, 2014
1 parent 1b24602 commit b3dcb85
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/librustc_typeck/coherence/mod.rs
Expand Up @@ -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};
Expand All @@ -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;
Expand Down Expand Up @@ -472,6 +471,17 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
impl_did.node);
let self_type = self_type.ty.subst(tcx, &param_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, &param_env) {
Ok(()) => {}
Err(ty::FieldDoesNotImplementCopy(name)) => {
Expand Down
38 changes: 38 additions & 0 deletions 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T> Copy for Foo<T>` 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<T> { x: T }

type Ty<'tcx> = &'tcx TyS<'tcx>;

enum TyS<'tcx> {
Boop(marker::InvariantLifetime<'tcx>)
}

enum Bar<'tcx> {
Baz(Foo<Ty<'tcx>>)
}

impl<'tcx> Copy for Bar<'tcx> { }

fn main() { }

0 comments on commit b3dcb85

Please sign in to comment.