Skip to content

Commit d25c8d5

Browse files
committed
Suggest setting associated type when type argument is given instead
When finding too many type arguments and too few associated types, suggest using associated types in the appropriate place instead.
1 parent 1670a53 commit d25c8d5

File tree

3 files changed

+108
-44
lines changed

3 files changed

+108
-44
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
200200
{
201201
let tcx = self.tcx();
202202

203-
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
204-
parameters={:?})",
203+
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, parameters={:?})",
205204
def_id, self_ty, parameters);
206205

207206
// If the type is parameterized by this region, then replace this
@@ -221,10 +220,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
221220
assert_eq!(decl_generics.has_self, self_ty.is_some());
222221

223222
// Check the number of type parameters supplied by the user.
224-
let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
225-
if !infer_types || num_types_provided > ty_param_defs.len() {
226-
check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
227-
}
223+
check_type_argument_count(tcx,
224+
def_id,
225+
span,
226+
infer_types,
227+
self_ty.is_some(),
228+
&parameters,
229+
&decl_generics);
228230

229231
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
230232
let default_needs_object_self = |p: &ty::TypeParameterDef| {
@@ -599,7 +601,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
599601
if !trait_bounds.is_empty() {
600602
let b = &trait_bounds[0];
601603
let span = b.trait_ref.path.span;
602-
struct_span_err!(self.tcx().sess, span, E0225,
604+
struct_span_err!(tcx.sess, span, E0225,
603605
"only auto traits can be used as additional traits in a trait object")
604606
.span_label(span, "non-auto additional trait")
605607
.emit();
@@ -1303,45 +1305,68 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
13031305
(auto_traits, trait_bounds)
13041306
}
13051307

1306-
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
1307-
ty_param_defs: &[ty::TypeParameterDef]) {
1308+
fn check_type_argument_count(tcx: TyCtxt,
1309+
_def_id: DefId,
1310+
span: Span,
1311+
infer_types: bool,
1312+
has_self_ty: bool,
1313+
parameters: &hir::PathParameters,
1314+
generics: &ty::Generics) {
1315+
let supplied = parameters.types.len();
1316+
let ty_param_defs = &generics.types[has_self_ty as usize..];
13081317
let accepted = ty_param_defs.len();
13091318
let required = ty_param_defs.iter().take_while(|x| !x.has_default).count();
1310-
if supplied < required {
1311-
let expected = if required < accepted {
1312-
"expected at least"
1313-
} else {
1314-
"expected"
1315-
};
1316-
let arguments_plural = if required == 1 { "" } else { "s" };
1317-
1318-
struct_span_err!(tcx.sess, span, E0243,
1319-
"wrong number of type arguments: {} {}, found {}",
1320-
expected, required, supplied)
1321-
.span_label(span,
1322-
format!("{} {} type argument{}",
1323-
expected,
1324-
required,
1325-
arguments_plural))
1326-
.emit();
1327-
} else if supplied > accepted {
1328-
let expected = if required < accepted {
1329-
format!("expected at most {}", accepted)
1330-
} else {
1331-
format!("expected {}", accepted)
1332-
};
1333-
let arguments_plural = if accepted == 1 { "" } else { "s" };
1334-
1335-
struct_span_err!(tcx.sess, span, E0244,
1336-
"wrong number of type arguments: {}, found {}",
1337-
expected, supplied)
1338-
.span_label(
1339-
span,
1340-
format!("{} type argument{}",
1341-
if accepted == 0 { "expected no" } else { &expected },
1342-
arguments_plural)
1343-
)
1344-
.emit();
1319+
//let total_expected = parameters.types.len() + parameters.bindings.len();
1320+
//let total_found = generics.types.len();// + tcx.associated_items(def_id)
1321+
// .filter(|item| item.kind == ty::AssociatedKind::Type)
1322+
// .count();
1323+
if !infer_types || supplied > accepted {
1324+
if supplied < required {
1325+
let expected = if required < accepted {
1326+
"expected at least"
1327+
} else {
1328+
"expected"
1329+
};
1330+
let arguments_plural = if required == 1 { "" } else { "s" };
1331+
1332+
let mut err = struct_span_err!(tcx.sess, span, E0243,
1333+
"wrong number of type arguments: {} {}, found {}",
1334+
expected, required, supplied);
1335+
err.span_label(span, format!("{} {} type argument{}",
1336+
expected,
1337+
required,
1338+
arguments_plural));
1339+
err.emit();
1340+
} else if supplied > accepted {
1341+
let expected = if required < accepted {
1342+
format!("expected at most {}", accepted)
1343+
} else {
1344+
format!("expected {}", accepted)
1345+
};
1346+
let arguments_plural = if accepted == 1 { "" } else { "s" };
1347+
1348+
let mut err = struct_span_err!(tcx.sess, span, E0244,
1349+
"wrong number of type arguments: {}, found {}",
1350+
expected, supplied);
1351+
err.span_label(
1352+
span,
1353+
format!("{} type argument{}",
1354+
if accepted == 0 { "expected no" } else { &expected },
1355+
arguments_plural)
1356+
);
1357+
for generic in &parameters.types[accepted..] {
1358+
if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(generic.span) {
1359+
err.span_suggestion(generic.span,
1360+
"if you meant to set an associated type, include the name",
1361+
format!("AssociatedType={}", snippet));
1362+
} else {
1363+
err.help("if you meant to set an associated type, include the name: \
1364+
`Trait<AssociatedType=Type>`, not `Trait<Type>`");
1365+
break;
1366+
}
1367+
}
1368+
err.emit();
1369+
}
13451370
}
13461371
}
13471372

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub trait T<X> {
12+
type Item;
13+
type OtherItem;
14+
}
15+
16+
pub struct Foo { i: Box<T<usize, usize, OtherItem=usize>> }
17+
//~^ ERROR wrong number of type arguments: expected 1, found 2
18+
//~| ERROR the value of the associated type `Item` (from the trait `T`) must be specified
19+
20+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0244]: wrong number of type arguments: expected 1, found 2
2+
--> $DIR/type-argument-instead-of-item.rs:16:25
3+
|
4+
16 | pub struct Foo { i: Box<T<usize, usize, OtherItem=usize>> }
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
6+
|
7+
help: if you meant to set an associated type, include the name
8+
|
9+
16 | pub struct Foo { i: Box<T<usize, AssociatedType="usize", OtherItem=usize>> }
10+
| ^^^^^^^^^^^^^^^^^^^^^^
11+
12+
error[E0191]: the value of the associated type `Item` (from the trait `T`) must be specified
13+
--> $DIR/type-argument-instead-of-item.rs:16:25
14+
|
15+
16 | pub struct Foo { i: Box<T<usize, usize, OtherItem=usize>> }
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing associated type `Item` value
17+
18+
error: aborting due to 2 previous errors
19+

0 commit comments

Comments
 (0)