-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Can't overload indexing for arrays #49786
Comments
Can we get a bisection? I remember there being some PRs that changed indexing of built-in types to work with impls though, so I suspect that is the cause. cc @rust-lang/release |
triage: P-high Regression, perhaps legit, but we need to see why. |
Bisected this, the regression is in #47167. cc @ivanbakel @nikomatsakis |
@pietroalbini thanks! That's the PR I was thinking of, I believe. |
Sigh. This was missing a T-compiler tag, so it was overlooked. |
Ok, so, I tracked down what's going on. The answer is that we have no impls of As a workaround, the code can be fixed by doing the unsize to impl ops::Index<MyIndex> for [String; 2] {
type Output = String;
fn index(&self, index: MyIndex) -> &String {
let this: &[String] = self;
match index.0 {
false => &this[0],
true => &this[1],
}
}
} The question is, is this the desired behavior? It seems like when we search for matching impls we are not taking the type of the index into account. Looking at the code, I can't quite see why that is. It seems like we have the info we need, we're just choosing to ignore it. I'm experimenting. For reference, this is the function that checks for whether rust/src/librustc_typeck/check/mod.rs Lines 2352 to 2358 in 90463a6
The rust/src/librustc_typeck/check/mod.rs Lines 2382 to 2384 in 90463a6
Perhaps this is meant to be analogous to |
Still, this diff makes the test pass: diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index db859e4205..ef5599f82b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2381,9 +2381,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// If some lookup succeeds, write callee into table and extract index/element
// type from the method signature.
// If some lookup succeeded, install method in table
- let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
let method = self.try_overloaded_place_op(
- expr.span, self_ty, &[input_ty], needs, PlaceOp::Index);
+ expr.span, self_ty, &[index_ty], needs, PlaceOp::Index);
let result = method.map(|ok| {
debug!("try_index_step: success, using overloaded indexing");
@@ -2418,7 +2417,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.apply_adjustments(base_expr, adjustments);
self.write_method_call(expr.hir_id, method);
- (input_ty, self.make_overloaded_place_return_type(method).ty)
+ (index_ty, self.make_overloaded_place_return_type(method).ty)
});
if result.is_some() {
return result; |
Now we just have to decide if we want to do that. I'll also want to check the other implications. I'm going to make a branch and start a |
The main complication seems to be that we regress some of the helpful error messages around indexing. |
Nominating for discussion in the lang-team meeting. There is a bit a question here about what behavior we want. Let me summarize:
Note that the index type The change I made is this:
What happens as a result is that we do not halt the autoderef loop at This seems good to me, but I wanted to run it by @rust-lang/lang. The current branch we probably don't want to land because the diagnostic impact is ungreat: there are many examples where people are using the wrong index type. As a result, the autoderef loop never finds any match, but the error we report says that the type is "not indexable" — where the correct thing to say is "not indexable by a value of type |
Didn't we want to use the index type from the |
@eddyb that is indeed one of the questions here. We do not presently. |
(At least that's what I remember, I can reconfirm.) |
We discussed this in the @rust-lang/lang meeting last week but didn't come to a firm conclusion. Previously, the language was basically so that One notable downside has to do with coercions. Consider the following example (which does not compile today): use std::collections::HashMap;
fn main() {
let map = HashMap::new();
map.insert("foo", "bar");
let x = &format!("foo");
let y = map[x];
} Here, the expected key is an In contrast, if we make this change, we would be searching for an impl of Part of the context here is that we are hoping, once the trait system impl is overhauled for chalk etc, to make more progress on being smarter about coercions and so forth, and so it may not make sense to make any changes to the core type system until we have those pieces in place, for fear of locking ourselves in (we are already, of course, locked in to the current behavior to a large extent). A counterpoint was raised by @joshtriplett, who pointed out that this existing code had stopped compiling, albeit as a result of a bugfix, and so we ought to do what we can to keep it working. In general, I agree with this sentiment, but this specific area of change is the sort that we do consider permissible -- in particular, bug fixes etc, and specifically where the existing code can be made to work with small tweaks (here, adding a |
I'm going to bump this down from P-high to P-medium. triage: P-medium |
@rfcbot fcp close I propose that we do not take action to fix this -- it does mean that the code above regressed, but arguably it is behaving "to spec" now, and I am nervous that changing the behavior here will close doors we might prefer to keep open for now (see summary here). |
Team member @nikomatsakis has proposed to close this. The next step is review by the rest of the tagged teams: No concerns currently listed. Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to close, as per the review above, is now complete. |
Following code compiled in Rust 1.24.1, but fails to compile under Rust 1.25.0:
Terminal session:
The text was updated successfully, but these errors were encountered: