Skip to content

Commit 66c8c5a

Browse files
Delay function resolution error until typeck
1 parent d4846f9 commit 66c8c5a

35 files changed

+383
-356
lines changed

compiler/rustc_errors/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ pub enum StashKey {
460460
ItemNoType,
461461
UnderscoreForArrayLengths,
462462
EarlySyntaxWarning,
463+
CallIntoMethod,
463464
}
464465

465466
fn default_track_diagnostic(_: &Diagnostic) {}

compiler/rustc_hir_analysis/src/check/callee.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::method::MethodCallee;
22
use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
33
use crate::type_error_struct;
44

5-
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
5+
use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey};
66
use rustc_hir as hir;
77
use rustc_hir::def::{self, Namespace, Res};
88
use rustc_hir::def_id::DefId;
@@ -60,6 +60,7 @@ pub fn check_legal_trait_for_method_call(
6060
}
6161
}
6262

63+
#[derive(Debug)]
6364
enum CallStep<'tcx> {
6465
Builtin(Ty<'tcx>),
6566
DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
@@ -188,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
188189
return None;
189190
}
190191

192+
ty::Error(_) => {
193+
return None;
194+
}
195+
191196
_ => {}
192197
}
193198

@@ -394,6 +399,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394399
}
395400
ty::FnPtr(sig) => (sig, None),
396401
_ => {
402+
if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
403+
&& let [segment] = path.segments
404+
&& let Some(mut diag) = self
405+
.tcx
406+
.sess
407+
.diagnostic()
408+
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
409+
{
410+
diag.emit();
411+
}
412+
397413
self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
398414

399415
// This is the "default" function signature, used in case of error.

compiler/rustc_resolve/src/diagnostics.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,15 @@ impl<'a> Resolver<'a> {
120120
}
121121

122122
fn report_with_use_injections(&mut self, krate: &Crate) {
123-
for UseError { mut err, candidates, def_id, instead, suggestion, path } in
123+
for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
124124
self.use_injections.drain(..)
125125
{
126126
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
127127
UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id])
128128
} else {
129129
(None, FoundUse::No)
130130
};
131+
131132
if !candidates.is_empty() {
132133
show_candidates(
133134
&self.session,
@@ -140,10 +141,15 @@ impl<'a> Resolver<'a> {
140141
IsPattern::No,
141142
path,
142143
);
144+
err.emit();
143145
} else if let Some((span, msg, sugg, appl)) = suggestion {
144146
err.span_suggestion(span, msg, sugg, appl);
147+
err.emit();
148+
} else if let [segment] = path.as_slice() && is_call {
149+
err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
150+
} else {
151+
err.emit();
145152
}
146-
err.emit();
147153
}
148154
}
149155

compiler/rustc_resolve/src/late.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3263,6 +3263,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
32633263
instead,
32643264
suggestion,
32653265
path: path.into(),
3266+
is_call: source.is_call(),
32663267
});
32673268
}
32683269

@@ -3327,6 +3328,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33273328
instead: false,
33283329
suggestion: None,
33293330
path: path.into(),
3331+
is_call: source.is_call(),
33303332
});
33313333
} else {
33323334
err.cancel();

compiler/rustc_resolve/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ struct UseError<'a> {
674674
/// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling
675675
/// the user to import the item directly.
676676
path: Vec<Segment>,
677+
/// Whether the expected source is a call
678+
is_call: bool,
677679
}
678680

679681
#[derive(Clone, Copy, PartialEq, Debug)]

src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
error[E0423]: expected function, tuple struct or tuple variant, found enum `Option`
2-
--> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
3-
|
4-
LL | let x = Option(1);
5-
| ^^^^^^ help: try to construct one of the enum's variants: `std::option::Option::Some`
6-
|
7-
= help: you might have meant to construct the enum's non-tuple variant
8-
91
error[E0532]: expected tuple struct or tuple variant, found enum `Option`
102
--> $DIR/issue-43871-enum-instead-of-variant.rs:21:12
113
|
@@ -27,6 +19,14 @@ note: the enum is defined here
2719
LL | enum Example { Ex(String), NotEx }
2820
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2921

22+
error[E0423]: expected function, tuple struct or tuple variant, found enum `Option`
23+
--> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
24+
|
25+
LL | let x = Option(1);
26+
| ^^^^^^ help: try to construct one of the enum's variants: `std::option::Option::Some`
27+
|
28+
= help: you might have meant to construct the enum's non-tuple variant
29+
3030
error[E0423]: expected function, tuple struct or tuple variant, found enum `Void`
3131
--> $DIR/issue-43871-enum-instead-of-variant.rs:31:13
3232
|

src/test/ui/empty/empty-struct-braces-expr.stderr

+23-23
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,6 @@ help: a unit struct with a similar name exists
2121
LL | let e1 = XEmpty2;
2222
| ~~~~~~~
2323

24-
error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
25-
--> $DIR/empty-struct-braces-expr.rs:16:14
26-
|
27-
LL | struct Empty1 {}
28-
| ---------------- `Empty1` defined here
29-
...
30-
LL | let e1 = Empty1();
31-
| ^^^^^^^^
32-
|
33-
::: $DIR/auxiliary/empty-struct.rs:2:1
34-
|
35-
LL | pub struct XEmpty2;
36-
| ------------------ similarly named unit struct `XEmpty2` defined here
37-
|
38-
help: use struct literal syntax instead
39-
|
40-
LL | let e1 = Empty1 {};
41-
| ~~~~~~~~~
42-
help: a unit struct with a similar name exists
43-
|
44-
LL | let e1 = XEmpty2();
45-
| ~~~~~~~
46-
4724
error[E0423]: expected value, found struct variant `E::Empty3`
4825
--> $DIR/empty-struct-braces-expr.rs:18:14
4926
|
@@ -84,6 +61,29 @@ help: a unit struct with a similar name exists
8461
LL | let xe1 = XEmpty2;
8562
| ~~~~~~~
8663

64+
error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
65+
--> $DIR/empty-struct-braces-expr.rs:16:14
66+
|
67+
LL | struct Empty1 {}
68+
| ---------------- `Empty1` defined here
69+
...
70+
LL | let e1 = Empty1();
71+
| ^^^^^^^^
72+
|
73+
::: $DIR/auxiliary/empty-struct.rs:2:1
74+
|
75+
LL | pub struct XEmpty2;
76+
| ------------------ similarly named unit struct `XEmpty2` defined here
77+
|
78+
help: use struct literal syntax instead
79+
|
80+
LL | let e1 = Empty1 {};
81+
| ~~~~~~~~~
82+
help: a unit struct with a similar name exists
83+
|
84+
LL | let e1 = XEmpty2();
85+
| ~~~~~~~
86+
8787
error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
8888
--> $DIR/empty-struct-braces-expr.rs:23:15
8989
|

src/test/ui/error-codes/E0423.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ help: surround the struct literal with parentheses
2626
LL | for _ in (std::ops::Range { start: 0, end: 10 }) {}
2727
| + +
2828

29+
error[E0423]: expected value, found struct `T`
30+
--> $DIR/E0423.rs:14:8
31+
|
32+
LL | if T {} == T {} { println!("Ok"); }
33+
| ^ not a value
34+
|
35+
help: surround the struct literal with parentheses
36+
|
37+
LL | if (T {}) == T {} { println!("Ok"); }
38+
| + +
39+
2940
error[E0423]: expected function, tuple struct or tuple variant, found struct `Foo`
3041
--> $DIR/E0423.rs:4:13
3142
|
@@ -47,17 +58,6 @@ help: a function with a similar name exists
4758
LL | let f = foo();
4859
| ~~~
4960

50-
error[E0423]: expected value, found struct `T`
51-
--> $DIR/E0423.rs:14:8
52-
|
53-
LL | if T {} == T {} { println!("Ok"); }
54-
| ^ not a value
55-
|
56-
help: surround the struct literal with parentheses
57-
|
58-
LL | if (T {}) == T {} { println!("Ok"); }
59-
| + +
60-
6161
error: aborting due to 5 previous errors
6262

6363
For more information about this error, try `rustc --explain E0423`.

src/test/ui/issues/issue-58022.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
2-
--> $DIR/issue-58022.rs:14:9
3-
|
4-
LL | Foo(Box::new(*slice))
5-
| ^^^ not a function, tuple struct or tuple variant
6-
71
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
82
--> $DIR/issue-58022.rs:4:25
93
|
@@ -13,6 +7,12 @@ LL |
137
LL | fn new(slice: &[u8; Foo::SIZE]) -> Self;
148
| ^^^^^^^^^ cannot refer to the associated constant of trait
159

10+
error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
11+
--> $DIR/issue-58022.rs:14:9
12+
|
13+
LL | Foo(Box::new(*slice))
14+
| ^^^ not a function, tuple struct or tuple variant
15+
1616
error: aborting due to 2 previous errors
1717

1818
Some errors have detailed explanations: E0423, E0790.

src/test/ui/lang-items/issue-83471.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ error[E0573]: expected type, found built-in attribute `export_name`
44
LL | fn call(export_name);
55
| ^^^^^^^^^^^ not a type
66

7-
error[E0425]: cannot find function `a` in this scope
8-
--> $DIR/issue-83471.rs:21:5
9-
|
10-
LL | a()
11-
| ^ not found in this scope
12-
137
error[E0658]: language items are subject to change
148
--> $DIR/issue-83471.rs:7:1
159
|
@@ -45,6 +39,12 @@ LL | #[lang = "fn"]
4539
LL | trait Fn {
4640
| - this trait has 0 generic arguments
4741

42+
error[E0425]: cannot find function `a` in this scope
43+
--> $DIR/issue-83471.rs:21:5
44+
|
45+
LL | a()
46+
| ^ not found in this scope
47+
4848
error: aborting due to 5 previous errors; 1 warning emitted
4949

5050
Some errors have detailed explanations: E0425, E0573, E0658, E0718.

src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr

+22-22
Original file line numberDiff line numberDiff line change
@@ -319,22 +319,39 @@ LL | unknown_metavar!(a);
319319
|
320320
= note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
321321

322-
error[E0425]: cannot find function `count` in this scope
323-
--> $DIR/syntax-errors.rs:29:30
322+
error[E0425]: cannot find value `i` in this scope
323+
--> $DIR/syntax-errors.rs:29:36
324324
|
325325
LL | ( $( $i:ident ),* ) => { count(i) };
326-
| ^^^^^ not found in this scope
326+
| ^ not found in this scope
327327
...
328328
LL | no_curly__no_rhs_dollar__round!(a, b, c);
329329
| ---------------------------------------- in this macro invocation
330330
|
331331
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
332332

333333
error[E0425]: cannot find value `i` in this scope
334-
--> $DIR/syntax-errors.rs:29:36
334+
--> $DIR/syntax-errors.rs:35:29
335+
|
336+
LL | ( $i:ident ) => { count(i) };
337+
| ^ not found in this scope
338+
...
339+
LL | no_curly__no_rhs_dollar__no_round!(a);
340+
| ------------------------------------- in this macro invocation
341+
|
342+
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
343+
344+
error[E0425]: cannot find value `a` in this scope
345+
--> $DIR/syntax-errors.rs:153:37
346+
|
347+
LL | no_curly__rhs_dollar__no_round!(a);
348+
| ^ not found in this scope
349+
350+
error[E0425]: cannot find function `count` in this scope
351+
--> $DIR/syntax-errors.rs:29:30
335352
|
336353
LL | ( $( $i:ident ),* ) => { count(i) };
337-
| ^ not found in this scope
354+
| ^^^^^ not found in this scope
338355
...
339356
LL | no_curly__no_rhs_dollar__round!(a, b, c);
340357
| ---------------------------------------- in this macro invocation
@@ -352,17 +369,6 @@ LL | no_curly__no_rhs_dollar__no_round!(a);
352369
|
353370
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
354371

355-
error[E0425]: cannot find value `i` in this scope
356-
--> $DIR/syntax-errors.rs:35:29
357-
|
358-
LL | ( $i:ident ) => { count(i) };
359-
| ^ not found in this scope
360-
...
361-
LL | no_curly__no_rhs_dollar__no_round!(a);
362-
| ------------------------------------- in this macro invocation
363-
|
364-
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
365-
366372
error[E0425]: cannot find function `count` in this scope
367373
--> $DIR/syntax-errors.rs:46:23
368374
|
@@ -374,12 +380,6 @@ LL | no_curly__rhs_dollar__no_round!(a);
374380
|
375381
= note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
376382

377-
error[E0425]: cannot find value `a` in this scope
378-
--> $DIR/syntax-errors.rs:153:37
379-
|
380-
LL | no_curly__rhs_dollar__no_round!(a);
381-
| ^ not found in this scope
382-
383383
error: aborting due to 40 previous errors
384384

385385
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)