Skip to content

Commit bd90b93

Browse files
committed
auto merge of #19884 : nikomatsakis/rust/issue-19730-perfect-forwarding, r=pnkfelix
Rewrite how the HRTB algorithm matches impls against obligations. Instead of impls providing higher-ranked trait-references, impls now once again only have early-bound regions. The skolemization checks are thus moved out into trait matching itself. This allows to implement "perfect forwarding" impls like those described in #19730. This PR builds on a previous PR that was already reviewed by @pnkfelix. r? @pnkfelix Fixes #19730
2 parents 0efafac + ebf1e4f commit bd90b93

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+3197
-2416
lines changed

src/libcollections/btree/set.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -762,8 +762,8 @@ mod test {
762762
expected: &'b [int],
763763
}
764764

765-
impl<'a, 'b> FnMut(&int) -> bool for Counter<'a, 'b> {
766-
extern "rust-call" fn call_mut(&mut self, (&x,): (&int,)) -> bool {
765+
impl<'a, 'b, 'c> FnMut(&'c int) -> bool for Counter<'a, 'b> {
766+
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c int,)) -> bool {
767767
assert_eq!(x, self.expected[*self.i]);
768768
*self.i += 1;
769769
true

src/libcore/str.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub use self::Searcher::{Naive, TwoWay, TwoWayLong};
2121

2222
use char::Char;
2323
use char;
24+
use clone::Clone;
2425
use cmp::{Eq, mod};
2526
use default::Default;
2627
use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
@@ -31,7 +32,7 @@ use mem;
3132
use num::Int;
3233
use option::Option;
3334
use option::Option::{None, Some};
34-
use ops::FnMut;
35+
use ops::{Fn, FnMut};
3536
use ptr::RawPtr;
3637
use raw::{Repr, Slice};
3738
use slice::{mod, SliceExt};
@@ -316,7 +317,23 @@ impl<'a> DoubleEndedIterator<(uint, char)> for CharOffsets<'a> {
316317

317318
/// External iterator for a string's bytes.
318319
/// Use with the `std::iter` module.
319-
pub type Bytes<'a> = Map<&'a u8, u8, slice::Items<'a, u8>, fn(&u8) -> u8>;
320+
pub type Bytes<'a> = Map<&'a u8, u8, slice::Items<'a, u8>, BytesFn>;
321+
322+
/// A temporary new type wrapper that ensures that the `Bytes` iterator
323+
/// is cloneable.
324+
#[deriving(Copy)]
325+
#[experimental = "iterator type instability"]
326+
pub struct BytesFn(fn(&u8) -> u8);
327+
328+
impl<'a> Fn(&'a u8) -> u8 for BytesFn {
329+
extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
330+
(self.0)(ptr)
331+
}
332+
}
333+
334+
impl Clone for BytesFn {
335+
fn clone(&self) -> BytesFn { *self }
336+
}
320337

321338
/// An iterator over the substrings of a string, separated by `sep`.
322339
#[deriving(Clone)]
@@ -2009,7 +2026,7 @@ impl StrPrelude for str {
20092026
fn bytes(&self) -> Bytes {
20102027
fn deref(&x: &u8) -> u8 { x }
20112028

2012-
self.as_bytes().iter().map(deref)
2029+
self.as_bytes().iter().map(BytesFn(deref))
20132030
}
20142031

20152032
#[inline]

src/librustc/lint/builtin.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1784,9 +1784,7 @@ impl LintPass for Stability {
17841784
method_num: index,
17851785
..
17861786
}) => {
1787-
ty::trait_item(cx.tcx,
1788-
trait_ref.def_id,
1789-
index).def_id()
1787+
ty::trait_item(cx.tcx, trait_ref.def_id, index).def_id()
17901788
}
17911789
}
17921790
}

src/librustc/metadata/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
704704
let name = item_name(&*intr, item);
705705
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
706706
ty::ty_bare_fn(ref f) =>
707-
(Some(ctor_ty), f.sig.inputs.clone(), None),
707+
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
708708
_ => { // Nullary or struct enum variant.
709709
let mut arg_names = Vec::new();
710710
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)

src/librustc/metadata/tydecode.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use self::DefIdSource::*;
2121
use middle::region;
2222
use middle::subst;
2323
use middle::subst::VecPerParamSpace;
24-
use middle::ty::{mod, Ty};
24+
use middle::ty::{mod, AsPredicate, Ty};
2525

2626
use std::rc::Rc;
2727
use std::str;
@@ -414,7 +414,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
414414
}
415415
'x' => {
416416
assert_eq!(next(st), '[');
417-
let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
417+
let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)));
418418
let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
419419
assert_eq!(next(st), ']');
420420
return ty::mk_trait(st.tcx, trait_ref, bounds);
@@ -603,7 +603,7 @@ fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
603603
}
604604
}
605605

606-
fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::FnSig<'tcx> {
606+
fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::PolyFnSig<'tcx> {
607607
assert_eq!(next(st), '[');
608608
let mut inputs = Vec::new();
609609
while peek(st) != ']' {
@@ -622,9 +622,9 @@ fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::FnSig<'
622622
}
623623
_ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
624624
};
625-
ty::FnSig {inputs: inputs,
626-
output: output,
627-
variadic: variadic}
625+
ty::Binder(ty::FnSig {inputs: inputs,
626+
output: output,
627+
variadic: variadic})
628628
}
629629

630630
// Rust metadata parsing
@@ -669,13 +669,13 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
669669
-> ty::Predicate<'tcx>
670670
{
671671
match next(st) {
672-
't' => ty::Predicate::Trait(Rc::new(parse_trait_ref(st, conv))),
673-
'e' => ty::Predicate::Equate(parse_ty(st, |x,y| conv(x,y)),
674-
parse_ty(st, |x,y| conv(x,y))),
675-
'r' => ty::Predicate::RegionOutlives(parse_region(st, |x,y| conv(x,y)),
676-
parse_region(st, |x,y| conv(x,y))),
677-
'o' => ty::Predicate::TypeOutlives(parse_ty(st, |x,y| conv(x,y)),
678-
parse_region(st, |x,y| conv(x,y))),
672+
't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
673+
'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
674+
parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
675+
'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
676+
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
677+
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
678+
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
679679
c => panic!("Encountered invalid character in metadata: {}", c)
680680
}
681681
}
@@ -759,10 +759,12 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
759759
loop {
760760
match next(st) {
761761
'R' => {
762-
param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
762+
param_bounds.region_bounds.push(
763+
parse_region(st, |x, y| conv (x, y)));
763764
}
764765
'I' => {
765-
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
766+
param_bounds.trait_bounds.push(
767+
Rc::new(ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)))));
766768
}
767769
'.' => {
768770
return param_bounds;

src/librustc/metadata/tyencode.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
251251
ty::ty_trait(box ty::TyTrait { ref principal,
252252
ref bounds }) => {
253253
mywrite!(w, "x[");
254-
enc_trait_ref(w, cx, principal);
254+
enc_trait_ref(w, cx, &principal.0);
255255
enc_existential_bounds(w, cx, bounds);
256256
mywrite!(w, "]");
257257
}
@@ -351,18 +351,18 @@ pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
351351
}
352352

353353
fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
354-
fsig: &ty::FnSig<'tcx>) {
354+
fsig: &ty::PolyFnSig<'tcx>) {
355355
mywrite!(w, "[");
356-
for ty in fsig.inputs.iter() {
356+
for ty in fsig.0.inputs.iter() {
357357
enc_ty(w, cx, *ty);
358358
}
359359
mywrite!(w, "]");
360-
if fsig.variadic {
360+
if fsig.0.variadic {
361361
mywrite!(w, "V");
362362
} else {
363363
mywrite!(w, "N");
364364
}
365-
match fsig.output {
365+
match fsig.0.output {
366366
ty::FnConverging(result_type) => {
367367
enc_ty(w, cx, result_type);
368368
}
@@ -401,7 +401,7 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
401401

402402
for tp in bs.trait_bounds.iter() {
403403
mywrite!(w, "I");
404-
enc_trait_ref(w, cx, &**tp);
404+
enc_trait_ref(w, cx, &tp.0);
405405
}
406406

407407
mywrite!(w, ".");
@@ -425,19 +425,19 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
425425
match *p {
426426
ty::Predicate::Trait(ref trait_ref) => {
427427
mywrite!(w, "t");
428-
enc_trait_ref(w, cx, &**trait_ref);
428+
enc_trait_ref(w, cx, &trait_ref.0);
429429
}
430-
ty::Predicate::Equate(a, b) => {
430+
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
431431
mywrite!(w, "e");
432432
enc_ty(w, cx, a);
433433
enc_ty(w, cx, b);
434434
}
435-
ty::Predicate::RegionOutlives(a, b) => {
435+
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
436436
mywrite!(w, "r");
437437
enc_region(w, cx, a);
438438
enc_region(w, cx, b);
439439
}
440-
ty::Predicate::TypeOutlives(a, b) => {
440+
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
441441
mywrite!(w, "o");
442442
enc_ty(w, cx, a);
443443
enc_region(w, cx, b);

src/librustc/middle/astencode.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
11131113
this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
11141114
this.emit_enum_variant_arg(0, |this| {
11151115
try!(this.emit_struct_field("principal", 0, |this| {
1116-
Ok(this.emit_trait_ref(ecx, &*principal))
1116+
Ok(this.emit_trait_ref(ecx, &principal.0))
11171117
}));
11181118
this.emit_struct_field("bounds", 1, |this| {
11191119
Ok(this.emit_existential_bounds(ecx, b))
@@ -1277,7 +1277,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
12771277
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
12781278
rbml_w.id(id);
12791279
rbml_w.tag(c::tag_table_val, |rbml_w| {
1280-
rbml_w.emit_trait_ref(ecx, &**trait_ref);
1280+
rbml_w.emit_trait_ref(ecx, &trait_ref.0);
12811281
})
12821282
})
12831283
}
@@ -1356,6 +1356,8 @@ trait rbml_decoder_decoder_helpers<'tcx> {
13561356
fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
13571357
fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
13581358
-> Rc<ty::TraitRef<'tcx>>;
1359+
fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1360+
-> Rc<ty::PolyTraitRef<'tcx>>;
13591361
fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
13601362
-> ty::TypeParameterDef<'tcx>;
13611363
fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1548,6 +1550,19 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
15481550
}).unwrap())
15491551
}
15501552

1553+
fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1554+
-> Rc<ty::PolyTraitRef<'tcx>> {
1555+
Rc::new(ty::Binder(self.read_opaque(|this, doc| {
1556+
let ty = tydecode::parse_trait_ref_data(
1557+
doc.data,
1558+
dcx.cdata.cnum,
1559+
doc.start,
1560+
dcx.tcx,
1561+
|s, a| this.convert_def_id(dcx, s, a));
1562+
Ok(ty)
1563+
}).unwrap()))
1564+
}
1565+
15511566
fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
15521567
-> ty::TypeParameterDef<'tcx> {
15531568
self.read_opaque(|this, doc| {
@@ -1753,7 +1768,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
17531768
2 => {
17541769
let ty_trait = try!(this.read_enum_variant_arg(0, |this| {
17551770
let principal = try!(this.read_struct_field("principal", 0, |this| {
1756-
Ok(this.read_trait_ref(dcx))
1771+
Ok(this.read_poly_trait_ref(dcx))
17571772
}));
17581773
Ok(ty::TyTrait {
17591774
principal: (*principal).clone(),
@@ -1926,7 +1941,7 @@ fn decode_side_tables(dcx: &DecodeContext,
19261941
dcx.tcx.method_map.borrow_mut().insert(method_call, method);
19271942
}
19281943
c::tag_table_object_cast_map => {
1929-
let trait_ref = val_dsr.read_trait_ref(dcx);
1944+
let trait_ref = val_dsr.read_poly_trait_ref(dcx);
19301945
dcx.tcx.object_cast_map.borrow_mut()
19311946
.insert(id, trait_ref);
19321947
}

src/librustc/middle/check_static.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ use middle::infer;
3131
use middle::traits;
3232
use middle::mem_categorization as mc;
3333
use middle::expr_use_visitor as euv;
34-
use util::common::ErrorReported;
3534
use util::nodemap::NodeSet;
3635

3736
use syntax::ast;
@@ -122,17 +121,12 @@ impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
122121
let ty = ty::node_id_to_type(self.tcx, e.id);
123122
let infcx = infer::new_infer_ctxt(self.tcx);
124123
let mut fulfill_cx = traits::FulfillmentContext::new();
125-
match traits::trait_ref_for_builtin_bound(self.tcx, ty::BoundSync, ty) {
126-
Ok(trait_ref) => {
127-
fulfill_cx.register_trait_ref(self.tcx, trait_ref,
128-
traits::ObligationCause::dummy());
129-
let env = ty::empty_parameter_environment();
130-
if !fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok() {
131-
self.tcx.sess.span_err(e.span, "shared static items must have a \
132-
type which implements Sync");
133-
}
134-
}
135-
Err(ErrorReported) => { }
124+
fulfill_cx.register_builtin_bound(self.tcx, ty, ty::BoundSync,
125+
traits::ObligationCause::dummy());
126+
let env = ty::empty_parameter_environment();
127+
if !fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok() {
128+
self.tcx.sess.span_err(e.span, "shared static items must have a \
129+
type which implements Sync");
136130
}
137131
}
138132
}

src/librustc/middle/fast_reject.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
6060
ty::ty_vec(..) => Some(VecSimplifiedType),
6161
ty::ty_ptr(_) => Some(PtrSimplifiedType),
6262
ty::ty_trait(ref trait_info) => {
63-
Some(TraitSimplifiedType(trait_info.principal.def_id))
63+
Some(TraitSimplifiedType(trait_info.principal.def_id()))
6464
}
6565
ty::ty_struct(def_id, _) => {
6666
Some(StructSimplifiedType(def_id))
@@ -83,10 +83,10 @@ pub fn simplify_type(tcx: &ty::ctxt,
8383
Some(TupleSimplifiedType(tys.len()))
8484
}
8585
ty::ty_closure(ref f) => {
86-
Some(FunctionSimplifiedType(f.sig.inputs.len()))
86+
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
8787
}
8888
ty::ty_bare_fn(ref f) => {
89-
Some(FunctionSimplifiedType(f.sig.inputs.len()))
89+
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
9090
}
9191
ty::ty_param(_) => {
9292
if can_simplify_params {

0 commit comments

Comments
 (0)