mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 17:24:06 +00:00
Auto merge of #51880 - varkor:generics-hir-generalisation-followup, r=eddyb
The Great Generics Generalisation: HIR Followup Addresses the final comments in #48149. r? @eddyb, but there are a few things I have yet to clean up. Making the PR now to more easily see when things break. cc @yodaldevoid
This commit is contained in:
commit
1558ae7cfd
@ -401,6 +401,13 @@ impl GenericArg {
|
||||
GenericArg::Type(t) => t.span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> NodeId {
|
||||
match self {
|
||||
GenericArg::Lifetime(l) => l.id,
|
||||
GenericArg::Type(t) => t.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
@ -445,6 +452,22 @@ impl GenericArgs {
|
||||
}
|
||||
bug!("GenericArgs::inputs: not a `Fn(T) -> U`");
|
||||
}
|
||||
|
||||
pub fn own_counts(&self) -> GenericParamCount {
|
||||
// We could cache this as a property of `GenericParamCount`, but
|
||||
// the aim is to refactor this away entirely eventually and the
|
||||
// presence of this method will be a constant reminder.
|
||||
let mut own_counts: GenericParamCount = Default::default();
|
||||
|
||||
for arg in &self.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
|
||||
GenericArg::Type(_) => own_counts.types += 1,
|
||||
};
|
||||
}
|
||||
|
||||
own_counts
|
||||
}
|
||||
}
|
||||
|
||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
||||
@ -503,6 +526,7 @@ pub struct GenericParam {
|
||||
pub kind: GenericParamKind,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GenericParamCount {
|
||||
pub lifetimes: usize,
|
||||
pub types: usize,
|
||||
@ -533,10 +557,7 @@ impl Generics {
|
||||
// We could cache this as a property of `GenericParamCount`, but
|
||||
// the aim is to refactor this away entirely eventually and the
|
||||
// presence of this method will be a constant reminder.
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
let mut own_counts: GenericParamCount = Default::default();
|
||||
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
|
@ -20,7 +20,7 @@ use hir::map as hir_map;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{DefId, CrateNum};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use ty::{self, TyCtxt, GenericParamDefKind};
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::query::Providers;
|
||||
use middle::privacy;
|
||||
use session::config;
|
||||
@ -34,18 +34,6 @@ use hir::intravisit::{Visitor, NestedVisitorMap};
|
||||
use hir::itemlikevisit::ItemLikeVisitor;
|
||||
use hir::intravisit;
|
||||
|
||||
// Returns true if the given set of generics implies that the item it's
|
||||
// associated with must be inlined.
|
||||
fn generics_require_inlining(generics: &ty::Generics) -> bool {
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime { .. } => {}
|
||||
GenericParamDefKind::Type { .. } => return true,
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Returns true if the given item must be inlined because it may be
|
||||
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||
// true for functions.
|
||||
@ -60,7 +48,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
hir::ItemKind::Impl(..) |
|
||||
hir::ItemKind::Fn(..) => {
|
||||
let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
|
||||
generics_require_inlining(generics)
|
||||
generics.requires_monomorphization(tcx)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@ -71,7 +59,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_src: DefId) -> bool {
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
|
||||
let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id));
|
||||
if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) {
|
||||
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
|
||||
return true
|
||||
}
|
||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
|
||||
@ -189,8 +177,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
if generics_require_inlining(&generics) ||
|
||||
attrs.requests_inline() {
|
||||
if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
|
||||
true
|
||||
} else {
|
||||
let impl_did = self.tcx
|
||||
@ -203,7 +190,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
||||
match self.tcx.hir.expect_item(impl_node_id).node {
|
||||
hir::ItemKind::Impl(..) => {
|
||||
let generics = self.tcx.generics_of(impl_did);
|
||||
generics_require_inlining(&generics)
|
||||
generics.requires_monomorphization(self.tcx)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
|
@ -881,6 +881,7 @@ impl GenericParamDef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GenericParamCount {
|
||||
pub lifetimes: usize,
|
||||
pub types: usize,
|
||||
@ -913,15 +914,12 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||
// We could cache this as a property of `GenericParamCount`, but
|
||||
// the aim is to refactor this away entirely eventually and the
|
||||
// presence of this method will be a constant reminder.
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
let mut own_counts: GenericParamCount = Default::default();
|
||||
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
|
||||
GenericParamDefKind::Type {..} => own_counts.types += 1,
|
||||
GenericParamDefKind::Type { .. } => own_counts.types += 1,
|
||||
};
|
||||
}
|
||||
|
||||
@ -931,7 +929,7 @@ impl<'a, 'gcx, 'tcx> Generics {
|
||||
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type {..} => return true,
|
||||
GenericParamDefKind::Type { .. } => return true,
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
mk_kind: &mut F)
|
||||
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
|
||||
{
|
||||
|
||||
if let Some(def_id) = defs.parent {
|
||||
let parent_defs = tcx.generics_of(def_id);
|
||||
Substs::fill_item(substs, tcx, parent_defs, mk_kind);
|
||||
|
@ -262,10 +262,7 @@ impl PrintContext {
|
||||
let verbose = self.is_verbose;
|
||||
let mut num_supplied_defaults = 0;
|
||||
let mut has_self = false;
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
let mut own_counts: GenericParamCount = Default::default();
|
||||
let mut is_value_path = false;
|
||||
let fn_trait_kind = ty::tls::with(|tcx| {
|
||||
// Unfortunately, some kinds of items (e.g., closures) don't have
|
||||
|
@ -819,14 +819,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||
if let hir::ItemKind::Enum(ref enum_definition, _) = it.node {
|
||||
let item_def_id = cx.tcx.hir.local_def_id(it.id);
|
||||
let generics = cx.tcx.generics_of(item_def_id);
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime { .. } => {},
|
||||
ty::GenericParamDefKind::Type { .. } => return,
|
||||
}
|
||||
}
|
||||
// Sizes only make sense for non-generic types.
|
||||
let t = cx.tcx.type_of(item_def_id);
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
match cx.layout_of(ty) {
|
||||
|
@ -1262,12 +1262,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
||||
hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id),
|
||||
hir::ItemKind::Fn(_, header, ..) => {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let has_types = generics.params.iter().any(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Type { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
let needs_inline =
|
||||
(has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
|
||||
(generics.requires_monomorphization(tcx) ||
|
||||
tcx.codegen_fn_attrs(def_id).requests_inline()) &&
|
||||
!self.metadata_output_only();
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
if needs_inline
|
||||
@ -1683,15 +1680,17 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { ref default, .. } => {
|
||||
let def_id = self.tcx.hir.local_def_id(param.id);
|
||||
let has_default = Untracked(default.is_some());
|
||||
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
|
||||
self.record(def_id, encode_info, (def_id, has_default));
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { ref default, .. } => {
|
||||
let def_id = self.tcx.hir.local_def_id(param.id);
|
||||
let has_default = Untracked(default.is_some());
|
||||
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
|
||||
self.record(def_id, encode_info, (def_id, has_default));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
|
||||
|
@ -539,10 +539,9 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
|
||||
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
|
||||
match *generic_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
for arg in &data.args {
|
||||
self.visit_generic_arg(arg)
|
||||
}
|
||||
for type_binding in &data.bindings {
|
||||
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
|
||||
// are allowed to contain nested `impl Trait`.
|
||||
|
@ -23,7 +23,7 @@ extern crate rustc_typeck;
|
||||
extern crate syntax_pos;
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
use rustc::hir::{self, GenericParamKind, PatKind};
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
@ -1270,14 +1270,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
self.check_generic_bound(bound);
|
||||
}
|
||||
for param in &generics.params {
|
||||
for bound in ¶m.bounds {
|
||||
self.check_generic_bound(bound);
|
||||
}
|
||||
});
|
||||
}
|
||||
for predicate in &generics.where_clause.predicates {
|
||||
match predicate {
|
||||
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {
|
||||
|
@ -822,11 +822,12 @@ impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> {
|
||||
.filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => None,
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
if found_default || default.is_some() {
|
||||
found_default = true;
|
||||
return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
|
||||
found_default |= default.is_some();
|
||||
if found_default {
|
||||
Some((Ident::with_empty_ctxt(param.ident.name), Def::Err))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
}));
|
||||
|
||||
@ -2339,28 +2340,30 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||
HasTypeParameters(generics, rib_kind) => {
|
||||
let mut function_type_rib = Rib::new(rib_kind);
|
||||
let mut seen_bindings = FxHashMap();
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
let ident = param.ident.modern();
|
||||
debug!("with_type_parameter_rib: {}", param.id);
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
let ident = param.ident.modern();
|
||||
debug!("with_type_parameter_rib: {}", param.id);
|
||||
|
||||
if seen_bindings.contains_key(&ident) {
|
||||
let span = seen_bindings.get(&ident).unwrap();
|
||||
let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
|
||||
ident.name,
|
||||
span,
|
||||
);
|
||||
resolve_error(self, param.ident.span, err);
|
||||
if seen_bindings.contains_key(&ident) {
|
||||
let span = seen_bindings.get(&ident).unwrap();
|
||||
let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
|
||||
ident.name,
|
||||
span,
|
||||
);
|
||||
resolve_error(self, param.ident.span, err);
|
||||
}
|
||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||
|
||||
// Plain insert (no renaming).
|
||||
let def = Def::TyParam(self.definitions.local_def_id(param.id));
|
||||
function_type_rib.bindings.insert(ident, def);
|
||||
self.record_def(param.id, PathResolution::new(def));
|
||||
}
|
||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||
|
||||
// Plain insert (no renaming).
|
||||
let def = Def::TyParam(self.definitions.local_def_id(param.id));
|
||||
function_type_rib.bindings.insert(ident, def);
|
||||
self.record_def(param.id, PathResolution::new(def));
|
||||
}
|
||||
});
|
||||
}
|
||||
self.ribs[TypeNS].push(function_type_rib);
|
||||
}
|
||||
|
||||
|
@ -824,10 +824,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
||||
if let Some(ref generic_args) = seg.args {
|
||||
match **generic_args {
|
||||
ast::GenericArgs::AngleBracketed(ref data) => {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::GenericArgs::Parenthesized(ref data) => {
|
||||
for t in &data.inputs {
|
||||
@ -911,10 +913,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
||||
// Explicit types in the turbo-fish.
|
||||
if let Some(ref generic_args) = seg.args {
|
||||
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1522,19 +1526,21 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'l ast::Generics) {
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {}
|
||||
ast::GenericParamKind::Type { ref default, .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {}
|
||||
ast::GenericParamKind::Type { ref default, .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
|
||||
}
|
||||
}
|
||||
if let Some(ref ty) = default {
|
||||
self.visit_ty(&ty);
|
||||
}
|
||||
}
|
||||
if let Some(ref ty) = default {
|
||||
self.visit_ty(&ty);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'l ast::Ty) {
|
||||
|
@ -13,27 +13,31 @@
|
||||
//! is parameterized by an instance of `AstConv`.
|
||||
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
use hir::{self, GenericArg};
|
||||
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::{Subst, Substs};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||
use rustc::ty::GenericParamDefKind;
|
||||
use rustc::ty::{GenericParamDef, GenericParamDefKind};
|
||||
use rustc::ty::wf::object_region_bounds;
|
||||
use rustc_target::spec::abi;
|
||||
use std::slice;
|
||||
use require_c_abi_if_variadic;
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::{FxHashSet, FxHashMap};
|
||||
use errors::FatalError;
|
||||
use errors::{FatalError, DiagnosticId};
|
||||
use lint;
|
||||
|
||||
use std::iter;
|
||||
use syntax::ast;
|
||||
use syntax::ptr::P;
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{Span, MultiSpan};
|
||||
|
||||
pub trait AstConv<'gcx, 'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
|
||||
@ -88,9 +92,17 @@ struct ConvertedBinding<'tcx> {
|
||||
span: Span,
|
||||
}
|
||||
|
||||
struct ParamRange {
|
||||
required: usize,
|
||||
accepted: usize
|
||||
#[derive(PartialEq)]
|
||||
enum GenericArgPosition {
|
||||
Type,
|
||||
Value, // e.g. functions
|
||||
MethodCall,
|
||||
}
|
||||
|
||||
// FIXME(#53525): these error codes should all be unified.
|
||||
struct GenericArgMismatchErrorCode {
|
||||
lifetimes: (&'static str, &'static str),
|
||||
types: (&'static str, &'static str),
|
||||
}
|
||||
|
||||
/// Dummy type used for the `Self` of a `TraitRef` created for converting
|
||||
@ -176,21 +188,370 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
-> &'tcx Substs<'tcx>
|
||||
{
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
item_segment.with_generic_args(|generic_args| {
|
||||
self.create_substs_for_ast_path(
|
||||
span,
|
||||
def_id,
|
||||
generic_args,
|
||||
item_segment.infer_types,
|
||||
None)
|
||||
});
|
||||
let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
|
||||
self.create_substs_for_ast_path(
|
||||
span,
|
||||
def_id,
|
||||
generic_args,
|
||||
item_segment.infer_types,
|
||||
None,
|
||||
)
|
||||
});
|
||||
|
||||
assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
|
||||
assoc_bindings.first().map(|b| Self::prohibit_assoc_ty_binding(self.tcx(), b.span));
|
||||
|
||||
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
|
||||
},
|
||||
if is_method_call {
|
||||
GenericArgPosition::MethodCall
|
||||
} else {
|
||||
GenericArgPosition::Value
|
||||
},
|
||||
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 datatypes and function calls.
|
||||
fn check_generic_arg_count(
|
||||
tcx: TyCtxt,
|
||||
span: Span,
|
||||
def: &ty::Generics,
|
||||
args: &hir::GenericArgs,
|
||||
position: GenericArgPosition,
|
||||
has_self: bool,
|
||||
infer_types: bool,
|
||||
error_codes: GenericArgMismatchErrorCode,
|
||||
) -> bool {
|
||||
// At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
|
||||
// that lifetimes will proceed types. So it suffices to check the number of each generic
|
||||
// arguments in order to validate them with respect to the generic parameters.
|
||||
let param_counts = def.own_counts();
|
||||
let arg_counts = args.own_counts();
|
||||
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
|
||||
|
||||
let mut defaults: ty::GenericParamCount = Default::default();
|
||||
for param in &def.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
defaults.types += has_default as usize
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if position != GenericArgPosition::Type && !args.bindings.is_empty() {
|
||||
AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
|
||||
}
|
||||
|
||||
// Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
|
||||
if !infer_lifetimes {
|
||||
if let Some(span_late) = def.has_late_bound_regions {
|
||||
let msg = "cannot specify lifetime arguments explicitly \
|
||||
if late bound lifetime parameters are present";
|
||||
let note = "the late bound lifetime parameter is introduced here";
|
||||
let span = args.args[0].span();
|
||||
if position == GenericArgPosition::Value
|
||||
&& arg_counts.lifetimes != param_counts.lifetimes {
|
||||
let mut err = tcx.sess.struct_span_err(span, msg);
|
||||
err.span_note(span_late, note);
|
||||
err.emit();
|
||||
return true;
|
||||
} else {
|
||||
let mut multispan = MultiSpan::from_span(span);
|
||||
multispan.push_span_label(span_late, note.to_string());
|
||||
tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||
args.args[0].id(), multispan, msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let check_kind_count = |error_code: (&str, &str),
|
||||
kind,
|
||||
required,
|
||||
permitted,
|
||||
provided,
|
||||
offset| {
|
||||
// We enforce the following: `required` <= `provided` <= `permitted`.
|
||||
// For kinds without defaults (i.e. lifetimes), `required == permitted`.
|
||||
// For other kinds (i.e. types), `permitted` may be greater than `required`.
|
||||
if required <= provided && provided <= permitted {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unfortunately lifetime and type parameter mismatches are typically styled
|
||||
// differently in diagnostics, which means we have a few cases to consider here.
|
||||
let (bound, quantifier) = if required != permitted {
|
||||
if provided < required {
|
||||
(required, "at least ")
|
||||
} else { // provided > permitted
|
||||
(permitted, "at most ")
|
||||
}
|
||||
} else {
|
||||
(required, "")
|
||||
};
|
||||
|
||||
let mut span = span;
|
||||
let label = if required == permitted && provided > permitted {
|
||||
let diff = provided - permitted;
|
||||
if diff == 1 {
|
||||
// In the case when the user has provided too many arguments,
|
||||
// we want to point to the first unexpected argument.
|
||||
let first_superfluous_arg: &GenericArg = &args.args[offset + permitted];
|
||||
span = first_superfluous_arg.span();
|
||||
}
|
||||
format!(
|
||||
"{}unexpected {} argument{}",
|
||||
if diff != 1 { format!("{} ", diff) } else { String::new() },
|
||||
kind,
|
||||
if diff != 1 { "s" } else { "" },
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"expected {}{} {} argument{}",
|
||||
quantifier,
|
||||
bound,
|
||||
kind,
|
||||
if required != 1 { "s" } else { "" },
|
||||
)
|
||||
};
|
||||
|
||||
tcx.sess.struct_span_err_with_code(
|
||||
span,
|
||||
&format!(
|
||||
"wrong number of {} arguments: expected {}{}, found {}",
|
||||
kind,
|
||||
quantifier,
|
||||
bound,
|
||||
provided,
|
||||
),
|
||||
DiagnosticId::Error({
|
||||
if provided <= permitted {
|
||||
error_code.0
|
||||
} else {
|
||||
error_code.1
|
||||
}
|
||||
}.into())
|
||||
).span_label(span, label).emit();
|
||||
|
||||
provided > required // `suppress_error`
|
||||
};
|
||||
|
||||
if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
|
||||
check_kind_count(
|
||||
error_codes.lifetimes,
|
||||
"lifetime",
|
||||
param_counts.lifetimes,
|
||||
param_counts.lifetimes,
|
||||
arg_counts.lifetimes,
|
||||
0,
|
||||
);
|
||||
}
|
||||
if !infer_types
|
||||
|| arg_counts.types > param_counts.types - defaults.types - has_self as usize {
|
||||
check_kind_count(
|
||||
error_codes.types,
|
||||
"type",
|
||||
param_counts.types - defaults.types - has_self as usize,
|
||||
param_counts.types - has_self as usize,
|
||||
arg_counts.types,
|
||||
arg_counts.lifetimes,
|
||||
)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates the relevant generic argument substitutions
|
||||
/// corresponding to a set of generic parameters.
|
||||
pub fn create_substs_for_generic_args<'a, 'b, A, P, I>(
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
parent_substs: &[Kind<'tcx>],
|
||||
has_self: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
args_for_def_id: A,
|
||||
provided_kind: P,
|
||||
inferred_kind: I,
|
||||
) -> &'tcx Substs<'tcx> where
|
||||
A: Fn(DefId) -> (Option<&'b GenericArgs>, bool),
|
||||
P: Fn(&GenericParamDef, &GenericArg) -> Kind<'tcx>,
|
||||
I: Fn(Option<&[Kind<'tcx>]>, &GenericParamDef, bool) -> Kind<'tcx>
|
||||
{
|
||||
// Collect the segments of the path: we need to substitute arguments
|
||||
// for parameters throughout the entire path (wherever there are
|
||||
// generic parameters).
|
||||
let mut parent_defs = tcx.generics_of(def_id);
|
||||
let count = parent_defs.count();
|
||||
let mut stack = vec![(def_id, parent_defs)];
|
||||
while let Some(def_id) = parent_defs.parent {
|
||||
parent_defs = tcx.generics_of(def_id);
|
||||
stack.push((def_id, parent_defs));
|
||||
}
|
||||
|
||||
// We manually build up the substitution, rather than using convenience
|
||||
// methods in subst.rs so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, rather than trying to match each pair.
|
||||
let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
|
||||
AccumulateVec::Array(ArrayVec::new())
|
||||
} else {
|
||||
AccumulateVec::Heap(Vec::with_capacity(count))
|
||||
};
|
||||
|
||||
fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) {
|
||||
match substs {
|
||||
AccumulateVec::Array(ref mut arr) => arr.push(kind),
|
||||
AccumulateVec::Heap(ref mut vec) => vec.push(kind),
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over each segment of the path.
|
||||
while let Some((def_id, defs)) = stack.pop() {
|
||||
let mut params = defs.params.iter().peekable();
|
||||
|
||||
// If we have already computed substitutions for parents, we can use those directly.
|
||||
while let Some(¶m) = params.peek() {
|
||||
if let Some(&kind) = parent_substs.get(param.index as usize) {
|
||||
push_kind(&mut substs, kind);
|
||||
params.next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// (Unless it's been handled in `parent_substs`) `Self` is handled first.
|
||||
if has_self {
|
||||
if let Some(¶m) = params.peek() {
|
||||
if param.index == 0 {
|
||||
if let GenericParamDefKind::Type { .. } = param.kind {
|
||||
push_kind(&mut substs, self_ty.map(|ty| ty.into())
|
||||
.unwrap_or_else(|| inferred_kind(None, param, true)));
|
||||
params.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether this segment takes generic arguments and the user has provided any.
|
||||
let (generic_args, infer_types) = args_for_def_id(def_id);
|
||||
|
||||
let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter())
|
||||
.peekable();
|
||||
|
||||
loop {
|
||||
// We're going to iterate through the generic arguments that the user
|
||||
// provided, matching them with the generic parameters we expect.
|
||||
// Mismatches can occur as a result of elided lifetimes, or for malformed
|
||||
// input. We try to handle both sensibly.
|
||||
match (args.peek(), params.peek()) {
|
||||
(Some(&arg), Some(¶m)) => {
|
||||
match (arg, ¶m.kind) {
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
|
||||
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
|
||||
push_kind(&mut substs, provided_kind(param, arg));
|
||||
args.next();
|
||||
params.next();
|
||||
}
|
||||
(GenericArg::Lifetime(_), GenericParamDefKind::Type { .. }) => {
|
||||
// We expected a type argument, but got a lifetime
|
||||
// argument. This is an error, but we need to handle it
|
||||
// gracefully so we can report sensible errors. In this
|
||||
// case, we're simply going to infer this argument.
|
||||
args.next();
|
||||
}
|
||||
(GenericArg::Type(_), GenericParamDefKind::Lifetime) => {
|
||||
// We expected a lifetime argument, but got a type
|
||||
// argument. That means we're inferring the lifetimes.
|
||||
push_kind(&mut substs, inferred_kind(None, param, infer_types));
|
||||
params.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
(Some(_), None) => {
|
||||
// We should never be able to reach this point with well-formed input.
|
||||
// Getting to this point means the user supplied more arguments than
|
||||
// there are parameters.
|
||||
args.next();
|
||||
}
|
||||
(None, Some(¶m)) => {
|
||||
// If there are fewer arguments than parameters, it means
|
||||
// we're inferring the remaining arguments.
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime | GenericParamDefKind::Type { .. } => {
|
||||
let kind = inferred_kind(Some(&substs), param, infer_types);
|
||||
push_kind(&mut substs, kind);
|
||||
}
|
||||
}
|
||||
args.next();
|
||||
params.next();
|
||||
}
|
||||
(None, None) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcx.intern_substs(&substs)
|
||||
}
|
||||
|
||||
/// Given the type/region arguments provided to some path (along with
|
||||
/// an implicit Self, if this is a trait reference) returns the complete
|
||||
/// set of substitutions. This may involve applying defaulted type parameters.
|
||||
@ -204,60 +565,33 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
|
||||
generic_args={:?})",
|
||||
def_id, self_ty, generic_args);
|
||||
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
|
||||
// FIXME(varkor): Separating out the parameters is messy.
|
||||
let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
|
||||
GenericArg::Lifetime(lt) => Some(lt),
|
||||
_ => None,
|
||||
}).collect();
|
||||
let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
|
||||
GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}).collect();
|
||||
let lt_provided = lifetimes.len();
|
||||
let ty_provided = types.len();
|
||||
|
||||
let decl_generics = tcx.generics_of(def_id);
|
||||
let mut lt_accepted = 0;
|
||||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &decl_generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
lt_accepted += 1;
|
||||
}
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
ty_params.accepted += 1;
|
||||
if !has_default {
|
||||
ty_params.required += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if self_ty.is_some() {
|
||||
ty_params.required -= 1;
|
||||
ty_params.accepted -= 1;
|
||||
}
|
||||
|
||||
if lt_accepted != lt_provided {
|
||||
report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
|
||||
}
|
||||
let tcx = self.tcx();
|
||||
let generic_params = tcx.generics_of(def_id);
|
||||
|
||||
// If a self-type was declared, one should be provided.
|
||||
assert_eq!(decl_generics.has_self, self_ty.is_some());
|
||||
assert_eq!(generic_params.has_self, self_ty.is_some());
|
||||
|
||||
// Check the number of type parameters supplied by the user.
|
||||
if !infer_types || ty_provided > ty_params.required {
|
||||
check_type_argument_count(tcx, span, ty_provided, ty_params);
|
||||
}
|
||||
let has_self = generic_params.has_self;
|
||||
Self::check_generic_arg_count(
|
||||
self.tcx(),
|
||||
span,
|
||||
&generic_params,
|
||||
&generic_args,
|
||||
GenericArgPosition::Type,
|
||||
has_self,
|
||||
infer_types,
|
||||
GenericArgMismatchErrorCode {
|
||||
lifetimes: ("E0107", "E0107"),
|
||||
types: ("E0243", "E0244"),
|
||||
},
|
||||
);
|
||||
|
||||
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||
let default_needs_object_self = |param: &ty::GenericParamDef| {
|
||||
@ -274,71 +608,74 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
false
|
||||
};
|
||||
|
||||
let own_self = self_ty.is_some() as usize;
|
||||
let substs = Substs::for_item(tcx, def_id, |param, substs| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let i = param.index as usize - own_self;
|
||||
if let Some(lt) = lifetimes.get(i) {
|
||||
self.ast_region_to_region(lt, Some(param)).into()
|
||||
} else {
|
||||
tcx.types.re_static.into()
|
||||
let substs = Self::create_substs_for_generic_args(
|
||||
self.tcx(),
|
||||
def_id,
|
||||
&[][..],
|
||||
self_ty.is_some(),
|
||||
self_ty,
|
||||
// Provide the generic args, and whether types should be inferred.
|
||||
|_| (Some(generic_args), infer_types),
|
||||
// Provide substitutions for parameters for which (valid) arguments have been provided.
|
||||
|param, arg| {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
self.ast_region_to_region(<, Some(param)).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.ast_ty_to_ty(&ty).into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
let i = param.index as usize;
|
||||
},
|
||||
// Provide substitutions for parameters for which arguments are inferred.
|
||||
|substs, param, infer_types| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.types.re_static.into(),
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
if !infer_types && has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if let (0, Some(ty)) = (i, self_ty) {
|
||||
return ty.into();
|
||||
}
|
||||
|
||||
let i = i - (lt_accepted + own_self);
|
||||
if i < ty_provided {
|
||||
// A provided type parameter.
|
||||
self.ast_ty_to_ty(&types[i]).into()
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
if !default_needs_object_self(param) {
|
||||
self.ty_infer_for_def(param, span).into()
|
||||
// If we are converting an object type, then the
|
||||
// `Self` parameter is unknown. However, some of the
|
||||
// other type parameters may reference `Self` in their
|
||||
// defaults. This will lead to an ICE if we are not
|
||||
// careful!
|
||||
if default_needs_object_self(param) {
|
||||
struct_span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly \
|
||||
specified",
|
||||
param.name)
|
||||
.span_label(span,
|
||||
format!("missing reference to `{}`", param.name))
|
||||
.note(&format!("because of the default `Self` reference, \
|
||||
type parameters must be specified on object \
|
||||
types"))
|
||||
.emit();
|
||||
tcx.types.err.into()
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
self.normalize_ty(
|
||||
span,
|
||||
tcx.at(span).type_of(param.def_id)
|
||||
.subst_spanned(tcx, substs.unwrap(), Some(span))
|
||||
).into()
|
||||
}
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
if !default_needs_object_self(param) {
|
||||
self.ty_infer_for_def(param, span).into()
|
||||
} else {
|
||||
self.ty_infer(span).into()
|
||||
}
|
||||
} else {
|
||||
self.ty_infer(span).into()
|
||||
}
|
||||
} else if has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// If we are converting an object type, then the
|
||||
// `Self` parameter is unknown. However, some of the
|
||||
// other type parameters may reference `Self` in their
|
||||
// defaults. This will lead to an ICE if we are not
|
||||
// careful!
|
||||
if default_needs_object_self(param) {
|
||||
struct_span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly \
|
||||
specified",
|
||||
param.name)
|
||||
.span_label(span,
|
||||
format!("missing reference to `{}`", param.name))
|
||||
.note(&format!("because of the default `Self` reference, \
|
||||
type parameters must be specified on object \
|
||||
types"))
|
||||
.emit();
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.types.err.into()
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
self.normalize_ty(
|
||||
span,
|
||||
tcx.at(span).type_of(param.def_id)
|
||||
.subst_spanned(tcx, substs, Some(span))
|
||||
).into()
|
||||
}
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.types.err.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
let assoc_bindings = generic_args.bindings.iter().map(|binding| {
|
||||
ConvertedBinding {
|
||||
@ -348,8 +685,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}).collect();
|
||||
|
||||
debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
|
||||
decl_generics, self_ty, substs);
|
||||
debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}",
|
||||
generic_params, self_ty, substs);
|
||||
|
||||
(substs, assoc_bindings)
|
||||
}
|
||||
@ -444,7 +781,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
trait_def_id,
|
||||
self_ty,
|
||||
trait_segment);
|
||||
assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
|
||||
assoc_bindings.first().map(|b| AstConv::prohibit_assoc_ty_binding(self.tcx(), b.span));
|
||||
ty::TraitRef::new(trait_def_id, substs)
|
||||
}
|
||||
|
||||
@ -978,7 +1315,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
|
||||
}
|
||||
|
||||
pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) {
|
||||
pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment>>(&self, segments: T) {
|
||||
for segment in segments {
|
||||
segment.with_generic_args(|generic_args| {
|
||||
let (mut err_for_lt, mut err_for_ty) = (false, false);
|
||||
@ -1009,15 +1346,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
for binding in &generic_args.bindings {
|
||||
self.prohibit_projection(binding.span);
|
||||
Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prohibit_projection(&self, span: Span) {
|
||||
let mut err = struct_span_err!(self.tcx().sess, span, E0229,
|
||||
pub fn prohibit_assoc_ty_binding(tcx: TyCtxt, span: Span) {
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0229,
|
||||
"associated type bindings are not allowed here");
|
||||
err.span_label(span, "associated type not allowed here").emit();
|
||||
}
|
||||
@ -1393,72 +1730,6 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
(auto_traits, trait_bounds)
|
||||
}
|
||||
|
||||
fn check_type_argument_count(tcx: TyCtxt,
|
||||
span: Span,
|
||||
supplied: usize,
|
||||
ty_params: ParamRange)
|
||||
{
|
||||
let (required, accepted) = (ty_params.required, ty_params.accepted);
|
||||
if supplied < required {
|
||||
let expected = if required < accepted {
|
||||
"expected at least"
|
||||
} else {
|
||||
"expected"
|
||||
};
|
||||
let arguments_plural = if required == 1 { "" } else { "s" };
|
||||
|
||||
struct_span_err!(tcx.sess, span, E0243,
|
||||
"wrong number of type arguments: {} {}, found {}",
|
||||
expected, required, supplied)
|
||||
.span_label(span,
|
||||
format!("{} {} type argument{}",
|
||||
expected,
|
||||
required,
|
||||
arguments_plural))
|
||||
.emit();
|
||||
} else if supplied > accepted {
|
||||
let expected = if required < accepted {
|
||||
format!("expected at most {}", accepted)
|
||||
} else {
|
||||
format!("expected {}", accepted)
|
||||
};
|
||||
let arguments_plural = if accepted == 1 { "" } else { "s" };
|
||||
|
||||
struct_span_err!(tcx.sess, span, E0244,
|
||||
"wrong number of type arguments: {}, found {}",
|
||||
expected, supplied)
|
||||
.span_label(
|
||||
span,
|
||||
format!("{} type argument{}",
|
||||
if accepted == 0 { "expected no" } else { &expected },
|
||||
arguments_plural)
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected: usize) {
|
||||
let label = if number < expected {
|
||||
if expected == 1 {
|
||||
format!("expected {} lifetime parameter", expected)
|
||||
} else {
|
||||
format!("expected {} lifetime parameters", expected)
|
||||
}
|
||||
} else {
|
||||
let additional = number - expected;
|
||||
if additional == 1 {
|
||||
"unexpected lifetime parameter".to_string()
|
||||
} else {
|
||||
format!("{} unexpected lifetime parameters", additional)
|
||||
}
|
||||
};
|
||||
struct_span_err!(tcx.sess, span, E0107,
|
||||
"wrong number of lifetime parameters: expected {}, found {}",
|
||||
expected, number)
|
||||
.span_label(span, label)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// A helper struct for conveniently grouping a set of bounds which we pass to
|
||||
// and return from functions in multiple places.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
|
@ -22,8 +22,8 @@ use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
|
||||
use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::infer::{self, InferOk};
|
||||
use syntax_pos::Span;
|
||||
use rustc::hir;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
@ -308,55 +308,55 @@ 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 mut fn_segment = Some((segment, method_generics));
|
||||
let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment);
|
||||
self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch);
|
||||
let generics = self.tcx.generics_of(pick.item.def_id);
|
||||
AstConv::check_generic_arg_count_for_call(
|
||||
self.tcx,
|
||||
self.span,
|
||||
&generics,
|
||||
&seg,
|
||||
true, // `is_method_call`
|
||||
);
|
||||
|
||||
// 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());
|
||||
let provided = &segment.args;
|
||||
let own_counts = method_generics.own_counts();
|
||||
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||
let mut i = param.index as usize;
|
||||
if i < parent_substs.len() {
|
||||
parent_substs[i]
|
||||
} else {
|
||||
let (is_lt, is_ty) = match param.kind {
|
||||
GenericParamDefKind::Lifetime => (true, false),
|
||||
GenericParamDefKind::Type { .. } => (false, true),
|
||||
};
|
||||
provided.as_ref().and_then(|data| {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) if is_lt => {
|
||||
if i == parent_substs.len() {
|
||||
return Some(AstConv::ast_region_to_region(
|
||||
self.fcx, lt, Some(param)).into());
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ty) if is_ty => {
|
||||
if i == parent_substs.len() + own_counts.lifetimes {
|
||||
return Some(self.to_ty(ty).into());
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
GenericArg::Type(_) => {}
|
||||
}
|
||||
assert_eq!(generics.parent_count, parent_substs.len());
|
||||
|
||||
AstConv::create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
pick.item.def_id,
|
||||
parent_substs,
|
||||
false,
|
||||
None,
|
||||
// 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) = seg.args {
|
||||
(Some(data), false)
|
||||
} else {
|
||||
(None, false)
|
||||
}
|
||||
},
|
||||
// Provide substitutions for parameters for which (valid) arguments have been provided.
|
||||
|param, arg| {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
AstConv::ast_region_to_region(self.fcx, lt, Some(param)).into()
|
||||
}
|
||||
None
|
||||
}).unwrap_or_else(|| self.var_for_def(self.span, param))
|
||||
}
|
||||
})
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.to_ty(ty).into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
},
|
||||
// Provide substitutions for parameters for which arguments are inferred.
|
||||
|_, param, _| self.var_for_def(self.span, param),
|
||||
)
|
||||
}
|
||||
|
||||
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
|
||||
|
@ -109,7 +109,7 @@ use session::{CompileIncomplete, config, Session};
|
||||
use TypeAndSubsts;
|
||||
use lint;
|
||||
use util::common::{ErrorReported, indenter};
|
||||
use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, NodeMap};
|
||||
use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap};
|
||||
|
||||
use std::cell::{Cell, RefCell, Ref, RefMut};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
@ -505,6 +505,9 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PathSeg(DefId, usize);
|
||||
|
||||
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
body_id: ast::NodeId,
|
||||
|
||||
@ -4277,8 +4280,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
match *qpath {
|
||||
hir::QPath::Resolved(ref maybe_qself, ref path) => {
|
||||
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
|
||||
let ty = AstConv::def_to_ty(self, opt_self_ty, path, true);
|
||||
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
|
||||
let ty = AstConv::def_to_ty(self, self_ty, path, true);
|
||||
(path.def, ty)
|
||||
}
|
||||
hir::QPath::TypeRelative(ref qself, ref segment) => {
|
||||
@ -4770,20 +4773,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
|
||||
}
|
||||
|
||||
// Instantiates the given path, which must refer to an item with the given
|
||||
// number of type parameters and type.
|
||||
pub fn instantiate_value_path(&self,
|
||||
segments: &[hir::PathSegment],
|
||||
opt_self_ty: Option<Ty<'tcx>>,
|
||||
def: Def,
|
||||
span: Span,
|
||||
node_id: ast::NodeId)
|
||||
-> Ty<'tcx> {
|
||||
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
|
||||
segments,
|
||||
def,
|
||||
node_id);
|
||||
|
||||
fn def_ids_for_path_segments(&self,
|
||||
segments: &[hir::PathSegment],
|
||||
def: Def)
|
||||
-> Vec<PathSeg> {
|
||||
// We need to extract the type parameters supplied by the user in
|
||||
// the path `path`. Due to the current setup, this is a bit of a
|
||||
// tricky-process; the problem is that resolve only tells us the
|
||||
@ -4829,33 +4822,69 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// The first step then is to categorize the segments appropriately.
|
||||
|
||||
assert!(!segments.is_empty());
|
||||
let last = segments.len() - 1;
|
||||
|
||||
let mut path_segs = vec![];
|
||||
|
||||
let mut ufcs_associated = None;
|
||||
let mut type_segment = None;
|
||||
let mut fn_segment = None;
|
||||
match def {
|
||||
// Case 1. Reference to a struct/variant constructor.
|
||||
Def::StructCtor(def_id, ..) |
|
||||
Def::VariantCtor(def_id, ..) => {
|
||||
// Everything but the final segment should have no
|
||||
// parameters at all.
|
||||
let mut generics = self.tcx.generics_of(def_id);
|
||||
if let Some(def_id) = generics.parent {
|
||||
// Variant and struct constructors use the
|
||||
// generics of their parent type definition.
|
||||
generics = self.tcx.generics_of(def_id);
|
||||
}
|
||||
type_segment = Some((segments.last().unwrap(), generics));
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
// Variant and struct constructors use the
|
||||
// generics of their parent type definition.
|
||||
let generics_def_id = generics.parent.unwrap_or(def_id);
|
||||
path_segs.push(PathSeg(generics_def_id, last));
|
||||
}
|
||||
|
||||
// Case 2. Reference to a top-level value.
|
||||
Def::Fn(def_id) |
|
||||
Def::Const(def_id) |
|
||||
Def::Static(def_id, _) => {
|
||||
fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id)));
|
||||
path_segs.push(PathSeg(def_id, last));
|
||||
}
|
||||
|
||||
// Case 3. Reference to a method or associated const.
|
||||
Def::Method(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
if segments.len() >= 2 {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
path_segs.push(PathSeg(generics.parent.unwrap(), last - 1));
|
||||
}
|
||||
path_segs.push(PathSeg(def_id, last));
|
||||
}
|
||||
|
||||
// Case 4. Local variable, no generics.
|
||||
Def::Local(..) | Def::Upvar(..) => {}
|
||||
|
||||
_ => bug!("unexpected definition: {:?}", def),
|
||||
}
|
||||
|
||||
debug!("path_segs = {:?}", path_segs);
|
||||
|
||||
path_segs
|
||||
}
|
||||
|
||||
// Instantiates the given path, which must refer to an item with the given
|
||||
// number of type parameters and type.
|
||||
pub fn instantiate_value_path(&self,
|
||||
segments: &[hir::PathSegment],
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
def: Def,
|
||||
span: Span,
|
||||
node_id: ast::NodeId)
|
||||
-> Ty<'tcx> {
|
||||
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})",
|
||||
segments,
|
||||
def,
|
||||
node_id);
|
||||
|
||||
let path_segs = self.def_ids_for_path_segments(segments, def);
|
||||
|
||||
let mut ufcs_associated = None;
|
||||
match def {
|
||||
Def::Method(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
let container = self.tcx.associated_item(def_id).container;
|
||||
@ -4865,34 +4894,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
ty::ImplContainer(_) => {}
|
||||
}
|
||||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
if segments.len() >= 2 {
|
||||
let parent_generics = self.tcx.generics_of(generics.parent.unwrap());
|
||||
type_segment = Some((&segments[segments.len() - 2], parent_generics));
|
||||
} else {
|
||||
if segments.len() == 1 {
|
||||
// `<T>::assoc` will end up here, and so can `T::assoc`.
|
||||
let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self");
|
||||
let self_ty = self_ty.expect("UFCS sugared assoc missing Self");
|
||||
ufcs_associated = Some((container, self_ty));
|
||||
}
|
||||
fn_segment = Some((segments.last().unwrap(), generics));
|
||||
}
|
||||
|
||||
// Case 4. Local variable, no generics.
|
||||
Def::Local(..) | Def::Upvar(..) => {}
|
||||
|
||||
_ => bug!("unexpected definition: {:?}", def),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment);
|
||||
|
||||
// Now that we have categorized what space the parameters for each
|
||||
// segment belong to, let's sort out the parameters that the user
|
||||
// provided (if any) into their appropriate spaces. We'll also report
|
||||
// errors if type parameters are provided in an inappropriate place.
|
||||
let poly_segments = type_segment.is_some() as usize +
|
||||
fn_segment.is_some() as usize;
|
||||
AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]);
|
||||
|
||||
let mut generic_segs = FxHashSet::default();
|
||||
for PathSeg(_, index) in &path_segs {
|
||||
generic_segs.insert(index);
|
||||
}
|
||||
AstConv::prohibit_generics(self, segments.iter().enumerate().filter_map(|(index, seg)| {
|
||||
if !generic_segs.contains(&index) {
|
||||
Some(seg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}));
|
||||
|
||||
match def {
|
||||
Def::Local(nid) | Def::Upvar(nid, ..) => {
|
||||
@ -4910,120 +4936,109 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// variables. If the user provided some types, we may still need
|
||||
// to add defaults. If the user provided *too many* types, that's
|
||||
// a problem.
|
||||
let supress_mismatch = self.check_impl_trait(span, fn_segment);
|
||||
self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch);
|
||||
self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch);
|
||||
|
||||
let (fn_start, has_self) = match (type_segment, fn_segment) {
|
||||
(_, Some((_, generics))) => {
|
||||
(generics.parent_count, generics.has_self)
|
||||
let mut infer_args_for_err = FxHashSet::default();
|
||||
for &PathSeg(def_id, index) in &path_segs {
|
||||
let seg = &segments[index];
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
// Argument-position `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_errors = AstConv::check_generic_arg_count_for_call(
|
||||
self.tcx,
|
||||
span,
|
||||
&generics,
|
||||
&seg,
|
||||
false, // `is_method_call`
|
||||
);
|
||||
if suppress_errors {
|
||||
infer_args_for_err.insert(index);
|
||||
self.set_tainted_by_errors(); // See issue #53251.
|
||||
}
|
||||
(Some((_, generics)), None) => {
|
||||
(generics.params.len(), generics.has_self)
|
||||
}
|
||||
(None, None) => (0, false)
|
||||
};
|
||||
// FIXME(varkor): Separating out the parameters is messy.
|
||||
let mut lifetimes_type_seg = vec![];
|
||||
let mut types_type_seg = vec![];
|
||||
let mut infer_types_type_seg = true;
|
||||
if let Some((seg, _)) = type_segment {
|
||||
if let Some(ref data) = seg.args {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt),
|
||||
GenericArg::Type(ty) => types_type_seg.push(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
infer_types_type_seg = seg.infer_types;
|
||||
}
|
||||
|
||||
let mut lifetimes_fn_seg = vec![];
|
||||
let mut types_fn_seg = vec![];
|
||||
let mut infer_types_fn_seg = true;
|
||||
if let Some((seg, _)) = fn_segment {
|
||||
if let Some(ref data) = seg.args {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt),
|
||||
GenericArg::Type(ty) => types_fn_seg.push(ty),
|
||||
let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
|
||||
self.tcx.generics_of(*def_id).has_self
|
||||
}).unwrap_or(false);
|
||||
|
||||
let def_id = def.def_id();
|
||||
|
||||
let substs = AstConv::create_substs_for_generic_args(
|
||||
self.tcx,
|
||||
def_id,
|
||||
&[][..],
|
||||
has_self,
|
||||
self_ty,
|
||||
// Provide the generic args, and whether types should be inferred.
|
||||
|def_id| {
|
||||
if let Some(&PathSeg(_, index)) = path_segs.iter().find(|&PathSeg(did, _)| {
|
||||
*did == def_id
|
||||
}) {
|
||||
// If we've encountered an `impl Trait`-related error, we're just
|
||||
// going to infer the arguments for better error messages.
|
||||
if !infer_args_for_err.contains(&index) {
|
||||
// Check whether the user has provided generic arguments.
|
||||
if let Some(ref data) = segments[index].args {
|
||||
return (Some(data), segments[index].infer_types);
|
||||
}
|
||||
}
|
||||
return (None, segments[index].infer_types);
|
||||
}
|
||||
}
|
||||
infer_types_fn_seg = seg.infer_types;
|
||||
}
|
||||
|
||||
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
|
||||
let mut i = param.index as usize;
|
||||
|
||||
let (segment, lifetimes, types, infer_types) = if i < fn_start {
|
||||
if let GenericParamDefKind::Type { .. } = param.kind {
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if has_self && i == 0 {
|
||||
return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
|
||||
self.var_for_def(span, param)
|
||||
});
|
||||
(None, true)
|
||||
},
|
||||
// Provide substitutions for parameters for which (valid) arguments have been provided.
|
||||
|param, arg| {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
|
||||
AstConv::ast_region_to_region(self, lt, Some(param)).into()
|
||||
}
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
|
||||
self.to_ty(ty).into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
i -= has_self as usize;
|
||||
(type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg)
|
||||
} else {
|
||||
i -= fn_start;
|
||||
(fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg)
|
||||
};
|
||||
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
if let Some(lifetime) = lifetimes.get(i) {
|
||||
AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
|
||||
} else {
|
||||
},
|
||||
// Provide substitutions for parameters for which arguments are inferred.
|
||||
|substs, param, infer_types| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
self.re_infer(span, Some(param)).unwrap().into()
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
// Skip over the lifetimes in the same segment.
|
||||
if let Some((_, generics)) = segment {
|
||||
i -= generics.own_counts().lifetimes;
|
||||
}
|
||||
|
||||
let has_default = match param.kind {
|
||||
GenericParamDefKind::Type { has_default, .. } => has_default,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if let Some(ast_ty) = types.get(i) {
|
||||
// A provided type parameter.
|
||||
self.to_ty(ast_ty).into()
|
||||
} else if !infer_types && has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
let default = self.tcx.type_of(param.def_id);
|
||||
self.normalize_ty(
|
||||
span,
|
||||
default.subst_spanned(self.tcx, substs, Some(span))
|
||||
).into()
|
||||
} else {
|
||||
// No type parameters were provided, we can infer all.
|
||||
// This can also be reached in some error cases:
|
||||
// We prefer to use inference variables instead of
|
||||
// TyError to let type inference recover somewhat.
|
||||
self.var_for_def(span, param)
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
if !infer_types && has_default {
|
||||
// If we have a default, then we it doesn't matter that we're not
|
||||
// inferring the type arguments: we provide the default where any
|
||||
// is missing.
|
||||
let default = self.tcx.type_of(param.def_id);
|
||||
self.normalize_ty(
|
||||
span,
|
||||
default.subst_spanned(self.tcx, substs.unwrap(), Some(span))
|
||||
).into()
|
||||
} else {
|
||||
// If no type arguments were provided, we have to infer them.
|
||||
// This case also occurs as a result of some malformed input, e.g.
|
||||
// a lifetime argument being given instead of a type paramter.
|
||||
// Using inference instead of `TyError` gives better error messages.
|
||||
self.var_for_def(span, param)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = self.tcx.type_of(def.def_id());
|
||||
let ty = self.tcx.type_of(def_id);
|
||||
assert!(!substs.has_escaping_regions());
|
||||
assert!(!ty.has_escaping_regions());
|
||||
|
||||
// Add all the obligations that are required, substituting and
|
||||
// normalized appropriately.
|
||||
let bounds = self.instantiate_bounds(span, def.def_id(), &substs);
|
||||
let bounds = self.instantiate_bounds(span, def_id, &substs);
|
||||
self.add_obligations_for_parameters(
|
||||
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())),
|
||||
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
|
||||
&bounds);
|
||||
|
||||
// Substitute the values for the type parameters into the type of
|
||||
@ -5049,7 +5064,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.check_rustc_args_require_const(def.def_id(), node_id, span);
|
||||
self.check_rustc_args_require_const(def_id, node_id, span);
|
||||
|
||||
debug!("instantiate_value_path: type of {:?} is {:?}",
|
||||
node_id,
|
||||
@ -5088,167 +5103,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
directly, not through a function pointer");
|
||||
}
|
||||
|
||||
/// Report errors if the provided parameters are too few or too many.
|
||||
fn check_generic_arg_count(&self,
|
||||
span: Span,
|
||||
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
|
||||
is_method_call: bool,
|
||||
supress_mismatch_error: bool) {
|
||||
let (lifetimes, types, infer_types, bindings) = segment.map_or(
|
||||
(vec![], vec![], true, &[][..]),
|
||||
|(s, _)| {
|
||||
s.args.as_ref().map_or(
|
||||
(vec![], vec![], s.infer_types, &[][..]),
|
||||
|data| {
|
||||
let (mut lifetimes, mut types) = (vec![], vec![]);
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes.push(lt),
|
||||
GenericArg::Type(ty) => types.push(ty),
|
||||
});
|
||||
(lifetimes, types, s.infer_types, &data.bindings[..])
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
// Check provided parameters.
|
||||
let ((ty_required, ty_accepted), lt_accepted) =
|
||||
segment.map_or(((0, 0), 0), |(_, generics)| {
|
||||
struct ParamRange {
|
||||
required: usize,
|
||||
accepted: usize
|
||||
};
|
||||
|
||||
let mut lt_accepted = 0;
|
||||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => lt_accepted += 1,
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
ty_params.accepted += 1;
|
||||
if !has_default {
|
||||
ty_params.required += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if generics.parent.is_none() && generics.has_self {
|
||||
ty_params.required -= 1;
|
||||
ty_params.accepted -= 1;
|
||||
}
|
||||
|
||||
((ty_params.required, ty_params.accepted), lt_accepted)
|
||||
});
|
||||
|
||||
let count_type_params = |n| {
|
||||
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
let expected_text = count_type_params(ty_accepted);
|
||||
let actual_text = count_type_params(types.len());
|
||||
if let Some((mut err, span)) = if types.len() > ty_accepted {
|
||||
// To prevent derived errors to accumulate due to extra
|
||||
// type parameters, we force instantiate_value_path to
|
||||
// use inference variables instead of the provided types.
|
||||
*segment = None;
|
||||
let span = types[ty_accepted].span;
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0087,
|
||||
"too many type parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
self.set_tainted_by_errors(); // #53251
|
||||
err.span_label(span, format!("expected {}", expected_text)).emit();
|
||||
}
|
||||
|
||||
if !bindings.is_empty() {
|
||||
AstConv::prohibit_projection(self, bindings[0].span);
|
||||
}
|
||||
|
||||
let infer_lifetimes = lifetimes.len() == 0;
|
||||
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
|
||||
let has_late_bound_lifetime_defs =
|
||||
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
|
||||
if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) {
|
||||
// Report this as a lint only if no error was reported previously.
|
||||
let primary_msg = "cannot specify lifetime arguments explicitly \
|
||||
if late bound lifetime parameters are present";
|
||||
let note_msg = "the late bound lifetime parameter is introduced here";
|
||||
if !is_method_call && (lifetimes.len() > lt_accepted ||
|
||||
lifetimes.len() < lt_accepted && !infer_lifetimes) {
|
||||
let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
|
||||
err.span_note(span_late, note_msg);
|
||||
err.emit();
|
||||
*segment = None;
|
||||
} else {
|
||||
let mut multispan = MultiSpan::from_span(lifetimes[0].span);
|
||||
multispan.push_span_label(span_late, note_msg.to_string());
|
||||
self.tcx.lint_node(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||
lifetimes[0].id, multispan, primary_msg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let count_lifetime_params = |n| {
|
||||
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
|
||||
let span = lifetimes[lt_accepted].span;
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
err.span_label(span, format!("expected {}", expected_text)).emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Report error if there is an explicit type parameter when using `impl Trait`.
|
||||
fn check_impl_trait(&self,
|
||||
span: Span,
|
||||
segment: Option<(&hir::PathSegment, &ty::Generics)>)
|
||||
-> bool {
|
||||
let segment = segment.map(|(path_segment, generics)| {
|
||||
let explicit = !path_segment.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
|
||||
});
|
||||
|
||||
segment.unwrap_or(false)
|
||||
}
|
||||
|
||||
// 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>() {}
|
||||
|
@ -2432,10 +2432,7 @@ impl Clean<Type> for hir::Ty {
|
||||
let mut ty_substs = FxHashMap();
|
||||
let mut lt_substs = FxHashMap();
|
||||
provided_params.with_generic_args(|generic_args| {
|
||||
let mut indices = ty::GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0
|
||||
};
|
||||
let mut indices: GenericParamCount = Default::default();
|
||||
for param in generics.params.iter() {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {
|
||||
|
@ -38,16 +38,16 @@ impl Trait<isize> for S2 {
|
||||
|
||||
fn foo<'a>() {
|
||||
let _ = S::new::<isize,f64>(1, 1.0);
|
||||
//~^ ERROR too many type parameters provided
|
||||
//~^ ERROR wrong number of type arguments
|
||||
|
||||
let _ = S::<'a,isize>::new::<f64>(1, 1.0);
|
||||
//~^ ERROR wrong number of lifetime parameters
|
||||
//~^ ERROR wrong number of lifetime arguments
|
||||
|
||||
let _: S2 = Trait::new::<isize,f64>(1, 1.0);
|
||||
//~^ ERROR too many type parameters provided
|
||||
//~^ ERROR wrong number of type arguments
|
||||
|
||||
let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
|
||||
//~^ ERROR too many lifetime parameters provided
|
||||
//~^ ERROR wrong number of lifetime arguments
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,26 +1,26 @@
|
||||
error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
|
||||
error[E0087]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/bad-mid-path-type-params.rs:40:28
|
||||
|
|
||||
LL | let _ = S::new::<isize,f64>(1, 1.0);
|
||||
| ^^^ expected 1 type parameter
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 0, found 1
|
||||
--> $DIR/bad-mid-path-type-params.rs:43:13
|
||||
error[E0107]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/bad-mid-path-type-params.rs:43:17
|
||||
|
|
||||
LL | let _ = S::<'a,isize>::new::<f64>(1, 1.0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unexpected lifetime parameter
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
|
||||
error[E0087]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/bad-mid-path-type-params.rs:46:36
|
||||
|
|
||||
LL | let _: S2 = Trait::new::<isize,f64>(1, 1.0);
|
||||
| ^^^ expected 1 type parameter
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 0 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0088]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/bad-mid-path-type-params.rs:49:25
|
||||
|
|
||||
LL | let _: S2 = Trait::<'a,isize>::new::<f64>(1, 1.0);
|
||||
| ^^ expected 0 lifetime parameters
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -25,12 +25,12 @@ enum E<'a, 'b> {
|
||||
fn main() {
|
||||
S(&0, &0); // OK
|
||||
S::<'static>(&0, &0);
|
||||
//~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
|
||||
S::<'static, 'static, 'static>(&0, &0);
|
||||
//~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
|
||||
E::V(&0); // OK
|
||||
E::V::<'static>(&0);
|
||||
//~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
|
||||
E::V::<'static, 'static, 'static>(&0);
|
||||
//~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0090]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/constructor-lifetime-args.rs:27:5
|
||||
|
|
||||
LL | S::<'static>(&0, &0);
|
||||
| ^^^^^^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
error[E0088]: wrong number of lifetime arguments: expected 2, found 3
|
||||
--> $DIR/constructor-lifetime-args.rs:29:27
|
||||
|
|
||||
LL | S::<'static, 'static, 'static>(&0, &0);
|
||||
| ^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0090]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/constructor-lifetime-args.rs:32:5
|
||||
|
|
||||
LL | E::V::<'static>(&0);
|
||||
| ^^^^^^^^^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^^^^^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
error[E0088]: wrong number of lifetime arguments: expected 2, found 3
|
||||
--> $DIR/constructor-lifetime-args.rs:34:30
|
||||
|
|
||||
LL | E::V::<'static, 'static, 'static>(&0);
|
||||
| ^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -12,7 +12,7 @@ fn foo() {}
|
||||
fn bar<T>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
|
||||
foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
|
||||
|
||||
bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
|
||||
bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
|
||||
error[E0087]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/E0087.rs:15:11
|
||||
|
|
||||
LL | foo::<f64>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter [E0087]
|
||||
| ^^^ expected 0 type parameters
|
||||
LL | foo::<f64>(); //~ ERROR wrong number of type arguments: expected 0, found 1 [E0087]
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
|
||||
error[E0087]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/E0087.rs:17:16
|
||||
|
|
||||
LL | bar::<f64, u64>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters [E0087]
|
||||
| ^^^ expected 1 type parameter
|
||||
LL | bar::<f64, u64>(); //~ ERROR wrong number of type arguments: expected 1, found 2 [E0087]
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 0 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0088]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/E0088.rs:15:9
|
||||
|
|
||||
LL | f::<'static>(); //~ ERROR E0088
|
||||
| ^^^^^^^ expected 0 lifetime parameters
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 1 lifetime parameter, found 2 lifetime parameters
|
||||
error[E0088]: wrong number of lifetime arguments: expected 1, found 2
|
||||
--> $DIR/E0088.rs:16:18
|
||||
|
|
||||
LL | g::<'static, 'static>(); //~ ERROR E0088
|
||||
| ^^^^^^^ expected 1 lifetime parameter
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -11,5 +11,5 @@
|
||||
fn foo<T, U>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
|
||||
foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0089]: too few type parameters provided: expected 2 type parameters, found 1 type parameter
|
||||
error[E0089]: wrong number of type arguments: expected 2, found 1
|
||||
--> $DIR/E0089.rs:14:5
|
||||
|
|
||||
LL | foo::<f64>(); //~ ERROR expected 2 type parameters, found 1 type parameter [E0089]
|
||||
| ^^^^^^^^^^ expected 2 type parameters
|
||||
LL | foo::<f64>(); //~ ERROR wrong number of type arguments: expected 2, found 1 [E0089]
|
||||
| ^^^^^^^^^^ expected 2 type arguments
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -11,5 +11,5 @@
|
||||
fn foo<'a: 'b, 'b: 'a>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090]
|
||||
foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0090]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/E0090.rs:14:5
|
||||
|
|
||||
LL | foo::<'static>(); //~ ERROR expected 2 lifetime parameters, found 1 lifetime parameter [E0090]
|
||||
| ^^^^^^^^^^^^^^ expected 2 lifetime parameters
|
||||
LL | foo::<'static>(); //~ ERROR wrong number of lifetime arguments: expected 2, found 1 [E0090]
|
||||
| ^^^^^^^^^^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -20,14 +20,13 @@ enum Bar {
|
||||
struct Baz<'a, 'b, 'c> {
|
||||
buzz: Buzz<'a>,
|
||||
//~^ ERROR E0107
|
||||
//~| expected 2 lifetime parameters
|
||||
//~| expected 2 lifetime arguments
|
||||
bar: Bar<'a>,
|
||||
//~^ ERROR E0107
|
||||
//~| unexpected lifetime parameter
|
||||
//~| unexpected lifetime argument
|
||||
foo2: Foo<'a, 'b, 'c>,
|
||||
//~^ ERROR E0107
|
||||
//~| 2 unexpected lifetime parameters
|
||||
//~| 2 unexpected lifetime arguments
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
@ -1,20 +1,20 @@
|
||||
error[E0107]: wrong number of lifetime parameters: expected 2, found 1
|
||||
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/E0107.rs:21:11
|
||||
|
|
||||
LL | buzz: Buzz<'a>,
|
||||
| ^^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 0, found 1
|
||||
--> $DIR/E0107.rs:24:10
|
||||
error[E0107]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/E0107.rs:24:14
|
||||
|
|
||||
LL | bar: Bar<'a>,
|
||||
| ^^^^^^^ unexpected lifetime parameter
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 1, found 3
|
||||
error[E0107]: wrong number of lifetime arguments: expected 1, found 3
|
||||
--> $DIR/E0107.rs:27:11
|
||||
|
|
||||
LL | foo2: Foo<'a, 'b, 'c>,
|
||||
| ^^^^^^^^^^^^^^^ 2 unexpected lifetime parameters
|
||||
| ^^^^^^^^^^^^^^^ 2 unexpected lifetime arguments
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected 0, found 2
|
||||
--> $DIR/E0244.rs:12:23
|
||||
|
|
||||
LL | struct Bar<S, T> { x: Foo<S, T> }
|
||||
| ^^^^^^^^^ expected no type arguments
|
||||
| ^^^^^^^^^ 2 unexpected type arguments
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
21
src/test/ui/generic/generic-arg-mismatch-recover.rs
Normal file
21
src/test/ui/generic/generic-arg-mismatch-recover.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
struct Foo<'a, T: 'a>(&'a T);
|
||||
|
||||
struct Bar<'a>(&'a ());
|
||||
|
||||
fn main() {
|
||||
Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
|
||||
//~^ ERROR wrong number of type arguments
|
||||
}
|
31
src/test/ui/generic/generic-arg-mismatch-recover.stderr
Normal file
31
src/test/ui/generic/generic-arg-mismatch-recover.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0088]: wrong number of lifetime arguments: expected 1, found 2
|
||||
--> $DIR/generic-arg-mismatch-recover.rs:16:20
|
||||
|
|
||||
LL | Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/generic-arg-mismatch-recover.rs:16:33
|
||||
|
|
||||
LL | Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
|
||||
| ^^ expected (), found integral variable
|
||||
|
|
||||
= note: expected type `&'static ()`
|
||||
found type `&{integer}`
|
||||
|
||||
error[E0088]: wrong number of lifetime arguments: expected 1, found 2
|
||||
--> $DIR/generic-arg-mismatch-recover.rs:19:20
|
||||
|
|
||||
LL | Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error[E0087]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/generic-arg-mismatch-recover.rs:19:29
|
||||
|
|
||||
LL | Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
|
||||
| ^^ unexpected type argument
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors occurred: E0087, E0088, E0308.
|
||||
For more information about an error, try `rustc --explain E0087`.
|
@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected at most 2, found 3
|
||||
--> $DIR/generic-impl-more-params-with-defaults.rs:23:5
|
||||
|
|
||||
LL | Vec::<isize, Heap, bool>::new();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0244]: wrong number of type arguments: expected at most 2, found 3
|
||||
--> $DIR/generic-type-more-params-with-defaults.rs:19:12
|
||||
|
|
||||
LL | let _: Vec<isize, Heap, bool>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type arguments
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected at most 2 type argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -19,10 +19,12 @@ macro_rules! impl_add {
|
||||
$(
|
||||
fn $n() {
|
||||
S::f::<i64>();
|
||||
//~^ ERROR too many type parameters provided
|
||||
//~^ ERROR wrong number of type arguments
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_add!(a b);
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,17 +1,12 @@
|
||||
error[E0601]: `main` function not found in crate `issue_53251`
|
||||
|
|
||||
= note: consider adding a `main` function to `$DIR/issue-53251.rs`
|
||||
|
||||
error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
|
||||
error[E0087]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/issue-53251.rs:21:24
|
||||
|
|
||||
LL | S::f::<i64>();
|
||||
| ^^^ expected 0 type parameters
|
||||
| ^^^ unexpected type argument
|
||||
...
|
||||
LL | impl_add!(a b);
|
||||
| --------------- in this macro invocation
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
Some errors occurred: E0087, E0601.
|
||||
For more information about an error, try `rustc --explain E0087`.
|
||||
For more information about this error, try `rustc --explain E0087`.
|
||||
|
@ -8,10 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that `Box` cannot be used with a lifetime parameter.
|
||||
// Test that `Box` cannot be used with a lifetime argument.
|
||||
|
||||
struct Foo<'a> {
|
||||
x: Box<'a, isize> //~ ERROR wrong number of lifetime parameters
|
||||
x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0107]: wrong number of lifetime parameters: expected 0, found 1
|
||||
--> $DIR/issue-18423.rs:14:8
|
||||
error[E0107]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/issue-18423.rs:14:12
|
||||
|
|
||||
LL | x: Box<'a, isize> //~ ERROR wrong number of lifetime parameters
|
||||
| ^^^^^^^^^^^^^^ unexpected lifetime parameter
|
||||
LL | x: Box<'a, isize> //~ ERROR wrong number of lifetime arguments
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -10,10 +10,10 @@ LL | x: T, //~ ERROR can't use type parameters from outer function
|
||||
| ^ use of type variable from outer function
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/issue-3214.rs:16:22
|
||||
--> $DIR/issue-3214.rs:16:26
|
||||
|
|
||||
LL | impl<T> Drop for foo<T> {
|
||||
| ^^^^^^ expected no type arguments
|
||||
| ^ unexpected type argument
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -24,9 +24,9 @@ impl S {
|
||||
fn method_call() {
|
||||
S.early(); // OK
|
||||
S.early::<'static>();
|
||||
//~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
|
||||
S.early::<'static, 'static, 'static>();
|
||||
//~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
|
||||
let _: &u8 = S.life_and_type::<'static>();
|
||||
S.life_and_type::<u8>();
|
||||
S.life_and_type::<'static, u8>();
|
||||
@ -71,9 +71,9 @@ fn ufcs() {
|
||||
|
||||
S::early(S); // OK
|
||||
S::early::<'static>(S);
|
||||
//~^ ERROR expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 1
|
||||
S::early::<'static, 'static, 'static>(S);
|
||||
//~^ ERROR expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 2, found 3
|
||||
let _: &u8 = S::life_and_type::<'static>(S);
|
||||
S::life_and_type::<u8>(S);
|
||||
S::life_and_type::<'static, u8>(S);
|
||||
|
@ -1,14 +1,14 @@
|
||||
error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0090]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/method-call-lifetime-args-fail.rs:26:7
|
||||
|
|
||||
LL | S.early::<'static>();
|
||||
| ^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
error[E0088]: wrong number of lifetime arguments: expected 2, found 3
|
||||
--> $DIR/method-call-lifetime-args-fail.rs:28:33
|
||||
|
|
||||
LL | S.early::<'static, 'static, 'static>();
|
||||
| ^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
|
||||
--> $DIR/method-call-lifetime-args-fail.rs:37:15
|
||||
@ -178,17 +178,17 @@ note: the late bound lifetime parameter is introduced here
|
||||
LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
|
||||
| ^^
|
||||
|
||||
error[E0090]: too few lifetime parameters provided: expected 2 lifetime parameters, found 1 lifetime parameter
|
||||
error[E0090]: wrong number of lifetime arguments: expected 2, found 1
|
||||
--> $DIR/method-call-lifetime-args-fail.rs:73:5
|
||||
|
|
||||
LL | S::early::<'static>(S);
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
|
||||
|
||||
error[E0088]: too many lifetime parameters provided: expected at most 2 lifetime parameters, found 3 lifetime parameters
|
||||
error[E0088]: wrong number of lifetime arguments: expected 2, found 3
|
||||
--> $DIR/method-call-lifetime-args-fail.rs:75:34
|
||||
|
|
||||
LL | S::early::<'static, 'static, 'static>(S);
|
||||
| ^^^^^^^ expected 2 lifetime parameters
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/seq-args.rs:14:9
|
||||
--> $DIR/seq-args.rs:14:13
|
||||
|
|
||||
LL | impl<T> seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
|
||||
| ^^^^^^ expected no type arguments
|
||||
| ^ unexpected type argument
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/seq-args.rs:17:6
|
||||
--> $DIR/seq-args.rs:17:10
|
||||
|
|
||||
LL | impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
|
||||
| ^^^^^^^^^ expected no type arguments
|
||||
| ^^^^ unexpected type argument
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -71,10 +71,10 @@ LL | x: 7,
|
||||
found type `{integer}`
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:58:15
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:58:24
|
||||
|
|
||||
LL | let pt3 = PointF::<i32> { //~ ERROR wrong number of type arguments
|
||||
| ^^^^^^^^^^^^^ expected no type arguments
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:59:12
|
||||
@ -101,10 +101,10 @@ LL | y: 10, //~ ERROR mismatched types
|
||||
found type `{integer}`
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:64:9
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:64:18
|
||||
|
|
||||
LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
|
||||
| ^^^^^^^^^^^^^ expected no type arguments
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/structure-constructor-type-mismatch.rs:64:9
|
||||
|
@ -21,7 +21,7 @@ fn main() {
|
||||
let _: S<'static, 'static +>;
|
||||
//~^ at least one non-builtin trait is required for an object type
|
||||
let _: S<'static, 'static>;
|
||||
//~^ ERROR wrong number of lifetime parameters: expected 1, found 2
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 1, found 2
|
||||
//~| ERROR wrong number of type arguments: expected 1, found 0
|
||||
let _: S<'static +, 'static>;
|
||||
//~^ ERROR lifetime parameters must be declared prior to type parameters
|
||||
|
@ -10,11 +10,11 @@ error[E0224]: at least one non-builtin trait is required for an object type
|
||||
LL | let _: S<'static, 'static +>;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 1, found 2
|
||||
--> $DIR/trait-object-vs-lifetime.rs:23:12
|
||||
error[E0107]: wrong number of lifetime arguments: expected 1, found 2
|
||||
--> $DIR/trait-object-vs-lifetime.rs:23:23
|
||||
|
|
||||
LL | let _: S<'static, 'static>;
|
||||
| ^^^^^^^^^^^^^^^^^^^ unexpected lifetime parameter
|
||||
| ^^^^^^^ unexpected lifetime argument
|
||||
|
||||
error[E0243]: wrong number of type arguments: expected 1, found 0
|
||||
--> $DIR/trait-object-vs-lifetime.rs:23:12
|
||||
|
@ -15,8 +15,8 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
|
||||
impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
|
||||
|
||||
fn main() {
|
||||
10.dup::<i32>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter
|
||||
10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
|
||||
10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
|
||||
10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
|
||||
(box 10 as Box<bar>).dup();
|
||||
//~^ ERROR E0038
|
||||
//~| ERROR E0038
|
||||
|
@ -1,14 +1,14 @@
|
||||
error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 1 type parameter
|
||||
error[E0087]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/trait-test-2.rs:18:14
|
||||
|
|
||||
LL | 10.dup::<i32>(); //~ ERROR expected at most 0 type parameters, found 1 type parameter
|
||||
| ^^^ expected 0 type parameters
|
||||
LL | 10.dup::<i32>(); //~ ERROR wrong number of type arguments: expected 0, found 1
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0087]: too many type parameters provided: expected at most 1 type parameter, found 2 type parameters
|
||||
error[E0087]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/trait-test-2.rs:19:20
|
||||
|
|
||||
LL | 10.blah::<i32, i32>(); //~ ERROR expected at most 1 type parameter, found 2 type parameters
|
||||
| ^^^ expected 1 type parameter
|
||||
LL | 10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
|
||||
| ^^^ unexpected type argument
|
||||
|
||||
error[E0277]: the trait bound `dyn bar: bar` is not satisfied
|
||||
--> $DIR/trait-test-2.rs:20:26
|
||||
|
@ -18,12 +18,12 @@ struct MyStruct1<T: Copy<T>>;
|
||||
//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
|
||||
|
||||
struct MyStruct2<'a, T: Copy<'a>>;
|
||||
//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1
|
||||
//~^ ERROR: wrong number of lifetime arguments: expected 0, found 1
|
||||
|
||||
|
||||
fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
|
||||
//~^ ERROR wrong number of type arguments: expected 0, found 1 [E0244]
|
||||
//~| ERROR: wrong number of lifetime parameters: expected 0, found 1
|
||||
//~| ERROR: wrong number of lifetime arguments: expected 0, found 1
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
@ -1,38 +1,38 @@
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:11:11
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:11:16
|
||||
|
|
||||
LL | fn foo1<T:Copy<U>, U>(x: T) {}
|
||||
| ^^^^^^^ expected no type arguments
|
||||
| ^ unexpected type argument
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:14:14
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:14:19
|
||||
|
|
||||
LL | trait Trait: Copy<Send> {}
|
||||
| ^^^^^^^^^^ expected no type arguments
|
||||
| ^^^^ unexpected type argument
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:17:21
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:17:26
|
||||
|
|
||||
LL | struct MyStruct1<T: Copy<T>>;
|
||||
| ^^^^^^^ expected no type arguments
|
||||
| ^ unexpected type argument
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:20:25
|
||||
error[E0107]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:20:30
|
||||
|
|
||||
LL | struct MyStruct2<'a, T: Copy<'a>>;
|
||||
| ^^^^^^^^ unexpected lifetime parameter
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error[E0107]: wrong number of lifetime parameters: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:24:15
|
||||
error[E0107]: wrong number of lifetime arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:24:20
|
||||
|
|
||||
LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
|
||||
| ^^^^^^^^^^^ unexpected lifetime parameter
|
||||
| ^^ unexpected lifetime argument
|
||||
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:24:15
|
||||
--> $DIR/typeck-builtin-bound-type-parameters.rs:24:24
|
||||
|
|
||||
LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
|
||||
| ^^^^^^^^^^^ expected no type arguments
|
||||
| ^ unexpected type argument
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0244]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/typeck_type_placeholder_lifetime_1.rs:19:12
|
||||
--> $DIR/typeck_type_placeholder_lifetime_1.rs:19:19
|
||||
|
|
||||
LL | let c: Foo<_, _> = Foo { r: &5 };
|
||||
| ^^^^^^^^^ expected 1 type argument
|
||||
| ^ unexpected type argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0244]: wrong number of type arguments: expected 1, found 2
|
||||
--> $DIR/typeck_type_placeholder_lifetime_2.rs:19:12
|
||||
--> $DIR/typeck_type_placeholder_lifetime_2.rs:19:19
|
||||
|
|
||||
LL | let c: Foo<_, usize> = Foo { r: &5 };
|
||||
| ^^^^^^^^^^^^^ expected 1 type argument
|
||||
| ^^^^^ unexpected type argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -22,5 +22,5 @@ impl<'a> IntoCow<'a, str> for String {
|
||||
|
||||
fn main() {
|
||||
<String as IntoCow>::into_cow("foo".to_string());
|
||||
//~^ ERROR too few type parameters provided: expected 1 type parameter
|
||||
//~^ ERROR wrong number of type arguments: expected 1, found 0
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0089]: too few type parameters provided: expected 1 type parameter, found 0 type parameters
|
||||
error[E0089]: wrong number of type arguments: expected 1, found 0
|
||||
--> $DIR/ufcs-qpath-missing-params.rs:24:5
|
||||
|
|
||||
LL | <String as IntoCow>::into_cow("foo".to_string());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type parameter
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -38,7 +38,7 @@ fn test<'a,'b>() {
|
||||
}
|
||||
|
||||
fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
|
||||
//~^ ERROR wrong number of lifetime parameters: expected 1, found 0
|
||||
//~^ ERROR wrong number of lifetime arguments: expected 1, found 0
|
||||
// Here, the omitted lifetimes are expanded to distinct things.
|
||||
same_type(x, y)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0107]: wrong number of lifetime parameters: expected 1, found 0
|
||||
error[E0107]: wrong number of lifetime arguments: expected 1, found 0
|
||||
--> $DIR/unboxed-closure-sugar-region.rs:40:43
|
||||
|
|
||||
LL | fn test2(x: &Foo<(isize,),Output=()>, y: &Foo(isize)) {
|
||||
| ^^^^^^^^^^ expected 1 lifetime parameter
|
||||
| ^^^^^^^^^^ expected 1 lifetime argument
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:11
|
||||
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:15
|
||||
|
|
||||
LL | fn foo(_: Zero())
|
||||
| ^^^^^^ expected no type arguments
|
||||
| ^^ unexpected type argument
|
||||
|
||||
error[E0220]: associated type `Output` not found for `Zero`
|
||||
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:15:15
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0244]: wrong number of type arguments: expected 0, found 1
|
||||
--> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:8
|
||||
--> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:13
|
||||
|
|
||||
LL | fn f<F:Trait(isize) -> isize>(x: F) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected no type arguments
|
||||
| ^^^^^^^^^^^^^^^^ unexpected type argument
|
||||
|
||||
error[E0220]: associated type `Output` not found for `Trait`
|
||||
--> $DIR/unboxed-closure-sugar-wrong-trait.rs:15:24
|
||||
|
Loading…
Reference in New Issue
Block a user