Skip to content

Commit 7786e14

Browse files
committed
Forbid object types with incomplete projections, before coercions.
1 parent bfb93ef commit 7786e14

File tree

7 files changed

+59
-48
lines changed

7 files changed

+59
-48
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ use middle::ty::{self, RegionEscape, Ty};
5959
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
6060
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
6161
use util::common::{ErrorReported, FN_OUTPUT_NAME};
62+
use util::nodemap::FnvHashSet;
6263
use util::ppaux::{self, Repr, UserString};
6364

6465
use std::iter::{repeat, AdditiveIterator};
@@ -1026,13 +1027,58 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
10261027
projection_bounds,
10271028
bounds);
10281029

1029-
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
1030+
let result = make_object_type(this, span, trait_ref, existential_bounds);
10301031
debug!("trait_ref_to_object_type: result={}",
10311032
result.repr(this.tcx()));
10321033

10331034
result
10341035
}
10351036

1037+
fn make_object_type<'tcx>(this: &AstConv<'tcx>,
1038+
span: Span,
1039+
principal: ty::PolyTraitRef<'tcx>,
1040+
bounds: ty::ExistentialBounds<'tcx>)
1041+
-> Ty<'tcx> {
1042+
let tcx = this.tcx();
1043+
let object = ty::TyTrait {
1044+
principal: principal,
1045+
bounds: bounds
1046+
};
1047+
let object_trait_ref =
1048+
object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
1049+
1050+
// ensure the super predicates and stop if we encountered an error
1051+
if this.ensure_super_predicates(span, object.principal_def_id()).is_err() {
1052+
return tcx.types.err;
1053+
}
1054+
1055+
let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
1056+
traits::supertraits(tcx, object_trait_ref)
1057+
.flat_map(|tr| {
1058+
let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
1059+
trait_def.associated_type_names
1060+
.clone()
1061+
.into_iter()
1062+
.map(move |associated_type_name| (tr.def_id(), associated_type_name))
1063+
})
1064+
.collect();
1065+
1066+
for projection_bound in &object.bounds.projection_bounds {
1067+
let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
1068+
projection_bound.0.projection_ty.item_name);
1069+
associated_types.remove(&pair);
1070+
}
1071+
1072+
for (trait_def_id, name) in associated_types {
1073+
span_err!(tcx.sess, span, E0191,
1074+
"the value of the associated type `{}` (from the trait `{}`) must be specified",
1075+
name.user_string(tcx),
1076+
ty::item_path_str(tcx, trait_def_id));
1077+
}
1078+
1079+
ty::mk_trait(tcx, object.principal, object.bounds)
1080+
}
1081+
10361082
fn report_ambiguous_associated_type(tcx: &ty::ctxt,
10371083
span: Span,
10381084
type_str: &str,
@@ -1785,7 +1831,7 @@ fn conv_ty_poly_trait_ref<'tcx>(
17851831
projection_bounds,
17861832
partitioned_bounds);
17871833

1788-
ty::mk_trait(this.tcx(), main_trait_bound, bounds)
1834+
make_object_type(this, span, main_trait_bound, bounds)
17891835
}
17901836

17911837
pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(

src/librustc_typeck/check/vtable.rs

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use middle::traits::report_fulfillment_errors;
1515
use middle::ty::{self, Ty, AsPredicate};
1616
use syntax::ast;
1717
use syntax::codemap::Span;
18-
use util::nodemap::FnvHashSet;
1918
use util::ppaux::{Repr, UserString};
2019

2120

@@ -134,46 +133,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
134133
fcx.register_predicate(projection_obligation);
135134
}
136135

137-
// Finally, check that there IS a projection predicate for every associated type.
138-
check_object_type_binds_all_associated_types(fcx.tcx(),
139-
span,
140-
object_trait);
141-
142136
object_trait_ref
143137
}
144138

145-
fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
146-
span: Span,
147-
object_trait: &ty::TyTrait<'tcx>)
148-
{
149-
let object_trait_ref =
150-
object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
151-
152-
let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
153-
traits::supertraits(tcx, object_trait_ref.clone())
154-
.flat_map(|tr| {
155-
let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
156-
trait_def.associated_type_names
157-
.clone()
158-
.into_iter()
159-
.map(move |associated_type_name| (tr.def_id(), associated_type_name))
160-
})
161-
.collect();
162-
163-
for projection_bound in &object_trait.bounds.projection_bounds {
164-
let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
165-
projection_bound.0.projection_ty.item_name);
166-
associated_types.remove(&pair);
167-
}
168-
169-
for (trait_def_id, name) in associated_types {
170-
span_err!(tcx.sess, span, E0191,
171-
"the value of the associated type `{}` (from the trait `{}`) must be specified",
172-
name.user_string(tcx),
173-
ty::item_path_str(tcx, trait_def_id));
174-
}
175-
}
176-
177139
pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) {
178140
debug!("select_all_fcx_obligations_and_apply_defaults");
179141

src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ fn dent<C:BoxCar>(c: C, color: C::Color) {
3434

3535
fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
3636
//~^ ERROR ambiguous associated type
37+
//~| ERROR the associated type `Color` (from the trait `Box`) must be specified
38+
//~| ERROR the associated type `Color` (from the trait `Vehicle`) must be specified
3739
}
3840

3941
fn paint<C:BoxCar>(c: C, d: C::Color) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl Foo for X {
2020
type Item = bool;
2121
}
2222

23-
fn print_x(_: &Foo, extra: &str) {
23+
fn print_x(_: &Foo<Item=bool>, extra: &str) {
2424
println!("{}", extra);
2525
}
2626

src/test/run-pass/issue-19121.rs renamed to src/test/compile-fail/issue-19482.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
// Test that a partially specified trait object with unspecified associated
12-
// type does not ICE.
12+
// type does not type-check.
1313

1414
// pretty-expanded FIXME #23616
1515

@@ -20,7 +20,6 @@ trait Foo {
2020
}
2121

2222
fn bar(x: &Foo) {}
23-
// FIXME(#19482) -- `Foo` should specify `A`, but this is not
24-
// currently enforced except at object creation
23+
//~^ ERROR the associated type `A` (from the trait `Foo`) must be specified
2524

2625
pub fn main() {}

src/test/compile-fail/retslot-cast.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
#![feature(rustc_attrs)]
1212
#![allow(warnings)]
1313

14-
pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> {
14+
pub fn fail(x: Option<&(Iterator<Item=()>+Send)>)
15+
-> Option<&Iterator<Item=()>> {
1516
// This call used to trigger an LLVM assertion because the return
1617
// slot had type "Option<&Iterator>"* instead of
1718
// "Option<&(Iterator+Send)>"* -- but this now yields a
@@ -23,7 +24,8 @@ pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> {
2324
inner(x) //~ ERROR mismatched types
2425
}
2526

26-
pub fn inner(x: Option<& (Iterator+Send)>) -> Option<&(Iterator+Send)> {
27+
pub fn inner(x: Option<&(Iterator<Item=()>+Send)>)
28+
-> Option<&(Iterator<Item=()>+Send)> {
2729
x
2830
}
2931

src/test/compile-fail/unboxed-closure-sugar-not-used-on-fn.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
// Test that the `Fn` traits require `()` form without a feature gate.
1313

14-
fn bar1(x: &Fn<()>) {
14+
fn bar1(x: &Fn<(), Output=()>) {
1515
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family
1616
}
1717

0 commit comments

Comments
 (0)