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
This commit is contained in:
bors 2017-09-29 15:54:44 +00:00
commit 51cd06170e
10 changed files with 102 additions and 2 deletions

View File

@ -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),
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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>>

View File

@ -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)]

View File

@ -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>

View File

@ -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,
}));
});
}

View File

@ -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.
}

View File

@ -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",

View File

@ -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
}