Skip to content

Permit perfect forwarding for Fn traits #19884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Dec 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
514dfdb
Add tests for sub relationship on free/bound regions, revealing a bug.
nikomatsakis Nov 29, 2014
3efc9d2
Fix bug in higher-ranked code that would sometimes leak skolemized re…
nikomatsakis Dec 1, 2014
eb6ea5d
Cleanup type resolution to use type folding infrastructure and not
nikomatsakis Dec 1, 2014
5a6a26a
Delete tests that passed in error. We currently do not support a Clone
nikomatsakis Dec 2, 2014
7be059f
Propagate expected type more widely so that we can rewrite the
nikomatsakis Dec 2, 2014
ff35eeb
Recycle skolemization counts and add some comments.
nikomatsakis Dec 10, 2014
885f7ee
Extract skolemize_regions() helper function.
nikomatsakis Dec 10, 2014
1b24602
Extract leak check into a distinct subroutine.
nikomatsakis Dec 10, 2014
b3dcb85
Fix a bug in the opt-in-copy work: it was failing to liberate the reg…
nikomatsakis Dec 11, 2014
3cf0fbe
Create distinct types for a PolyTraitRef (with bindings) and a normal…
nikomatsakis Dec 11, 2014
416e629
Rename the code that replaces unbound variables to "freshen" rather t…
nikomatsakis Dec 12, 2014
ed4952e
Add (currently unused) helper routine for skolemizing bound regions.
nikomatsakis Dec 12, 2014
1205fd8
Centralize on using `Binder` to introduce new binding levels, rather …
nikomatsakis Dec 12, 2014
4f34524
Move `leak_check` into its own method, and ensure that all higher-ran…
nikomatsakis Dec 12, 2014
c2ca1a4
Make all predicates higher-ranked, not just trait references.
nikomatsakis Dec 13, 2014
f45c0ef
Implement "perfect forwarding" for HR impls (#19730).
nikomatsakis Dec 14, 2014
dab6e70
Convert gigantic comment away from `//!` form. It is annoying to
nikomatsakis Dec 15, 2014
0b88c5d
Remove text on method matching, which is now out of date.
nikomatsakis Dec 15, 2014
aa20e2f
Document new algorithm at a high-level.
nikomatsakis Dec 15, 2014
d4f8a5a
Work around #19982 by rewriting test impls to not use anonymous
nikomatsakis Dec 16, 2014
1085012
Kill some warnings about shadowed lifetimes
nikomatsakis Dec 16, 2014
89922e5
Correct comment on Binder.
nikomatsakis Dec 18, 2014
a04ce71
Modify the `Bytes` type so that it remains cloneable even
nikomatsakis Dec 19, 2014
ebf1e4f
Three random test cases that seem to produce more errors now. I've
nikomatsakis Dec 19, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libcollections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,8 +762,8 @@ mod test {
expected: &'b [int],
}

impl<'a, 'b> FnMut(&int) -> bool for Counter<'a, 'b> {
extern "rust-call" fn call_mut(&mut self, (&x,): (&int,)) -> bool {
impl<'a, 'b, 'c> FnMut(&'c int) -> bool for Counter<'a, 'b> {
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c int,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
true
Expand Down
23 changes: 20 additions & 3 deletions src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use self::Searcher::{Naive, TwoWay, TwoWayLong};

use char::Char;
use char;
use clone::Clone;
use cmp::{Eq, mod};
use default::Default;
use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
Expand All @@ -31,7 +32,7 @@ use mem;
use num::Int;
use option::Option;
use option::Option::{None, Some};
use ops::FnMut;
use ops::{Fn, FnMut};
use ptr::RawPtr;
use raw::{Repr, Slice};
use slice::{mod, SliceExt};
Expand Down Expand Up @@ -316,7 +317,23 @@ impl<'a> DoubleEndedIterator<(uint, char)> for CharOffsets<'a> {

/// External iterator for a string's bytes.
/// Use with the `std::iter` module.
pub type Bytes<'a> = Map<&'a u8, u8, slice::Items<'a, u8>, fn(&u8) -> u8>;
pub type Bytes<'a> = Map<&'a u8, u8, slice::Items<'a, u8>, BytesFn>;

/// A temporary new type wrapper that ensures that the `Bytes` iterator
/// is cloneable.
#[deriving(Copy)]
#[experimental = "iterator type instability"]
pub struct BytesFn(fn(&u8) -> u8);

impl<'a> Fn(&'a u8) -> u8 for BytesFn {
extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
(self.0)(ptr)
}
}

impl Clone for BytesFn {
fn clone(&self) -> BytesFn { *self }
}

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

self.as_bytes().iter().map(deref)
self.as_bytes().iter().map(BytesFn(deref))
}

#[inline]
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1784,9 +1784,7 @@ impl LintPass for Stability {
method_num: index,
..
}) => {
ty::trait_item(cx.tcx,
trait_ref.def_id,
index).def_id()
ty::trait_item(cx.tcx, trait_ref.def_id, index).def_id()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
let name = item_name(&*intr, item);
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
ty::ty_bare_fn(ref f) =>
(Some(ctor_ty), f.sig.inputs.clone(), None),
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
_ => { // Nullary or struct enum variant.
let mut arg_names = Vec::new();
let arg_tys = get_struct_fields(intr.clone(), cdata, did.node)
Expand Down
32 changes: 17 additions & 15 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use self::DefIdSource::*;
use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{mod, Ty};
use middle::ty::{mod, AsPredicate, Ty};

use std::rc::Rc;
use std::str;
Expand Down Expand Up @@ -414,7 +414,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
}
'x' => {
assert_eq!(next(st), '[');
let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)));
let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
assert_eq!(next(st), ']');
return ty::mk_trait(st.tcx, trait_ref, bounds);
Expand Down Expand Up @@ -603,7 +603,7 @@ fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
}
}

fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::FnSig<'tcx> {
fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::PolyFnSig<'tcx> {
assert_eq!(next(st), '[');
let mut inputs = Vec::new();
while peek(st) != ']' {
Expand All @@ -622,9 +622,9 @@ fn parse_sig<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::FnSig<'
}
_ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
};
ty::FnSig {inputs: inputs,
output: output,
variadic: variadic}
ty::Binder(ty::FnSig {inputs: inputs,
output: output,
variadic: variadic})
}

// Rust metadata parsing
Expand Down Expand Up @@ -669,13 +669,13 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
-> ty::Predicate<'tcx>
{
match next(st) {
't' => ty::Predicate::Trait(Rc::new(parse_trait_ref(st, conv))),
'e' => ty::Predicate::Equate(parse_ty(st, |x,y| conv(x,y)),
parse_ty(st, |x,y| conv(x,y))),
'r' => ty::Predicate::RegionOutlives(parse_region(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y))),
'o' => ty::Predicate::TypeOutlives(parse_ty(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y))),
't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
c => panic!("Encountered invalid character in metadata: {}", c)
}
}
Expand Down Expand Up @@ -759,10 +759,12 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
loop {
match next(st) {
'R' => {
param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
param_bounds.region_bounds.push(
parse_region(st, |x, y| conv (x, y)));
}
'I' => {
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
param_bounds.trait_bounds.push(
Rc::new(ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)))));
}
'.' => {
return param_bounds;
Expand Down
20 changes: 10 additions & 10 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
ty::ty_trait(box ty::TyTrait { ref principal,
ref bounds }) => {
mywrite!(w, "x[");
enc_trait_ref(w, cx, principal);
enc_trait_ref(w, cx, &principal.0);
enc_existential_bounds(w, cx, bounds);
mywrite!(w, "]");
}
Expand Down Expand Up @@ -351,18 +351,18 @@ pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
}

fn enc_fn_sig<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
fsig: &ty::FnSig<'tcx>) {
fsig: &ty::PolyFnSig<'tcx>) {
mywrite!(w, "[");
for ty in fsig.inputs.iter() {
for ty in fsig.0.inputs.iter() {
enc_ty(w, cx, *ty);
}
mywrite!(w, "]");
if fsig.variadic {
if fsig.0.variadic {
mywrite!(w, "V");
} else {
mywrite!(w, "N");
}
match fsig.output {
match fsig.0.output {
ty::FnConverging(result_type) => {
enc_ty(w, cx, result_type);
}
Expand Down Expand Up @@ -401,7 +401,7 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,

for tp in bs.trait_bounds.iter() {
mywrite!(w, "I");
enc_trait_ref(w, cx, &**tp);
enc_trait_ref(w, cx, &tp.0);
}

mywrite!(w, ".");
Expand All @@ -425,19 +425,19 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
match *p {
ty::Predicate::Trait(ref trait_ref) => {
mywrite!(w, "t");
enc_trait_ref(w, cx, &**trait_ref);
enc_trait_ref(w, cx, &trait_ref.0);
}
ty::Predicate::Equate(a, b) => {
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
mywrite!(w, "e");
enc_ty(w, cx, a);
enc_ty(w, cx, b);
}
ty::Predicate::RegionOutlives(a, b) => {
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "r");
enc_region(w, cx, a);
enc_region(w, cx, b);
}
ty::Predicate::TypeOutlives(a, b) => {
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "o");
enc_ty(w, cx, a);
enc_region(w, cx, b);
Expand Down
23 changes: 19 additions & 4 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
this.emit_enum_variant_arg(0, |this| {
try!(this.emit_struct_field("principal", 0, |this| {
Ok(this.emit_trait_ref(ecx, &*principal))
Ok(this.emit_trait_ref(ecx, &principal.0))
}));
this.emit_struct_field("bounds", 1, |this| {
Ok(this.emit_existential_bounds(ecx, b))
Expand Down Expand Up @@ -1277,7 +1277,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
rbml_w.emit_trait_ref(ecx, &**trait_ref);
rbml_w.emit_trait_ref(ecx, &trait_ref.0);
})
})
}
Expand Down Expand Up @@ -1356,6 +1356,8 @@ trait rbml_decoder_decoder_helpers<'tcx> {
fn read_tys<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> Vec<Ty<'tcx>>;
fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> Rc<ty::TraitRef<'tcx>>;
fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> Rc<ty::PolyTraitRef<'tcx>>;
fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::TypeParameterDef<'tcx>;
fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
Expand Down Expand Up @@ -1548,6 +1550,19 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
}).unwrap())
}

fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> Rc<ty::PolyTraitRef<'tcx>> {
Rc::new(ty::Binder(self.read_opaque(|this, doc| {
let ty = tydecode::parse_trait_ref_data(
doc.data,
dcx.cdata.cnum,
doc.start,
dcx.tcx,
|s, a| this.convert_def_id(dcx, s, a));
Ok(ty)
}).unwrap()))
}

fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::TypeParameterDef<'tcx> {
self.read_opaque(|this, doc| {
Expand Down Expand Up @@ -1753,7 +1768,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
2 => {
let ty_trait = try!(this.read_enum_variant_arg(0, |this| {
let principal = try!(this.read_struct_field("principal", 0, |this| {
Ok(this.read_trait_ref(dcx))
Ok(this.read_poly_trait_ref(dcx))
}));
Ok(ty::TyTrait {
principal: (*principal).clone(),
Expand Down Expand Up @@ -1926,7 +1941,7 @@ fn decode_side_tables(dcx: &DecodeContext,
dcx.tcx.method_map.borrow_mut().insert(method_call, method);
}
c::tag_table_object_cast_map => {
let trait_ref = val_dsr.read_trait_ref(dcx);
let trait_ref = val_dsr.read_poly_trait_ref(dcx);
dcx.tcx.object_cast_map.borrow_mut()
.insert(id, trait_ref);
}
Expand Down
18 changes: 6 additions & 12 deletions src/librustc/middle/check_static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ use middle::infer;
use middle::traits;
use middle::mem_categorization as mc;
use middle::expr_use_visitor as euv;
use util::common::ErrorReported;
use util::nodemap::NodeSet;

use syntax::ast;
Expand Down Expand Up @@ -122,17 +121,12 @@ impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
let ty = ty::node_id_to_type(self.tcx, e.id);
let infcx = infer::new_infer_ctxt(self.tcx);
let mut fulfill_cx = traits::FulfillmentContext::new();
match traits::trait_ref_for_builtin_bound(self.tcx, ty::BoundSync, ty) {
Ok(trait_ref) => {
fulfill_cx.register_trait_ref(self.tcx, trait_ref,
traits::ObligationCause::dummy());
let env = ty::empty_parameter_environment();
if !fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok() {
self.tcx.sess.span_err(e.span, "shared static items must have a \
type which implements Sync");
}
}
Err(ErrorReported) => { }
fulfill_cx.register_builtin_bound(self.tcx, ty, ty::BoundSync,
traits::ObligationCause::dummy());
let env = ty::empty_parameter_environment();
if !fulfill_cx.select_all_or_error(&infcx, &env, self.tcx).is_ok() {
self.tcx.sess.span_err(e.span, "shared static items must have a \
type which implements Sync");
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
ty::ty_vec(..) => Some(VecSimplifiedType),
ty::ty_ptr(_) => Some(PtrSimplifiedType),
ty::ty_trait(ref trait_info) => {
Some(TraitSimplifiedType(trait_info.principal.def_id))
Some(TraitSimplifiedType(trait_info.principal.def_id()))
}
ty::ty_struct(def_id, _) => {
Some(StructSimplifiedType(def_id))
Expand All @@ -83,10 +83,10 @@ pub fn simplify_type(tcx: &ty::ctxt,
Some(TupleSimplifiedType(tys.len()))
}
ty::ty_closure(ref f) => {
Some(FunctionSimplifiedType(f.sig.inputs.len()))
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
}
ty::ty_bare_fn(ref f) => {
Some(FunctionSimplifiedType(f.sig.inputs.len()))
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
}
ty::ty_param(_) => {
if can_simplify_params {
Expand Down
Loading