Avoid clone and update documentation

This commit is contained in:
varkor 2018-08-08 01:18:03 +01:00
parent 04d33bbdb3
commit 03c4628a5b
4 changed files with 97 additions and 80 deletions

View File

@ -17,6 +17,7 @@ use rustc_data_structures::array_vec::ArrayVec;
use hir::{self, GenericArg, GenericArgs};
use hir::def::Def;
use hir::def_id::DefId;
use hir::HirVec;
use middle::resolve_lifetime as rl;
use namespace::Namespace;
use rustc::ty::subst::{Kind, Subst, Substs};
@ -34,6 +35,7 @@ use lint;
use std::iter;
use syntax::ast;
use syntax::ptr::P;
use syntax::feature_gate::{GateIssue, emit_feature_err};
use syntax_pos::{Span, MultiSpan};
@ -90,9 +92,9 @@ struct ConvertedBinding<'tcx> {
span: Span,
}
pub struct GenericArgMismatchErrorCode {
pub lifetimes: (&'static str, &'static str),
pub types: (&'static str, &'static str),
struct GenericArgMismatchErrorCode {
lifetimes: (&'static str, &'static str),
types: (&'static str, &'static str),
}
/// Dummy type used for the `Self` of a `TraitRef` created for converting
@ -193,9 +195,72 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
substs
}
/// Report error if there is an explicit type parameter when using `impl Trait`.
fn check_impl_trait(
tcx: TyCtxt,
span: Span,
seg: &hir::PathSegment,
generics: &ty::Generics,
) -> bool {
let explicit = !seg.infer_types;
let impl_trait = generics.params.iter().any(|param| match param.kind {
ty::GenericParamDefKind::Type {
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
} => true,
_ => false,
});
if explicit && impl_trait {
let mut err = struct_span_err! {
tcx.sess,
span,
E0632,
"cannot provide explicit type parameters when `impl Trait` is \
used in argument position."
};
err.emit();
}
impl_trait
}
/// Check that the correct number of generic arguments have been provided.
/// Used specifically for function calls.
pub fn check_generic_arg_count_for_call(
tcx: TyCtxt,
span: Span,
def: &ty::Generics,
seg: &hir::PathSegment,
is_method_call: bool,
) -> bool {
let empty_args = P(hir::GenericArgs {
args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
});
let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def);
Self::check_generic_arg_count(
tcx,
span,
def,
if let Some(ref args) = seg.args {
args
} else {
&empty_args
},
false, // `is_declaration`
is_method_call,
def.parent.is_none() && def.has_self, // `has_self`
seg.infer_types || suppress_mismatch, // `infer_types`
GenericArgMismatchErrorCode {
lifetimes: ("E0090", "E0088"),
types: ("E0089", "E0087"),
},
)
}
/// Check that the correct number of generic arguments have been provided.
/// This is used both for type declarations and function calls.
pub fn check_generic_arg_count(
fn check_generic_arg_count(
tcx: TyCtxt,
span: Span,
def: &ty::Generics,

View File

@ -10,11 +10,10 @@
use super::{probe, MethodCallee};
use astconv::{AstConv, GenericArgMismatchErrorCode};
use astconv::AstConv;
use check::{FnCtxt, PlaceOp, callee, Needs};
use hir::GenericArg;
use hir::def_id::DefId;
use hir::HirVec;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty, GenericParamDefKind};
@ -25,7 +24,6 @@ use rustc::ty::fold::TypeFoldable;
use rustc::infer::{self, InferOk};
use rustc::hir;
use syntax_pos::Span;
use syntax::ptr::P;
use std::ops::Deref;
@ -310,34 +308,24 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
fn instantiate_method_substs(
&mut self,
pick: &probe::Pick<'tcx>,
segment: &hir::PathSegment,
seg: &hir::PathSegment,
parent_substs: &Substs<'tcx>,
) -> &'tcx Substs<'tcx> {
// Determine the values for the generic parameters of the method.
// If they were not explicitly supplied, just construct fresh
// variables.
let method_generics = self.tcx.generics_of(pick.item.def_id);
let suppress_mismatch = self.fcx.check_impl_trait(self.span, segment, &method_generics);
AstConv::check_generic_arg_count(
let generics = self.tcx.generics_of(pick.item.def_id);
AstConv::check_generic_arg_count_for_call(
self.tcx,
self.span,
&method_generics,
&segment.args.clone().unwrap_or_else(|| P(hir::GenericArgs {
args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
})),
false, // `is_declaration`
&generics,
&seg,
true, // `is_method_call`
method_generics.parent.is_none() && method_generics.has_self,
segment.infer_types || suppress_mismatch,
GenericArgMismatchErrorCode {
lifetimes: ("E0090", "E0088"),
types: ("E0089", "E0087"),
},
);
// Create subst for early-bound lifetime parameters, combining
// parameters from the type and those from the method.
assert_eq!(method_generics.parent_count, parent_substs.len());
assert_eq!(generics.parent_count, parent_substs.len());
AstConv::create_substs_for_generic_args(
self.tcx,
@ -348,7 +336,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// Provide the generic args, and whether types should be inferred.
|_| {
// The last argument of the returned tuple here is unimportant.
if let Some(ref data) = segment.args {
if let Some(ref data) = seg.args {
(Some(data), false)
} else {
(None, false)

View File

@ -84,10 +84,9 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
use self::method::MethodCallee;
use self::TupleArgumentsFlag::*;
use astconv::{AstConv, GenericArgMismatchErrorCode};
use astconv::AstConv;
use hir::GenericArg;
use hir::def::Def;
use hir::HirVec;
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use std::slice;
use namespace::Namespace;
@ -4945,22 +4944,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// `impl Trait` is treated as a normal generic parameter internally,
// but we don't allow users to specify the parameter's value
// explicitly, so we have to do some error-checking here.
let suppress_mismatch = self.check_impl_trait(span, seg, &generics);
suppress_errors.insert(index, AstConv::check_generic_arg_count(
suppress_errors.insert(index, AstConv::check_generic_arg_count_for_call(
self.tcx,
span,
&generics,
&seg.args.clone().unwrap_or_else(|| P(hir::GenericArgs {
args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
})),
false, // `is_declaration`
&seg,
false, // `is_method_call`
generics.parent.is_none() && generics.has_self,
seg.infer_types || suppress_mismatch,
GenericArgMismatchErrorCode {
lifetimes: ("E0090", "E0088"), // FIXME: E0090 and E0088 should be unified.
types: ("E0089", "E0087"), // FIXME: E0089 and E0087 should be unified.
},
));
}
@ -5112,35 +5101,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
directly, not through a function pointer");
}
/// Report error if there is an explicit type parameter when using `impl Trait`.
fn check_impl_trait(&self,
span: Span,
seg: &hir::PathSegment,
generics: &ty::Generics)
-> bool {
let explicit = !seg.infer_types;
let impl_trait = generics.params.iter().any(|param| match param.kind {
ty::GenericParamDefKind::Type {
synthetic: Some(hir::SyntheticTyParamKind::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();
}
impl_trait
}
// Resolves `typ` by a single level if `typ` is a type variable.
// If no resolution is possible, then an error is reported.
// Numeric inference variables may be left unresolved.

View File

@ -1041,32 +1041,34 @@ enum NightsWatch {}
"##,
E0087: r##"
Too many type parameters were supplied for a function. For example:
Too many type arguments were supplied for a function. For example:
```compile_fail,E0087
fn foo<T>() {}
fn main() {
foo::<f64, bool>(); // error, expected 1 parameter, found 2 parameters
foo::<f64, bool>(); // error: wrong number of type arguments:
// expected 1, found 2
}
```
The number of supplied parameters must exactly match the number of defined type
The number of supplied arguments must exactly match the number of defined type
parameters.
"##,
E0088: r##"
You gave too many lifetime parameters. Erroneous code example:
You gave too many lifetime arguments. Erroneous code example:
```compile_fail,E0088
fn f() {}
fn main() {
f::<'static>() // error: too many lifetime parameters provided
f::<'static>() // error: wrong number of lifetime arguments:
// expected 0, found 1
}
```
Please check you give the right number of lifetime parameters. Example:
Please check you give the right number of lifetime arguments. Example:
```
fn f() {}
@ -1101,17 +1103,17 @@ fn main() {
"##,
E0089: r##"
Not enough type parameters were supplied for a function. For example:
Too few type arguments were supplied for a function. For example:
```compile_fail,E0089
fn foo<T, U>() {}
fn main() {
foo::<f64>(); // error, expected 2 parameters, found 1 parameter
foo::<f64>(); // error: wrong number of type arguments: expected 2, found 1
}
```
Note that if a function takes multiple type parameters but you want the compiler
Note that if a function takes multiple type arguments but you want the compiler
to infer some of them, you can use type placeholders:
```compile_fail,E0089
@ -1119,24 +1121,26 @@ fn foo<T, U>(x: T) {}
fn main() {
let x: bool = true;
foo::<f64>(x); // error, expected 2 parameters, found 1 parameter
foo::<f64>(x); // error: wrong number of type arguments:
// expected 2, found 1
foo::<_, f64>(x); // same as `foo::<bool, f64>(x)`
}
```
"##,
E0090: r##"
You gave too few lifetime parameters. Example:
You gave too few lifetime arguments. Example:
```compile_fail,E0090
fn foo<'a: 'b, 'b: 'a>() {}
fn main() {
foo::<'static>(); // error, expected 2 lifetime parameters
foo::<'static>(); // error: wrong number of lifetime arguments:
// expected 2, found 1
}
```
Please check you give the right number of lifetime parameters. Example:
Please check you give the right number of lifetime arguments. Example:
```
fn foo<'a: 'b, 'b: 'a>() {}