Skip to content

Commit 9169e6c

Browse files
committed
Auto merge of #28629 - arielb1:supertrait-self, r=eddyb
Fixes #28576 r? @eddyb
2 parents b94c4f5 + 77e8f33 commit 9169e6c

File tree

8 files changed

+80
-13
lines changed

8 files changed

+80
-13
lines changed

src/librustc/middle/traits/error_reporting.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
248248
}
249249

250250
ty::Predicate::ObjectSafe(trait_def_id) => {
251+
let violations = object_safety_violations(
252+
infcx.tcx, trait_def_id);
251253
report_object_safety_error(infcx.tcx,
252254
obligation.cause.span,
253255
trait_def_id,
256+
violations,
254257
is_warning);
255258
note_obligation_cause(infcx, obligation);
256259
}
@@ -286,7 +289,9 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
286289
}
287290

288291
TraitNotObjectSafe(did) => {
289-
report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
292+
let violations = object_safety_violations(infcx.tcx, did);
293+
report_object_safety_error(infcx.tcx, obligation.cause.span, did,
294+
violations, is_warning);
290295
note_obligation_cause(infcx, obligation);
291296
}
292297
}
@@ -295,14 +300,15 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
295300
pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
296301
span: Span,
297302
trait_def_id: DefId,
303+
violations: Vec<ObjectSafetyViolation>,
298304
is_warning: bool)
299305
{
300306
span_err_or_warn!(
301307
is_warning, tcx.sess, span, E0038,
302308
"the trait `{}` cannot be made into an object",
303309
tcx.item_path_str(trait_def_id));
304310

305-
for violation in object_safety_violations(tcx, trait_def_id) {
311+
for violation in violations {
306312
match violation {
307313
ObjectSafetyViolation::SizedSelf => {
308314
tcx.sess.fileline_note(

src/librustc/middle/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub use self::project::MismatchedProjectionTypes;
3737
pub use self::project::normalize;
3838
pub use self::project::Normalized;
3939
pub use self::object_safety::is_object_safe;
40+
pub use self::object_safety::astconv_object_safety_violations;
4041
pub use self::object_safety::object_safety_violations;
4142
pub use self::object_safety::ObjectSafetyViolation;
4243
pub use self::object_safety::MethodViolationCode;

src/librustc/middle/traits/object_safety.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,27 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
7676
result
7777
}
7878

79+
/// Returns the object safety violations that affect
80+
/// astconv - currently, Self in supertraits. This is needed
81+
/// because `object_safety_violations` can't be used during
82+
/// type collection.
83+
pub fn astconv_object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
84+
trait_def_id: DefId)
85+
-> Vec<ObjectSafetyViolation<'tcx>>
86+
{
87+
let mut violations = vec![];
88+
89+
if supertraits_reference_self(tcx, trait_def_id) {
90+
violations.push(ObjectSafetyViolation::SupertraitSelf);
91+
}
92+
93+
debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
94+
trait_def_id,
95+
violations);
96+
97+
violations
98+
}
99+
79100
pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
80101
trait_def_id: DefId)
81102
-> Vec<ObjectSafetyViolation<'tcx>>
@@ -118,9 +139,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
118139
violations
119140
}
120141

121-
fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
122-
trait_def_id: DefId)
123-
-> bool
142+
pub fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
143+
trait_def_id: DefId)
144+
-> bool
124145
{
125146
let trait_def = tcx.lookup_trait_def(trait_def_id);
126147
let trait_ref = trait_def.trait_ref.clone();

src/librustc_typeck/astconv.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ fn create_substs_for_ast_path<'tcx>(
393393
let tcx = this.tcx();
394394

395395
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
396-
types_provided={:?}, region_substs={:?}",
396+
types_provided={:?}, region_substs={:?})",
397397
decl_generics, self_ty, types_provided,
398398
region_substs);
399399

@@ -474,6 +474,9 @@ fn create_substs_for_ast_path<'tcx>(
474474
}
475475
}
476476

477+
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
478+
decl_generics, self_ty, substs);
479+
477480
substs
478481
}
479482

@@ -741,6 +744,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
741744
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
742745
-> ty::PolyTraitRef<'tcx>
743746
{
747+
debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment);
744748
// The trait reference introduces a binding level here, so
745749
// we need to shift the `rscope`. It'd be nice if we could
746750
// do away with this rscope stuff and work this knowledge
@@ -774,6 +778,8 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
774778
poly_projections.extend(converted_bindings);
775779
}
776780

781+
debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
782+
trait_segment, poly_projections, poly_trait_ref);
777783
poly_trait_ref
778784
}
779785

@@ -1103,7 +1109,18 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
11031109
object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
11041110

11051111
// ensure the super predicates and stop if we encountered an error
1106-
if this.ensure_super_predicates(span, object.principal_def_id()).is_err() {
1112+
if this.ensure_super_predicates(span, principal.def_id()).is_err() {
1113+
return tcx.types.err;
1114+
}
1115+
1116+
// check that there are no gross object safety violations,
1117+
// most importantly, that the supertraits don't contain Self,
1118+
// to avoid ICE-s.
1119+
let object_safety_violations =
1120+
traits::astconv_object_safety_violations(tcx, principal.def_id());
1121+
if !object_safety_violations.is_empty() {
1122+
traits::report_object_safety_error(
1123+
tcx, span, principal.def_id(), object_safety_violations, false);
11071124
return tcx.types.err;
11081125
}
11091126

src/librustc_typeck/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3355,5 +3355,5 @@ register_diagnostics! {
33553355
E0399, // trait items need to be implemented because the associated
33563356
// type `{}` was overridden
33573357
E0436, // functional record update requires a struct
3358-
E0513, // no type for local variable ..
3358+
E0513 // no type for local variable ..
33593359
}

src/test/compile-fail/issue-28576.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub trait Foo<RHS=Self> {
12+
type Assoc;
13+
}
14+
15+
pub trait Bar: Foo<Assoc=()> {
16+
fn new(&self, b: &
17+
Bar //~ ERROR the trait `Bar` cannot be made into an object
18+
<Assoc=()>
19+
);
20+
}
21+
22+
fn main() {}

src/test/compile-fail/object-safety-issue-22040.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ trait Expr: Debug + PartialEq {
2020
#[derive(Debug)]
2121
struct SExpr<'x> {
2222
elements: Vec<Box<Expr+ 'x>>,
23+
//~^ ERROR E0038
2324
}
2425

2526
impl<'x> PartialEq for SExpr<'x> {
2627
fn eq(&self, other:&SExpr<'x>) -> bool {
2728
println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
28-
//~^ ERROR E0038
2929
let result = self.elements.len() == other.elements.len();
3030

3131
println!("Got compare {}", result);
@@ -44,8 +44,8 @@ impl <'x> Expr for SExpr<'x> {
4444
}
4545

4646
fn main() {
47-
let a: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
48-
let b: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
47+
let a: Box<Expr> = Box::new(SExpr::new());
48+
let b: Box<Expr> = Box::new(SExpr::new());
4949

5050
// assert_eq!(a , b);
5151
}

src/test/compile-fail/object-safety-supertrait-mentions-Self.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
2323
}
2424

2525
fn make_baz<T:Baz>(t: &T) -> &Baz {
26+
//~^ ERROR E0038
27+
//~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
2628
t
27-
//~^ ERROR E0038
28-
//~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
2929
}
3030

3131
fn main() {

0 commit comments

Comments
 (0)