Auto merge of #28629 - arielb1:supertrait-self, r=eddyb

Fixes #28576

r? @eddyb
This commit is contained in:
bors 2015-09-26 13:03:08 +00:00
commit 9169e6c53c
8 changed files with 80 additions and 13 deletions

View File

@ -248,9 +248,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
}
ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = object_safety_violations(
infcx.tcx, trait_def_id);
report_object_safety_error(infcx.tcx,
obligation.cause.span,
trait_def_id,
violations,
is_warning);
note_obligation_cause(infcx, obligation);
}
@ -286,7 +289,9 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
}
TraitNotObjectSafe(did) => {
report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
let violations = object_safety_violations(infcx.tcx, did);
report_object_safety_error(infcx.tcx, obligation.cause.span, did,
violations, is_warning);
note_obligation_cause(infcx, obligation);
}
}
@ -295,6 +300,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
trait_def_id: DefId,
violations: Vec<ObjectSafetyViolation>,
is_warning: bool)
{
span_err_or_warn!(
@ -302,7 +308,7 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
"the trait `{}` cannot be made into an object",
tcx.item_path_str(trait_def_id));
for violation in object_safety_violations(tcx, trait_def_id) {
for violation in violations {
match violation {
ObjectSafetyViolation::SizedSelf => {
tcx.sess.fileline_note(

View File

@ -37,6 +37,7 @@ pub use self::project::MismatchedProjectionTypes;
pub use self::project::normalize;
pub use self::project::Normalized;
pub use self::object_safety::is_object_safe;
pub use self::object_safety::astconv_object_safety_violations;
pub use self::object_safety::object_safety_violations;
pub use self::object_safety::ObjectSafetyViolation;
pub use self::object_safety::MethodViolationCode;

View File

@ -76,6 +76,27 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
result
}
/// Returns the object safety violations that affect
/// astconv - currently, Self in supertraits. This is needed
/// because `object_safety_violations` can't be used during
/// type collection.
pub fn astconv_object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
{
let mut violations = vec![];
if supertraits_reference_self(tcx, trait_def_id) {
violations.push(ObjectSafetyViolation::SupertraitSelf);
}
debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
trait_def_id,
violations);
violations
}
pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: DefId)
-> Vec<ObjectSafetyViolation<'tcx>>
@ -118,9 +139,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
violations
}
fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: DefId)
-> bool
pub fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: DefId)
-> bool
{
let trait_def = tcx.lookup_trait_def(trait_def_id);
let trait_ref = trait_def.trait_ref.clone();

View File

@ -393,7 +393,7 @@ fn create_substs_for_ast_path<'tcx>(
let tcx = this.tcx();
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
types_provided={:?}, region_substs={:?}",
types_provided={:?}, region_substs={:?})",
decl_generics, self_ty, types_provided,
region_substs);
@ -474,6 +474,9 @@ fn create_substs_for_ast_path<'tcx>(
}
}
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
decl_generics, self_ty, substs);
substs
}
@ -741,6 +744,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment);
// The trait reference introduces a binding level here, so
// we need to shift the `rscope`. It'd be nice if we could
// do away with this rscope stuff and work this knowledge
@ -774,6 +778,8 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
poly_projections.extend(converted_bindings);
}
debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
trait_segment, poly_projections, poly_trait_ref);
poly_trait_ref
}
@ -1103,7 +1109,18 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
// ensure the super predicates and stop if we encountered an error
if this.ensure_super_predicates(span, object.principal_def_id()).is_err() {
if this.ensure_super_predicates(span, principal.def_id()).is_err() {
return tcx.types.err;
}
// check that there are no gross object safety violations,
// most importantly, that the supertraits don't contain Self,
// to avoid ICE-s.
let object_safety_violations =
traits::astconv_object_safety_violations(tcx, principal.def_id());
if !object_safety_violations.is_empty() {
traits::report_object_safety_error(
tcx, span, principal.def_id(), object_safety_violations, false);
return tcx.types.err;
}

View File

@ -3355,5 +3355,5 @@ register_diagnostics! {
E0399, // trait items need to be implemented because the associated
// type `{}` was overridden
E0436, // functional record update requires a struct
E0513, // no type for local variable ..
E0513 // no type for local variable ..
}

View File

@ -0,0 +1,22 @@
// Copyright 2015 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.
pub trait Foo<RHS=Self> {
type Assoc;
}
pub trait Bar: Foo<Assoc=()> {
fn new(&self, b: &
Bar //~ ERROR the trait `Bar` cannot be made into an object
<Assoc=()>
);
}
fn main() {}

View File

@ -20,12 +20,12 @@ trait Expr: Debug + PartialEq {
#[derive(Debug)]
struct SExpr<'x> {
elements: Vec<Box<Expr+ 'x>>,
//~^ ERROR E0038
}
impl<'x> PartialEq for SExpr<'x> {
fn eq(&self, other:&SExpr<'x>) -> bool {
println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
//~^ ERROR E0038
let result = self.elements.len() == other.elements.len();
println!("Got compare {}", result);
@ -44,8 +44,8 @@ impl <'x> Expr for SExpr<'x> {
}
fn main() {
let a: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
let b: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
let a: Box<Expr> = Box::new(SExpr::new());
let b: Box<Expr> = Box::new(SExpr::new());
// assert_eq!(a , b);
}

View File

@ -23,9 +23,9 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
}
fn make_baz<T:Baz>(t: &T) -> &Baz {
//~^ ERROR E0038
//~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
t
//~^ ERROR E0038
//~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
}
fn main() {