-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[experiment] fulfill diagnostics: do not look into T: IntoIterator
#99719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,8 +135,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
// candidate which assumes $0 == int, one that assumes `$0 == | ||
// usize`, etc. This spells an ambiguity. | ||
|
||
let mut candidates = self.filter_impls(candidates, stack.obligation); | ||
|
||
let candidates = self.filter_impls(candidates, stack.obligation); | ||
let mut candidates = candidates | ||
.into_iter() | ||
.map(|c| match c { | ||
ImplCandidate(impl_def) if self.tcx().is_general_impl(impl_def) => { | ||
match self.evaluate_candidate(stack, &c) { | ||
Ok(eval) if eval.may_apply() => Ok(Some(c)), | ||
Ok(_) => Ok(None), | ||
Err(OverflowError::Canonical) => Err(Overflow(OverflowError::Canonical)), | ||
Err(OverflowError::ErrorReporting) => Err(ErrorReporting), | ||
Err(OverflowError::Error(e)) => Err(Overflow(OverflowError::Error(e))), | ||
} | ||
} | ||
_ => Ok(Some(c)), | ||
}) | ||
.flat_map(Result::transpose) | ||
.collect::<Result<Vec<_>, _>>()?; | ||
Comment on lines
+143
to
+154
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I see, this is a copy of the winnowing code below. What about making It could be framed as "only early-succeed when the candidate is a refinement of the obligation", where e.g. " Then such candidates would hit the winnowing step, which already exists and wouldn't need duplication. |
||
// If there is more than one candidate, first winnow them down | ||
// by considering extra conditions (nested obligations and so | ||
// forth). We don't winnow if there is exactly one | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxIndexSet; | |
use rustc_hir as hir; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_middle::ty::subst::Subst; | ||
use rustc_middle::ty::util::IgnoreRegions; | ||
use rustc_middle::ty::{ | ||
self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, | ||
}; | ||
|
@@ -460,6 +461,13 @@ pub fn conservative_is_privately_uninhabited_raw<'tcx>( | |
} | ||
} | ||
|
||
fn is_general_impl(tcx: TyCtxt<'_>, id: DefId) -> bool { | ||
let Some(trait_ref) = tcx.impl_trait_ref(id) else { | ||
span_bug!(tcx.def_span(id), "expected impl, found `{:?} for `{:?}`", tcx.def_kind(id), id); | ||
}; | ||
tcx.uses_unique_generic_params(trait_ref.substs, IgnoreRegions::No).is_ok() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh, fascinating, never seen this before. |
||
} | ||
|
||
pub fn provide(providers: &mut ty::query::Providers) { | ||
*providers = ty::query::Providers { | ||
asyncness, | ||
|
@@ -469,6 +477,7 @@ pub fn provide(providers: &mut ty::query::Providers) { | |
instance_def_size_estimate, | ||
issue33140_self_ty, | ||
impl_defaultness, | ||
is_general_impl, | ||
conservative_is_privately_uninhabited: conservative_is_privately_uninhabited_raw, | ||
..*providers | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,18 +70,11 @@ help: use parentheses to call this function | |
LL | let x: () = foo::<'static>(); | ||
| ++ | ||
|
||
error[E0277]: the size for values of type `str` cannot be known at compilation time | ||
error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied | ||
--> $DIR/substs-ppaux.rs:49:5 | ||
| | ||
LL | <str as Foo<u8>>::bar; | ||
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | ||
| | ||
= help: the trait `Sized` is not implemented for `str` | ||
note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str` | ||
--> $DIR/substs-ppaux.rs:11:17 | ||
| | ||
LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} | ||
| ^^^^^^^^^^^^^^ ^ | ||
Comment on lines
-80
to
-84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 should we be pointing at blanket impls always, if any, on E0277s? |
||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<'_, '_, u8>` is not implemented for `str` | ||
|
||
error: aborting due to 5 previous errors | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,15 +24,14 @@ LL | fn main() { | |
LL | (|_| 2333).await; | ||
| ^^^^^^ only allowed inside `async` functions and blocks | ||
|
||
error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future | ||
error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` cannot be converted to a future | ||
--> $DIR/issue-62009-1.rs:12:15 | ||
| | ||
LL | (|_| 2333).await; | ||
| ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future | ||
| ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` cannot be converted to a future | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really hate how we display closures 😩 Ideally we should number them and display a span label naming all the ones that are involved, but this will require handling that on every error independently :-/ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. related discussion on irlo wants to display fn items more like closures, specifically so they don't look like fn pointers. Perhaps lying and calling the closure There is a potential way to number closures automatically, but it would still require touching every location that's naming types; roughly one of:
Either way it seems reasonable to add a |
||
| | ||
= help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` | ||
= help: the trait `IntoFuture` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` | ||
= note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited | ||
= note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` | ||
help: remove the `.await` | ||
| | ||
LL - (|_| 2333).await; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,18 @@ | ||
error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied | ||
error[E0277]: the trait bound `&C: Delegates<()>` is not satisfied | ||
--> $DIR/issue-85848.rs:24:29 | ||
| | ||
LL | writes_to_specific_path(&cap); | ||
| ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` | ||
| ----------------------- ^^^^ the trait `Delegates<()>` is not implemented for `&C` | ||
| | | ||
| required by a bound introduced by this call | ||
| | ||
= help: the trait `Delegates<U>` is implemented for `T` | ||
note: required because of the requirements on the impl of `Contains<(), true>` for `&C` | ||
--> $DIR/issue-85848.rs:21:12 | ||
| | ||
LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ | ||
note: required because of the requirements on the impl of `Delegates<()>` for `&C` | ||
--> $DIR/issue-85848.rs:12:12 | ||
| | ||
LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} | ||
| ^^^^^^^^^^^^ ^ | ||
note: required by a bound in `writes_to_specific_path` | ||
--> $DIR/issue-85848.rs:30:31 | ||
| | ||
LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} | ||
| ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` | ||
|
||
error: unconstrained generic constant | ||
--> $DIR/issue-85848.rs:24:29 | ||
| | ||
LL | writes_to_specific_path(&cap); | ||
| ----------------------- ^^^^ | ||
| | | ||
| required by a bound introduced by this call | ||
| | ||
= help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:` | ||
note: required because of the requirements on the impl of `Contains<(), true>` for `&C` | ||
--> $DIR/issue-85848.rs:21:12 | ||
| | ||
LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ | ||
note: required because of the requirements on the impl of `Delegates<()>` for `&C` | ||
--> $DIR/issue-85848.rs:12:12 | ||
| | ||
LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {} | ||
| ^^^^^^^^^^^^ ^ | ||
note: required by a bound in `writes_to_specific_path` | ||
--> $DIR/issue-85848.rs:30:31 | ||
| | ||
LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {} | ||
| ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/issue-85848.rs:24:5 | ||
| | ||
LL | writes_to_specific_path(&cap); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::<T, U>() }` | ||
| | ||
= note: expected type `true` | ||
found type `{ contains::<T, U>() }` | ||
|
||
error: aborting due to 3 previous errors | ||
error: aborting due to previous error | ||
|
||
Some errors have detailed explanations: E0277, E0308. | ||
For more information about an error, try `rustc --explain E0277`. | ||
For more information about this error, try `rustc --explain E0277`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,18 @@ | ||
error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied | ||
error[E0599]: no method named `f` found for struct `S` in the current scope | ||
--> $DIR/method-unsatified-assoc-type-predicate.rs:30:7 | ||
| | ||
LL | struct S; | ||
| -------- | ||
| | | ||
| method `f` not found for this struct | ||
| doesn't satisfy `<S as X>::Y<i32> = i32` | ||
| doesn't satisfy `S: M` | ||
| -------- method `f` not found for this struct | ||
... | ||
LL | a.f(); | ||
| ^ method cannot be called on `S` due to unsatisfied trait bounds | ||
| ^ method not found in `S` | ||
| | ||
note: trait bound `<S as X>::Y<i32> = i32` was not satisfied | ||
--> $DIR/method-unsatified-assoc-type-predicate.rs:14:11 | ||
= help: items from traits can only be used if the trait is implemented and in scope | ||
note: `M` defines an item `f`, perhaps you need to implement it | ||
--> $DIR/method-unsatified-assoc-type-predicate.rs:10:1 | ||
| | ||
LL | impl<T: X<Y<i32> = i32>> M for T {} | ||
| ^^^^^^^^^^^^ - - | ||
| | | ||
| unsatisfied trait bound introduced here | ||
Comment on lines
-1
to
-20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would qualify as a regression, right? Maybe we need a two-step mechanism, where we create the error first and then we try to resolve without accounting for trait bounds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO this suggests that it's the right error:
At most we could show the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But in this case it is a blanket impl, which means that the user can't impl M themselves due to orphan rules, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As an analogy (to avoid the If the type wasn't a locally-defined |
||
LL | trait M { | ||
| ^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this needs to use a qualifier like "fully" or "maximally" to apply to "general" (I suppose "general" is better than "blanket"? at least a doc comment here could explain the connection).