diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 95b8e49d60c6..769f1cbcb5d0 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1103,6 +1103,10 @@ impl<'a> LoweringContext<'a> {
default: tp.default.as_ref().map(|x| self.lower_ty(x)),
span: tp.span,
pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
+ synthetic: tp.attrs.iter()
+ .filter(|attr| attr.check_name("rustc_synthetic"))
+ .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+ .nth(0),
}
}
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index bff71155440a..9bfedd7a381c 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -351,6 +351,7 @@ pub struct TyParam {
pub default: Option
>,
pub span: Span,
pub pure_wrt_drop: bool,
+ pub synthetic: Option,
}
/// Represents lifetimes and type parameters attached to a declaration
@@ -419,6 +420,13 @@ impl Generics {
}
}
+/// Synthetic Type Parameters are converted to an other form during lowering, this allows
+/// to track the original form they had. Usefull for error messages.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum SyntheticTyParamKind {
+ ImplTrait
+}
+
/// A `where` clause in a definition
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct WhereClause {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 96d5940caf6a..776f85cf5da9 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -177,7 +177,8 @@ impl_stable_hash_for!(struct hir::TyParam {
bounds,
default,
span,
- pure_wrt_drop
+ pure_wrt_drop,
+ synthetic
});
impl_stable_hash_for!(struct hir::Generics {
@@ -187,6 +188,10 @@ impl_stable_hash_for!(struct hir::Generics {
span
});
+impl_stable_hash_for!(enum hir::SyntheticTyParamKind {
+ ImplTrait
+});
+
impl_stable_hash_for!(struct hir::WhereClause {
id,
predicates
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 2bbf807807ba..fe060aaf4269 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -463,7 +463,8 @@ impl_stable_hash_for!(struct ty::TypeParameterDef {
index,
has_default,
object_lifetime_default,
- pure_wrt_drop
+ pure_wrt_drop,
+ synthetic
});
impl<'gcx, T> HashStable>
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 2c1b3e28ffb0..da635ec80fc9 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -675,6 +675,8 @@ pub struct TypeParameterDef {
/// on generic parameter `T`, asserts data behind the parameter
/// `T` won't be accessed during the parent type's `Drop` impl.
pub pure_wrt_drop: bool,
+
+ pub synthetic: Option,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6fe49644fe81..a0099a48c896 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4647,6 +4647,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// a problem.
self.check_path_parameter_count(span, &mut type_segment, false);
self.check_path_parameter_count(span, &mut fn_segment, false);
+ self.check_impl_trait(span, &mut fn_segment);
let (fn_start, has_self) = match (type_segment, fn_segment) {
(_, Some((_, generics))) => {
@@ -4871,6 +4872,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
+ /// Report error if there is an explicit type parameter when using `impl Trait`.
+ fn check_impl_trait(&self,
+ span: Span,
+ segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+ use hir::SyntheticTyParamKind::*;
+
+ segment.map(|(path_segment, generics)| {
+ let explicit = !path_segment.infer_types;
+ let impl_trait = generics.types.iter()
+ .any(|ty_param| {
+ match ty_param.synthetic {
+ Some(ImplTrait) => true,
+ _ => false,
+ }
+ });
+
+ if explicit && impl_trait {
+ let mut err = struct_span_err! {
+ self.tcx.sess,
+ span,
+ E0632,
+ "cannot provide explicit type parameters when `impl Trait` is \
+ used in argument position."
+ };
+
+ err.emit();
+ }
+ });
+ }
+
fn structurally_resolve_type_or_else(&self, sp: Span, ty: Ty<'tcx>, f: F)
-> Ty<'tcx>
where F: Fn() -> Ty<'tcx>
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a36594cb6e55..229a1084b0c1 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -922,6 +922,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
pure_wrt_drop: false,
+ synthetic: None,
});
allow_defaults = true;
@@ -993,6 +994,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
object_lifetime_default:
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
pure_wrt_drop: p.pure_wrt_drop,
+ synthetic: p.synthetic,
}
});
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
@@ -1009,6 +1011,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
pure_wrt_drop: false,
+ synthetic: None,
}));
});
}
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 6bbe2233ff1f..8df973555744 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4677,4 +4677,6 @@ register_diagnostics! {
E0592, // duplicate definitions with name `{}`
// E0613, // Removed (merged with E0609)
E0627, // yield statement outside of generator literal
+ E0632, // cannot provide explicit type parameters when `impl Trait` is used in
+ // argument position.
}
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 5c730aaa8d0f..246300a24a9a 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -724,6 +724,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
is just used for rustc unit tests \
and will never be stable",
cfg_fn!(rustc_attrs))),
+ ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
+ "rustc_attrs",
+ "this attribute \
+ is just used for rustc unit tests \
+ and will never be stable",
+ cfg_fn!(rustc_attrs))),
("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
"rustc_attrs",
"internal rustc attributes will never be stable",
diff --git a/src/test/compile-fail/synthetic-param.rs b/src/test/compile-fail/synthetic-param.rs
new file mode 100644
index 000000000000..a9762e383fe4
--- /dev/null
+++ b/src/test/compile-fail/synthetic-param.rs
@@ -0,0 +1,38 @@
+// Copyright 2015 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 or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generic_param_attrs, rustc_attrs)]
+
+fn func<#[rustc_synthetic] T>(_: T) {}
+
+struct Foo;
+
+impl Foo {
+ pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+struct Bar {
+ t: S
+}
+
+impl Bar {
+ pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+fn main() {
+ func::(42); //~ ERROR cannot provide explicit type parameters
+ func(42); // Ok
+
+ Foo::func::(42); //~ ERROR cannot provide explicit type parameters
+ Foo::func(42); // Ok
+
+ Bar::::func::(42); //~ ERROR cannot provide explicit type parameters
+ Bar::::func(42); // Ok
+}