Avoid clone and update documentation
This commit is contained in:
parent
04d33bbdb3
commit
03c4628a5b
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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>() {}
|
||||
|
Loading…
Reference in New Issue
Block a user