Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e302e7f

Browse files
committedAug 5, 2024
Add naïve mechanism to filter Into suggestions involving math ops
``` error[E0284]: type annotations needed --> $DIR/issue-70082.rs:7:33 | LL | let y: f64 = 0.01f64 * 1i16.into(); | - ^^^^ | | | type must be known at this point | = note: cannot satisfy `<f64 as Mul<_>>::Output == f64` help: try using a fully qualified path to specify the expected types | LL | let y: f64 = 0.01f64 * <i16 as Into<f64>>::into(1i16); | +++++++++++++++++++++++++ ~ ``` Note that we only suggest `Into<f64>`, and not `Into<i32>`, `Into<i64>`, `Into<i128>`, `Into<isize>`, `Into<f32>` or `Into<AtomicI16>`.
1 parent a831d59 commit e302e7f

File tree

8 files changed

+42
-57
lines changed

8 files changed

+42
-57
lines changed
 

‎compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15401540
TypeAnnotationNeeded::E0282,
15411541
true,
15421542
self.param_env,
1543+
None,
15431544
)
15441545
.emit()
15451546
});

‎compiler/rustc_hir_typeck/src/method/probe.rs

+1
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
436436
TypeAnnotationNeeded::E0282,
437437
!raw_ptr_call,
438438
self.param_env,
439+
None,
439440
);
440441
if raw_ptr_call {
441442
err.span_label(span, "cannot call a method on a raw pointer with an unknown pointee type");

‎compiler/rustc_hir_typeck/src/writeback.rs

+1
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
785785
TypeAnnotationNeeded::E0282,
786786
false,
787787
self.fcx.param_env,
788+
None,
788789
)
789790
.emit()
790791
}

‎compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs

+32-3
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
419419
error_code: TypeAnnotationNeeded,
420420
should_label_span: bool,
421421
param_env: ty::ParamEnv<'tcx>,
422+
predicate: Option<ty::Predicate<'tcx>>,
422423
) -> Diag<'a> {
423424
let arg = self.resolve_vars_if_possible(arg);
424425
let arg_data = self.extract_inference_diagnostics_data(arg, None);
@@ -460,7 +461,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
460461
&& let hir::ExprKind::MethodCall(_, rcvr, _, _) = expr.kind
461462
&& let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id)
462463
{
463-
paths = self.get_suggestions(ty, def_id, true, param_env, None);
464+
paths = self.get_suggestions(ty, def_id, true, param_env, None, predicate);
464465
}
465466

466467
if paths.is_empty() {
@@ -587,8 +588,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
587588

588589
// Look for all the possible implementations to suggest, otherwise we'll show
589590
// just suggest the syntax for the fully qualified path with placeholders.
590-
let paths =
591-
self.get_suggestions(args.type_at(0), def_id, false, param_env, Some(args));
591+
let paths = self.get_suggestions(
592+
args.type_at(0),
593+
def_id,
594+
false,
595+
param_env,
596+
Some(args),
597+
predicate,
598+
);
592599
if paths.len() > 20 || paths.is_empty() {
593600
// This will show the fallback impl, so the expression will have type
594601
// parameter placeholders, but it's better than nothing.
@@ -667,6 +674,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
667674
target_type: bool,
668675
param_env: ty::ParamEnv<'tcx>,
669676
args: Option<&ty::GenericArgs<'tcx>>,
677+
predicate: Option<ty::Predicate<'tcx>>,
670678
) -> Vec<String> {
671679
let tcx = self.infcx.tcx;
672680
let mut paths = vec![];
@@ -695,6 +703,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
695703
// Nope, don't bother.
696704
return;
697705
}
706+
707+
let filter = if let Some(ty::ProjectionPredicate {
708+
projection_term: ty::AliasTerm { def_id, .. },
709+
term,
710+
}) =
711+
predicate.and_then(|p| p.as_projection_clause()).map(|p| p.skip_binder())
712+
&& let ty::TermKind::Ty(assoc_ty) = term.unpack()
713+
&& tcx.item_name(def_id) == sym::Output
714+
{
715+
// If the predicate that failed to be inferred is an associated type called
716+
// "Output" (presumably from one of the math traits), we will only mention the
717+
// `Into` and `From` impls that correspond to the self type as well, so as to
718+
// avoid showing multiple conversion options.
719+
Some(assoc_ty)
720+
} else {
721+
None
722+
};
698723
let assocs = tcx.associated_items(impl_def_id);
699724

700725
if tcx.is_diagnostic_item(sym::blanket_into_impl, impl_def_id)
@@ -712,6 +737,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
712737
return;
713738
};
714739
let target = header.trait_ref.skip_binder().args.type_at(0);
740+
if filter.is_some() && filter != Some(target) {
741+
return;
742+
};
743+
let target = header.trait_ref.skip_binder().args.type_at(0);
715744
let ty = header.trait_ref.skip_binder().args.type_at(1);
716745
if ty == self_ty {
717746
if target_type {

‎compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs

+7
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
209209
TypeAnnotationNeeded::E0282,
210210
false,
211211
obligation.param_env,
212+
None,
212213
);
213214
return err.stash(span, StashKey::MaybeForgetReturn).unwrap();
214215
}
@@ -239,6 +240,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
239240
TypeAnnotationNeeded::E0283,
240241
true,
241242
obligation.param_env,
243+
None,
242244
)
243245
} else {
244246
struct_span_code_err!(
@@ -452,6 +454,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
452454
TypeAnnotationNeeded::E0282,
453455
false,
454456
obligation.param_env,
457+
None,
455458
)
456459
}
457460

@@ -472,6 +475,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
472475
TypeAnnotationNeeded::E0282,
473476
true,
474477
obligation.param_env,
478+
None,
475479
)
476480
}
477481
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
@@ -503,6 +507,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
503507
TypeAnnotationNeeded::E0284,
504508
true,
505509
obligation.param_env,
510+
Some(predicate),
506511
)
507512
.with_note(format!("cannot satisfy `{predicate}`"))
508513
} else {
@@ -534,6 +539,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
534539
TypeAnnotationNeeded::E0284,
535540
true,
536541
obligation.param_env,
542+
None,
537543
);
538544
err
539545
} else {
@@ -557,6 +563,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
557563
TypeAnnotationNeeded::E0284,
558564
true,
559565
obligation.param_env,
566+
None,
560567
),
561568
ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
562569
if term.is_infer() =>

‎tests/ui/inference/issue-70082.rs

-6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,4 @@ fn main() {
77
let y: f64 = 0.01f64 * 1i16.into();
88
//~^ ERROR type annotations needed
99
//~| HELP try using a fully qualified path
10-
//~| HELP try using a fully qualified path
11-
//~| HELP try using a fully qualified path
12-
//~| HELP try using a fully qualified path
13-
//~| HELP try using a fully qualified path
14-
//~| HELP try using a fully qualified path
15-
//~| HELP try using a fully qualified path
1610
}

‎tests/ui/inference/issue-70082.stderr

-24
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,8 @@ LL | let y: f64 = 0.01f64 * 1i16.into();
99
= note: cannot satisfy `<f64 as Mul<_>>::Output == f64`
1010
help: try using a fully qualified path to specify the expected types
1111
|
12-
LL | let y: f64 = 0.01f64 * <i16 as Into<i32>>::into(1i16);
13-
| +++++++++++++++++++++++++ ~
14-
help: try using a fully qualified path to specify the expected types
15-
|
16-
LL | let y: f64 = 0.01f64 * <i16 as Into<i64>>::into(1i16);
17-
| +++++++++++++++++++++++++ ~
18-
help: try using a fully qualified path to specify the expected types
19-
|
20-
LL | let y: f64 = 0.01f64 * <i16 as Into<i128>>::into(1i16);
21-
| ++++++++++++++++++++++++++ ~
22-
help: try using a fully qualified path to specify the expected types
23-
|
24-
LL | let y: f64 = 0.01f64 * <i16 as Into<isize>>::into(1i16);
25-
| +++++++++++++++++++++++++++ ~
26-
help: try using a fully qualified path to specify the expected types
27-
|
28-
LL | let y: f64 = 0.01f64 * <i16 as Into<f32>>::into(1i16);
29-
| +++++++++++++++++++++++++ ~
30-
help: try using a fully qualified path to specify the expected types
31-
|
3212
LL | let y: f64 = 0.01f64 * <i16 as Into<f64>>::into(1i16);
3313
| +++++++++++++++++++++++++ ~
34-
help: try using a fully qualified path to specify the expected types
35-
|
36-
LL | let y: f64 = 0.01f64 * <i16 as Into<AtomicI16>>::into(1i16);
37-
| +++++++++++++++++++++++++++++++ ~
3814

3915
error: aborting due to 1 previous error
4016

‎tests/ui/inference/issue-71584.stderr

-24
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,6 @@ help: try using a fully qualified path to specify the expected types
1111
|
1212
LL | d = d % <u32 as Into<u64>>::into(n);
1313
| +++++++++++++++++++++++++ ~
14-
help: try using a fully qualified path to specify the expected types
15-
|
16-
LL | d = d % <u32 as Into<u128>>::into(n);
17-
| ++++++++++++++++++++++++++ ~
18-
help: try using a fully qualified path to specify the expected types
19-
|
20-
LL | d = d % <u32 as Into<i64>>::into(n);
21-
| +++++++++++++++++++++++++ ~
22-
help: try using a fully qualified path to specify the expected types
23-
|
24-
LL | d = d % <u32 as Into<i128>>::into(n);
25-
| ++++++++++++++++++++++++++ ~
26-
help: try using a fully qualified path to specify the expected types
27-
|
28-
LL | d = d % <u32 as Into<f64>>::into(n);
29-
| +++++++++++++++++++++++++ ~
30-
help: try using a fully qualified path to specify the expected types
31-
|
32-
LL | d = d % <u32 as Into<Ipv4Addr>>::into(n);
33-
| ++++++++++++++++++++++++++++++ ~
34-
help: try using a fully qualified path to specify the expected types
35-
|
36-
LL | d = d % <u32 as Into<AtomicU32>>::into(n);
37-
| +++++++++++++++++++++++++++++++ ~
3814

3915
error: aborting due to 1 previous error
4016

0 commit comments

Comments
 (0)
Failed to load comments.