Auto merge of #28629 - arielb1:supertrait-self, r=eddyb
Fixes #28576 r? @eddyb
This commit is contained in:
commit
9169e6c53c
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 ..
|
||||
}
|
||||
|
22
src/test/compile-fail/issue-28576.rs
Normal file
22
src/test/compile-fail/issue-28576.rs
Normal 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() {}
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user