Skip to content
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
779fc37
Move E0562 to librustc from librustc_typeck
chrisvittal Nov 10, 2017
8fd48e7
Split hir::TyImplTrait, move checks to HIR lowering
chrisvittal Nov 10, 2017
e4c7e2c
Add bool item is_in_impl_trait to LoweringContext
chrisvittal Nov 10, 2017
94df3c5
Alter type collection to collect impl Trait bounds
chrisvittal Nov 10, 2017
f225fe4
Add collection of impl Trait argument lifetimes
chrisvittal Nov 10, 2017
109f2dd
Add new error comparision to hide desugaring
chrisvittal Nov 10, 2017
bdff946
Add universal_impl_trait feature gate
chrisvittal Nov 10, 2017
06dff80
Add/Modify tests for argument position impl Trait
chrisvittal Nov 10, 2017
a23bea5
Fix style and grammar
chrisvittal Nov 10, 2017
7d25d2e
Remove unamed parameters
chrisvittal Nov 10, 2017
04ad8fd
Fix unclosed delimiter in sample error
chrisvittal Nov 10, 2017
b4c1aef
Add universal_impl_trait unstable-book entry
chrisvittal Nov 10, 2017
2520279
test we reject equivalent signatures with more than one argument
nikomatsakis Nov 13, 2017
ebc4408
rename many-cases to where-allowed
nikomatsakis Nov 13, 2017
37dd79f
extend `where-allowed.rs` with many more cases
nikomatsakis Nov 13, 2017
6f9fb91
rename `equality-universal` to a more extensible naming scheme
nikomatsakis Nov 13, 2017
9d71bf6
add some more positive tests
nikomatsakis Nov 13, 2017
15001ee
add a UI test showing the current output from an impl trait type
nikomatsakis Nov 13, 2017
2786ea6
some tests featuring multiple bounds, other errors
nikomatsakis Nov 13, 2017
7e9948f
Add proper names to impl Trait parameters.
chrisvittal Nov 14, 2017
9b4372e
Incorporate review feedback
chrisvittal Nov 14, 2017
b276429
Disallow all impl Trait within Fn trait sugar
chrisvittal Nov 15, 2017
f710d41
Add/Fix stderr references for impl Trait ui tests
chrisvittal Nov 15, 2017
22f0940
Add cases to where-allowed.rs
chrisvittal Nov 15, 2017
517db79
Renumber error to fix tidy
chrisvittal Nov 15, 2017
337dee4
Remove Fn trait + impl Trait rustdoc tests
chrisvittal Nov 15, 2017
98d5db3
add a new test featuring two impl traits to show what it looks like
nikomatsakis Nov 15, 2017
4ce61b7
Change clippy to broken after hir::Ty enum change
chrisvittal Nov 15, 2017
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# `universal_impl_trait`

The tracking issue for this feature is: [#34511].

[#34511]: https://github.com/rust-lang/rust/issues/34511

--------------------

The `universal_impl_trait` feature extends the [`conservative_impl_trait`]
feature allowing the `impl Trait` syntax in arguments (universal
quantification).

[`conservative_impl_trait`]: ./language-features/conservative-impl-trait.html

## Examples

```rust
#![feature(universal_impl_trait)]
use std::ops::Not;

fn any_zero(values: impl IntoIterator<Item = i32>) -> bool {
for val in values { if val == 0 { return true; } }
false
}

fn main() {
let test1 = -5..;
let test2 = vec![1, 8, 42, -87, 60];
assert!(any_zero(test1));
assert!(bool::not(any_zero(test2)));
}
```
40 changes: 40 additions & 0 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1770,6 +1770,46 @@ If you want to get command-line arguments, use `std::env::args`. To exit with a
specified exit code, use `std::process::exit`.
"##,

E0562: r##"
Abstract return types (written `impl Trait` for some trait `Trait`) are only
allowed as function return types.
Erroneous code example:
```compile_fail,E0562
#![feature(conservative_impl_trait)]
fn main() {
let count_to_ten: impl Iterator<Item=usize> = 0..10;
// error: `impl Trait` not allowed outside of function and inherent method
// return types
for i in count_to_ten {
println!("{}", i);
}
}
```
Make sure `impl Trait` only appears in return-type position.
```
#![feature(conservative_impl_trait)]
fn count_to_n(n: usize) -> impl Iterator<Item=usize> {
0..n
}
fn main() {
for i in count_to_n(10) { // ok!
println!("{}", i);
}
}
```
See [RFC 1522] for more details.
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
"##,

E0591: r##"
Per [RFC 401][rfc401], if you have a function declaration `foo`:
5 changes: 4 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
@@ -591,7 +591,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
visitor.visit_lifetime(lifetime);
}
TyImplTrait(ref bounds) => {
TyImplTraitExistential(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyImplTraitUniversal(_, ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
}
TyTypeof(expression) => {
305 changes: 219 additions & 86 deletions src/librustc/hir/lowering.rs

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -1461,9 +1461,12 @@ pub enum Ty_ {
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TyTraitObject(HirVec<PolyTraitRef>, Lifetime),
/// An `impl Bound1 + Bound2 + Bound3` type
/// where `Bound` is a trait or a lifetime.
TyImplTrait(TyParamBounds),
/// An exsitentially quantified (there exists a type satisfying) `impl
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
TyImplTraitExistential(TyParamBounds),
/// An universally quantified (for all types satisfying) `impl
/// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime.
TyImplTraitUniversal(DefId, TyParamBounds),
/// Unused for now
TyTypeof(BodyId),
/// TyInfer means the type should be inferred instead of it having been
5 changes: 3 additions & 2 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
@@ -421,8 +421,9 @@ impl<'a> State<'a> {
self.print_lifetime(lifetime)?;
}
}
hir::TyImplTrait(ref bounds) => {
self.print_bounds("impl ", &bounds[..])?;
hir::TyImplTraitExistential(ref bounds) |
hir::TyImplTraitUniversal(_, ref bounds) => {
self.print_bounds("impl", &bounds[..])?;
}
hir::TyArray(ref ty, v) => {
self.s.word("[")?;
3 changes: 2 additions & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
@@ -287,7 +287,8 @@ impl_stable_hash_for!(enum hir::Ty_ {
TyTup(ts),
TyPath(qpath),
TyTraitObject(trait_refs, lifetime),
TyImplTrait(bounds),
TyImplTraitExistential(bounds),
TyImplTraitUniversal(def_id, bounds),
TyTypeof(body_id),
TyErr,
TyInfer
13 changes: 12 additions & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -1604,6 +1604,17 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
walk_list!(&mut appears_in_where_clause,
visit_where_predicate,
&generics.where_clause.predicates);
// We need to collect argument impl Trait lifetimes as well,
// we do so here.
walk_list!(&mut appears_in_where_clause,
visit_ty,
decl.inputs.iter().filter(|ty| {
if let hir::TyImplTraitUniversal(..) = ty.node {
true
} else {
false
}
}));
for lifetime_def in &generics.lifetimes {
if !lifetime_def.bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced
@@ -1698,7 +1709,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
}

fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyImplTrait(_) = ty.node {
if let hir::TyImplTraitExistential(_) = ty.node {
self.impl_trait = true;
}
intravisit::walk_ty(self, ty);
2 changes: 1 addition & 1 deletion src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
@@ -1487,7 +1487,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {

fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
match ty.node {
hir::TyImplTrait(_) => {
hir::TyImplTraitExistential(_) => {
let def_id = self.tcx.hir.local_def_id(ty.id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
}
4 changes: 2 additions & 2 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
@@ -373,7 +373,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
}

fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
if self.get(ty.id).is_some() {
// Reach the (potentially private) type and the API being exposed.
self.reach(ty.id).ty().predicates();
@@ -1557,7 +1557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
}

fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
// Check the traits being exposed, as they're separate,
// e.g. `impl Iterator<Item=T>` has two predicates,
// `X: Iterator` and `<X as Iterator>::Item == T`,
58 changes: 11 additions & 47 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ use util::nodemap::FxHashSet;

use std::iter;
use syntax::{abi, ast};
use syntax::symbol::Symbol;
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax_pos::Span;

@@ -1033,53 +1034,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
hir::TyTraitObject(ref bounds, ref lifetime) => {
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
}
hir::TyImplTrait(_) => {
// Figure out if we can allow an `impl Trait` here, by walking up
// to a `fn` or inherent `impl` method, going only through `Ty`
// or `TraitRef` nodes (as nothing else should be in types) and
// ensuring that we reach the `fn`/method signature's return type.
let mut node_id = ast_ty.id;
let fn_decl = loop {
let parent = tcx.hir.get_parent_node(node_id);
match tcx.hir.get(parent) {
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(ref fn_decl, ..), ..
}) => break Some(fn_decl),

hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(ref sig, _), ..
}) => {
match tcx.hir.expect_item(tcx.hir.get_parent(parent)).node {
hir::ItemImpl(.., None, _, _) => {
break Some(&sig.decl)
}
_ => break None
}
}

hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => {}

_ => break None
}
node_id = parent;
};
let allow = fn_decl.map_or(false, |fd| {
match fd.output {
hir::DefaultReturn(_) => false,
hir::Return(ref ty) => ty.id == node_id
}
});

// Create the anonymized type.
if allow {
let def_id = tcx.hir.local_def_id(ast_ty.id);
tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id))
} else {
span_err!(tcx.sess, ast_ty.span, E0562,
"`impl Trait` not allowed outside of function \
and inherent method return types");
tcx.types.err
}
hir::TyImplTraitExistential(_) => {
let def_id = tcx.hir.local_def_id(ast_ty.id);
tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id))
}
hir::TyImplTraitUniversal(fn_def_id, _) => {
let impl_trait_def_id = tcx.hir.local_def_id(ast_ty.id);
let generics = tcx.generics_of(fn_def_id);
let index = generics.type_param_to_index[&impl_trait_def_id.index];
tcx.mk_param(index,
Symbol::intern(&tcx.hir.node_to_pretty_string(ast_ty.id)))
}
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
47 changes: 47 additions & 0 deletions src/librustc_typeck/check/compare_method.rs
Original file line number Diff line number Diff line change
@@ -67,6 +67,14 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
return;
}

if let Err(ErrorReported) = compare_synthetic_generics(tcx,
impl_m,
impl_m_span,
trait_m,
trait_item_span) {
return;
}

if let Err(ErrorReported) = compare_predicate_entailment(tcx,
impl_m,
impl_m_span,
@@ -708,6 +716,45 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Ok(())
}

fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_m: &ty::AssociatedItem,
_impl_m_span: Span, // FIXME necessary?
trait_m: &ty::AssociatedItem,
_trait_item_span: Option<Span>) // FIXME necessary?
-> Result<(), ErrorReported> {
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
// 1. Better messages for the span lables
// 2. Explanation as to what is going on
// 3. Correct the function signature for what we actually use
// If we get here, we already have the same number of generics, so the zip will
// be okay.
let mut error_found = false;
let impl_m_generics = tcx.generics_of(impl_m.def_id);
let trait_m_generics = tcx.generics_of(trait_m.def_id);
for (impl_ty, trait_ty) in impl_m_generics.types.iter().zip(trait_m_generics.types.iter()) {
if impl_ty.synthetic != trait_ty.synthetic {
let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
let impl_span = tcx.hir.span(impl_node_id);
let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap();
let trait_span = tcx.hir.span(trait_node_id);
let mut err = struct_span_err!(tcx.sess,
impl_span,
E0643,
"method `{}` has incompatible signature for trait",
trait_m.name);
err.span_label(trait_span, "annotation in trait");
err.span_label(impl_span, "annotation in impl");
err.emit();
error_found = true;
}
}
if error_found {
Err(ErrorReported)
} else {
Ok(())
}
}

pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl_c: &ty::AssociatedItem,
impl_c_span: Span,
4 changes: 4 additions & 0 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -5035,6 +5035,10 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
tps_used[idx as usize - generics.lifetimes.len()] = true;
} else if let ty::TyError = leaf_ty.sty {
// If there already another error, do not emit an error for not using a type Parameter
assert!(tcx.sess.err_count() > 0);
return;
}
}

159 changes: 131 additions & 28 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ use rustc_const_math::ConstInt;
use std::collections::BTreeMap;

use syntax::{abi, ast};
use syntax::ptr::P;
use syntax::codemap::Spanned;
use syntax::symbol::{Symbol, keywords};
use syntax_pos::{Span, DUMMY_SP};
@@ -130,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
}

fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTrait(..) = ty.node {
if let hir::TyImplTraitExistential(..) = ty.node {
let def_id = self.tcx.hir.local_def_id(ty.id);
self.tcx.generics_of(def_id);
self.tcx.predicates_of(def_id);
@@ -854,7 +855,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
Some(tcx.closure_base_def_id(def_id))
}
NodeTy(&hir::Ty { node: hir::TyImplTrait(..), .. }) => {
NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => {
let mut parent_id = node_id;
loop {
match tcx.hir.get(parent_id) {
@@ -873,22 +874,32 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut allow_defaults = false;

let no_generics = hir::Generics::empty();
let ast_generics = match node {
NodeTraitItem(item) => &item.generics,
let (ast_generics, opt_inputs) = match node {
NodeTraitItem(item) => {
match item.node {
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
_ => (&item.generics, None)
}
}

NodeImplItem(item) => &item.generics,
NodeImplItem(item) => {
match item.node {
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
_ => (&item.generics, None)
}
}

NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemImpl(_, _, _, ref generics, ..) => generics,
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),
ItemImpl(_, _, _, ref generics, ..) => (generics, None),

ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
ItemUnion(_, ref generics) => {
allow_defaults = true;
generics
(generics, None)
}

ItemTrait(_, _, ref generics, ..) => {
@@ -909,22 +920,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
});

allow_defaults = true;
generics
(generics, None)
}

_ => &no_generics
_ => (&no_generics, None)
}
}

NodeForeignItem(item) => {
match item.node {
ForeignItemStatic(..) => &no_generics,
ForeignItemFn(_, _, ref generics) => generics,
ForeignItemType => &no_generics,
ForeignItemStatic(..) => (&no_generics, None),
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
ForeignItemType => (&no_generics, None)
}
}

_ => &no_generics
_ => (&no_generics, None)
};

let has_self = opt_self.is_some();
@@ -981,7 +992,24 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
synthetic: p.synthetic,
}
});
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();

let fn_ins = opt_inputs.map(|tys| &tys[..]);
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
let other_type_start = type_start + ast_generics.ty_params.len() as u32;
let mut types: Vec<_> = opt_self.into_iter()
.chain(types)
.chain(univ_impl_trait_info.iter().enumerate().map(|(i, info)| {
ty::TypeParameterDef {
index: other_type_start + i as u32,
name: Symbol::intern(&tcx.hir.node_to_pretty_string(info.id)),
def_id: info.def_id,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
pure_wrt_drop: false,
synthetic: Some(SyntheticTyParamKind::ImplTrait),
}
}))
.collect();

// provide junk type parameter defs - the only place that
// cares about anything but the length is instantiation,
@@ -1155,7 +1183,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
icx.to_ty(ty)
}

NodeTy(&hir::Ty { node: TyImplTrait(..), .. }) => {
NodeTy(&hir::Ty { node: TyImplTraitExistential(..), .. }) => {
let owner = tcx.hir.get_parent_did(node_id);
let hir_id = tcx.hir.node_to_hir_id(node_id);
tcx.typeck_tables_of(owner).node_id_to_type(hir_id)
@@ -1337,43 +1365,54 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let ast_generics = match node {
NodeTraitItem(item) => &item.generics,
let (ast_generics, opt_inputs) = match node {
NodeTraitItem(item) => {
match item.node {
TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
_ => (&item.generics, None)
}
}

NodeImplItem(item) => &item.generics,
NodeImplItem(item) => {
match item.node {
ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)),
_ => (&item.generics, None)
}
}

NodeItem(item) => {
match item.node {
ItemFn(.., ref generics, _) |
ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)),

ItemImpl(_, _, _, ref generics, ..) |
ItemTy(_, ref generics) |
ItemEnum(_, ref generics) |
ItemStruct(_, ref generics) |
ItemUnion(_, ref generics) => {
generics
(generics, None)
}

ItemTrait(_, _, ref generics, .., ref items) => {
is_trait = Some((ty::TraitRef {
def_id,
substs: Substs::identity_for_item(tcx, def_id)
}, items));
generics
(generics, None)
}

_ => &no_generics
_ => (&no_generics, None)
}
}

NodeForeignItem(item) => {
match item.node {
ForeignItemStatic(..) => &no_generics,
ForeignItemFn(_, _, ref generics) => generics,
ForeignItemType => &no_generics,
ForeignItemStatic(..) => (&no_generics, None),
ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)),
ForeignItemType => (&no_generics, None),
}
}

NodeTy(&Ty { node: TyImplTrait(ref bounds), span, .. }) => {
NodeTy(&Ty { node: TyImplTraitExistential(ref bounds), span, .. }) => {
let substs = Substs::identity_for_item(tcx, def_id);
let anon_ty = tcx.mk_anon(def_id, substs);

@@ -1387,7 +1426,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
};
}

_ => &no_generics
_ => (&no_generics, None)
};

let generics = tcx.generics_of(def_id);
@@ -1518,6 +1557,19 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}))
}

// Add predicates from impl Trait arguments
let fn_ins = opt_inputs.map(|tys| &tys[..]);
let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins);
for info in univ_impl_trait_info.iter() {
let name = keywords::Invalid.name();
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
index += 1;
let bounds = compute_bounds(&icx, param_ty, info.bounds,
SizedByDefault::Yes,
info.span);
predicates.extend(bounds.predicates(tcx, param_ty));
}

// Subtle: before we store the predicates into the tcx, we
// sort them so that predicates like `T: Foo<Item=U>` come
// before uses of `U`. This avoids false ambiguity errors
@@ -1678,3 +1730,54 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
_ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
}
}

struct ImplTraitUniversalInfo<'hir> {
id: ast::NodeId,
def_id: DefId,
span: Span,
bounds: &'hir [hir::TyParamBound],
}

/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal
/// arguments
fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
opt_inputs: Option<&'tcx [P<hir::Ty>]>)
-> Vec<ImplTraitUniversalInfo<'tcx>>
{
// A visitor for simply collecting Universally quantified impl Trait arguments
struct ImplTraitUniversalVisitor<'tcx> {
items: Vec<&'tcx hir::Ty>
}

impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}

fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyImplTraitUniversal(..) = ty.node {
self.items.push(ty);
}
intravisit::walk_ty(self, ty);
}
}

let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() };

if let Some(inputs) = opt_inputs {
for t in inputs.iter() {
visitor.visit_ty(t);
}
}

visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node {
ImplTraitUniversalInfo {
id: ty.id,
def_id: tcx.hir.local_def_id(ty.id),
span: ty.span,
bounds: bounds
}
} else {
span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug")
}).collect()
}
56 changes: 16 additions & 40 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -3818,46 +3818,6 @@ let s = Simba { mother: 1, father: 0 }; // ok!
```
"##,

E0562: r##"
Abstract return types (written `impl Trait` for some trait `Trait`) are only
allowed as function return types.
Erroneous code example:
```compile_fail,E0562
#![feature(conservative_impl_trait)]
fn main() {
let count_to_ten: impl Iterator<Item=usize> = 0..10;
// error: `impl Trait` not allowed outside of function and inherent method
// return types
for i in count_to_ten {
println!("{}", i);
}
}
```
Make sure `impl Trait` only appears in return-type position.
```
#![feature(conservative_impl_trait)]
fn count_to_n(n: usize) -> impl Iterator<Item=usize> {
0..n
}
fn main() {
for i in count_to_n(10) { // ok!
println!("{}", i);
}
}
```
See [RFC 1522] for more details.
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
"##,

E0569: r##"
If an impl has a generic parameter with the `#[may_dangle]` attribute, then
that impl must be declared as an `unsafe impl.
@@ -4665,6 +4625,22 @@ It is recommended that you look for a `new` function or equivalent in the
crate's documentation.
"##,

E0643: r##"
This error indicates that there is a mismatch between generic parameters and
impl Trait parameters in a trait declaration versus its impl.
```compile_fail,E0643
#![feature(universal_impl_trait)]
trait Foo {
fn foo(&self, _: &impl Iterator);
}
impl Foo for () {
fn foo<U: Iterator>(&self, _: &U) { } // error method `foo` has incompatible
// signature for trait
}
```
"##,

}

register_diagnostics! {
4 changes: 3 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -1960,7 +1960,9 @@ impl Clean<Type> for hir::Ty {
}
}
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
TyImplTraitExistential(ref bounds) |
TyImplTraitUniversal(_, ref bounds) =>
ImplTrait(bounds.clean(cx)),
TyInfer | TyErr => Infer,
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
}
7 changes: 3 additions & 4 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -275,6 +275,9 @@ declare_features! (
// Allows `impl Trait` in function return types.
(active, conservative_impl_trait, "1.12.0", Some(34511)),

// Allows `impl Trait` in function arguments.
(active, universal_impl_trait, "1.23.0", Some(34511)),

// The `!` type
(active, never_type, "1.13.0", Some(35121)),

@@ -1451,10 +1454,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(ref bare_fn_ty) => {
self.check_abi(bare_fn_ty.abi, ty.span);
}
ast::TyKind::ImplTrait(..) => {
gate_feature_post!(&self, conservative_impl_trait, ty.span,
"`impl Trait` is experimental");
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span,
"The `!` type is experimental");
61 changes: 0 additions & 61 deletions src/test/compile-fail/impl-trait/disallowed.rs

This file was deleted.

16 changes: 16 additions & 0 deletions src/test/compile-fail/impl-trait/feature-gate-universal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2017 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.

// gate-test-universal_impl_trait

fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); }
//~^ ERROR `impl Trait` in argument position is experimental

fn main() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/impl-trait/feature-gate.rs
Original file line number Diff line number Diff line change
@@ -11,6 +11,6 @@
// gate-test-conservative_impl_trait

fn foo() -> impl Fn() { || {} }
//~^ ERROR `impl Trait` is experimental
//~^ ERROR `impl Trait` in return position is experimental

fn main() {}
23 changes: 23 additions & 0 deletions src/test/compile-fail/impl-trait/impl-generic-mismatch-ab.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]
use std::fmt::Debug;

trait Foo {
fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
}

impl Foo for () {
fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
//~^ ERROR method `foo` has an incompatible type for trait
}

fn main() {}
32 changes: 32 additions & 0 deletions src/test/compile-fail/impl-trait/impl-generic-mismatch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]
use std::fmt::Debug;

trait Foo {
fn foo(&self, _: &impl Debug);
}

impl Foo for () {
fn foo<U: Debug>(&self, _: &U) { }
//~^ Error method `foo` has incompatible signature for trait
}

trait Bar {
fn bar<U: Debug>(&self, _: &U);
}

impl Bar for () {
fn bar(&self, _: &impl Debug) { }
//~^ Error method `bar` has incompatible signature for trait
}

fn main() {}
234 changes: 234 additions & 0 deletions src/test/compile-fail/impl-trait/where-allowed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// Copyright 2017 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.

//! A simple test for testing many permutations of allowedness of
//! impl Trait
#![feature(conservative_impl_trait, universal_impl_trait, dyn_trait)]
use std::fmt::Debug;

// Allowed
fn in_parameters(_: impl Debug) { panic!() }

// Allowed
fn in_return() -> impl Debug { panic!() }

// Allowed
fn in_adt_in_parameters(_: Vec<impl Debug>) { panic!() }

// Allowed
fn in_adt_in_return() -> Vec<impl Debug> { panic!() }

// Disallowed
fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types


// Allowed
fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!() }

// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
vec![vec![0; 10], vec![12; 7], vec![8; 3]]
}

// Disallowed
struct InBraceStructField { x: impl Debug }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InAdtInBraceStructField { x: Vec<impl Debug> }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
struct InTupleStructField(impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed
enum InEnum {
InBraceVariant { x: impl Debug },
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
InTupleVariant(impl Debug),
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
trait InTraitDefnParameters {
fn in_parameters(_: impl Debug);
}

// Disallowed
trait InTraitDefnReturn {
fn in_return() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed and disallowed in trait impls
trait DummyTrait {
type Out;
fn in_trait_impl_parameter(impl Debug);
fn in_trait_impl_return() -> Self::Out;
}
impl DummyTrait for () {
type Out = impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

fn in_trait_impl_parameter(_: impl Debug) { }
// Allowed

fn in_trait_impl_return() -> impl Debug { () }
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
struct DummyType;
impl DummyType {
fn in_inherent_impl_parameters(_: impl Debug) { }
fn in_inherent_impl_return() -> impl Debug { () }
}

// Disallowed
extern "C" {
fn in_foreign_parameters(_: impl Debug);
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

fn in_foreign_return() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Allowed
extern "C" fn in_extern_fn_parameters(_: impl Debug) {
}

// Allowed
extern "C" fn in_extern_fn_return() -> impl Debug {
22
}

type InTypeAlias<R> = impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

type InReturnInTypeAlias<R> = fn() -> impl Debug;
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types

// Disallowed in impl headers
impl PartialEq<impl Debug> for () {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in impl headers
impl PartialEq<()> for impl Debug {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
impl impl Debug {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in inherent impls
struct InInherentImplAdt<T> { t: T }
impl InInherentImplAdt<impl Debug> {
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

// Disallowed in where clauses
fn in_fn_where_clause()
where impl Debug: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed in where clauses
fn in_adt_in_fn_where_clause()
where Vec<impl Debug>: Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_trait_parameter_in_fn_where_clause<T>()
where T: PartialEq<impl Debug>
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_parameter_in_fn_where_clause<T>()
where T: Fn(impl Debug)
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

// Disallowed
fn in_Fn_return_in_fn_where_clause<T>()
where T: Fn() -> impl Debug
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
{
}

fn main() {
let _in_local_variable: impl Fn() = || {};
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
let _in_return_in_local_variable = || -> impl Fn() { || {} };
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
}

7 changes: 4 additions & 3 deletions src/test/run-pass/impl-trait/auxiliary/xcrate.rs
Original file line number Diff line number Diff line change
@@ -10,9 +10,10 @@

#![feature(conservative_impl_trait)]

pub fn fourway_add(a: i32) -> impl Fn(i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
move |b| move |c| move |d| a + b + c + d
}
// NOTE commented out due to issue #45994
//pub fn fourway_add(a: i32) -> impl Fn(i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
// move |b| move |c| move |d| a + b + c + d
//}

fn some_internal_fn() -> u32 {
1
31 changes: 18 additions & 13 deletions src/test/run-pass/impl-trait/example-calendar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// Copyright 2016-2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -8,7 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(conservative_impl_trait, fn_traits, step_trait, unboxed_closures)]
#![feature(conservative_impl_trait,
universal_impl_trait,
fn_traits,
step_trait,
unboxed_closures
)]

//! Derived from: <https://github.com/raw/quickfur/dcal/master/dcal.d>.
//!
@@ -457,9 +462,9 @@ fn test_group_by() {
///
/// Groups an iterator of dates by month.
///
fn by_month<It>(it: It)
-> impl Iterator<Item=(u32, impl Iterator<Item=NaiveDate> + Clone)> + Clone
where It: Iterator<Item=NaiveDate> + Clone {
fn by_month(it: impl Iterator<Item=NaiveDate> + Clone)
-> impl Iterator<Item=(u32, impl Iterator<Item=NaiveDate> + Clone)> + Clone
{
it.group_by(|d| d.month())
}

@@ -474,9 +479,9 @@ fn test_by_month() {
///
/// Groups an iterator of dates by week.
///
fn by_week<It>(it: It)
-> impl Iterator<Item=(u32, impl DateIterator)> + Clone
where It: DateIterator {
fn by_week(it: impl DateIterator)
-> impl Iterator<Item=(u32, impl DateIterator)> + Clone
{
// We go forward one day because `isoweekdate` considers the week to start on a Monday.
it.group_by(|d| d.succ().isoweekdate().1)
}
@@ -548,8 +553,7 @@ const COLS_PER_WEEK: u32 = 7 * COLS_PER_DAY;
///
/// Formats an iterator of weeks into an iterator of strings.
///
fn format_weeks<It>(it: It) -> impl Iterator<Item=String>
where It: Iterator, It::Item: DateIterator {
fn format_weeks(it: impl Iterator<Item = impl DateIterator>) -> impl Iterator<Item=String> {
it.map(|week| {
let mut buf = String::with_capacity((COLS_PER_DAY * COLS_PER_WEEK + 2) as usize);

@@ -627,7 +631,7 @@ fn test_month_title() {
///
/// Formats a month.
///
fn format_month<It: DateIterator>(it: It) -> impl Iterator<Item=String> {
fn format_month(it: impl DateIterator) -> impl Iterator<Item=String> {
let mut month_days = it.peekable();
let title = month_title(month_days.peek().unwrap().month());

@@ -659,8 +663,9 @@ fn test_format_month() {
///
/// Formats an iterator of months.
///
fn format_months<It>(it: It) -> impl Iterator<Item=impl Iterator<Item=String>>
where It: Iterator, It::Item: DateIterator {
fn format_months(it: impl Iterator<Item = impl DateIterator>)
-> impl Iterator<Item=impl Iterator<Item=String>>
{
it.map(format_month)
}

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -8,11 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(conservative_impl_trait)]
#![feature(universal_impl_trait)]

fn hrtb(f: impl Fn(&u32) -> u32) -> u32 {
f(&22) + f(&44)
}

fn main() {
let _: impl Fn() = || {};
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
let _ = || -> impl Fn() { || {} };
//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
let sum = hrtb(|x| x * 2);
assert_eq!(sum, 22*2 + 44*2);
}
20 changes: 20 additions & 0 deletions src/test/run-pass/impl-trait/universal_hrtb_named.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

fn hrtb(f: impl for<'a> Fn(&'a u32) -> &'a u32) -> u32 {
f(&22) + f(&44)
}

fn main() {
let sum = hrtb(|x| x);
assert_eq!(sum, 22 + 44);
}
31 changes: 31 additions & 0 deletions src/test/run-pass/impl-trait/universal_in_adt_in_parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]
use std::fmt::Display;

fn check_display_eq(iter: &Vec<impl Display>) {
let mut collected = String::new();
for it in iter {
let disp = format!("{} ", it);
collected.push_str(&disp);
}
assert_eq!("0 3 27 823 4891 1 0", collected.trim());
}

fn main() {
let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0];
let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0];
let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"];

check_display_eq(&i32_list_vec);
check_display_eq(&u32_list_vec);
check_display_eq(&str_list_vec);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]
use std::fmt::Display;

fn check_display_eq(iter: impl IntoIterator<Item = impl Display>) {
let mut collected = String::new();
for it in iter {
let disp = format!("{} ", it);
collected.push_str(&disp);
}
assert_eq!("0 3 27 823 4891 1 0", collected.trim());
}

fn main() {
let i32_list = [0i32, 3, 27, 823, 4891, 1, 0];
let i32_list_vec = vec![0i32, 3, 27, 823, 4891, 1, 0];
let u32_list = [0u32, 3, 27, 823, 4891, 1, 0];
let u32_list_vec = vec![0u32, 3, 27, 823, 4891, 1, 0];
let u16_list = [0u16, 3, 27, 823, 4891, 1, 0];
let str_list = ["0", "3", "27", "823", "4891", "1", "0"];
let str_list_vec = vec!["0", "3", "27", "823", "4891", "1", "0"];

check_display_eq(&i32_list);
check_display_eq(i32_list_vec);
check_display_eq(&u32_list);
check_display_eq(u32_list_vec);
check_display_eq(&u16_list);
check_display_eq(&str_list);
check_display_eq(str_list_vec);
}
28 changes: 28 additions & 0 deletions src/test/run-pass/impl-trait/universal_in_trait_defn_parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

use std::fmt::Debug;

trait InTraitDefnParameters {
fn in_parameters(_: impl Debug) -> String;
}

impl InTraitDefnParameters for () {
fn in_parameters(v: impl Debug) -> String {
format!("() + {:?}", v)
}
}

fn main() {
let s = <() as InTraitDefnParameters>::in_parameters(22);
assert_eq!(s, "() + 22");
}
23 changes: 23 additions & 0 deletions src/test/run-pass/impl-trait/universal_multiple_bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

use std::fmt::Display;

fn foo(f: impl Display + Clone) -> String {
let g = f.clone();
format!("{} + {}", f, g)
}

fn main() {
let sum = foo(format!("22"));
assert_eq!(sum, r"22 + 22");
}
3 changes: 2 additions & 1 deletion src/test/run-pass/impl-trait/xcrate.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
extern crate xcrate;

fn main() {
assert_eq!(xcrate::fourway_add(1)(2)(3)(4), 10);
// NOTE line below commeted out due to issue #45994
// assert_eq!(xcrate::fourway_add(1)(2)(3)(4), 10);
xcrate::return_closure_accessing_internal_fn()();
}
18 changes: 9 additions & 9 deletions src/test/rustdoc/issue-43869.rs
Original file line number Diff line number Diff line change
@@ -55,13 +55,15 @@ pub fn test_44731_1() -> Result<Box<impl Clone>, ()> {
Ok(Box::new(j()))
}

pub fn test_44731_2() -> Box<Fn(impl Clone)> {
Box::new(|_: u32| {})
}

pub fn test_44731_3() -> Box<Fn() -> impl Clone> {
Box::new(|| 0u32)
}
// NOTE these involve Fn sugar, where impl Trait is disallowed for now, see issue #45994
//
//pub fn test_44731_2() -> Box<Fn(impl Clone)> {
// Box::new(|_: u32| {})
//}
//
//pub fn test_44731_3() -> Box<Fn() -> impl Clone> {
// Box::new(|| 0u32)
//}

pub fn test_44731_4() -> Box<Iterator<Item=impl Clone>> {
Box::new(g())
@@ -78,6 +80,4 @@ pub fn test_44731_4() -> Box<Iterator<Item=impl Clone>> {
// @has issue_43869/fn.o.html
// @has issue_43869/fn.test_44731_0.html
// @has issue_43869/fn.test_44731_1.html
// @has issue_43869/fn.test_44731_2.html
// @has issue_43869/fn.test_44731_3.html
// @has issue_43869/fn.test_44731_4.html
19 changes: 19 additions & 0 deletions src/test/ui/impl-trait/universal-mismatched-type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

use std::fmt::Debug;

fn foo(x: impl Debug) -> String {
x
}

fn main() { }
13 changes: 13 additions & 0 deletions src/test/ui/impl-trait/universal-mismatched-type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0308]: mismatched types
--> $DIR/universal-mismatched-type.rs:16:5
|
15 | fn foo(x: impl Debug) -> String {
| ------ expected `std::string::String` because of return type
16 | x
| ^ expected struct `std::string::String`, found type parameter
|
= note: expected type `std::string::String`
found type `impl Debug`

error: aborting due to previous error

21 changes: 21 additions & 0 deletions src/test/ui/impl-trait/universal-two-impl-traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

use std::fmt::Debug;

fn foo(x: impl Debug, y: impl Debug) -> String {
let mut a = x;
a = y;
format!("{:?}", a)
}

fn main() { }
11 changes: 11 additions & 0 deletions src/test/ui/impl-trait/universal-two-impl-traits.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/universal-two-impl-traits.rs:17:9
|
17 | a = y;
| ^ expected type parameter, found a different type parameter
|
= note: expected type `impl Debug` (type parameter)
found type `impl Debug` (type parameter)

error: aborting due to previous error

26 changes: 26 additions & 0 deletions src/test/ui/impl-trait/universal_wrong_bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2017 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.

#![feature(universal_impl_trait)]

use std::fmt::Display;

fn foo(f: impl Display + Clone) -> String {
wants_debug(f);
wants_display(f);
wants_clone(f);
}

fn wants_debug(g: impl Debug) { }
fn wants_display(g: impl Debug) { }
fn wants_cone(g: impl Clone) { }

fn main() {
}
30 changes: 30 additions & 0 deletions src/test/ui/impl-trait/universal_wrong_bounds.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error[E0425]: cannot find function `wants_clone` in this scope
--> $DIR/universal_wrong_bounds.rs:18:5
|
18 | wants_clone(f);
| ^^^^^^^^^^^ did you mean `wants_cone`?

error[E0405]: cannot find trait `Debug` in this scope
--> $DIR/universal_wrong_bounds.rs:21:24
|
21 | fn wants_debug(g: impl Debug) { }
| ^^^^^ not found in this scope
|
help: possible candidate is found in another module, you can import it into scope
|
13 | use std::fmt::Debug;
|

error[E0405]: cannot find trait `Debug` in this scope
--> $DIR/universal_wrong_bounds.rs:22:26
|
22 | fn wants_display(g: impl Debug) { }
| ^^^^^ not found in this scope
|
help: possible candidate is found in another module, you can import it into scope
|
13 | use std::fmt::Debug;
|

error: cannot continue compilation due to previous error

14 changes: 1 addition & 13 deletions src/test/ui/resolve/use_suggestion_placement.stderr
Original file line number Diff line number Diff line change
@@ -33,17 +33,5 @@ help: possible candidates are found in other modules, you can import them into s
11 | use std::collections::hash_map::HashMap;
|

error[E0091]: type parameter `K` is unused
--> $DIR/use_suggestion_placement.rs:35:15
|
35 | type Dict<K, V> = HashMap<K, V>;
| ^ unused type parameter

error[E0091]: type parameter `V` is unused
--> $DIR/use_suggestion_placement.rs:35:18
|
35 | type Dict<K, V> = HashMap<K, V>;
| ^ unused type parameter

error: aborting due to 5 previous errors
error: aborting due to 3 previous errors

2 changes: 1 addition & 1 deletion src/tools/toolstate.toml
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
miri = "Broken"

# ping @Manishearth @llogiq @mcarton @oli-obk
clippy = "Testing"
clippy = "Broken"

# ping @nrc
rls = "Testing"