Skip to content

Commit c874676

Browse files
Rework ambiguity errors
1 parent 70b29f7 commit c874676

12 files changed

+95
-145
lines changed

compiler/rustc_middle/src/ty/generics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@ pub struct Generics {
122122
}
123123

124124
impl<'tcx> Generics {
125+
pub fn param_def_id_to_index(&self, tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<u32> {
126+
if let Some(idx) = self.param_def_id_to_index.get(&def_id) {
127+
Some(*idx)
128+
} else if let Some(parent) = self.parent {
129+
let parent = tcx.generics_of(parent);
130+
parent.param_def_id_to_index(tcx, def_id)
131+
} else {
132+
None
133+
}
134+
}
135+
125136
#[inline]
126137
pub fn count(&self) -> usize {
127138
self.parent_count + self.params.len()

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@ use rustc_infer::infer::InferOk;
2727
use rustc_infer::infer::TypeTrace;
2828
use rustc_middle::ty::adjustment::AllowTwoPhase;
2929
use rustc_middle::ty::visit::TypeVisitable;
30-
use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
30+
use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
3131
use rustc_session::Session;
3232
use rustc_span::symbol::Ident;
3333
use rustc_span::{self, Span};
3434
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
3535

3636
use std::iter;
37+
use std::ops::ControlFlow;
3738
use std::slice;
3839

3940
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -1649,7 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16491650
ty::PredicateKind::Projection(pred) => pred.projection_ty.substs,
16501651
_ => ty::List::empty(),
16511652
};
1652-
let param_to_point_at = predicate_substs.types().find_map(|ty| {
1653+
let mut param_to_point_at = predicate_substs.types().find_map(|ty| {
16531654
ty.walk().find_map(|arg| {
16541655
if let ty::GenericArgKind::Type(ty) = arg.unpack()
16551656
&& let ty::Param(param_ty) = ty.kind()
@@ -1663,7 +1664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16631664
}
16641665
})
16651666
});
1666-
let fallback_param_to_point_at = predicate_substs.types().find_map(|ty| {
1667+
let mut fallback_param_to_point_at = predicate_substs.types().find_map(|ty| {
16671668
ty.walk().find_map(|arg| {
16681669
if let ty::GenericArgKind::Type(ty) = arg.unpack()
16691670
&& let ty::Param(param_ty) = ty.kind()
@@ -1676,6 +1677,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16761677
})
16771678
});
16781679

1680+
// Also skip over ambiguity errors, which have their own machinery
1681+
// to print a relevant error.
1682+
if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
1683+
fallback_param_to_point_at = None;
1684+
param_to_point_at =
1685+
self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
1686+
}
1687+
16791688
let hir = self.tcx.hir();
16801689

16811690
match hir.get(hir_id) {
@@ -1737,6 +1746,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17371746
}
17381747
}
17391748

1749+
fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
1750+
&self,
1751+
item_def_id: DefId,
1752+
t: T,
1753+
) -> Option<ty::GenericArg<'tcx>> {
1754+
struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
1755+
impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
1756+
type BreakTy = ty::GenericArg<'tcx>;
1757+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
1758+
if let Some(origin) = self.0.type_var_origin(ty)
1759+
&& let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id))
1760+
= origin.kind
1761+
&& let generics = self.0.tcx.generics_of(self.1)
1762+
&& let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
1763+
&& let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1).get(index as usize)
1764+
{
1765+
ControlFlow::Break(*subst)
1766+
} else {
1767+
ty.super_visit_with(self)
1768+
}
1769+
}
1770+
}
1771+
t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
1772+
}
1773+
17401774
fn point_at_args_if_possible(
17411775
&self,
17421776
error: &mut traits::FulfillmentError<'tcx>,

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

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,11 @@ help: use a fully-qualified path to a specific available implementation (2 found
1212
LL | let cont: u32 = <::Impl as Generator>::create();
1313
| ++++++++++ +
1414

15-
error[E0282]: type annotations needed
16-
--> $DIR/E0283.rs:35:24
17-
|
18-
LL | let bar = foo_impl.into() * 1u32;
19-
| ^^^^
20-
|
21-
help: try using a fully qualified path to specify the expected types
22-
|
23-
LL | let bar = <Impl as Into<T>>::into(foo_impl) * 1u32;
24-
| ++++++++++++++++++++++++ ~
25-
2615
error[E0283]: type annotations needed
2716
--> $DIR/E0283.rs:35:24
2817
|
2918
LL | let bar = foo_impl.into() * 1u32;
30-
| -------- ^^^^
31-
| |
32-
| type must be known at this point
19+
| ^^^^
3320
|
3421
note: multiple `impl`s satisfying `Impl: Into<_>` found
3522
--> $DIR/E0283.rs:17:1
@@ -44,7 +31,7 @@ help: try using a fully qualified path to specify the expected types
4431
LL | let bar = <Impl as Into<T>>::into(foo_impl) * 1u32;
4532
| ++++++++++++++++++++++++ ~
4633

47-
error: aborting due to 3 previous errors
34+
error: aborting due to 2 previous errors
4835

49-
Some errors have detailed explanations: E0282, E0283, E0790.
50-
For more information about an error, try `rustc --explain E0282`.
36+
Some errors have detailed explanations: E0283, E0790.
37+
For more information about an error, try `rustc --explain E0283`.

src/test/ui/inference/issue-72690.stderr

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ error[E0283]: type annotations needed
1212
--> $DIR/issue-72690.rs:7:22
1313
|
1414
LL | String::from("x".as_ref());
15-
| --- ^^^^^^
16-
| |
17-
| type must be known at this point
15+
| ^^^^^^
1816
|
1917
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
2018
- impl AsRef<OsStr> for str;
@@ -41,9 +39,7 @@ error[E0283]: type annotations needed
4139
--> $DIR/issue-72690.rs:12:26
4240
|
4341
LL | |x| String::from("x".as_ref());
44-
| --- ^^^^^^
45-
| |
46-
| type must be known at this point
42+
| ^^^^^^
4743
|
4844
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
4945
- impl AsRef<OsStr> for str;
@@ -59,9 +55,7 @@ error[E0283]: type annotations needed for `&T`
5955
--> $DIR/issue-72690.rs:17:9
6056
|
6157
LL | let _ = "x".as_ref();
62-
| ^ --- ------ required by a bound introduced by this call
63-
| |
64-
| type must be known at this point
58+
| ^ ------ type must be known at this point
6559
|
6660
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
6761
- impl AsRef<OsStr> for str;
@@ -87,9 +81,7 @@ error[E0283]: type annotations needed
8781
--> $DIR/issue-72690.rs:21:22
8882
|
8983
LL | String::from("x".as_ref());
90-
| --- ^^^^^^
91-
| |
92-
| type must be known at this point
84+
| ^^^^^^
9385
|
9486
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
9587
- impl AsRef<OsStr> for str;
@@ -115,9 +107,7 @@ error[E0283]: type annotations needed
115107
--> $DIR/issue-72690.rs:28:22
116108
|
117109
LL | String::from("x".as_ref());
118-
| --- ^^^^^^
119-
| |
120-
| type must be known at this point
110+
| ^^^^^^
121111
|
122112
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
123113
- impl AsRef<OsStr> for str;
@@ -143,9 +133,7 @@ error[E0283]: type annotations needed
143133
--> $DIR/issue-72690.rs:37:22
144134
|
145135
LL | String::from("x".as_ref());
146-
| --- ^^^^^^
147-
| |
148-
| type must be known at this point
136+
| ^^^^^^
149137
|
150138
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
151139
- impl AsRef<OsStr> for str;
@@ -171,9 +159,7 @@ error[E0283]: type annotations needed
171159
--> $DIR/issue-72690.rs:46:22
172160
|
173161
LL | String::from("x".as_ref());
174-
| --- ^^^^^^
175-
| |
176-
| type must be known at this point
162+
| ^^^^^^
177163
|
178164
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
179165
- impl AsRef<OsStr> for str;
@@ -199,9 +185,7 @@ error[E0283]: type annotations needed
199185
--> $DIR/issue-72690.rs:53:22
200186
|
201187
LL | String::from("x".as_ref());
202-
| --- ^^^^^^
203-
| |
204-
| type must be known at this point
188+
| ^^^^^^
205189
|
206190
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
207191
- impl AsRef<OsStr> for str;
@@ -227,9 +211,7 @@ error[E0283]: type annotations needed
227211
--> $DIR/issue-72690.rs:62:22
228212
|
229213
LL | String::from("x".as_ref());
230-
| --- ^^^^^^
231-
| |
232-
| type must be known at this point
214+
| ^^^^^^
233215
|
234216
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
235217
- impl AsRef<OsStr> for str;

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ error[E0283]: type annotations needed
1414
--> $DIR/issue-69455.rs:29:41
1515
|
1616
LL | println!("{}", 23u64.test(xs.iter().sum()));
17-
| ----- ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
18-
| | |
19-
| | required by a bound introduced by this call
20-
| type must be known at this point
17+
| ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
18+
| |
19+
| required by a bound introduced by this call
2120
|
2221
note: multiple `impl`s satisfying `u64: Test<_>` found
2322
--> $DIR/issue-69455.rs:11:1

src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ error[E0283]: type annotations needed
1313
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7
1414
|
1515
LL | x.foo();
16-
| - ^^^
17-
| |
18-
| type must be known at this point
16+
| ^^^
1917
|
2018
note: multiple `impl`s satisfying `Vec<_>: Foo` found
2119
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:9:1

src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ error[E0283]: type annotations needed
1313
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11
1414
|
1515
LL | thing.method(42);
16-
| ----- ^^^^^^
17-
| |
18-
| type must be known at this point
16+
| ^^^^^^
1917
|
2018
note: multiple `impl`s satisfying `Thing<bool>: Method<_>` found
2119
--> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1

src/test/ui/traits/issue-77982.stderr

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ error[E0283]: type annotations needed
2424
--> $DIR/issue-77982.rs:8:10
2525
|
2626
LL | opts.get(opt.as_ref());
27-
| ^^^ --- ------ required by a bound introduced by this call
28-
| | |
29-
| | type must be known at this point
27+
| ^^^ ------ type must be known at this point
28+
| |
3029
| cannot infer type of the type parameter `Q` declared on the associated function `get`
3130
|
3231
= note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`:
@@ -39,24 +38,13 @@ help: consider specifying the generic argument
3938
LL | opts.get::<Q>(opt.as_ref());
4039
| +++++
4140

42-
error[E0282]: type annotations needed
43-
--> $DIR/issue-77982.rs:13:59
44-
|
45-
LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
46-
| ^^^^
47-
|
48-
help: try using a fully qualified path to specify the expected types
49-
|
50-
LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
51-
| +++++++++++++++++++++++ ~
52-
5341
error[E0283]: type annotations needed
5442
--> $DIR/issue-77982.rs:13:59
5543
|
5644
LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
5745
| --------- ^^^^
5846
| |
59-
| type must be known at this point
47+
| required by a bound introduced by this call
6048
|
6149
= note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
6250
- impl From<Ipv4Addr> for u32;
@@ -73,9 +61,7 @@ error[E0283]: type annotations needed for `Box<T>`
7361
--> $DIR/issue-77982.rs:36:9
7462
|
7563
LL | let _ = ().foo();
76-
| ^ -- --- required by a bound introduced by this call
77-
| |
78-
| type must be known at this point
64+
| ^ --- type must be known at this point
7965
|
8066
note: multiple `impl`s satisfying `(): Foo<'_, _>` found
8167
--> $DIR/issue-77982.rs:29:1
@@ -93,9 +79,7 @@ error[E0283]: type annotations needed for `Box<T>`
9379
--> $DIR/issue-77982.rs:40:9
9480
|
9581
LL | let _ = (&()).bar();
96-
| ^ ----- --- required by a bound introduced by this call
97-
| |
98-
| type must be known at this point
82+
| ^ --- type must be known at this point
9983
|
10084
note: multiple `impl`s satisfying `&(): Bar<'_, _>` found
10185
--> $DIR/issue-77982.rs:32:1
@@ -109,7 +93,6 @@ help: consider giving this pattern a type, where the type for type parameter `T`
10993
LL | let _: Box<T> = (&()).bar();
11094
| ++++++++
11195

112-
error: aborting due to 6 previous errors
96+
error: aborting due to 5 previous errors
11397

114-
Some errors have detailed explanations: E0282, E0283.
115-
For more information about an error, try `rustc --explain E0282`.
98+
For more information about this error, try `rustc --explain E0283`.

src/test/ui/traits/multidispatch-convert-ambig-dest.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ error[E0283]: type annotations needed
1313
--> $DIR/multidispatch-convert-ambig-dest.rs:26:5
1414
|
1515
LL | test(22, std::default::Default::default());
16-
| ^^^^ -- type must be known at this point
16+
| ^^^^ -------------------------------- type must be known at this point
1717
| |
1818
| cannot infer type of the type parameter `U` declared on the function `test`
1919
|

src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ error[E0283]: type annotations needed
1313
--> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7
1414
|
1515
LL | a.method();
16-
| - ^^^^^^
17-
| |
18-
| type must be known at this point
16+
| ^^^^^^
1917
|
2018
note: multiple `impl`s satisfying `B: I<_>` found
2119
--> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1

0 commit comments

Comments
 (0)