Skip to content

Commit b83352e

Browse files
committed
Introduce TyErr independent from TyInfer
Add a `TyErr` type to represent unknown types in places where parse errors have happened, while still able to build the AST. Initially only used to represent incorrectly written fn arguments and avoid "expected X parameters, found Y" errors when called with the appropriate amount of parameters. We cannot use `TyInfer` for this as `_` is not allowed as a valid argument type. Example output: ```rust error: expected one of `:` or `@`, found `,` --> file.rs:12:9 | 12 | fn bar(x, y: usize) {} | ^ error[E0061]: this function takes 2 parameters but 3 parameters were supplied --> file.rs:19:9 | 12 | fn bar(x, y) {} | --------------- defined here ... 19 | bar(1, 2, 3); | ^^^^^^^ expected 2 parameters ```
1 parent 5e122f5 commit b83352e

File tree

14 files changed

+115
-7
lines changed

14 files changed

+115
-7
lines changed

src/librustc/hir/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
578578
TyTypeof(expression) => {
579579
visitor.visit_nested_body(expression)
580580
}
581-
TyInfer => {}
581+
TyInfer | TyErr => {}
582582
}
583583
}
584584

src/librustc/hir/lowering.rs

+1
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ impl<'a> LoweringContext<'a> {
555555
fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
556556
let kind = match t.node {
557557
TyKind::Infer => hir::TyInfer,
558+
TyKind::Err => hir::TyErr,
558559
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
559560
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
560561
TyKind::Rptr(ref region, ref mt) => {

src/librustc/hir/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,8 @@ pub enum Ty_ {
13511351
/// TyInfer means the type should be inferred instead of it having been
13521352
/// specified. This can appear anywhere in a type.
13531353
TyInfer,
1354+
/// Placeholder for a type that has failed to be defined.
1355+
TyErr,
13541356
}
13551357

13561358
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]

src/librustc/hir/print.rs

+3
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ impl<'a> State<'a> {
450450
hir::TyInfer => {
451451
word(&mut self.s, "_")?;
452452
}
453+
hir::TyErr => {
454+
word(&mut self.s, "?")?;
455+
}
453456
}
454457
self.end()
455458
}

src/librustc_incremental/calculate_svh/svh_visitor.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,8 @@ enum SawTyComponent {
432432
SawTyObjectSum,
433433
SawTyImplTrait,
434434
SawTyTypeof,
435-
SawTyInfer
435+
SawTyInfer,
436+
SawTyErr,
436437
}
437438

438439
fn saw_ty(node: &Ty_) -> SawTyComponent {
@@ -448,7 +449,8 @@ fn saw_ty(node: &Ty_) -> SawTyComponent {
448449
TyTraitObject(..) => SawTyObjectSum,
449450
TyImplTrait(..) => SawTyImplTrait,
450451
TyTypeof(..) => SawTyTypeof,
451-
TyInfer => SawTyInfer
452+
TyInfer => SawTyInfer,
453+
TyErr => SawTyErr,
452454
}
453455
}
454456

src/librustc_typeck/astconv.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
12291229
// handled specially and will not descend into this routine.
12301230
self.ty_infer(ast_ty.span)
12311231
}
1232+
hir::TyErr => {
1233+
tcx.types.err
1234+
}
12321235
};
12331236

12341237
cache.borrow_mut().insert(ast_ty.id, result_ty);

src/librustdoc/clean/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,7 @@ impl Clean<Type> for hir::Ty {
18051805
}
18061806
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
18071807
TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
1808-
TyInfer => Infer,
1808+
TyInfer | TyErr => Infer,
18091809
TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
18101810
}
18111811
}

src/libsyntax/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,8 @@ pub enum TyKind {
13611361
ImplicitSelf,
13621362
// A macro in the type position.
13631363
Mac(Mac),
1364+
/// Placeholder for a kind that has failed to be defined.
1365+
Err,
13641366
}
13651367

13661368
/// Inline assembly dialect.

src/libsyntax/fold.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
358358
t.map(|Ty {id, node, span}| Ty {
359359
id: fld.new_id(id),
360360
node: match node {
361-
TyKind::Infer | TyKind::ImplicitSelf => node,
361+
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => node,
362362
TyKind::Slice(ty) => TyKind::Slice(fld.fold_ty(ty)),
363363
TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)),
364364
TyKind::Rptr(region, mt) => {

src/libsyntax/parse/parser.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,25 @@ impl From<P<Expr>> for LhsExpr {
407407
}
408408
}
409409

410+
/// Create a placeholder argument.
411+
fn dummy_arg(span: Span) -> Arg {
412+
let spanned = Spanned {
413+
span: span,
414+
node: keywords::Invalid.ident()
415+
};
416+
let pat = P(Pat {
417+
id: ast::DUMMY_NODE_ID,
418+
node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None),
419+
span: span
420+
});
421+
let ty = Ty {
422+
node: TyKind::Err,
423+
span: span,
424+
id: ast::DUMMY_NODE_ID
425+
};
426+
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
427+
}
428+
410429
impl<'a> Parser<'a> {
411430
pub fn new(sess: &'a ParseSess,
412431
tokens: TokenStream,
@@ -4343,8 +4362,12 @@ impl<'a> Parser<'a> {
43434362
Ok(arg) => Ok(Some(arg)),
43444363
Err(mut e) => {
43454364
e.emit();
4365+
let lo = p.prev_span;
4366+
// Skip every token until next possible arg or end.
43464367
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
4347-
Ok(None)
4368+
// Create a placeholder argument for proper arg count (#34264).
4369+
let span = lo.to(p.prev_span);
4370+
Ok(Some(dummy_arg(span)))
43484371
}
43494372
}
43504373
}

src/libsyntax/print/pprust.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,9 @@ impl<'a> State<'a> {
10951095
ast::TyKind::Infer => {
10961096
word(&mut self.s, "_")?;
10971097
}
1098+
ast::TyKind::Err => {
1099+
word(&mut self.s, "?")?;
1100+
}
10981101
ast::TyKind::ImplicitSelf => {
10991102
word(&mut self.s, "Self")?;
11001103
}

src/libsyntax/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
350350
TyKind::Typeof(ref expression) => {
351351
visitor.visit_expr(expression)
352352
}
353-
TyKind::Infer | TyKind::ImplicitSelf => {}
353+
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
354354
TyKind::Mac(ref mac) => {
355355
visitor.visit_mac(mac)
356356
}

src/test/ui/span/issue-34264.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 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+
fn foo(Option<i32>, String) {}
12+
fn bar(x, y: usize) {}
13+
14+
fn main() {
15+
foo(Some(42), 2);
16+
foo(Some(42), 2, "");
17+
bar("", "");
18+
bar(1, 2);
19+
bar(1, 2, 3);
20+
}

src/test/ui/span/issue-34264.stderr

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error: expected one of `:` or `@`, found `<`
2+
--> $DIR/issue-34264.rs:11:14
3+
|
4+
11 | fn foo(Option<i32>, String) {}
5+
| ^
6+
7+
error: expected one of `:` or `@`, found `)`
8+
--> $DIR/issue-34264.rs:11:27
9+
|
10+
11 | fn foo(Option<i32>, String) {}
11+
| ^
12+
13+
error: expected one of `:` or `@`, found `,`
14+
--> $DIR/issue-34264.rs:12:9
15+
|
16+
12 | fn bar(x, y: usize) {}
17+
| ^
18+
19+
error[E0061]: this function takes 2 parameters but 3 parameters were supplied
20+
--> $DIR/issue-34264.rs:16:9
21+
|
22+
11 | fn foo(Option<i32>, String) {}
23+
| ------------------------------ defined here
24+
...
25+
16 | foo(Some(42), 2, "");
26+
| ^^^^^^^^^^^^^^^ expected 2 parameters
27+
28+
error[E0308]: mismatched types
29+
--> $DIR/issue-34264.rs:17:13
30+
|
31+
17 | bar("", "");
32+
| ^^ expected usize, found reference
33+
|
34+
= note: expected type `usize`
35+
found type `&'static str`
36+
= help: here are some functions which might fulfill your needs:
37+
- .len()
38+
39+
error[E0061]: this function takes 2 parameters but 3 parameters were supplied
40+
--> $DIR/issue-34264.rs:19:9
41+
|
42+
12 | fn bar(x, y: usize) {}
43+
| ---------------------- defined here
44+
...
45+
19 | bar(1, 2, 3);
46+
| ^^^^^^^ expected 2 parameters
47+
48+
error: aborting due to 3 previous errors
49+

0 commit comments

Comments
 (0)