about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-29 15:54:44 +0000
committerbors <bors@rust-lang.org>2017-09-29 15:54:44 +0000
commit51cd06170eccf91a2d93018e939473a8db18da92 (patch)
tree327859d8d72c0ccee89da206fa782f9a1826bb8e
parent09ee9b723a6e8bdfbbd43ab452b1a4317b38e1e1 (diff)
parent838105f09b407aa6e5239ac1aa68e53846b5b712 (diff)
downloadrust-51cd06170eccf91a2d93018e939473a8db18da92.tar.gz
rust-51cd06170eccf91a2d93018e939473a8db18da92.zip
Auto merge of #44866 - mdevlamynck:impl-trait, r=eddyb
First step toward implementing impl Trait in argument position

First step implementing #44721.

Add a flag to hir and ty TypeParameterDef and raise an error when using
explicit type parameters when calling a function using impl Trait in
argument position.

I don't know if there is a procedure to add an error code so I just took an available code. Is that ok ?

r? @nikomatsakis
-rw-r--r--src/librustc/hir/lowering.rs4
-rw-r--r--src/librustc/hir/mod.rs8
-rw-r--r--src/librustc/ich/impls_hir.rs7
-rw-r--r--src/librustc/ich/impls_ty.rs3
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs31
-rw-r--r--src/librustc_typeck/collect.rs3
-rw-r--r--src/librustc_typeck/diagnostics.rs2
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/test/compile-fail/synthetic-param.rs38
10 files changed, 102 insertions, 2 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 411cdde3190..1fdfbe20328 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 bff71155440..9bfedd7a381 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -351,6 +351,7 @@ pub struct TyParam {
     pub default: Option<P<Ty>>,
     pub span: Span,
     pub pure_wrt_drop: bool,
+    pub synthetic: Option<SyntheticTyParamKind>,
 }
 
 /// 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 96d5940caf6..776f85cf5da 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 2bbf807807b..fe060aaf426 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<StableHashingContext<'gcx>>
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 2c1b3e28ffb..da635ec80fc 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<hir::SyntheticTyParamKind>,
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 6fe49644fe8..a0099a48c89 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<F>(&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 a36594cb6e5..229a1084b0c 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 6bbe2233ff1..8df97355574 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 4da0df5b0de..e92a7484f33 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -727,6 +727,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 00000000000..a9762e383fe
--- /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 <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(generic_param_attrs, rustc_attrs)]
+
+fn func<#[rustc_synthetic] T>(_: T) {}
+
+struct Foo;
+
+impl Foo {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+struct Bar<S> {
+    t: S
+}
+
+impl<S> Bar<S> {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+fn main() {
+    func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    func(42); // Ok
+
+    Foo::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Foo::func(42); // Ok
+
+    Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Bar::<i8>::func(42); // Ok
+}