mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-04 02:54:00 +00:00
impl Trait in argument position desugaring:
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.
This commit is contained in:
parent
82ae9682ca
commit
3730dfdaf5
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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>>
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
E0631,
|
||||
"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>
|
||||
|
@ -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,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
@ -4677,4 +4677,6 @@ register_diagnostics! {
|
||||
E0592, // duplicate definitions with name `{}`
|
||||
// E0613, // Removed (merged with E0609)
|
||||
E0627, // yield statement outside of generator literal
|
||||
E0631, // cannot provide explicit type parameters when `impl Trait` is used in
|
||||
// argument position.
|
||||
}
|
||||
|
@ -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",
|
||||
|
38
src/test/compile-fail/synthetic-param.rs
Normal file
38
src/test/compile-fail/synthetic-param.rs
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user